Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

V4L/DVB (4410): Cleanups and fixes for dsbr100

Signed-off-by: Alan Cox <alan@redhat.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>

authored by

Alan Cox and committed by
Mauro Carvalho Chehab
5aff308c c0c7fa09

+126 -70
+1 -1
drivers/media/radio/Kconfig
··· 352 352 353 353 config USB_DSBR 354 354 tristate "D-Link USB FM radio support (EXPERIMENTAL)" 355 - depends on USB && VIDEO_V4L1 && EXPERIMENTAL 355 + depends on USB && VIDEO_V4L2 && EXPERIMENTAL 356 356 ---help--- 357 357 Say Y here if you want to connect this type of radio to your 358 358 computer's USB port. Note that the audio is not digital, and
+125 -69
drivers/media/radio/dsbr100.c
··· 33 33 34 34 History: 35 35 36 + Version 0.41-ac1: 37 + Alan Cox: Some cleanups and fixes 38 + 39 + Version 0.41: 40 + Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org> 41 + 36 42 Version 0.40: 37 - Markus: Updates for 2.6.x kernels, code layout changes, name sanitizing 43 + Markus: Updates for 2.6.x kernels, code layout changes, name sanitizing 38 44 39 45 Version 0.30: 40 46 Markus: Updates for 2.5.x kernel and more ISO compliant source ··· 71 65 72 66 */ 73 67 74 - 75 68 #include <linux/kernel.h> 76 69 #include <linux/module.h> 77 70 #include <linux/init.h> 78 71 #include <linux/slab.h> 79 72 #include <linux/input.h> 80 - #include <linux/videodev.h> 73 + #include <linux/videodev2.h> 81 74 #include <media/v4l2-common.h> 82 75 #include <linux/usb.h> 83 76 #include <linux/smp_lock.h> ··· 84 79 /* 85 80 * Version Information 86 81 */ 87 - #define DRIVER_VERSION "v0.40" 82 + #include <linux/version.h> /* for KERNEL_VERSION MACRO */ 83 + 84 + #define DRIVER_VERSION "v0.41" 85 + #define RADIO_VERSION KERNEL_VERSION(0,4,1) 86 + 87 + static struct v4l2_queryctrl radio_qctrl[] = { 88 + { 89 + .id = V4L2_CID_AUDIO_MUTE, 90 + .name = "Mute", 91 + .minimum = 0, 92 + .maximum = 1, 93 + .default_value = 1, 94 + .type = V4L2_CTRL_TYPE_BOOLEAN, 95 + } 96 + }; 97 + 88 98 #define DRIVER_AUTHOR "Markus Demleitner <msdemlei@tucana.harvard.edu>" 89 99 #define DRIVER_DESC "D-Link DSB-R100 USB FM radio driver" 90 100 ··· 131 111 module_param(radio_nr, int, 0); 132 112 133 113 /* Data for one (physical) device */ 134 - typedef struct { 114 + struct dsbr100_device { 135 115 struct usb_device *usbdev; 136 116 struct video_device *videodev; 137 117 unsigned char transfer_buffer[TB_LEN]; ··· 139 119 int stereo; 140 120 int users; 141 121 int removed; 142 - } dsbr100_device; 122 + int muted; 123 + }; 143 124 144 125 145 126 /* File system interface */ ··· 159 138 .owner = THIS_MODULE, 160 139 .name = "D-Link DSB-R 100", 161 140 .type = VID_TYPE_TUNER, 162 - .hardware = VID_HARDWARE_AZTECH, 163 141 .fops = &usb_dsbr100_fops, 164 142 .release = video_device_release, 165 143 }; ··· 181 161 /* Low-level device interface begins here */ 182 162 183 163 /* switch on radio */ 184 - static int dsbr100_start(dsbr100_device *radio) 164 + static int dsbr100_start(struct dsbr100_device *radio) 185 165 { 186 166 if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), 187 167 USB_REQ_GET_STATUS, ··· 192 172 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, 193 173 0x01, 0x00, radio->transfer_buffer, 8, 300)<0) 194 174 return -1; 175 + radio->muted=0; 195 176 return (radio->transfer_buffer)[0]; 196 177 } 197 178 198 179 199 180 /* switch off radio */ 200 - static int dsbr100_stop(dsbr100_device *radio) 181 + static int dsbr100_stop(struct dsbr100_device *radio) 201 182 { 202 183 if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), 203 184 USB_REQ_GET_STATUS, ··· 209 188 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, 210 189 0x00, 0x00, radio->transfer_buffer, 8, 300)<0) 211 190 return -1; 191 + radio->muted=1; 212 192 return (radio->transfer_buffer)[0]; 213 193 } 214 194 215 195 /* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */ 216 - static int dsbr100_setfreq(dsbr100_device *radio, int freq) 196 + static int dsbr100_setfreq(struct dsbr100_device *radio, int freq) 217 197 { 218 198 freq = (freq/16*80)/1000+856; 219 199 if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), ··· 239 217 240 218 /* return the device status. This is, in effect, just whether it 241 219 sees a stereo signal or not. Pity. */ 242 - static void dsbr100_getstat(dsbr100_device *radio) 220 + static void dsbr100_getstat(struct dsbr100_device *radio) 243 221 { 244 222 if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), 245 223 USB_REQ_GET_STATUS, ··· 258 236 static int usb_dsbr100_probe(struct usb_interface *intf, 259 237 const struct usb_device_id *id) 260 238 { 261 - dsbr100_device *radio; 239 + struct dsbr100_device *radio; 262 240 263 - if (!(radio = kmalloc(sizeof(dsbr100_device), GFP_KERNEL))) 241 + if (!(radio = kmalloc(sizeof(struct dsbr100_device), GFP_KERNEL))) 264 242 return -ENOMEM; 265 243 if (!(radio->videodev = video_device_alloc())) { 266 244 kfree(radio); ··· 293 271 leak here it's tiny (~50 bytes per disconnect) */ 294 272 static void usb_dsbr100_disconnect(struct usb_interface *intf) 295 273 { 296 - dsbr100_device *radio = usb_get_intfdata(intf); 274 + struct dsbr100_device *radio = usb_get_intfdata(intf); 297 275 298 276 usb_set_intfdata (intf, NULL); 299 277 if (radio) { ··· 313 291 static int usb_dsbr100_do_ioctl(struct inode *inode, struct file *file, 314 292 unsigned int cmd, void *arg) 315 293 { 316 - dsbr100_device *radio=video_get_drvdata(video_devdata(file)); 294 + struct dsbr100_device *radio=video_get_drvdata(video_devdata(file)); 317 295 318 296 if (!radio) 319 297 return -EIO; 320 298 321 299 switch(cmd) { 322 - case VIDIOCGCAP: { 323 - struct video_capability *v = arg; 300 + case VIDIOC_QUERYCAP: 301 + { 302 + struct v4l2_capability *v = arg; 303 + memset(v,0,sizeof(*v)); 304 + strlcpy(v->driver, "dsbr100", sizeof (v->driver)); 305 + strlcpy(v->card, "D-Link R-100 USB FM Radio", sizeof (v->card)); 306 + sprintf(v->bus_info,"ISA"); 307 + v->version = RADIO_VERSION; 308 + v->capabilities = V4L2_CAP_TUNER; 324 309 325 - memset(v, 0, sizeof(*v)); 326 - v->type = VID_TYPE_TUNER; 327 - v->channels = 1; 328 - v->audios = 1; 329 - strcpy(v->name, "D-Link R-100 USB FM Radio"); 330 310 return 0; 331 311 } 332 - case VIDIOCGTUNER: { 333 - struct video_tuner *v = arg; 312 + case VIDIOC_G_TUNER: 313 + { 314 + struct v4l2_tuner *v = arg; 315 + 316 + if (v->index > 0) 317 + return -EINVAL; 334 318 335 319 dsbr100_getstat(radio); 336 - if(v->tuner) /* Only 1 tuner */ 337 - return -EINVAL; 320 + 321 + memset(v,0,sizeof(*v)); 322 + strcpy(v->name, "FM"); 323 + v->type = V4L2_TUNER_RADIO; 324 + 338 325 v->rangelow = FREQ_MIN*FREQ_MUL; 339 326 v->rangehigh = FREQ_MAX*FREQ_MUL; 340 - v->flags = VIDEO_TUNER_LOW; 341 - v->mode = VIDEO_MODE_AUTO; 342 - v->signal = radio->stereo*0x7000; 343 - /* Don't know how to get signal strength */ 344 - v->flags |= VIDEO_TUNER_STEREO_ON*radio->stereo; 345 - strcpy(v->name, "DSB R-100"); 327 + v->rxsubchans =V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO; 328 + v->capability=V4L2_TUNER_CAP_LOW; 329 + if(radio->stereo) 330 + v->audmode = V4L2_TUNER_MODE_STEREO; 331 + else 332 + v->audmode = V4L2_TUNER_MODE_MONO; 333 + v->signal = 0xFFFF; /* We can't get the signal strength */ 334 + 346 335 return 0; 347 336 } 348 - case VIDIOCSTUNER: { 349 - struct video_tuner *v = arg; 337 + case VIDIOC_S_TUNER: 338 + { 339 + struct v4l2_tuner *v = arg; 350 340 351 - if(v->tuner!=0) 341 + if (v->index > 0) 352 342 return -EINVAL; 353 - /* Only 1 tuner so no setting needed ! */ 343 + 354 344 return 0; 355 345 } 356 - case VIDIOCGFREQ: { 357 - int *freq = arg; 346 + case VIDIOC_S_FREQUENCY: 347 + { 348 + struct v4l2_frequency *f = arg; 358 349 359 - if (radio->curfreq==-1) 360 - return -EINVAL; 361 - *freq = radio->curfreq; 362 - return 0; 363 - } 364 - case VIDIOCSFREQ: { 365 - int *freq = arg; 366 - 367 - radio->curfreq = *freq; 350 + radio->curfreq = f->frequency; 368 351 if (dsbr100_setfreq(radio, radio->curfreq)==-1) 369 352 warn("Set frequency failed"); 370 353 return 0; 371 354 } 372 - case VIDIOCGAUDIO: { 373 - struct video_audio *v = arg; 355 + case VIDIOC_G_FREQUENCY: 356 + { 357 + struct v4l2_frequency *f = arg; 374 358 375 - memset(v, 0, sizeof(*v)); 376 - v->flags |= VIDEO_AUDIO_MUTABLE; 377 - v->mode = VIDEO_SOUND_STEREO; 378 - v->volume = 1; 379 - v->step = 1; 380 - strcpy(v->name, "Radio"); 359 + f->type = V4L2_TUNER_RADIO; 360 + f->frequency = radio->curfreq; 361 + 381 362 return 0; 382 363 } 383 - case VIDIOCSAUDIO: { 384 - struct video_audio *v = arg; 364 + case VIDIOC_QUERYCTRL: 365 + { 366 + struct v4l2_queryctrl *qc = arg; 367 + int i; 385 368 386 - if (v->audio) 387 - return -EINVAL; 388 - if (v->flags&VIDEO_AUDIO_MUTE) { 389 - if (dsbr100_stop(radio)==-1) 390 - warn("Radio did not respond properly"); 369 + for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { 370 + if (qc->id && qc->id == radio_qctrl[i].id) { 371 + memcpy(qc, &(radio_qctrl[i]), 372 + sizeof(*qc)); 373 + return 0; 374 + } 391 375 } 392 - else 393 - if (dsbr100_start(radio)==-1) 394 - warn("Radio did not respond properly"); 395 - return 0; 376 + return -EINVAL; 377 + } 378 + case VIDIOC_G_CTRL: 379 + { 380 + struct v4l2_control *ctrl= arg; 381 + 382 + switch (ctrl->id) { 383 + case V4L2_CID_AUDIO_MUTE: 384 + ctrl->value=radio->muted; 385 + return 0; 386 + } 387 + return -EINVAL; 388 + } 389 + case VIDIOC_S_CTRL: 390 + { 391 + struct v4l2_control *ctrl= arg; 392 + 393 + switch (ctrl->id) { 394 + case V4L2_CID_AUDIO_MUTE: 395 + if (ctrl->value) { 396 + if (dsbr100_stop(radio)==-1) 397 + warn("Radio did not respond properly"); 398 + } else { 399 + if (dsbr100_start(radio)==-1) 400 + warn("Radio did not respond properly"); 401 + } 402 + return 0; 403 + } 404 + return -EINVAL; 396 405 } 397 406 default: 398 - return -ENOIOCTLCMD; 407 + return v4l_compat_translate_ioctl(inode,file,cmd,arg, 408 + usb_dsbr100_do_ioctl); 399 409 } 400 410 } 401 411 ··· 439 385 440 386 static int usb_dsbr100_open(struct inode *inode, struct file *file) 441 387 { 442 - dsbr100_device *radio=video_get_drvdata(video_devdata(file)); 388 + struct dsbr100_device *radio=video_get_drvdata(video_devdata(file)); 443 389 444 390 radio->users = 1; 391 + radio->muted = 1; 392 + 445 393 if (dsbr100_start(radio)<0) { 446 394 warn("Radio did not start up properly"); 447 395 radio->users = 0; ··· 455 399 456 400 static int usb_dsbr100_close(struct inode *inode, struct file *file) 457 401 { 458 - dsbr100_device *radio=video_get_drvdata(video_devdata(file)); 402 + struct dsbr100_device *radio=video_get_drvdata(video_devdata(file)); 459 403 460 404 if (!radio) 461 405 return -ENODEV;