0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044 #include <linux/kernel.h>
0045 #include <linux/module.h>
0046 #include <linux/init.h>
0047 #include <linux/slab.h>
0048 #include <linux/input.h>
0049 #include <linux/videodev2.h>
0050 #include <media/v4l2-device.h>
0051 #include <media/v4l2-ioctl.h>
0052 #include <media/v4l2-ctrls.h>
0053 #include <media/v4l2-event.h>
0054 #include <linux/usb.h>
0055 #include <linux/mutex.h>
0056
0057
0058 #define DRIVER_AUTHOR "Alexey Klimov <klimov.linux@gmail.com>"
0059 #define DRIVER_DESC "AverMedia MR 800 USB FM radio driver"
0060 #define DRIVER_VERSION "0.1.2"
0061
0062 MODULE_AUTHOR(DRIVER_AUTHOR);
0063 MODULE_DESCRIPTION(DRIVER_DESC);
0064 MODULE_LICENSE("GPL");
0065 MODULE_VERSION(DRIVER_VERSION);
0066
0067 #define USB_AMRADIO_VENDOR 0x07ca
0068 #define USB_AMRADIO_PRODUCT 0xb800
0069
0070
0071 #define MR800_DRIVER_NAME "radio-mr800"
0072 #define amradio_dev_warn(dev, fmt, arg...) \
0073 dev_warn(dev, MR800_DRIVER_NAME " - " fmt, ##arg)
0074
0075 #define amradio_dev_err(dev, fmt, arg...) \
0076 dev_err(dev, MR800_DRIVER_NAME " - " fmt, ##arg)
0077
0078
0079 #define BUFFER_LENGTH 8
0080 #define USB_TIMEOUT 500
0081
0082
0083
0084 #define FREQ_MIN 87.5
0085 #define FREQ_MAX 108.0
0086 #define FREQ_MUL 16000
0087
0088
0089
0090
0091
0092 #define AMRADIO_SET_FREQ 0xa4
0093 #define AMRADIO_GET_READY_FLAG 0xa5
0094 #define AMRADIO_GET_SIGNAL 0xa7
0095 #define AMRADIO_GET_FREQ 0xa8
0096 #define AMRADIO_SET_SEARCH_UP 0xa9
0097 #define AMRADIO_SET_SEARCH_DOWN 0xaa
0098 #define AMRADIO_SET_MUTE 0xab
0099 #define AMRADIO_SET_RIGHT_MUTE 0xac
0100 #define AMRADIO_SET_LEFT_MUTE 0xad
0101 #define AMRADIO_SET_MONO 0xae
0102 #define AMRADIO_SET_SEARCH_LVL 0xb0
0103 #define AMRADIO_STOP_SEARCH 0xb1
0104
0105
0106 #define WANT_STEREO 0x00
0107 #define WANT_MONO 0x01
0108
0109
0110 static int radio_nr = -1;
0111 module_param(radio_nr, int, 0);
0112 MODULE_PARM_DESC(radio_nr, "Radio Nr");
0113
0114
0115 struct amradio_device {
0116
0117 struct usb_device *usbdev;
0118 struct usb_interface *intf;
0119 struct video_device vdev;
0120 struct v4l2_device v4l2_dev;
0121 struct v4l2_ctrl_handler hdl;
0122
0123 u8 *buffer;
0124 struct mutex lock;
0125 int curfreq;
0126 int stereo;
0127 int muted;
0128 };
0129
0130 static inline struct amradio_device *to_amradio_dev(struct v4l2_device *v4l2_dev)
0131 {
0132 return container_of(v4l2_dev, struct amradio_device, v4l2_dev);
0133 }
0134
0135 static int amradio_send_cmd(struct amradio_device *radio, u8 cmd, u8 arg,
0136 u8 *extra, u8 extralen, bool reply)
0137 {
0138 int retval;
0139 int size;
0140
0141 radio->buffer[0] = 0x00;
0142 radio->buffer[1] = 0x55;
0143 radio->buffer[2] = 0xaa;
0144 radio->buffer[3] = extralen;
0145 radio->buffer[4] = cmd;
0146 radio->buffer[5] = arg;
0147 radio->buffer[6] = 0x00;
0148 radio->buffer[7] = extra || reply ? 8 : 0;
0149
0150 retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2),
0151 radio->buffer, BUFFER_LENGTH, &size, USB_TIMEOUT);
0152
0153 if (retval < 0 || size != BUFFER_LENGTH) {
0154 if (video_is_registered(&radio->vdev))
0155 amradio_dev_warn(&radio->vdev.dev,
0156 "cmd %02x failed\n", cmd);
0157 return retval ? retval : -EIO;
0158 }
0159 if (!extra && !reply)
0160 return 0;
0161
0162 if (extra) {
0163 memcpy(radio->buffer, extra, extralen);
0164 memset(radio->buffer + extralen, 0, 8 - extralen);
0165 retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2),
0166 radio->buffer, BUFFER_LENGTH, &size, USB_TIMEOUT);
0167 } else {
0168 memset(radio->buffer, 0, 8);
0169 retval = usb_bulk_msg(radio->usbdev, usb_rcvbulkpipe(radio->usbdev, 0x81),
0170 radio->buffer, BUFFER_LENGTH, &size, USB_TIMEOUT);
0171 }
0172 if (retval == 0 && size == BUFFER_LENGTH)
0173 return 0;
0174 if (video_is_registered(&radio->vdev) && cmd != AMRADIO_GET_READY_FLAG)
0175 amradio_dev_warn(&radio->vdev.dev, "follow-up to cmd %02x failed\n", cmd);
0176 return retval ? retval : -EIO;
0177 }
0178
0179
0180 static int amradio_set_mute(struct amradio_device *radio, bool mute)
0181 {
0182 int ret = amradio_send_cmd(radio,
0183 AMRADIO_SET_MUTE, mute, NULL, 0, false);
0184
0185 if (!ret)
0186 radio->muted = mute;
0187 return ret;
0188 }
0189
0190
0191 static int amradio_set_freq(struct amradio_device *radio, int freq)
0192 {
0193 unsigned short freq_send;
0194 u8 buf[3];
0195 int retval;
0196
0197
0198 freq = clamp_t(unsigned, freq, FREQ_MIN * FREQ_MUL, FREQ_MAX * FREQ_MUL);
0199 freq_send = 0x10 + (freq >> 3) / 25;
0200
0201
0202 buf[0] = (freq_send >> 8) & 0xff;
0203 buf[1] = freq_send & 0xff;
0204 buf[2] = 0x01;
0205
0206 retval = amradio_send_cmd(radio, AMRADIO_SET_FREQ, 0, buf, 3, false);
0207 if (retval)
0208 return retval;
0209 radio->curfreq = freq;
0210 msleep(40);
0211 return 0;
0212 }
0213
0214 static int amradio_set_stereo(struct amradio_device *radio, bool stereo)
0215 {
0216 int ret = amradio_send_cmd(radio,
0217 AMRADIO_SET_MONO, !stereo, NULL, 0, false);
0218
0219 if (!ret)
0220 radio->stereo = stereo;
0221 return ret;
0222 }
0223
0224 static int amradio_get_stat(struct amradio_device *radio, bool *is_stereo, u32 *signal)
0225 {
0226 int ret = amradio_send_cmd(radio,
0227 AMRADIO_GET_SIGNAL, 0, NULL, 0, true);
0228
0229 if (ret)
0230 return ret;
0231 *is_stereo = radio->buffer[2] >> 7;
0232 *signal = (radio->buffer[3] & 0xf0) << 8;
0233 return 0;
0234 }
0235
0236
0237
0238
0239
0240
0241 static void usb_amradio_disconnect(struct usb_interface *intf)
0242 {
0243 struct amradio_device *radio = to_amradio_dev(usb_get_intfdata(intf));
0244
0245 mutex_lock(&radio->lock);
0246 video_unregister_device(&radio->vdev);
0247 amradio_set_mute(radio, true);
0248 usb_set_intfdata(intf, NULL);
0249 v4l2_device_disconnect(&radio->v4l2_dev);
0250 mutex_unlock(&radio->lock);
0251 v4l2_device_put(&radio->v4l2_dev);
0252 }
0253
0254
0255 static int vidioc_querycap(struct file *file, void *priv,
0256 struct v4l2_capability *v)
0257 {
0258 struct amradio_device *radio = video_drvdata(file);
0259
0260 strscpy(v->driver, "radio-mr800", sizeof(v->driver));
0261 strscpy(v->card, "AverMedia MR 800 USB FM Radio", sizeof(v->card));
0262 usb_make_path(radio->usbdev, v->bus_info, sizeof(v->bus_info));
0263 return 0;
0264 }
0265
0266
0267 static int vidioc_g_tuner(struct file *file, void *priv,
0268 struct v4l2_tuner *v)
0269 {
0270 struct amradio_device *radio = video_drvdata(file);
0271 bool is_stereo = false;
0272 int retval;
0273
0274 if (v->index > 0)
0275 return -EINVAL;
0276
0277 v->signal = 0;
0278 retval = amradio_get_stat(radio, &is_stereo, &v->signal);
0279 if (retval)
0280 return retval;
0281
0282 strscpy(v->name, "FM", sizeof(v->name));
0283 v->type = V4L2_TUNER_RADIO;
0284 v->rangelow = FREQ_MIN * FREQ_MUL;
0285 v->rangehigh = FREQ_MAX * FREQ_MUL;
0286 v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO |
0287 V4L2_TUNER_CAP_HWSEEK_WRAP;
0288 v->rxsubchans = is_stereo ? V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO;
0289 v->audmode = radio->stereo ?
0290 V4L2_TUNER_MODE_STEREO : V4L2_TUNER_MODE_MONO;
0291 return 0;
0292 }
0293
0294
0295 static int vidioc_s_tuner(struct file *file, void *priv,
0296 const struct v4l2_tuner *v)
0297 {
0298 struct amradio_device *radio = video_drvdata(file);
0299
0300 if (v->index > 0)
0301 return -EINVAL;
0302
0303
0304 switch (v->audmode) {
0305 case V4L2_TUNER_MODE_MONO:
0306 return amradio_set_stereo(radio, WANT_MONO);
0307 default:
0308 return amradio_set_stereo(radio, WANT_STEREO);
0309 }
0310 }
0311
0312
0313 static int vidioc_s_frequency(struct file *file, void *priv,
0314 const struct v4l2_frequency *f)
0315 {
0316 struct amradio_device *radio = video_drvdata(file);
0317
0318 if (f->tuner != 0)
0319 return -EINVAL;
0320 return amradio_set_freq(radio, f->frequency);
0321 }
0322
0323
0324 static int vidioc_g_frequency(struct file *file, void *priv,
0325 struct v4l2_frequency *f)
0326 {
0327 struct amradio_device *radio = video_drvdata(file);
0328
0329 if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
0330 return -EINVAL;
0331 f->type = V4L2_TUNER_RADIO;
0332 f->frequency = radio->curfreq;
0333
0334 return 0;
0335 }
0336
0337 static int vidioc_s_hw_freq_seek(struct file *file, void *priv,
0338 const struct v4l2_hw_freq_seek *seek)
0339 {
0340 static u8 buf[8] = {
0341 0x3d, 0x32, 0x0f, 0x08, 0x3d, 0x32, 0x0f, 0x08
0342 };
0343 struct amradio_device *radio = video_drvdata(file);
0344 unsigned long timeout;
0345 int retval;
0346
0347 if (seek->tuner != 0 || !seek->wrap_around)
0348 return -EINVAL;
0349
0350 if (file->f_flags & O_NONBLOCK)
0351 return -EWOULDBLOCK;
0352
0353 retval = amradio_send_cmd(radio,
0354 AMRADIO_SET_SEARCH_LVL, 0, buf, 8, false);
0355 if (retval)
0356 return retval;
0357 amradio_set_freq(radio, radio->curfreq);
0358 retval = amradio_send_cmd(radio,
0359 seek->seek_upward ? AMRADIO_SET_SEARCH_UP : AMRADIO_SET_SEARCH_DOWN,
0360 0, NULL, 0, false);
0361 if (retval)
0362 return retval;
0363 timeout = jiffies + msecs_to_jiffies(30000);
0364 for (;;) {
0365 if (time_after(jiffies, timeout)) {
0366 retval = -ENODATA;
0367 break;
0368 }
0369 if (schedule_timeout_interruptible(msecs_to_jiffies(10))) {
0370 retval = -ERESTARTSYS;
0371 break;
0372 }
0373 retval = amradio_send_cmd(radio, AMRADIO_GET_READY_FLAG,
0374 0, NULL, 0, true);
0375 if (retval)
0376 continue;
0377 amradio_send_cmd(radio, AMRADIO_GET_FREQ, 0, NULL, 0, true);
0378 if (radio->buffer[1] || radio->buffer[2]) {
0379
0380 radio->curfreq = (radio->buffer[1] << 8) | radio->buffer[2];
0381 radio->curfreq = (radio->curfreq - 0x10) * 200;
0382 amradio_send_cmd(radio, AMRADIO_STOP_SEARCH,
0383 0, NULL, 0, false);
0384 amradio_set_freq(radio, radio->curfreq);
0385 retval = 0;
0386 break;
0387 }
0388 }
0389 amradio_send_cmd(radio, AMRADIO_STOP_SEARCH, 0, NULL, 0, false);
0390 amradio_set_freq(radio, radio->curfreq);
0391 return retval;
0392 }
0393
0394 static int usb_amradio_s_ctrl(struct v4l2_ctrl *ctrl)
0395 {
0396 struct amradio_device *radio =
0397 container_of(ctrl->handler, struct amradio_device, hdl);
0398
0399 switch (ctrl->id) {
0400 case V4L2_CID_AUDIO_MUTE:
0401 return amradio_set_mute(radio, ctrl->val);
0402 }
0403
0404 return -EINVAL;
0405 }
0406
0407 static int usb_amradio_init(struct amradio_device *radio)
0408 {
0409 int retval;
0410
0411 retval = amradio_set_mute(radio, true);
0412 if (retval)
0413 goto out_err;
0414 retval = amradio_set_stereo(radio, true);
0415 if (retval)
0416 goto out_err;
0417 retval = amradio_set_freq(radio, radio->curfreq);
0418 if (retval)
0419 goto out_err;
0420 return 0;
0421
0422 out_err:
0423 amradio_dev_err(&radio->vdev.dev, "initialization failed\n");
0424 return retval;
0425 }
0426
0427
0428 static int usb_amradio_suspend(struct usb_interface *intf, pm_message_t message)
0429 {
0430 struct amradio_device *radio = to_amradio_dev(usb_get_intfdata(intf));
0431
0432 mutex_lock(&radio->lock);
0433 if (!radio->muted) {
0434 amradio_set_mute(radio, true);
0435 radio->muted = false;
0436 }
0437 mutex_unlock(&radio->lock);
0438
0439 dev_info(&intf->dev, "going into suspend..\n");
0440 return 0;
0441 }
0442
0443
0444 static int usb_amradio_resume(struct usb_interface *intf)
0445 {
0446 struct amradio_device *radio = to_amradio_dev(usb_get_intfdata(intf));
0447
0448 mutex_lock(&radio->lock);
0449 amradio_set_stereo(radio, radio->stereo);
0450 amradio_set_freq(radio, radio->curfreq);
0451
0452 if (!radio->muted)
0453 amradio_set_mute(radio, false);
0454
0455 mutex_unlock(&radio->lock);
0456
0457 dev_info(&intf->dev, "coming out of suspend..\n");
0458 return 0;
0459 }
0460
0461 static const struct v4l2_ctrl_ops usb_amradio_ctrl_ops = {
0462 .s_ctrl = usb_amradio_s_ctrl,
0463 };
0464
0465
0466 static const struct v4l2_file_operations usb_amradio_fops = {
0467 .owner = THIS_MODULE,
0468 .open = v4l2_fh_open,
0469 .release = v4l2_fh_release,
0470 .poll = v4l2_ctrl_poll,
0471 .unlocked_ioctl = video_ioctl2,
0472 };
0473
0474 static const struct v4l2_ioctl_ops usb_amradio_ioctl_ops = {
0475 .vidioc_querycap = vidioc_querycap,
0476 .vidioc_g_tuner = vidioc_g_tuner,
0477 .vidioc_s_tuner = vidioc_s_tuner,
0478 .vidioc_g_frequency = vidioc_g_frequency,
0479 .vidioc_s_frequency = vidioc_s_frequency,
0480 .vidioc_s_hw_freq_seek = vidioc_s_hw_freq_seek,
0481 .vidioc_log_status = v4l2_ctrl_log_status,
0482 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
0483 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
0484 };
0485
0486 static void usb_amradio_release(struct v4l2_device *v4l2_dev)
0487 {
0488 struct amradio_device *radio = to_amradio_dev(v4l2_dev);
0489
0490
0491 v4l2_ctrl_handler_free(&radio->hdl);
0492 v4l2_device_unregister(&radio->v4l2_dev);
0493 kfree(radio->buffer);
0494 kfree(radio);
0495 }
0496
0497
0498 static int usb_amradio_probe(struct usb_interface *intf,
0499 const struct usb_device_id *id)
0500 {
0501 struct amradio_device *radio;
0502 int retval;
0503
0504 radio = kzalloc(sizeof(struct amradio_device), GFP_KERNEL);
0505
0506 if (!radio) {
0507 dev_err(&intf->dev, "kmalloc for amradio_device failed\n");
0508 retval = -ENOMEM;
0509 goto err;
0510 }
0511
0512 radio->buffer = kmalloc(BUFFER_LENGTH, GFP_KERNEL);
0513
0514 if (!radio->buffer) {
0515 dev_err(&intf->dev, "kmalloc for radio->buffer failed\n");
0516 retval = -ENOMEM;
0517 goto err_nobuf;
0518 }
0519
0520 retval = v4l2_device_register(&intf->dev, &radio->v4l2_dev);
0521 if (retval < 0) {
0522 dev_err(&intf->dev, "couldn't register v4l2_device\n");
0523 goto err_v4l2;
0524 }
0525
0526 v4l2_ctrl_handler_init(&radio->hdl, 1);
0527 v4l2_ctrl_new_std(&radio->hdl, &usb_amradio_ctrl_ops,
0528 V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
0529 if (radio->hdl.error) {
0530 retval = radio->hdl.error;
0531 dev_err(&intf->dev, "couldn't register control\n");
0532 goto err_ctrl;
0533 }
0534 mutex_init(&radio->lock);
0535
0536 radio->v4l2_dev.ctrl_handler = &radio->hdl;
0537 radio->v4l2_dev.release = usb_amradio_release;
0538 strscpy(radio->vdev.name, radio->v4l2_dev.name,
0539 sizeof(radio->vdev.name));
0540 radio->vdev.v4l2_dev = &radio->v4l2_dev;
0541 radio->vdev.fops = &usb_amradio_fops;
0542 radio->vdev.ioctl_ops = &usb_amradio_ioctl_ops;
0543 radio->vdev.release = video_device_release_empty;
0544 radio->vdev.lock = &radio->lock;
0545 radio->vdev.device_caps = V4L2_CAP_RADIO | V4L2_CAP_TUNER |
0546 V4L2_CAP_HW_FREQ_SEEK;
0547
0548 radio->usbdev = interface_to_usbdev(intf);
0549 radio->intf = intf;
0550 usb_set_intfdata(intf, &radio->v4l2_dev);
0551 radio->curfreq = 95.16 * FREQ_MUL;
0552
0553 video_set_drvdata(&radio->vdev, radio);
0554 retval = usb_amradio_init(radio);
0555 if (retval)
0556 goto err_vdev;
0557
0558 retval = video_register_device(&radio->vdev, VFL_TYPE_RADIO,
0559 radio_nr);
0560 if (retval < 0) {
0561 dev_err(&intf->dev, "could not register video device\n");
0562 goto err_vdev;
0563 }
0564
0565 return 0;
0566
0567 err_vdev:
0568 v4l2_ctrl_handler_free(&radio->hdl);
0569 err_ctrl:
0570 v4l2_device_unregister(&radio->v4l2_dev);
0571 err_v4l2:
0572 kfree(radio->buffer);
0573 err_nobuf:
0574 kfree(radio);
0575 err:
0576 return retval;
0577 }
0578
0579
0580 static const struct usb_device_id usb_amradio_device_table[] = {
0581 { USB_DEVICE_AND_INTERFACE_INFO(USB_AMRADIO_VENDOR, USB_AMRADIO_PRODUCT,
0582 USB_CLASS_HID, 0, 0) },
0583 { }
0584 };
0585
0586 MODULE_DEVICE_TABLE(usb, usb_amradio_device_table);
0587
0588
0589 static struct usb_driver usb_amradio_driver = {
0590 .name = MR800_DRIVER_NAME,
0591 .probe = usb_amradio_probe,
0592 .disconnect = usb_amradio_disconnect,
0593 .suspend = usb_amradio_suspend,
0594 .resume = usb_amradio_resume,
0595 .reset_resume = usb_amradio_resume,
0596 .id_table = usb_amradio_device_table,
0597 };
0598
0599 module_usb_driver(usb_amradio_driver);