I have an issue with my silicon labs usb fmradio and after apending with Hans de Goede, he suggested that I should email you people. I have bought a silicon labs usb fmradio and I have written a python GUI to control it. I have downloaded pyv4l2radio-0.3 which would also offer me RDS decoding. But except for opening and closing the radio device nothing else works in this library. I also downloaded pyFMRadio-0.22 and again the same problem. Note however that the radio does work. I am running gnomeradio and I can scan and tune to radio stations and everything works fine. But when I am using the python FMRadio library included in pyv4l2radio-0.3 or pyFMRadio-0.22 the usb radio automatically tunes to 96.3MHz. Amazingly enough, RDS decoding does work, and that's how I know that the radio is tuned to 96.3, its in the RDS text transmitted by the radio station at 96.3MHz. This is the output I get from dmesg: [ 131.804472] usb 2-1.2: new full-speed USB device number 3 using ehci_hcd [ 131.983778] USB radio driver for Si470x FM Radio Receivers, Version 1.0.10 [ 131.984497] radio-si470x 2-1.2:1.2: DeviceID=0x1242 ChipID=0x0a0f [ 131.985051] radio-si470x 2-1.2:1.2: software version 0, hardware version 4 [ 131.985060] radio-si470x 2-1.2:1.2: This driver is known to work with software version 7, [ 131.985065] radio-si470x 2-1.2:1.2: but the device has software version 0. [ 131.985070] radio-si470x 2-1.2:1.2: If you have some trouble using this driver, [ 131.985074] radio-si470x 2-1.2:1.2: please report to V4L ML at linux-media@xxxxxxxxxxxxxxx [ 132.034526] usbcore: registered new interface driver radio-si470x [ 132.036412] usbcore: registered new interface driver snd-usb-audio I think that there is a problem with the kernel definitions for ioctl commands. can you take a look and tell me if you see anything weird? _IOC_NRBITS = 8 _IOC_TYPEBITS = 8 _IOC_SIZEBITS = 14 _IOC_DIRBITS = 2 _IOC_NRSHIFT = 0 _IOC_TYPESHIFT = _IOC_NRSHIFT + _IOC_NRBITS _IOC_SIZESHIFT = _IOC_TYPESHIFT + _IOC_TYPEBITS _IOC_DIRSHIFT = _IOC_SIZESHIFT + _IOC_SIZEBITS _IOC_WRITE = 1 _IOC_READ = 2 _IOC = lambda d,t,nr,size: (d << _IOC_DIRSHIFT) | (ord(t) << _IOC_TYPESHIFT) | \ (nr << _IOC_NRSHIFT) | (size << _IOC_SIZESHIFT) _IOW = lambda t,nr,size: _IOC(_IOC_WRITE, t, nr, size) _IOWR = lambda t,nr,size: _IOC(_IOC_READ | _IOC_WRITE, t, nr, size) # V4L2 stuff for accessing the tuner driver _VIDIOC_G_TUNER = _IOWR('V', 29, 84) _VIDIOC_G_FREQUENCY = _IOWR('V', 56, 44) _VIDIOC_S_FREQUENCY = _IOW ('V', 57, 44) _VIDIOC_G_CTRL = _IOWR('V', 27, 8) _VIDIOC_S_CTRL = _IOWR('V', 28, 8) # tuner capabilities _V4L2_TUNER_CAP_LOW = 0x0001 _V4L2_TUNER_CAP_NORM_ = 0x0002 _V4L2_TUNER_CAP_STEREO = 0x0010 _V4L2_TUNER_CAP_LANG2 = 0x0020 _V4L2_TUNER_CAP_SAP = 0x0020 # user-class control IDs defined by V4L2 _V4L2_CTRL_CLASS_USER = 0x00980000 _V4L2_CID_BASE = _V4L2_CTRL_CLASS_USER | 0x900 _V4L2_CID_FM_BAND = _V4L2_CID_BASE + 0 # signal scanning parameters _SIGNAL_LOCK_TIME = 0.1 _SIGNAL_TRIES = 1 _SIGNAL_SAMPLE_SLEEP = 0.005 _SIGNAL_THRESHOLD = 20 _SCAN_STEP_KHZ = 50 I also noticed that if I tune to a station with gnomeradio and shut gnomeradio down, if I run a test python program (based on FMRadio) to open the radio, the radio device starts automatically tuned to the frequency last tuned by gnomeradio. If I try to set_frequency to anywhere the usb radio tunes to 96.3 and the get_frequency, get_signal_strength functions return 0. Also function __get_tuner executes an ioctl call: data = ioctl(self.__fd, _VIDIOC_G_TUNER, struct.pack("84x")) fields = struct.unpack("L32sLLLLLLll4L", data) which crashes with a message about 'struct unpack expects 136 bytes' Then I changed it to: data = ioctl(self.__fd, _VIDIOC_G_TUNER, struct.pack("136x")) and no more crashes. However, printing the frequency range and factor I get rangelow:1.14933324841e+16 rangehigh 62.5 factor: 0.016 The frequency ranges do not make any sense and perhaps the entire answer of the ioctl is garbage. Any ideas, that would point me to the correct direction as to how to fix this, would be greatly appreciated. I include some of the other ioctl calls for you and I am also attaching the entire file for you to have a more complete picture (The file is 400 lines long) get_fm_band: inp = struct.pack("Ll", _V4L2_CID_FM_BAND, 0) data = ioctl(self.__fd, _VIDIOC_G_CTRL, inp) get_frequency: inp = struct.pack("LLL8L", self.__tuner["index"], self.__tuner["type"], 0, 0, 0, 0, 0, 0, 0, 0, 0) data = ioctl(self.__fd, _VIDIOC_G_FREQUENCY, inp) set_fm_band: inp = struct.pack("Ll", _V4L2_CID_FM_BAND, band) ioctl(self.__fd, _VIDIOC_S_CTRL, inp) get_fm_band: inp = struct.pack("Ll", _V4L2_CID_FM_BAND, 0) data = ioctl(self.__fd, _VIDIOC_G_CTRL, inp) __set_frequency: inp = struct.pack("LLL8L", self.__tuner["index"], self.__tuner["type"], #freq, 0, 0, 0, 0, 0, 0, 0, 0) int(freq * self.__factor), 0, 0, 0, 0, 0, 0, 0, 0) ioctl(self.__fd, _VIDIOC_S_FREQUENCY, inp)
Attachment:
FMRadio.py
Description: Binary data