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