2 * Copyright (c) 2012 Hans Verkuil <hverkuil@xs4all.nl>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include <linux/kernel.h>
21 #include <linux/module.h>
22 #include <linux/init.h>
23 #include <linux/slab.h>
24 #include <linux/input.h>
25 #include <linux/videodev2.h>
26 #include <media/v4l2-device.h>
27 #include <media/v4l2-ioctl.h>
28 #include <media/v4l2-ctrls.h>
29 #include <media/v4l2-event.h>
30 #include <linux/usb.h>
31 #include <linux/mutex.h>
33 /* driver and module definitions */
34 MODULE_AUTHOR("Hans Verkuil <hverkuil@xs4all.nl>");
35 MODULE_DESCRIPTION("Keene FM Transmitter driver");
36 MODULE_LICENSE("GPL");
38 /* Actually, it advertises itself as a Logitech */
39 #define USB_KEENE_VENDOR 0x046d
40 #define USB_KEENE_PRODUCT 0x0a0e
42 /* Probably USB_TIMEOUT should be modified in module parameter */
43 #define BUFFER_LENGTH 8
44 #define USB_TIMEOUT 500
46 /* Frequency limits in MHz */
49 #define FREQ_MUL 16000U
51 /* USB Device ID List */
52 static struct usb_device_id usb_keene_device_table
[] = {
53 {USB_DEVICE_AND_INTERFACE_INFO(USB_KEENE_VENDOR
, USB_KEENE_PRODUCT
,
54 USB_CLASS_HID
, 0, 0) },
55 { } /* Terminating entry */
58 MODULE_DEVICE_TABLE(usb
, usb_keene_device_table
);
61 struct usb_device
*usbdev
;
62 struct usb_interface
*intf
;
63 struct video_device vdev
;
64 struct v4l2_device v4l2_dev
;
65 struct v4l2_ctrl_handler hdl
;
77 static inline struct keene_device
*to_keene_dev(struct v4l2_device
*v4l2_dev
)
79 return container_of(v4l2_dev
, struct keene_device
, v4l2_dev
);
82 /* Set frequency (if non-0), PA, mute and turn on/off the FM transmitter. */
83 static int keene_cmd_main(struct keene_device
*radio
, unsigned freq
, bool play
)
85 unsigned short freq_send
= freq
? (freq
- 76 * 16000) / 800 : 0;
88 radio
->buffer
[0] = 0x00;
89 radio
->buffer
[1] = 0x50;
90 radio
->buffer
[2] = (freq_send
>> 8) & 0xff;
91 radio
->buffer
[3] = freq_send
& 0xff;
92 radio
->buffer
[4] = radio
->pa
;
93 /* If bit 4 is set, then tune to the frequency.
94 If bit 3 is set, then unmute; if bit 2 is set, then mute.
95 If bit 1 is set, then enter idle mode; if bit 0 is set,
96 then enter transmit mode.
98 radio
->buffer
[5] = (radio
->muted
? 4 : 8) | (play
? 1 : 2) |
100 radio
->buffer
[6] = 0x00;
101 radio
->buffer
[7] = 0x00;
103 ret
= usb_control_msg(radio
->usbdev
, usb_sndctrlpipe(radio
->usbdev
, 0),
104 9, 0x21, 0x200, 2, radio
->buffer
, BUFFER_LENGTH
, USB_TIMEOUT
);
107 dev_warn(&radio
->vdev
.dev
, "%s failed (%d)\n", __func__
, ret
);
111 radio
->curfreq
= freq
;
115 /* Set TX, stereo and preemphasis mode (50 us vs 75 us). */
116 static int keene_cmd_set(struct keene_device
*radio
)
120 radio
->buffer
[0] = 0x00;
121 radio
->buffer
[1] = 0x51;
122 radio
->buffer
[2] = radio
->tx
;
123 /* If bit 0 is set, then transmit mono, otherwise stereo.
124 If bit 2 is set, then enable 75 us preemphasis, otherwise
126 radio
->buffer
[3] = (radio
->stereo
? 0 : 1) | (radio
->preemph_75_us
? 4 : 0);
127 radio
->buffer
[4] = 0x00;
128 radio
->buffer
[5] = 0x00;
129 radio
->buffer
[6] = 0x00;
130 radio
->buffer
[7] = 0x00;
132 ret
= usb_control_msg(radio
->usbdev
, usb_sndctrlpipe(radio
->usbdev
, 0),
133 9, 0x21, 0x200, 2, radio
->buffer
, BUFFER_LENGTH
, USB_TIMEOUT
);
136 dev_warn(&radio
->vdev
.dev
, "%s failed (%d)\n", __func__
, ret
);
142 /* Handle unplugging the device.
143 * We call video_unregister_device in any case.
144 * The last function called in this procedure is
145 * usb_keene_device_release.
147 static void usb_keene_disconnect(struct usb_interface
*intf
)
149 struct keene_device
*radio
= to_keene_dev(usb_get_intfdata(intf
));
151 mutex_lock(&radio
->lock
);
152 usb_set_intfdata(intf
, NULL
);
153 video_unregister_device(&radio
->vdev
);
154 v4l2_device_disconnect(&radio
->v4l2_dev
);
155 mutex_unlock(&radio
->lock
);
156 v4l2_device_put(&radio
->v4l2_dev
);
159 static int usb_keene_suspend(struct usb_interface
*intf
, pm_message_t message
)
161 struct keene_device
*radio
= to_keene_dev(usb_get_intfdata(intf
));
163 return keene_cmd_main(radio
, 0, false);
166 static int usb_keene_resume(struct usb_interface
*intf
)
168 struct keene_device
*radio
= to_keene_dev(usb_get_intfdata(intf
));
171 keene_cmd_set(radio
);
172 keene_cmd_main(radio
, radio
->curfreq
, true);
176 static int vidioc_querycap(struct file
*file
, void *priv
,
177 struct v4l2_capability
*v
)
179 struct keene_device
*radio
= video_drvdata(file
);
181 strlcpy(v
->driver
, "radio-keene", sizeof(v
->driver
));
182 strlcpy(v
->card
, "Keene FM Transmitter", sizeof(v
->card
));
183 usb_make_path(radio
->usbdev
, v
->bus_info
, sizeof(v
->bus_info
));
184 v
->device_caps
= V4L2_CAP_RADIO
| V4L2_CAP_MODULATOR
;
185 v
->capabilities
= v
->device_caps
| V4L2_CAP_DEVICE_CAPS
;
189 static int vidioc_g_modulator(struct file
*file
, void *priv
,
190 struct v4l2_modulator
*v
)
192 struct keene_device
*radio
= video_drvdata(file
);
197 strlcpy(v
->name
, "FM", sizeof(v
->name
));
198 v
->rangelow
= FREQ_MIN
* FREQ_MUL
;
199 v
->rangehigh
= FREQ_MAX
* FREQ_MUL
;
200 v
->txsubchans
= radio
->stereo
? V4L2_TUNER_SUB_STEREO
: V4L2_TUNER_SUB_MONO
;
201 v
->capability
= V4L2_TUNER_CAP_LOW
| V4L2_TUNER_CAP_STEREO
;
205 static int vidioc_s_modulator(struct file
*file
, void *priv
,
206 const struct v4l2_modulator
*v
)
208 struct keene_device
*radio
= video_drvdata(file
);
213 radio
->stereo
= (v
->txsubchans
== V4L2_TUNER_SUB_STEREO
);
214 return keene_cmd_set(radio
);
217 static int vidioc_s_frequency(struct file
*file
, void *priv
,
218 const struct v4l2_frequency
*f
)
220 struct keene_device
*radio
= video_drvdata(file
);
221 unsigned freq
= f
->frequency
;
223 if (f
->tuner
!= 0 || f
->type
!= V4L2_TUNER_RADIO
)
225 freq
= clamp(freq
, FREQ_MIN
* FREQ_MUL
, FREQ_MAX
* FREQ_MUL
);
226 return keene_cmd_main(radio
, freq
, true);
229 static int vidioc_g_frequency(struct file
*file
, void *priv
,
230 struct v4l2_frequency
*f
)
232 struct keene_device
*radio
= video_drvdata(file
);
236 f
->type
= V4L2_TUNER_RADIO
;
237 f
->frequency
= radio
->curfreq
;
241 static int keene_s_ctrl(struct v4l2_ctrl
*ctrl
)
243 static const u8 db2tx
[] = {
244 /* -15, -12, -9, -6, -3, 0 dB */
245 0x03, 0x13, 0x02, 0x12, 0x22, 0x32,
246 /* 3, 6, 9, 12, 15, 18 dB */
247 0x21, 0x31, 0x20, 0x30, 0x40, 0x50
249 struct keene_device
*radio
=
250 container_of(ctrl
->handler
, struct keene_device
, hdl
);
253 case V4L2_CID_AUDIO_MUTE
:
254 radio
->muted
= ctrl
->val
;
255 return keene_cmd_main(radio
, 0, true);
257 case V4L2_CID_TUNE_POWER_LEVEL
:
258 /* To go from dBuV to the register value we apply the
259 following formula: */
260 radio
->pa
= (ctrl
->val
- 71) * 100 / 62;
261 return keene_cmd_main(radio
, 0, true);
263 case V4L2_CID_TUNE_PREEMPHASIS
:
264 radio
->preemph_75_us
= ctrl
->val
== V4L2_PREEMPHASIS_75_uS
;
265 return keene_cmd_set(radio
);
267 case V4L2_CID_AUDIO_COMPRESSION_GAIN
:
268 radio
->tx
= db2tx
[(ctrl
->val
- (s32
)ctrl
->minimum
) / (s32
)ctrl
->step
];
269 return keene_cmd_set(radio
);
274 /* File system interface */
275 static const struct v4l2_file_operations usb_keene_fops
= {
276 .owner
= THIS_MODULE
,
277 .open
= v4l2_fh_open
,
278 .release
= v4l2_fh_release
,
279 .poll
= v4l2_ctrl_poll
,
280 .unlocked_ioctl
= video_ioctl2
,
283 static const struct v4l2_ctrl_ops keene_ctrl_ops
= {
284 .s_ctrl
= keene_s_ctrl
,
287 static const struct v4l2_ioctl_ops usb_keene_ioctl_ops
= {
288 .vidioc_querycap
= vidioc_querycap
,
289 .vidioc_g_modulator
= vidioc_g_modulator
,
290 .vidioc_s_modulator
= vidioc_s_modulator
,
291 .vidioc_g_frequency
= vidioc_g_frequency
,
292 .vidioc_s_frequency
= vidioc_s_frequency
,
293 .vidioc_log_status
= v4l2_ctrl_log_status
,
294 .vidioc_subscribe_event
= v4l2_ctrl_subscribe_event
,
295 .vidioc_unsubscribe_event
= v4l2_event_unsubscribe
,
298 static void usb_keene_video_device_release(struct v4l2_device
*v4l2_dev
)
300 struct keene_device
*radio
= to_keene_dev(v4l2_dev
);
302 /* free rest memory */
303 v4l2_ctrl_handler_free(&radio
->hdl
);
304 kfree(radio
->buffer
);
308 /* check if the device is present and register with v4l and usb if it is */
309 static int usb_keene_probe(struct usb_interface
*intf
,
310 const struct usb_device_id
*id
)
312 struct usb_device
*dev
= interface_to_usbdev(intf
);
313 struct keene_device
*radio
;
314 struct v4l2_ctrl_handler
*hdl
;
318 * The Keene FM transmitter USB device has the same USB ID as
319 * the Logitech AudioHub Speaker, but it should ignore the hid.
320 * Check if the name is that of the Keene device.
321 * If not, then someone connected the AudioHub and we shouldn't
322 * attempt to handle this driver.
323 * For reference: the product name of the AudioHub is
324 * "AudioHub Speaker".
326 if (dev
->product
&& strcmp(dev
->product
, "B-LINK USB Audio "))
329 radio
= kzalloc(sizeof(struct keene_device
), GFP_KERNEL
);
331 radio
->buffer
= kmalloc(BUFFER_LENGTH
, GFP_KERNEL
);
333 if (!radio
|| !radio
->buffer
) {
334 dev_err(&intf
->dev
, "kmalloc for keene_device failed\n");
341 v4l2_ctrl_handler_init(hdl
, 4);
342 v4l2_ctrl_new_std(hdl
, &keene_ctrl_ops
, V4L2_CID_AUDIO_MUTE
,
344 v4l2_ctrl_new_std_menu(hdl
, &keene_ctrl_ops
, V4L2_CID_TUNE_PREEMPHASIS
,
345 V4L2_PREEMPHASIS_75_uS
, 1, V4L2_PREEMPHASIS_50_uS
);
346 v4l2_ctrl_new_std(hdl
, &keene_ctrl_ops
, V4L2_CID_TUNE_POWER_LEVEL
,
348 v4l2_ctrl_new_std(hdl
, &keene_ctrl_ops
, V4L2_CID_AUDIO_COMPRESSION_GAIN
,
352 radio
->stereo
= true;
356 v4l2_ctrl_handler_free(hdl
);
359 retval
= v4l2_device_register(&intf
->dev
, &radio
->v4l2_dev
);
361 dev_err(&intf
->dev
, "couldn't register v4l2_device\n");
365 mutex_init(&radio
->lock
);
367 radio
->v4l2_dev
.ctrl_handler
= hdl
;
368 radio
->v4l2_dev
.release
= usb_keene_video_device_release
;
369 strlcpy(radio
->vdev
.name
, radio
->v4l2_dev
.name
,
370 sizeof(radio
->vdev
.name
));
371 radio
->vdev
.v4l2_dev
= &radio
->v4l2_dev
;
372 radio
->vdev
.fops
= &usb_keene_fops
;
373 radio
->vdev
.ioctl_ops
= &usb_keene_ioctl_ops
;
374 radio
->vdev
.lock
= &radio
->lock
;
375 radio
->vdev
.release
= video_device_release_empty
;
376 radio
->vdev
.vfl_dir
= VFL_DIR_TX
;
378 radio
->usbdev
= interface_to_usbdev(intf
);
380 usb_set_intfdata(intf
, &radio
->v4l2_dev
);
382 video_set_drvdata(&radio
->vdev
, radio
);
384 /* at least 11ms is needed in order to settle hardware */
386 keene_cmd_main(radio
, 95.16 * FREQ_MUL
, false);
388 retval
= video_register_device(&radio
->vdev
, VFL_TYPE_RADIO
, -1);
390 dev_err(&intf
->dev
, "could not register video device\n");
393 v4l2_ctrl_handler_setup(hdl
);
394 dev_info(&intf
->dev
, "V4L2 device registered as %s\n",
395 video_device_node_name(&radio
->vdev
));
399 v4l2_device_unregister(&radio
->v4l2_dev
);
401 kfree(radio
->buffer
);
407 /* USB subsystem interface */
408 static struct usb_driver usb_keene_driver
= {
409 .name
= "radio-keene",
410 .probe
= usb_keene_probe
,
411 .disconnect
= usb_keene_disconnect
,
412 .id_table
= usb_keene_device_table
,
413 .suspend
= usb_keene_suspend
,
414 .resume
= usb_keene_resume
,
415 .reset_resume
= usb_keene_resume
,
418 module_usb_driver(usb_keene_driver
);