aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/radio/dsbr100.c345
1 files changed, 186 insertions, 159 deletions
diff --git a/drivers/media/radio/dsbr100.c b/drivers/media/radio/dsbr100.c
index 449df1bb00d3..3bd07f7e3774 100644
--- a/drivers/media/radio/dsbr100.c
+++ b/drivers/media/radio/dsbr100.c
@@ -33,6 +33,10 @@
33 33
34 History: 34 History:
35 35
36 Version 0.42:
37 Converted dsbr100 to use video_ioctl2
38 by Douglas Landgraf <dougsland@gmail.com>
39
36 Version 0.41-ac1: 40 Version 0.41-ac1:
37 Alan Cox: Some cleanups and fixes 41 Alan Cox: Some cleanups and fixes
38 42
@@ -121,8 +125,6 @@ devices, that would be 76 and 91. */
121static int usb_dsbr100_probe(struct usb_interface *intf, 125static int usb_dsbr100_probe(struct usb_interface *intf,
122 const struct usb_device_id *id); 126 const struct usb_device_id *id);
123static void usb_dsbr100_disconnect(struct usb_interface *intf); 127static void usb_dsbr100_disconnect(struct usb_interface *intf);
124static int usb_dsbr100_ioctl(struct inode *inode, struct file *file,
125 unsigned int cmd, unsigned long arg);
126static int usb_dsbr100_open(struct inode *inode, struct file *file); 128static int usb_dsbr100_open(struct inode *inode, struct file *file);
127static int usb_dsbr100_close(struct inode *inode, struct file *file); 129static int usb_dsbr100_close(struct inode *inode, struct file *file);
128 130
@@ -142,26 +144,6 @@ struct dsbr100_device {
142}; 144};
143 145
144 146
145/* File system interface */
146static const struct file_operations usb_dsbr100_fops = {
147 .owner = THIS_MODULE,
148 .open = usb_dsbr100_open,
149 .release = usb_dsbr100_close,
150 .ioctl = usb_dsbr100_ioctl,
151 .compat_ioctl = v4l_compat_ioctl32,
152 .llseek = no_llseek,
153};
154
155/* V4L interface */
156static struct video_device dsbr100_videodev_template=
157{
158 .owner = THIS_MODULE,
159 .name = "D-Link DSB-R 100",
160 .type = VID_TYPE_TUNER,
161 .fops = &usb_dsbr100_fops,
162 .release = video_device_release,
163};
164
165static struct usb_device_id usb_dsbr100_device_table [] = { 147static struct usb_device_id usb_dsbr100_device_table [] = {
166 { USB_DEVICE(DSB100_VENDOR, DSB100_PRODUCT) }, 148 { USB_DEVICE(DSB100_VENDOR, DSB100_PRODUCT) },
167 { } /* Terminating entry */ 149 { } /* Terminating entry */
@@ -252,37 +234,6 @@ static void dsbr100_getstat(struct dsbr100_device *radio)
252 234
253/* USB subsystem interface begins here */ 235/* USB subsystem interface begins here */
254 236
255/* check if the device is present and register with v4l and
256usb if it is */
257static int usb_dsbr100_probe(struct usb_interface *intf,
258 const struct usb_device_id *id)
259{
260 struct dsbr100_device *radio;
261
262 if (!(radio = kmalloc(sizeof(struct dsbr100_device), GFP_KERNEL)))
263 return -ENOMEM;
264 if (!(radio->videodev = video_device_alloc())) {
265 kfree(radio);
266 return -ENOMEM;
267 }
268 memcpy(radio->videodev, &dsbr100_videodev_template,
269 sizeof(dsbr100_videodev_template));
270 radio->removed = 0;
271 radio->users = 0;
272 radio->usbdev = interface_to_usbdev(intf);
273 radio->curfreq = FREQ_MIN*FREQ_MUL;
274 video_set_drvdata(radio->videodev, radio);
275 if (video_register_device(radio->videodev, VFL_TYPE_RADIO,
276 radio_nr)) {
277 warn("Could not register video device");
278 video_device_release(radio->videodev);
279 kfree(radio);
280 return -EIO;
281 }
282 usb_set_intfdata(intf, radio);
283 return 0;
284}
285
286/* handle unplugging of the device, release data structures 237/* handle unplugging of the device, release data structures
287if nothing keeps us from doing it. If something is still 238if nothing keeps us from doing it. If something is still
288keeping us busy, the release callback of v4l will take care 239keeping us busy, the release callback of v4l will take care
@@ -307,133 +258,147 @@ static void usb_dsbr100_disconnect(struct usb_interface *intf)
307} 258}
308 259
309 260
310/* Video for Linux interface */ 261static int vidioc_querycap(struct file *file, void *priv,
262 struct v4l2_capability *v)
263{
264 strlcpy(v->driver, "dsbr100", sizeof(v->driver));
265 strlcpy(v->card, "D-Link R-100 USB FM Radio", sizeof(v->card));
266 sprintf(v->bus_info, "ISA");
267 v->version = RADIO_VERSION;
268 v->capabilities = V4L2_CAP_TUNER;
269 return 0;
270}
311 271
312static int usb_dsbr100_do_ioctl(struct inode *inode, struct file *file, 272static int vidioc_g_tuner(struct file *file, void *priv,
313 unsigned int cmd, void *arg) 273 struct v4l2_tuner *v)
314{ 274{
315 struct dsbr100_device *radio=video_get_drvdata(video_devdata(file)); 275 struct dsbr100_device *radio = video_get_drvdata(video_devdata(file));
276
277 if (v->index > 0)
278 return -EINVAL;
279
280 dsbr100_getstat(radio);
281 strcpy(v->name, "FM");
282 v->type = V4L2_TUNER_RADIO;
283 v->rangelow = FREQ_MIN*FREQ_MUL;
284 v->rangehigh = FREQ_MAX*FREQ_MUL;
285 v->rxsubchans = V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO;
286 v->capability = V4L2_TUNER_CAP_LOW;
287 if(radio->stereo)
288 v->audmode = V4L2_TUNER_MODE_STEREO;
289 else
290 v->audmode = V4L2_TUNER_MODE_MONO;
291 v->signal = 0xffff; /* We can't get the signal strength */
292 return 0;
293}
316 294
317 if (!radio) 295static int vidioc_s_tuner(struct file *file, void *priv,
318 return -EIO; 296 struct v4l2_tuner *v)
297{
298 if (v->index > 0)
299 return -EINVAL;
319 300
320 switch(cmd) { 301 return 0;
321 case VIDIOC_QUERYCAP: 302}
322 {
323 struct v4l2_capability *v = arg;
324 memset(v,0,sizeof(*v));
325 strlcpy(v->driver, "dsbr100", sizeof (v->driver));
326 strlcpy(v->card, "D-Link R-100 USB FM Radio", sizeof (v->card));
327 sprintf(v->bus_info,"ISA");
328 v->version = RADIO_VERSION;
329 v->capabilities = V4L2_CAP_TUNER;
330 303
331 return 0; 304static int vidioc_s_frequency(struct file *file, void *priv,
332 } 305 struct v4l2_frequency *f)
333 case VIDIOC_G_TUNER: 306{
334 { 307 struct dsbr100_device *radio = video_get_drvdata(video_devdata(file));
335 struct v4l2_tuner *v = arg;
336 308
337 if (v->index > 0) 309 radio->curfreq = f->frequency;
338 return -EINVAL; 310 if (dsbr100_setfreq(radio, radio->curfreq)==-1)
311 warn("Set frequency failed");
312 return 0;
313}
339 314
340 dsbr100_getstat(radio); 315static int vidioc_g_frequency(struct file *file, void *priv,
316 struct v4l2_frequency *f)
317{
318 struct dsbr100_device *radio = video_get_drvdata(video_devdata(file));
341 319
342 memset(v,0,sizeof(*v)); 320 f->type = V4L2_TUNER_RADIO;
343 strcpy(v->name, "FM"); 321 f->frequency = radio->curfreq;
344 v->type = V4L2_TUNER_RADIO; 322 return 0;
323}
345 324
346 v->rangelow = FREQ_MIN*FREQ_MUL; 325static int vidioc_queryctrl(struct file *file, void *priv,
347 v->rangehigh = FREQ_MAX*FREQ_MUL; 326 struct v4l2_queryctrl *qc)
348 v->rxsubchans =V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO; 327{
349 v->capability=V4L2_TUNER_CAP_LOW; 328 int i;
350 if(radio->stereo)
351 v->audmode = V4L2_TUNER_MODE_STEREO;
352 else
353 v->audmode = V4L2_TUNER_MODE_MONO;
354 v->signal = 0xFFFF; /* We can't get the signal strength */
355 329
330 for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
331 if (qc->id && qc->id == radio_qctrl[i].id) {
332 memcpy(qc, &(radio_qctrl[i]),
333 sizeof(*qc));
356 return 0; 334 return 0;
357 } 335 }
358 case VIDIOC_S_TUNER: 336 }
359 { 337 return -EINVAL;
360 struct v4l2_tuner *v = arg; 338}
361
362 if (v->index > 0)
363 return -EINVAL;
364 339
365 return 0; 340static int vidioc_g_ctrl(struct file *file, void *priv,
366 } 341 struct v4l2_control *ctrl)
367 case VIDIOC_S_FREQUENCY: 342{
368 { 343 struct dsbr100_device *radio = video_get_drvdata(video_devdata(file));
369 struct v4l2_frequency *f = arg;
370 344
371 radio->curfreq = f->frequency; 345 switch (ctrl->id) {
372 if (dsbr100_setfreq(radio, radio->curfreq)==-1) 346 case V4L2_CID_AUDIO_MUTE:
373 warn("Set frequency failed"); 347 ctrl->value = radio->muted;
374 return 0; 348 return 0;
375 } 349 }
376 case VIDIOC_G_FREQUENCY: 350 return -EINVAL;
377 { 351}
378 struct v4l2_frequency *f = arg;
379 352
380 f->type = V4L2_TUNER_RADIO; 353static int vidioc_s_ctrl(struct file *file, void *priv,
381 f->frequency = radio->curfreq; 354 struct v4l2_control *ctrl)
355{
356 struct dsbr100_device *radio = video_get_drvdata(video_devdata(file));
382 357
383 return 0; 358 switch (ctrl->id) {
384 } 359 case V4L2_CID_AUDIO_MUTE:
385 case VIDIOC_QUERYCTRL: 360 if (ctrl->value) {
386 { 361 if (dsbr100_stop(radio)==-1)
387 struct v4l2_queryctrl *qc = arg; 362 warn("Radio did not respond properly");
388 int i; 363 } else {
389 364 if (dsbr100_start(radio)==-1)
390 for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { 365 warn("Radio did not respond properly");
391 if (qc->id && qc->id == radio_qctrl[i].id) {
392 memcpy(qc, &(radio_qctrl[i]),
393 sizeof(*qc));
394 return 0;
395 }
396 }
397 return -EINVAL;
398 }
399 case VIDIOC_G_CTRL:
400 {
401 struct v4l2_control *ctrl= arg;
402
403 switch (ctrl->id) {
404 case V4L2_CID_AUDIO_MUTE:
405 ctrl->value=radio->muted;
406 return 0;
407 }
408 return -EINVAL;
409 }
410 case VIDIOC_S_CTRL:
411 {
412 struct v4l2_control *ctrl= arg;
413
414 switch (ctrl->id) {
415 case V4L2_CID_AUDIO_MUTE:
416 if (ctrl->value) {
417 if (dsbr100_stop(radio)==-1)
418 warn("Radio did not respond properly");
419 } else {
420 if (dsbr100_start(radio)==-1)
421 warn("Radio did not respond properly");
422 }
423 return 0;
424 }
425 return -EINVAL;
426 } 366 }
427 default: 367 return 0;
428 return v4l_compat_translate_ioctl(inode,file,cmd,arg,
429 usb_dsbr100_do_ioctl);
430 } 368 }
369 return -EINVAL;
431} 370}
432 371
433static int usb_dsbr100_ioctl(struct inode *inode, struct file *file, 372static int vidioc_g_audio(struct file *file, void *priv,
434 unsigned int cmd, unsigned long arg) 373 struct v4l2_audio *a)
435{ 374{
436 return video_usercopy(inode, file, cmd, arg, usb_dsbr100_do_ioctl); 375 if (a->index > 1)
376 return -EINVAL;
377
378 strcpy(a->name, "Radio");
379 a->capability = V4L2_AUDCAP_STEREO;
380 return 0;
381}
382
383static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
384{
385 *i = 0;
386 return 0;
387}
388
389static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
390{
391 if (i != 0)
392 return -EINVAL;
393 return 0;
394}
395
396static int vidioc_s_audio(struct file *file, void *priv,
397 struct v4l2_audio *a)
398{
399 if (a->index != 0)
400 return -EINVAL;
401 return 0;
437} 402}
438 403
439static int usb_dsbr100_open(struct inode *inode, struct file *file) 404static int usb_dsbr100_open(struct inode *inode, struct file *file)
@@ -465,6 +430,68 @@ static int usb_dsbr100_close(struct inode *inode, struct file *file)
465 return 0; 430 return 0;
466} 431}
467 432
433/* File system interface */
434static const struct file_operations usb_dsbr100_fops = {
435 .owner = THIS_MODULE,
436 .open = usb_dsbr100_open,
437 .release = usb_dsbr100_close,
438 .ioctl = video_ioctl2,
439 .compat_ioctl = v4l_compat_ioctl32,
440 .llseek = no_llseek,
441};
442
443/* V4L2 interface */
444static struct video_device dsbr100_videodev_template =
445{
446 .owner = THIS_MODULE,
447 .name = "D-Link DSB-R 100",
448 .type = VID_TYPE_TUNER,
449 .fops = &usb_dsbr100_fops,
450 .release = video_device_release,
451 .vidioc_querycap = vidioc_querycap,
452 .vidioc_g_tuner = vidioc_g_tuner,
453 .vidioc_s_tuner = vidioc_s_tuner,
454 .vidioc_g_frequency = vidioc_g_frequency,
455 .vidioc_s_frequency = vidioc_s_frequency,
456 .vidioc_queryctrl = vidioc_queryctrl,
457 .vidioc_g_ctrl = vidioc_g_ctrl,
458 .vidioc_s_ctrl = vidioc_s_ctrl,
459 .vidioc_g_audio = vidioc_g_audio,
460 .vidioc_s_audio = vidioc_s_audio,
461 .vidioc_g_input = vidioc_g_input,
462 .vidioc_s_input = vidioc_s_input,
463};
464
465/* check if the device is present and register with v4l and
466usb if it is */
467static int usb_dsbr100_probe(struct usb_interface *intf,
468 const struct usb_device_id *id)
469{
470 struct dsbr100_device *radio;
471
472 if (!(radio = kmalloc(sizeof(struct dsbr100_device), GFP_KERNEL)))
473 return -ENOMEM;
474 if (!(radio->videodev = video_device_alloc())) {
475 kfree(radio);
476 return -ENOMEM;
477 }
478 memcpy(radio->videodev, &dsbr100_videodev_template,
479 sizeof(dsbr100_videodev_template));
480 radio->removed = 0;
481 radio->users = 0;
482 radio->usbdev = interface_to_usbdev(intf);
483 radio->curfreq = FREQ_MIN*FREQ_MUL;
484 video_set_drvdata(radio->videodev, radio);
485 if (video_register_device(radio->videodev, VFL_TYPE_RADIO,radio_nr)) {
486 warn("Could not register video device");
487 video_device_release(radio->videodev);
488 kfree(radio);
489 return -EIO;
490 }
491 usb_set_intfdata(intf, radio);
492 return 0;
493}
494
468static int __init dsbr100_init(void) 495static int __init dsbr100_init(void)
469{ 496{
470 int retval = usb_register(&usb_dsbr100_driver); 497 int retval = usb_register(&usb_dsbr100_driver);