V4L/DVB (10057): dsbr100: place dev_warn instead of printk
[deliverable/linux.git] / drivers / media / radio / dsbr100.c
CommitLineData
1da177e4
LT
1/* A driver for the D-Link DSB-R100 USB radio. The R100 plugs
2 into both the USB and an analog audio input, so this thing
3 only deals with initialisation and frequency setting, the
4 audio data has to be handled by a sound driver.
5
6 Major issue: I can't find out where the device reports the signal
7 strength, and indeed the windows software appearantly just looks
8 at the stereo indicator as well. So, scanning will only find
9 stereo stations. Sad, but I can't help it.
10
11 Also, the windows program sends oodles of messages over to the
12 device, and I couldn't figure out their meaning. My suspicion
13 is that they don't have any:-)
14
15 You might find some interesting stuff about this module at
16 http://unimut.fsk.uni-heidelberg.de/unimut/demi/dsbr
17
18 Copyright (c) 2000 Markus Demleitner <msdemlei@cl.uni-heidelberg.de>
19
20 This program is free software; you can redistribute it and/or modify
21 it under the terms of the GNU General Public License as published by
22 the Free Software Foundation; either version 2 of the License, or
23 (at your option) any later version.
24
25 This program is distributed in the hope that it will be useful,
26 but WITHOUT ANY WARRANTY; without even the implied warranty of
27 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 GNU General Public License for more details.
29
30 You should have received a copy of the GNU General Public License
31 along with this program; if not, write to the Free Software
32 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
33
34 History:
35
863c86dd
ON
36 Version 0.43:
37 Oliver Neukum: avoided DMA coherency issue
38
7002a4f3
DL
39 Version 0.42:
40 Converted dsbr100 to use video_ioctl2
41 by Douglas Landgraf <dougsland@gmail.com>
42
5aff308c
AC
43 Version 0.41-ac1:
44 Alan Cox: Some cleanups and fixes
45
46 Version 0.41:
47 Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org>
48
1da177e4 49 Version 0.40:
5aff308c 50 Markus: Updates for 2.6.x kernels, code layout changes, name sanitizing
1da177e4
LT
51
52 Version 0.30:
d56410e0 53 Markus: Updates for 2.5.x kernel and more ISO compliant source
1da177e4
LT
54
55 Version 0.25:
d56410e0 56 PSL and Markus: Cleanup, radio now doesn't stop on device close
1da177e4
LT
57
58 Version 0.24:
d56410e0 59 Markus: Hope I got these silly VIDEO_TUNER_LOW issues finally
1da177e4
LT
60 right. Some minor cleanup, improved standalone compilation
61
62 Version 0.23:
d56410e0 63 Markus: Sign extension bug fixed by declaring transfer_buffer unsigned
1da177e4
LT
64
65 Version 0.22:
d56410e0 66 Markus: Some (brown bag) cleanup in what VIDIOCSTUNER returns,
1da177e4
LT
67 thanks to Mike Cox for pointing the problem out.
68
69 Version 0.21:
d56410e0 70 Markus: Minor cleanup, warnings if something goes wrong, lame attempt
1da177e4
LT
71 to adhere to Documentation/CodingStyle
72
d56410e0
MCC
73 Version 0.2:
74 Brad Hards <bradh@dynamite.com.au>: Fixes to make it work as non-module
1da177e4
LT
75 Markus: Copyright clarification
76
77 Version 0.01: Markus: initial release
78
79*/
80
1da177e4
LT
81#include <linux/kernel.h>
82#include <linux/module.h>
83#include <linux/init.h>
84#include <linux/slab.h>
85#include <linux/input.h>
5aff308c 86#include <linux/videodev2.h>
5e87efa3 87#include <media/v4l2-common.h>
35ea11ff 88#include <media/v4l2-ioctl.h>
1da177e4 89#include <linux/usb.h>
1da177e4
LT
90
91/*
92 * Version Information
93 */
5aff308c
AC
94#include <linux/version.h> /* for KERNEL_VERSION MACRO */
95
54b7b0de
AK
96#define DRIVER_VERSION "v0.43"
97#define RADIO_VERSION KERNEL_VERSION(0, 4, 3)
5aff308c
AC
98
99static struct v4l2_queryctrl radio_qctrl[] = {
100 {
101 .id = V4L2_CID_AUDIO_MUTE,
102 .name = "Mute",
103 .minimum = 0,
104 .maximum = 1,
105 .default_value = 1,
106 .type = V4L2_CTRL_TYPE_BOOLEAN,
54b7b0de
AK
107 },
108/* HINT: the disabled controls are only here to satify kradio and such apps */
109 { .id = V4L2_CID_AUDIO_VOLUME,
110 .flags = V4L2_CTRL_FLAG_DISABLED,
111 },
112 {
113 .id = V4L2_CID_AUDIO_BALANCE,
114 .flags = V4L2_CTRL_FLAG_DISABLED,
115 },
116 {
117 .id = V4L2_CID_AUDIO_BASS,
118 .flags = V4L2_CTRL_FLAG_DISABLED,
119 },
120 {
121 .id = V4L2_CID_AUDIO_TREBLE,
122 .flags = V4L2_CTRL_FLAG_DISABLED,
123 },
124 {
125 .id = V4L2_CID_AUDIO_LOUDNESS,
126 .flags = V4L2_CTRL_FLAG_DISABLED,
127 },
5aff308c
AC
128};
129
1da177e4
LT
130#define DRIVER_AUTHOR "Markus Demleitner <msdemlei@tucana.harvard.edu>"
131#define DRIVER_DESC "D-Link DSB-R100 USB FM radio driver"
132
133#define DSB100_VENDOR 0x04b4
134#define DSB100_PRODUCT 0x1002
135
136/* Commands the device appears to understand */
137#define DSB100_TUNE 1
138#define DSB100_ONOFF 2
139
140#define TB_LEN 16
141
142/* Frequency limits in MHz -- these are European values. For Japanese
143devices, that would be 76 and 91. */
144#define FREQ_MIN 87.5
145#define FREQ_MAX 108.0
146#define FREQ_MUL 16000
147
3a0efc32 148#define videodev_to_radio(d) container_of(d, struct dsbr100_device, videodev)
1da177e4
LT
149
150static int usb_dsbr100_probe(struct usb_interface *intf,
151 const struct usb_device_id *id);
152static void usb_dsbr100_disconnect(struct usb_interface *intf);
1da177e4
LT
153static int usb_dsbr100_open(struct inode *inode, struct file *file);
154static int usb_dsbr100_close(struct inode *inode, struct file *file);
04e0ffbb
AK
155static int usb_dsbr100_suspend(struct usb_interface *intf,
156 pm_message_t message);
157static int usb_dsbr100_resume(struct usb_interface *intf);
1da177e4
LT
158
159static int radio_nr = -1;
160module_param(radio_nr, int, 0);
161
162/* Data for one (physical) device */
5aff308c 163struct dsbr100_device {
1da177e4 164 struct usb_device *usbdev;
3a0efc32 165 struct video_device videodev;
863c86dd 166 u8 *transfer_buffer;
3a0efc32 167 struct mutex lock; /* buffer locking */
1da177e4
LT
168 int curfreq;
169 int stereo;
170 int users;
171 int removed;
5aff308c
AC
172 int muted;
173};
1da177e4
LT
174
175
1da177e4
LT
176static struct usb_device_id usb_dsbr100_device_table [] = {
177 { USB_DEVICE(DSB100_VENDOR, DSB100_PRODUCT) },
178 { } /* Terminating entry */
179};
180
181MODULE_DEVICE_TABLE (usb, usb_dsbr100_device_table);
182
183/* USB subsystem interface */
184static struct usb_driver usb_dsbr100_driver = {
04e0ffbb
AK
185 .name = "dsbr100",
186 .probe = usb_dsbr100_probe,
187 .disconnect = usb_dsbr100_disconnect,
188 .id_table = usb_dsbr100_device_table,
189 .suspend = usb_dsbr100_suspend,
190 .resume = usb_dsbr100_resume,
191 .reset_resume = usb_dsbr100_resume,
192 .supports_autosuspend = 0,
1da177e4
LT
193};
194
195/* Low-level device interface begins here */
196
197/* switch on radio */
5aff308c 198static int dsbr100_start(struct dsbr100_device *radio)
1da177e4 199{
3a0efc32 200 mutex_lock(&radio->lock);
1da177e4 201 if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
d56410e0 202 USB_REQ_GET_STATUS,
1da177e4 203 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
223377e7 204 0x00, 0xC7, radio->transfer_buffer, 8, 300) < 0 ||
1da177e4 205 usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
d56410e0 206 DSB100_ONOFF,
1da177e4 207 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
3a0efc32
AK
208 0x01, 0x00, radio->transfer_buffer, 8, 300) < 0) {
209 mutex_unlock(&radio->lock);
1da177e4 210 return -1;
3a0efc32
AK
211 }
212
5aff308c 213 radio->muted=0;
3a0efc32 214 mutex_unlock(&radio->lock);
1da177e4
LT
215 return (radio->transfer_buffer)[0];
216}
217
218
219/* switch off radio */
5aff308c 220static int dsbr100_stop(struct dsbr100_device *radio)
1da177e4 221{
3a0efc32 222 mutex_lock(&radio->lock);
1da177e4 223 if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
d56410e0 224 USB_REQ_GET_STATUS,
1da177e4 225 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
223377e7 226 0x16, 0x1C, radio->transfer_buffer, 8, 300) < 0 ||
1da177e4 227 usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
d56410e0 228 DSB100_ONOFF,
1da177e4 229 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
3a0efc32
AK
230 0x00, 0x00, radio->transfer_buffer, 8, 300) < 0) {
231 mutex_unlock(&radio->lock);
1da177e4 232 return -1;
3a0efc32
AK
233 }
234
5aff308c 235 radio->muted=1;
3a0efc32 236 mutex_unlock(&radio->lock);
1da177e4
LT
237 return (radio->transfer_buffer)[0];
238}
239
240/* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */
5aff308c 241static int dsbr100_setfreq(struct dsbr100_device *radio, int freq)
1da177e4 242{
223377e7 243 freq = (freq / 16 * 80) / 1000 + 856;
3a0efc32 244 mutex_lock(&radio->lock);
1da177e4 245 if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
d56410e0 246 DSB100_TUNE,
1da177e4 247 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
223377e7
AK
248 (freq >> 8) & 0x00ff, freq & 0xff,
249 radio->transfer_buffer, 8, 300) < 0 ||
1da177e4 250 usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
d56410e0 251 USB_REQ_GET_STATUS,
1da177e4 252 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
223377e7 253 0x96, 0xB7, radio->transfer_buffer, 8, 300) < 0 ||
1da177e4 254 usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
d56410e0 255 USB_REQ_GET_STATUS,
1da177e4 256 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
223377e7 257 0x00, 0x24, radio->transfer_buffer, 8, 300) < 0) {
1da177e4 258 radio->stereo = -1;
3a0efc32 259 mutex_unlock(&radio->lock);
1da177e4
LT
260 return -1;
261 }
3a0efc32 262
223377e7 263 radio->stereo = !((radio->transfer_buffer)[0] & 0x01);
3a0efc32 264 mutex_unlock(&radio->lock);
1da177e4
LT
265 return (radio->transfer_buffer)[0];
266}
267
268/* return the device status. This is, in effect, just whether it
269sees a stereo signal or not. Pity. */
5aff308c 270static void dsbr100_getstat(struct dsbr100_device *radio)
1da177e4 271{
3a0efc32 272 mutex_lock(&radio->lock);
1da177e4 273 if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
d56410e0 274 USB_REQ_GET_STATUS,
1da177e4 275 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
223377e7 276 0x00 , 0x24, radio->transfer_buffer, 8, 300) < 0)
1da177e4
LT
277 radio->stereo = -1;
278 else
223377e7 279 radio->stereo = !(radio->transfer_buffer[0] & 0x01);
3a0efc32 280 mutex_unlock(&radio->lock);
1da177e4
LT
281}
282
283
284/* USB subsystem interface begins here */
285
1da177e4
LT
286/* handle unplugging of the device, release data structures
287if nothing keeps us from doing it. If something is still
288keeping us busy, the release callback of v4l will take care
863c86dd 289of releasing it. */
1da177e4
LT
290static void usb_dsbr100_disconnect(struct usb_interface *intf)
291{
5aff308c 292 struct dsbr100_device *radio = usb_get_intfdata(intf);
1da177e4
LT
293
294 usb_set_intfdata (intf, NULL);
3a0efc32
AK
295
296 mutex_lock(&radio->lock);
297 radio->removed = 1;
298 mutex_unlock(&radio->lock);
299
300 video_unregister_device(&radio->videodev);
1da177e4
LT
301}
302
303
7002a4f3
DL
304static int vidioc_querycap(struct file *file, void *priv,
305 struct v4l2_capability *v)
306{
307 strlcpy(v->driver, "dsbr100", sizeof(v->driver));
308 strlcpy(v->card, "D-Link R-100 USB FM Radio", sizeof(v->card));
448441cf 309 sprintf(v->bus_info, "USB");
7002a4f3
DL
310 v->version = RADIO_VERSION;
311 v->capabilities = V4L2_CAP_TUNER;
312 return 0;
313}
1da177e4 314
7002a4f3
DL
315static int vidioc_g_tuner(struct file *file, void *priv,
316 struct v4l2_tuner *v)
1da177e4 317{
c170ecf4 318 struct dsbr100_device *radio = video_drvdata(file);
7002a4f3 319
3a0efc32
AK
320 /* safety check */
321 if (radio->removed)
322 return -EIO;
323
7002a4f3
DL
324 if (v->index > 0)
325 return -EINVAL;
326
327 dsbr100_getstat(radio);
328 strcpy(v->name, "FM");
329 v->type = V4L2_TUNER_RADIO;
223377e7
AK
330 v->rangelow = FREQ_MIN * FREQ_MUL;
331 v->rangehigh = FREQ_MAX * FREQ_MUL;
332 v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
7002a4f3
DL
333 v->capability = V4L2_TUNER_CAP_LOW;
334 if(radio->stereo)
335 v->audmode = V4L2_TUNER_MODE_STEREO;
336 else
337 v->audmode = V4L2_TUNER_MODE_MONO;
338 v->signal = 0xffff; /* We can't get the signal strength */
339 return 0;
340}
1da177e4 341
7002a4f3
DL
342static int vidioc_s_tuner(struct file *file, void *priv,
343 struct v4l2_tuner *v)
344{
3a0efc32
AK
345 struct dsbr100_device *radio = video_drvdata(file);
346
347 /* safety check */
348 if (radio->removed)
349 return -EIO;
350
7002a4f3
DL
351 if (v->index > 0)
352 return -EINVAL;
1da177e4 353
7002a4f3
DL
354 return 0;
355}
5aff308c 356
7002a4f3
DL
357static int vidioc_s_frequency(struct file *file, void *priv,
358 struct v4l2_frequency *f)
359{
c170ecf4 360 struct dsbr100_device *radio = video_drvdata(file);
1da177e4 361
3a0efc32
AK
362 /* safety check */
363 if (radio->removed)
364 return -EIO;
365
7002a4f3 366 radio->curfreq = f->frequency;
223377e7 367 if (dsbr100_setfreq(radio, radio->curfreq) == -1)
aa82661b 368 dev_warn(&radio->usbdev->dev, "Set frequency failed\n");
7002a4f3
DL
369 return 0;
370}
5aff308c 371
7002a4f3
DL
372static int vidioc_g_frequency(struct file *file, void *priv,
373 struct v4l2_frequency *f)
374{
c170ecf4 375 struct dsbr100_device *radio = video_drvdata(file);
5aff308c 376
3a0efc32
AK
377 /* safety check */
378 if (radio->removed)
379 return -EIO;
380
7002a4f3
DL
381 f->type = V4L2_TUNER_RADIO;
382 f->frequency = radio->curfreq;
383 return 0;
384}
5aff308c 385
7002a4f3
DL
386static int vidioc_queryctrl(struct file *file, void *priv,
387 struct v4l2_queryctrl *qc)
388{
389 int i;
1da177e4 390
7002a4f3
DL
391 for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
392 if (qc->id && qc->id == radio_qctrl[i].id) {
223377e7 393 memcpy(qc, &(radio_qctrl[i]), sizeof(*qc));
1da177e4
LT
394 return 0;
395 }
7002a4f3
DL
396 }
397 return -EINVAL;
398}
5aff308c 399
7002a4f3
DL
400static int vidioc_g_ctrl(struct file *file, void *priv,
401 struct v4l2_control *ctrl)
402{
c170ecf4 403 struct dsbr100_device *radio = video_drvdata(file);
1da177e4 404
3a0efc32
AK
405 /* safety check */
406 if (radio->removed)
407 return -EIO;
408
7002a4f3
DL
409 switch (ctrl->id) {
410 case V4L2_CID_AUDIO_MUTE:
411 ctrl->value = radio->muted;
412 return 0;
413 }
414 return -EINVAL;
415}
5aff308c 416
7002a4f3
DL
417static int vidioc_s_ctrl(struct file *file, void *priv,
418 struct v4l2_control *ctrl)
419{
c170ecf4 420 struct dsbr100_device *radio = video_drvdata(file);
5aff308c 421
3a0efc32
AK
422 /* safety check */
423 if (radio->removed)
424 return -EIO;
425
7002a4f3
DL
426 switch (ctrl->id) {
427 case V4L2_CID_AUDIO_MUTE:
428 if (ctrl->value) {
90b698dd 429 if (dsbr100_stop(radio) == -1) {
aa82661b
GKH
430 dev_warn(&radio->usbdev->dev,
431 "Radio did not respond properly\n");
90b698dd
AK
432 return -EBUSY;
433 }
7002a4f3 434 } else {
90b698dd 435 if (dsbr100_start(radio) == -1) {
aa82661b
GKH
436 dev_warn(&radio->usbdev->dev,
437 "Radio did not respond properly\n");
90b698dd
AK
438 return -EBUSY;
439 }
1da177e4 440 }
7002a4f3 441 return 0;
1da177e4 442 }
7002a4f3 443 return -EINVAL;
1da177e4
LT
444}
445
7002a4f3
DL
446static int vidioc_g_audio(struct file *file, void *priv,
447 struct v4l2_audio *a)
1da177e4 448{
7002a4f3
DL
449 if (a->index > 1)
450 return -EINVAL;
451
452 strcpy(a->name, "Radio");
453 a->capability = V4L2_AUDCAP_STEREO;
454 return 0;
455}
456
457static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
458{
459 *i = 0;
460 return 0;
461}
462
463static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
464{
465 if (i != 0)
466 return -EINVAL;
467 return 0;
468}
469
470static int vidioc_s_audio(struct file *file, void *priv,
471 struct v4l2_audio *a)
472{
473 if (a->index != 0)
474 return -EINVAL;
475 return 0;
1da177e4
LT
476}
477
478static int usb_dsbr100_open(struct inode *inode, struct file *file)
479{
c170ecf4 480 struct dsbr100_device *radio = video_drvdata(file);
b9f35737 481 int retval;
1da177e4 482
d56dc612 483 lock_kernel();
1da177e4 484 radio->users = 1;
5aff308c
AC
485 radio->muted = 1;
486
223377e7 487 if (dsbr100_start(radio) < 0) {
aa82661b
GKH
488 dev_warn(&radio->usbdev->dev,
489 "Radio did not start up properly\n");
1da177e4 490 radio->users = 0;
d56dc612 491 unlock_kernel();
1da177e4
LT
492 return -EIO;
493 }
b9f35737
AK
494
495 retval = dsbr100_setfreq(radio, radio->curfreq);
496
497 if (retval == -1)
290588e0
AK
498 dev_warn(&radio->usbdev->dev,
499 "set frequency failed\n");
b9f35737 500
d56dc612 501 unlock_kernel();
1da177e4
LT
502 return 0;
503}
504
505static int usb_dsbr100_close(struct inode *inode, struct file *file)
506{
c170ecf4 507 struct dsbr100_device *radio = video_drvdata(file);
3a0efc32 508 int retval;
1da177e4
LT
509
510 if (!radio)
511 return -ENODEV;
3a0efc32 512
1da177e4 513 radio->users = 0;
3a0efc32
AK
514 if (!radio->removed) {
515 retval = dsbr100_stop(radio);
516 if (retval == -1) {
517 dev_warn(&radio->usbdev->dev,
518 "dsbr100_stop failed\n");
519 }
520
1da177e4
LT
521 }
522 return 0;
523}
524
04e0ffbb
AK
525/* Suspend device - stop device. */
526static int usb_dsbr100_suspend(struct usb_interface *intf, pm_message_t message)
527{
528 struct dsbr100_device *radio = usb_get_intfdata(intf);
529 int retval;
530
531 retval = dsbr100_stop(radio);
532 if (retval == -1)
533 dev_warn(&intf->dev, "dsbr100_stop failed\n");
534
535 dev_info(&intf->dev, "going into suspend..\n");
536
537 return 0;
538}
539
540/* Resume device - start device. */
541static int usb_dsbr100_resume(struct usb_interface *intf)
542{
543 struct dsbr100_device *radio = usb_get_intfdata(intf);
544 int retval;
545
546 retval = dsbr100_start(radio);
547 if (retval == -1)
548 dev_warn(&intf->dev, "dsbr100_start failed\n");
549
550 dev_info(&intf->dev, "coming out of suspend..\n");
551
552 return 0;
553}
554
3a0efc32
AK
555static void usb_dsbr100_video_device_release(struct video_device *videodev)
556{
557 struct dsbr100_device *radio = videodev_to_radio(videodev);
558
559 kfree(radio->transfer_buffer);
560 kfree(radio);
561}
562
7002a4f3
DL
563/* File system interface */
564static const struct file_operations usb_dsbr100_fops = {
565 .owner = THIS_MODULE,
566 .open = usb_dsbr100_open,
567 .release = usb_dsbr100_close,
568 .ioctl = video_ioctl2,
078ff795 569#ifdef CONFIG_COMPAT
7002a4f3 570 .compat_ioctl = v4l_compat_ioctl32,
078ff795 571#endif
7002a4f3
DL
572 .llseek = no_llseek,
573};
574
a399810c 575static const struct v4l2_ioctl_ops usb_dsbr100_ioctl_ops = {
7002a4f3
DL
576 .vidioc_querycap = vidioc_querycap,
577 .vidioc_g_tuner = vidioc_g_tuner,
578 .vidioc_s_tuner = vidioc_s_tuner,
579 .vidioc_g_frequency = vidioc_g_frequency,
580 .vidioc_s_frequency = vidioc_s_frequency,
581 .vidioc_queryctrl = vidioc_queryctrl,
582 .vidioc_g_ctrl = vidioc_g_ctrl,
583 .vidioc_s_ctrl = vidioc_s_ctrl,
584 .vidioc_g_audio = vidioc_g_audio,
585 .vidioc_s_audio = vidioc_s_audio,
586 .vidioc_g_input = vidioc_g_input,
587 .vidioc_s_input = vidioc_s_input,
588};
589
a399810c 590/* V4L2 interface */
3a0efc32 591static struct video_device dsbr100_videodev_data = {
a399810c 592 .name = "D-Link DSB-R 100",
a399810c
HV
593 .fops = &usb_dsbr100_fops,
594 .ioctl_ops = &usb_dsbr100_ioctl_ops,
3a0efc32 595 .release = usb_dsbr100_video_device_release,
a399810c
HV
596};
597
7002a4f3
DL
598/* check if the device is present and register with v4l and
599usb if it is */
600static int usb_dsbr100_probe(struct usb_interface *intf,
601 const struct usb_device_id *id)
602{
603 struct dsbr100_device *radio;
604
223377e7
AK
605 radio = kmalloc(sizeof(struct dsbr100_device), GFP_KERNEL);
606
607 if (!radio)
7002a4f3 608 return -ENOMEM;
223377e7
AK
609
610 radio->transfer_buffer = kmalloc(TB_LEN, GFP_KERNEL);
611
612 if (!(radio->transfer_buffer)) {
863c86dd
ON
613 kfree(radio);
614 return -ENOMEM;
615 }
223377e7 616
3a0efc32
AK
617 mutex_init(&radio->lock);
618 radio->videodev = dsbr100_videodev_data;
619
7002a4f3
DL
620 radio->removed = 0;
621 radio->users = 0;
622 radio->usbdev = interface_to_usbdev(intf);
223377e7 623 radio->curfreq = FREQ_MIN * FREQ_MUL;
3a0efc32
AK
624 video_set_drvdata(&radio->videodev, radio);
625 if (video_register_device(&radio->videodev, VFL_TYPE_RADIO, radio_nr) < 0) {
aa82661b 626 dev_warn(&intf->dev, "Could not register video device\n");
863c86dd 627 kfree(radio->transfer_buffer);
7002a4f3
DL
628 kfree(radio);
629 return -EIO;
630 }
631 usb_set_intfdata(intf, radio);
632 return 0;
633}
634
1da177e4
LT
635static int __init dsbr100_init(void)
636{
637 int retval = usb_register(&usb_dsbr100_driver);
a482f327
GKH
638 printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
639 DRIVER_DESC "\n");
1da177e4
LT
640 return retval;
641}
642
643static void __exit dsbr100_exit(void)
644{
645 usb_deregister(&usb_dsbr100_driver);
646}
647
648module_init (dsbr100_init);
649module_exit (dsbr100_exit);
650
651MODULE_AUTHOR( DRIVER_AUTHOR );
652MODULE_DESCRIPTION( DRIVER_DESC );
653MODULE_LICENSE("GPL");
This page took 0.47033 seconds and 5 git commands to generate.