···352352353353config USB_DSBR354354 tristate "D-Link USB FM radio support (EXPERIMENTAL)"355355- depends on USB && VIDEO_V4L1 && EXPERIMENTAL355355+ depends on USB && VIDEO_V4L2 && EXPERIMENTAL356356 ---help---357357 Say Y here if you want to connect this type of radio to your358358 computer's USB port. Note that the audio is not digital, and
+125-69
drivers/media/radio/dsbr100.c
···33333434 History:35353636+ Version 0.41-ac1:3737+ Alan Cox: Some cleanups and fixes3838+3939+ Version 0.41:4040+ Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org>4141+3642 Version 0.40:3737- Markus: Updates for 2.6.x kernels, code layout changes, name sanitizing4343+ Markus: Updates for 2.6.x kernels, code layout changes, name sanitizing38443945 Version 0.30:4046 Markus: Updates for 2.5.x kernel and more ISO compliant source···71657266*/73677474-7568#include <linux/kernel.h>7669#include <linux/module.h>7770#include <linux/init.h>7871#include <linux/slab.h>7972#include <linux/input.h>8080-#include <linux/videodev.h>7373+#include <linux/videodev2.h>8174#include <media/v4l2-common.h>8275#include <linux/usb.h>8376#include <linux/smp_lock.h>···8479/*8580 * Version Information8681 */8787-#define DRIVER_VERSION "v0.40"8282+#include <linux/version.h> /* for KERNEL_VERSION MACRO */8383+8484+#define DRIVER_VERSION "v0.41"8585+#define RADIO_VERSION KERNEL_VERSION(0,4,1)8686+8787+static struct v4l2_queryctrl radio_qctrl[] = {8888+ {8989+ .id = V4L2_CID_AUDIO_MUTE,9090+ .name = "Mute",9191+ .minimum = 0,9292+ .maximum = 1,9393+ .default_value = 1,9494+ .type = V4L2_CTRL_TYPE_BOOLEAN,9595+ }9696+};9797+8898#define DRIVER_AUTHOR "Markus Demleitner <msdemlei@tucana.harvard.edu>"8999#define DRIVER_DESC "D-Link DSB-R100 USB FM radio driver"90100···131111module_param(radio_nr, int, 0);132112133113/* Data for one (physical) device */134134-typedef struct {114114+struct dsbr100_device {135115 struct usb_device *usbdev;136116 struct video_device *videodev;137117 unsigned char transfer_buffer[TB_LEN];···139119 int stereo;140120 int users;141121 int removed;142142-} dsbr100_device;122122+ int muted;123123+};143124144125145126/* File system interface */···159138 .owner = THIS_MODULE,160139 .name = "D-Link DSB-R 100",161140 .type = VID_TYPE_TUNER,162162- .hardware = VID_HARDWARE_AZTECH,163141 .fops = &usb_dsbr100_fops,164142 .release = video_device_release,165143};···181161/* Low-level device interface begins here */182162183163/* switch on radio */184184-static int dsbr100_start(dsbr100_device *radio)164164+static int dsbr100_start(struct dsbr100_device *radio)185165{186166 if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),187167 USB_REQ_GET_STATUS,···192172 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,193173 0x01, 0x00, radio->transfer_buffer, 8, 300)<0)194174 return -1;175175+ radio->muted=0;195176 return (radio->transfer_buffer)[0];196177}197178198179199180/* switch off radio */200200-static int dsbr100_stop(dsbr100_device *radio)181181+static int dsbr100_stop(struct dsbr100_device *radio)201182{202183 if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),203184 USB_REQ_GET_STATUS,···209188 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,210189 0x00, 0x00, radio->transfer_buffer, 8, 300)<0)211190 return -1;191191+ radio->muted=1;212192 return (radio->transfer_buffer)[0];213193}214194215195/* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */216216-static int dsbr100_setfreq(dsbr100_device *radio, int freq)196196+static int dsbr100_setfreq(struct dsbr100_device *radio, int freq)217197{218198 freq = (freq/16*80)/1000+856;219199 if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),···239217240218/* return the device status. This is, in effect, just whether it241219sees a stereo signal or not. Pity. */242242-static void dsbr100_getstat(dsbr100_device *radio)220220+static void dsbr100_getstat(struct dsbr100_device *radio)243221{244222 if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),245223 USB_REQ_GET_STATUS,···258236static int usb_dsbr100_probe(struct usb_interface *intf,259237 const struct usb_device_id *id)260238{261261- dsbr100_device *radio;239239+ struct dsbr100_device *radio;262240263263- if (!(radio = kmalloc(sizeof(dsbr100_device), GFP_KERNEL)))241241+ if (!(radio = kmalloc(sizeof(struct dsbr100_device), GFP_KERNEL)))264242 return -ENOMEM;265243 if (!(radio->videodev = video_device_alloc())) {266244 kfree(radio);···293271leak here it's tiny (~50 bytes per disconnect) */294272static void usb_dsbr100_disconnect(struct usb_interface *intf)295273{296296- dsbr100_device *radio = usb_get_intfdata(intf);274274+ struct dsbr100_device *radio = usb_get_intfdata(intf);297275298276 usb_set_intfdata (intf, NULL);299277 if (radio) {···313291static int usb_dsbr100_do_ioctl(struct inode *inode, struct file *file,314292 unsigned int cmd, void *arg)315293{316316- dsbr100_device *radio=video_get_drvdata(video_devdata(file));294294+ struct dsbr100_device *radio=video_get_drvdata(video_devdata(file));317295318296 if (!radio)319297 return -EIO;320298321299 switch(cmd) {322322- case VIDIOCGCAP: {323323- struct video_capability *v = arg;300300+ case VIDIOC_QUERYCAP:301301+ {302302+ struct v4l2_capability *v = arg;303303+ memset(v,0,sizeof(*v));304304+ strlcpy(v->driver, "dsbr100", sizeof (v->driver));305305+ strlcpy(v->card, "D-Link R-100 USB FM Radio", sizeof (v->card));306306+ sprintf(v->bus_info,"ISA");307307+ v->version = RADIO_VERSION;308308+ v->capabilities = V4L2_CAP_TUNER;324309325325- memset(v, 0, sizeof(*v));326326- v->type = VID_TYPE_TUNER;327327- v->channels = 1;328328- v->audios = 1;329329- strcpy(v->name, "D-Link R-100 USB FM Radio");330310 return 0;331311 }332332- case VIDIOCGTUNER: {333333- struct video_tuner *v = arg;312312+ case VIDIOC_G_TUNER:313313+ {314314+ struct v4l2_tuner *v = arg;315315+316316+ if (v->index > 0)317317+ return -EINVAL;334318335319 dsbr100_getstat(radio);336336- if(v->tuner) /* Only 1 tuner */337337- return -EINVAL;320320+321321+ memset(v,0,sizeof(*v));322322+ strcpy(v->name, "FM");323323+ v->type = V4L2_TUNER_RADIO;324324+338325 v->rangelow = FREQ_MIN*FREQ_MUL;339326 v->rangehigh = FREQ_MAX*FREQ_MUL;340340- v->flags = VIDEO_TUNER_LOW;341341- v->mode = VIDEO_MODE_AUTO;342342- v->signal = radio->stereo*0x7000;343343- /* Don't know how to get signal strength */344344- v->flags |= VIDEO_TUNER_STEREO_ON*radio->stereo;345345- strcpy(v->name, "DSB R-100");327327+ v->rxsubchans =V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO;328328+ v->capability=V4L2_TUNER_CAP_LOW;329329+ if(radio->stereo)330330+ v->audmode = V4L2_TUNER_MODE_STEREO;331331+ else332332+ v->audmode = V4L2_TUNER_MODE_MONO;333333+ v->signal = 0xFFFF; /* We can't get the signal strength */334334+346335 return 0;347336 }348348- case VIDIOCSTUNER: {349349- struct video_tuner *v = arg;337337+ case VIDIOC_S_TUNER:338338+ {339339+ struct v4l2_tuner *v = arg;350340351351- if(v->tuner!=0)341341+ if (v->index > 0)352342 return -EINVAL;353353- /* Only 1 tuner so no setting needed ! */343343+354344 return 0;355345 }356356- case VIDIOCGFREQ: {357357- int *freq = arg;346346+ case VIDIOC_S_FREQUENCY:347347+ {348348+ struct v4l2_frequency *f = arg;358349359359- if (radio->curfreq==-1)360360- return -EINVAL;361361- *freq = radio->curfreq;362362- return 0;363363- }364364- case VIDIOCSFREQ: {365365- int *freq = arg;366366-367367- radio->curfreq = *freq;350350+ radio->curfreq = f->frequency;368351 if (dsbr100_setfreq(radio, radio->curfreq)==-1)369352 warn("Set frequency failed");370353 return 0;371354 }372372- case VIDIOCGAUDIO: {373373- struct video_audio *v = arg;355355+ case VIDIOC_G_FREQUENCY:356356+ {357357+ struct v4l2_frequency *f = arg;374358375375- memset(v, 0, sizeof(*v));376376- v->flags |= VIDEO_AUDIO_MUTABLE;377377- v->mode = VIDEO_SOUND_STEREO;378378- v->volume = 1;379379- v->step = 1;380380- strcpy(v->name, "Radio");359359+ f->type = V4L2_TUNER_RADIO;360360+ f->frequency = radio->curfreq;361361+381362 return 0;382363 }383383- case VIDIOCSAUDIO: {384384- struct video_audio *v = arg;364364+ case VIDIOC_QUERYCTRL:365365+ {366366+ struct v4l2_queryctrl *qc = arg;367367+ int i;385368386386- if (v->audio)387387- return -EINVAL;388388- if (v->flags&VIDEO_AUDIO_MUTE) {389389- if (dsbr100_stop(radio)==-1)390390- warn("Radio did not respond properly");369369+ for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {370370+ if (qc->id && qc->id == radio_qctrl[i].id) {371371+ memcpy(qc, &(radio_qctrl[i]),372372+ sizeof(*qc));373373+ return 0;374374+ }391375 }392392- else393393- if (dsbr100_start(radio)==-1)394394- warn("Radio did not respond properly");395395- return 0;376376+ return -EINVAL;377377+ }378378+ case VIDIOC_G_CTRL:379379+ {380380+ struct v4l2_control *ctrl= arg;381381+382382+ switch (ctrl->id) {383383+ case V4L2_CID_AUDIO_MUTE:384384+ ctrl->value=radio->muted;385385+ return 0;386386+ }387387+ return -EINVAL;388388+ }389389+ case VIDIOC_S_CTRL:390390+ {391391+ struct v4l2_control *ctrl= arg;392392+393393+ switch (ctrl->id) {394394+ case V4L2_CID_AUDIO_MUTE:395395+ if (ctrl->value) {396396+ if (dsbr100_stop(radio)==-1)397397+ warn("Radio did not respond properly");398398+ } else {399399+ if (dsbr100_start(radio)==-1)400400+ warn("Radio did not respond properly");401401+ }402402+ return 0;403403+ }404404+ return -EINVAL;396405 }397406 default:398398- return -ENOIOCTLCMD;407407+ return v4l_compat_translate_ioctl(inode,file,cmd,arg,408408+ usb_dsbr100_do_ioctl);399409 }400410}401411···439385440386static int usb_dsbr100_open(struct inode *inode, struct file *file)441387{442442- dsbr100_device *radio=video_get_drvdata(video_devdata(file));388388+ struct dsbr100_device *radio=video_get_drvdata(video_devdata(file));443389444390 radio->users = 1;391391+ radio->muted = 1;392392+445393 if (dsbr100_start(radio)<0) {446394 warn("Radio did not start up properly");447395 radio->users = 0;···455399456400static int usb_dsbr100_close(struct inode *inode, struct file *file)457401{458458- dsbr100_device *radio=video_get_drvdata(video_devdata(file));402402+ struct dsbr100_device *radio=video_get_drvdata(video_devdata(file));459403460404 if (!radio)461405 return -ENODEV;