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.
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.
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:-)
15 You might find some interesting stuff about this module at
16 http://unimut.fsk.uni-heidelberg.de/unimut/demi/dsbr
18 Copyright (c) 2000 Markus Demleitner
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.
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.
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
37 Markus Demleitner <msdemlei@tucana.harvard.edu>:
38 Minor cleanup, warnings if something goes wrong, lame attempt
39 to adhere to Documentation/CodingStyle
42 Brad Hards <bradh@dynamite.com.au>: Fixes to make it work as non-module
43 Markus: Copyright clarification
45 Version 0.01: Markus: initial release
50 #include <linux/kernel.h>
51 #include <linux/module.h>
52 #include <linux/init.h>
53 #include <linux/malloc.h>
54 #include <linux/input.h>
55 #include <linux/videodev.h>
56 #include <linux/usb.h>
58 #define DSB100_VENDOR 0x04b4
59 #define DSB100_PRODUCT 0x1002
63 static void *usb_dsbr100_probe(struct usb_device
*dev
, unsigned int ifnum
);
64 static void usb_dsbr100_disconnect(struct usb_device
*dev
, void *ptr
);
65 static int usb_dsbr100_ioctl(struct video_device
*dev
, unsigned int cmd
,
67 static int usb_dsbr100_open(struct video_device
*dev
, int flags
);
68 static void usb_dsbr100_close(struct video_device
*dev
);
72 { struct urb readurb
,writeurb
;
73 struct usb_device
*dev
;
74 char transfer_buffer
[TB_LEN
];
81 static struct video_device usb_dsbr100_radio
=
83 "D-Link DSB R-100 USB radio",
88 NULL
, /* Can't read (no capture ability) */
89 NULL
, /* Can't write */
98 static struct usb_driver usb_dsbr100_driver
= {
100 probe
: usb_dsbr100_probe
,
101 disconnect
: usb_dsbr100_disconnect
,
102 driver_list
: {NULL
,NULL
},
108 static int dsbr100_start(usb_dsbr100
*radio
)
110 if (usb_control_msg(radio
->dev
, usb_rcvctrlpipe(radio
->dev
, 0),
111 0x00, 0xC0, 0x00, 0xC7, radio
->transfer_buffer
, 8, 300)<0 ||
112 usb_control_msg(radio
->dev
, usb_rcvctrlpipe(radio
->dev
, 0),
113 0x02, 0xC0, 0x01, 0x00, radio
->transfer_buffer
, 8, 300)<0)
115 return (radio
->transfer_buffer
)[0];
119 static int dsbr100_stop(usb_dsbr100
*radio
)
121 if (usb_control_msg(radio
->dev
, usb_rcvctrlpipe(radio
->dev
, 0),
122 0x00, 0xC0, 0x16, 0x1C, radio
->transfer_buffer
, 8, 300)<0 ||
123 usb_control_msg(radio
->dev
, usb_rcvctrlpipe(radio
->dev
, 0),
124 0x02, 0xC0, 0x00, 0x00, radio
->transfer_buffer
, 8, 300)<0)
126 return (radio
->transfer_buffer
)[0];
130 static int dsbr100_setfreq(usb_dsbr100
*radio
, int freq
)
132 freq
= (freq
*80)/16+856;
133 if (usb_control_msg(radio
->dev
, usb_rcvctrlpipe(radio
->dev
, 0),
134 0x01, 0xC0, (freq
&0xff00)>>8, freq
&0xff,
135 radio
->transfer_buffer
, 8, 300)<0
136 || usb_control_msg(radio
->dev
, usb_rcvctrlpipe(radio
->dev
, 0),
137 0x00, 0xC0, 0x96, 0xB7, radio
->transfer_buffer
, 8, 300)<0 ||
138 usb_control_msg(radio
->dev
, usb_rcvctrlpipe(radio
->dev
, 0),
139 0x00, 0xC0, 0x00, 0x24, radio
->transfer_buffer
, 8, 300)<0) {
143 radio
->stereo
= ! ((radio
->transfer_buffer
)[0]&0x01);
144 return (radio
->transfer_buffer
)[0];
147 static void dsbr100_getstat(usb_dsbr100
*radio
)
149 if (usb_control_msg(radio
->dev
, usb_rcvctrlpipe(radio
->dev
, 0),
150 0x00, 0xC0, 0x00 , 0x24, radio
->transfer_buffer
, 8, 300)<0)
153 radio
->stereo
= ! (radio
->transfer_buffer
[0]&0x01);
157 static void *usb_dsbr100_probe(struct usb_device
*dev
, unsigned int ifnum
)
161 if (dev
->descriptor
.idVendor
!=DSB100_VENDOR
||
162 dev
->descriptor
.idProduct
!=DSB100_PRODUCT
)
164 if (!(radio
= kmalloc(sizeof(usb_dsbr100
),GFP_KERNEL
)))
166 usb_dsbr100_radio
.priv
= radio
;
168 radio
->ifnum
= ifnum
;
169 radio
->curfreq
= 1454;
173 static void usb_dsbr100_disconnect(struct usb_device
*dev
, void *ptr
)
175 usb_dsbr100
*radio
=ptr
;
180 usb_dsbr100_radio
.priv
= NULL
;
183 static int usb_dsbr100_ioctl(struct video_device
*dev
, unsigned int cmd
,
186 usb_dsbr100
*radio
=dev
->priv
;
194 struct video_capability v
;
195 v
.type
=VID_TYPE_TUNER
;
198 /* No we don't do pictures */
203 strcpy(v
.name
, "D-Link R-100 USB Radio");
204 if(copy_to_user(arg
,&v
,sizeof(v
)))
209 struct video_tuner v
;
210 dsbr100_getstat(radio
);
211 if(copy_from_user(&v
, arg
,sizeof(v
))!=0)
213 if(v
.tuner
) /* Only 1 tuner */
215 v
.rangelow
=(87*16000);
216 v
.rangehigh
=(108*16000);
217 /*v.flags=VIDEO_TUNER_LOW;*/
218 v
.mode
=VIDEO_MODE_AUTO
;
219 v
.signal
=radio
->stereo
;
220 v
.flags
|=VIDEO_TUNER_STEREO_ON
;
221 strcpy(v
.name
, "FM");
222 if(copy_to_user(arg
,&v
, sizeof(v
)))
227 struct video_tuner v
;
228 if(copy_from_user(&v
, arg
, sizeof(v
)))
232 /* Only 1 tuner so no setting needed ! */
236 if (radio
->curfreq
==-1)
238 if(copy_to_user(arg
, &(radio
->curfreq
),
239 sizeof(radio
->curfreq
)))
244 if(copy_from_user(&(radio
->curfreq
), arg
,
245 sizeof(radio
->curfreq
)))
247 if (dsbr100_setfreq(radio
, radio
->curfreq
)==-1)
248 warn("set frequency failed");
252 struct video_audio v
;
253 memset(&v
,0, sizeof(v
));
254 v
.flags
|=VIDEO_AUDIO_MUTABLE
;
255 v
.mode
=VIDEO_SOUND_STEREO
;
258 strcpy(v
.name
, "Radio");
259 if(copy_to_user(arg
,&v
, sizeof(v
)))
264 struct video_audio v
;
265 if(copy_from_user(&v
, arg
, sizeof(v
)))
270 if(v
.flags
&VIDEO_AUDIO_MUTE
) {
271 if (dsbr100_stop(radio
)==-1)
272 warn("radio did not respond properly");
275 if (dsbr100_start(radio
)==-1)
276 warn("radio did not respond properly");
285 static int usb_dsbr100_open(struct video_device
*dev
, int flags
)
287 usb_dsbr100
*radio
=dev
->priv
;
290 warn("radio not initialised");
295 warn("radio in use");
300 if (dsbr100_start(radio
)<0)
301 warn("radio did not start up properly");
302 dsbr100_setfreq(radio
,radio
->curfreq
);
306 static void usb_dsbr100_close(struct video_device
*dev
)
308 usb_dsbr100
*radio
=dev
->priv
;
317 int __init
dsbr100_init(void)
319 usb_dsbr100_radio
.priv
= NULL
;
320 usb_register(&usb_dsbr100_driver
);
321 if (video_register_device(&usb_dsbr100_radio
,VFL_TYPE_RADIO
)==-1) {
322 warn("couldn't register video device");
328 int __init
init_module(void)
330 return dsbr100_init();
333 void cleanup_module(void)
335 usb_dsbr100
*radio
=usb_dsbr100_radio
.priv
;
339 video_unregister_device(&usb_dsbr100_radio
);
340 usb_deregister(&usb_dsbr100_driver
);
345 Sigh. Of course, I am one of the ts=2 heretics, but Linus' wish is