linux/drivers/media/radio/radio-ma901.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Driver for the MasterKit MA901 USB FM radio. This device plugs
   4 * into the USB port and an analog audio input or headphones, so this thing
   5 * only deals with initialization, frequency setting, volume.
   6 *
   7 * Copyright (c) 2012 Alexey Klimov <klimov.linux@gmail.com>
   8 */
   9
  10#include <linux/kernel.h>
  11#include <linux/module.h>
  12#include <linux/init.h>
  13#include <linux/slab.h>
  14#include <linux/input.h>
  15#include <linux/videodev2.h>
  16#include <media/v4l2-device.h>
  17#include <media/v4l2-ioctl.h>
  18#include <media/v4l2-ctrls.h>
  19#include <media/v4l2-event.h>
  20#include <linux/usb.h>
  21#include <linux/mutex.h>
  22
  23#define DRIVER_AUTHOR "Alexey Klimov <klimov.linux@gmail.com>"
  24#define DRIVER_DESC "Masterkit MA901 USB FM radio driver"
  25#define DRIVER_VERSION "0.0.1"
  26
  27MODULE_AUTHOR(DRIVER_AUTHOR);
  28MODULE_DESCRIPTION(DRIVER_DESC);
  29MODULE_LICENSE("GPL");
  30MODULE_VERSION(DRIVER_VERSION);
  31
  32#define USB_MA901_VENDOR  0x16c0
  33#define USB_MA901_PRODUCT 0x05df
  34
  35/* dev_warn macro with driver name */
  36#define MA901_DRIVER_NAME "radio-ma901"
  37#define ma901radio_dev_warn(dev, fmt, arg...)                           \
  38                dev_warn(dev, MA901_DRIVER_NAME " - " fmt, ##arg)
  39
  40#define ma901radio_dev_err(dev, fmt, arg...) \
  41                dev_err(dev, MA901_DRIVER_NAME " - " fmt, ##arg)
  42
  43/* Probably USB_TIMEOUT should be modified in module parameter */
  44#define BUFFER_LENGTH 8
  45#define USB_TIMEOUT 500
  46
  47#define FREQ_MIN  87.5
  48#define FREQ_MAX 108.0
  49#define FREQ_MUL 16000
  50
  51#define MA901_VOLUME_MAX 16
  52#define MA901_VOLUME_MIN 0
  53
  54/* Commands that device should understand
  55 * List isn't full and will be updated with implementation of new functions
  56 */
  57#define MA901_RADIO_SET_FREQ            0x03
  58#define MA901_RADIO_SET_VOLUME          0x04
  59#define MA901_RADIO_SET_MONO_STEREO     0x05
  60
  61/* Comfortable defines for ma901radio_set_stereo */
  62#define MA901_WANT_STEREO               0x50
  63#define MA901_WANT_MONO                 0xd0
  64
  65/* module parameter */
  66static int radio_nr = -1;
  67module_param(radio_nr, int, 0);
  68MODULE_PARM_DESC(radio_nr, "Radio file number");
  69
  70/* Data for one (physical) device */
  71struct ma901radio_device {
  72        /* reference to USB and video device */
  73        struct usb_device *usbdev;
  74        struct usb_interface *intf;
  75        struct video_device vdev;
  76        struct v4l2_device v4l2_dev;
  77        struct v4l2_ctrl_handler hdl;
  78
  79        u8 *buffer;
  80        struct mutex lock;      /* buffer locking */
  81        int curfreq;
  82        u16 volume;
  83        int stereo;
  84        bool muted;
  85};
  86
  87static inline struct ma901radio_device *to_ma901radio_dev(struct v4l2_device *v4l2_dev)
  88{
  89        return container_of(v4l2_dev, struct ma901radio_device, v4l2_dev);
  90}
  91
  92/* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */
  93static int ma901radio_set_freq(struct ma901radio_device *radio, int freq)
  94{
  95        unsigned int freq_send = 0x300 + (freq >> 5) / 25;
  96        int retval;
  97
  98        radio->buffer[0] = 0x0a;
  99        radio->buffer[1] = MA901_RADIO_SET_FREQ;
 100        radio->buffer[2] = ((freq_send >> 8) & 0xff) + 0x80;
 101        radio->buffer[3] = freq_send & 0xff;
 102        radio->buffer[4] = 0x00;
 103        radio->buffer[5] = 0x00;
 104        radio->buffer[6] = 0x00;
 105        radio->buffer[7] = 0x00;
 106
 107        retval = usb_control_msg(radio->usbdev, usb_sndctrlpipe(radio->usbdev, 0),
 108                                9, 0x21, 0x0300, 0,
 109                                radio->buffer, BUFFER_LENGTH, USB_TIMEOUT);
 110        if (retval < 0)
 111                return retval;
 112
 113        radio->curfreq = freq;
 114        return 0;
 115}
 116
 117static int ma901radio_set_volume(struct ma901radio_device *radio, u16 vol_to_set)
 118{
 119        int retval;
 120
 121        radio->buffer[0] = 0x0a;
 122        radio->buffer[1] = MA901_RADIO_SET_VOLUME;
 123        radio->buffer[2] = 0xc2;
 124        radio->buffer[3] = vol_to_set + 0x20;
 125        radio->buffer[4] = 0x00;
 126        radio->buffer[5] = 0x00;
 127        radio->buffer[6] = 0x00;
 128        radio->buffer[7] = 0x00;
 129
 130        retval = usb_control_msg(radio->usbdev, usb_sndctrlpipe(radio->usbdev, 0),
 131                                9, 0x21, 0x0300, 0,
 132                                radio->buffer, BUFFER_LENGTH, USB_TIMEOUT);
 133        if (retval < 0)
 134                return retval;
 135
 136        radio->volume = vol_to_set;
 137        return retval;
 138}
 139
 140static int ma901_set_stereo(struct ma901radio_device *radio, u8 stereo)
 141{
 142        int retval;
 143
 144        radio->buffer[0] = 0x0a;
 145        radio->buffer[1] = MA901_RADIO_SET_MONO_STEREO;
 146        radio->buffer[2] = stereo;
 147        radio->buffer[3] = 0x00;
 148        radio->buffer[4] = 0x00;
 149        radio->buffer[5] = 0x00;
 150        radio->buffer[6] = 0x00;
 151        radio->buffer[7] = 0x00;
 152
 153        retval = usb_control_msg(radio->usbdev, usb_sndctrlpipe(radio->usbdev, 0),
 154                                9, 0x21, 0x0300, 0,
 155                                radio->buffer, BUFFER_LENGTH, USB_TIMEOUT);
 156
 157        if (retval < 0)
 158                return retval;
 159
 160        if (stereo == MA901_WANT_STEREO)
 161                radio->stereo = V4L2_TUNER_MODE_STEREO;
 162        else
 163                radio->stereo = V4L2_TUNER_MODE_MONO;
 164
 165        return retval;
 166}
 167
 168/* Handle unplugging the device.
 169 * We call video_unregister_device in any case.
 170 * The last function called in this procedure is
 171 * usb_ma901radio_device_release.
 172 */
 173static void usb_ma901radio_disconnect(struct usb_interface *intf)
 174{
 175        struct ma901radio_device *radio = to_ma901radio_dev(usb_get_intfdata(intf));
 176
 177        mutex_lock(&radio->lock);
 178        video_unregister_device(&radio->vdev);
 179        usb_set_intfdata(intf, NULL);
 180        v4l2_device_disconnect(&radio->v4l2_dev);
 181        mutex_unlock(&radio->lock);
 182        v4l2_device_put(&radio->v4l2_dev);
 183}
 184
 185/* vidioc_querycap - query device capabilities */
 186static int vidioc_querycap(struct file *file, void *priv,
 187                                        struct v4l2_capability *v)
 188{
 189        struct ma901radio_device *radio = video_drvdata(file);
 190
 191        strscpy(v->driver, "radio-ma901", sizeof(v->driver));
 192        strscpy(v->card, "Masterkit MA901 USB FM Radio", sizeof(v->card));
 193        usb_make_path(radio->usbdev, v->bus_info, sizeof(v->bus_info));
 194        v->device_caps = V4L2_CAP_RADIO | V4L2_CAP_TUNER;
 195        v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS;
 196        return 0;
 197}
 198
 199/* vidioc_g_tuner - get tuner attributes */
 200static int vidioc_g_tuner(struct file *file, void *priv,
 201                                struct v4l2_tuner *v)
 202{
 203        struct ma901radio_device *radio = video_drvdata(file);
 204
 205        if (v->index > 0)
 206                return -EINVAL;
 207
 208        v->signal = 0;
 209
 210        /* TODO: the same words like in _probe() goes here.
 211         * When receiving of stats will be implemented then we can call
 212         * ma901radio_get_stat().
 213         * retval = ma901radio_get_stat(radio, &is_stereo, &v->signal);
 214         */
 215
 216        strscpy(v->name, "FM", sizeof(v->name));
 217        v->type = V4L2_TUNER_RADIO;
 218        v->rangelow = FREQ_MIN * FREQ_MUL;
 219        v->rangehigh = FREQ_MAX * FREQ_MUL;
 220        v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
 221        /* v->rxsubchans = is_stereo ? V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO; */
 222        v->audmode = radio->stereo ?
 223                V4L2_TUNER_MODE_STEREO : V4L2_TUNER_MODE_MONO;
 224        return 0;
 225}
 226
 227/* vidioc_s_tuner - set tuner attributes */
 228static int vidioc_s_tuner(struct file *file, void *priv,
 229                                const struct v4l2_tuner *v)
 230{
 231        struct ma901radio_device *radio = video_drvdata(file);
 232
 233        if (v->index > 0)
 234                return -EINVAL;
 235
 236        /* mono/stereo selector */
 237        switch (v->audmode) {
 238        case V4L2_TUNER_MODE_MONO:
 239                return ma901_set_stereo(radio, MA901_WANT_MONO);
 240        default:
 241                return ma901_set_stereo(radio, MA901_WANT_STEREO);
 242        }
 243}
 244
 245/* vidioc_s_frequency - set tuner radio frequency */
 246static int vidioc_s_frequency(struct file *file, void *priv,
 247                                const struct v4l2_frequency *f)
 248{
 249        struct ma901radio_device *radio = video_drvdata(file);
 250
 251        if (f->tuner != 0)
 252                return -EINVAL;
 253
 254        return ma901radio_set_freq(radio, clamp_t(unsigned, f->frequency,
 255                                FREQ_MIN * FREQ_MUL, FREQ_MAX * FREQ_MUL));
 256}
 257
 258/* vidioc_g_frequency - get tuner radio frequency */
 259static int vidioc_g_frequency(struct file *file, void *priv,
 260                                struct v4l2_frequency *f)
 261{
 262        struct ma901radio_device *radio = video_drvdata(file);
 263
 264        if (f->tuner != 0)
 265                return -EINVAL;
 266        f->frequency = radio->curfreq;
 267
 268        return 0;
 269}
 270
 271static int usb_ma901radio_s_ctrl(struct v4l2_ctrl *ctrl)
 272{
 273        struct ma901radio_device *radio =
 274                container_of(ctrl->handler, struct ma901radio_device, hdl);
 275
 276        switch (ctrl->id) {
 277        case V4L2_CID_AUDIO_VOLUME:     /* set volume */
 278                return ma901radio_set_volume(radio, (u16)ctrl->val);
 279        }
 280
 281        return -EINVAL;
 282}
 283
 284/* TODO: Should we really need to implement suspend and resume functions?
 285 * Radio has it's own memory and will continue playing if power is present
 286 * on usb port and on resume it will start to play again based on freq, volume
 287 * values in device memory.
 288 */
 289static int usb_ma901radio_suspend(struct usb_interface *intf, pm_message_t message)
 290{
 291        return 0;
 292}
 293
 294static int usb_ma901radio_resume(struct usb_interface *intf)
 295{
 296        return 0;
 297}
 298
 299static const struct v4l2_ctrl_ops usb_ma901radio_ctrl_ops = {
 300        .s_ctrl = usb_ma901radio_s_ctrl,
 301};
 302
 303/* File system interface */
 304static const struct v4l2_file_operations usb_ma901radio_fops = {
 305        .owner          = THIS_MODULE,
 306        .open           = v4l2_fh_open,
 307        .release        = v4l2_fh_release,
 308        .poll           = v4l2_ctrl_poll,
 309        .unlocked_ioctl = video_ioctl2,
 310};
 311
 312static const struct v4l2_ioctl_ops usb_ma901radio_ioctl_ops = {
 313        .vidioc_querycap    = vidioc_querycap,
 314        .vidioc_g_tuner     = vidioc_g_tuner,
 315        .vidioc_s_tuner     = vidioc_s_tuner,
 316        .vidioc_g_frequency = vidioc_g_frequency,
 317        .vidioc_s_frequency = vidioc_s_frequency,
 318        .vidioc_log_status  = v4l2_ctrl_log_status,
 319        .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
 320        .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
 321};
 322
 323static void usb_ma901radio_release(struct v4l2_device *v4l2_dev)
 324{
 325        struct ma901radio_device *radio = to_ma901radio_dev(v4l2_dev);
 326
 327        v4l2_ctrl_handler_free(&radio->hdl);
 328        v4l2_device_unregister(&radio->v4l2_dev);
 329        kfree(radio->buffer);
 330        kfree(radio);
 331}
 332
 333/* check if the device is present and register with v4l and usb if it is */
 334static int usb_ma901radio_probe(struct usb_interface *intf,
 335                                const struct usb_device_id *id)
 336{
 337        struct usb_device *dev = interface_to_usbdev(intf);
 338        struct ma901radio_device *radio;
 339        int retval = 0;
 340
 341        /* Masterkit MA901 usb radio has the same USB ID as many others
 342         * Atmel V-USB devices. Let's make additional checks to be sure
 343         * that this is our device.
 344         */
 345
 346        if (dev->product && dev->manufacturer &&
 347                (strncmp(dev->product, "MA901", 5) != 0
 348                || strncmp(dev->manufacturer, "www.masterkit.ru", 16) != 0))
 349                return -ENODEV;
 350
 351        radio = kzalloc(sizeof(struct ma901radio_device), GFP_KERNEL);
 352        if (!radio) {
 353                dev_err(&intf->dev, "kzalloc for ma901radio_device failed\n");
 354                retval = -ENOMEM;
 355                goto err;
 356        }
 357
 358        radio->buffer = kmalloc(BUFFER_LENGTH, GFP_KERNEL);
 359        if (!radio->buffer) {
 360                dev_err(&intf->dev, "kmalloc for radio->buffer failed\n");
 361                retval = -ENOMEM;
 362                goto err_nobuf;
 363        }
 364
 365        retval = v4l2_device_register(&intf->dev, &radio->v4l2_dev);
 366        if (retval < 0) {
 367                dev_err(&intf->dev, "couldn't register v4l2_device\n");
 368                goto err_v4l2;
 369        }
 370
 371        v4l2_ctrl_handler_init(&radio->hdl, 1);
 372
 373        /* TODO:It looks like this radio doesn't have mute/unmute control
 374         * and windows program just emulate it using volume control.
 375         * Let's plan to do the same in this driver.
 376         *
 377         * v4l2_ctrl_new_std(&radio->hdl, &usb_ma901radio_ctrl_ops,
 378         *                V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
 379         */
 380
 381        v4l2_ctrl_new_std(&radio->hdl, &usb_ma901radio_ctrl_ops,
 382                          V4L2_CID_AUDIO_VOLUME, MA901_VOLUME_MIN,
 383                          MA901_VOLUME_MAX, 1, MA901_VOLUME_MAX);
 384
 385        if (radio->hdl.error) {
 386                retval = radio->hdl.error;
 387                dev_err(&intf->dev, "couldn't register control\n");
 388                goto err_ctrl;
 389        }
 390        mutex_init(&radio->lock);
 391
 392        radio->v4l2_dev.ctrl_handler = &radio->hdl;
 393        radio->v4l2_dev.release = usb_ma901radio_release;
 394        strscpy(radio->vdev.name, radio->v4l2_dev.name,
 395                sizeof(radio->vdev.name));
 396        radio->vdev.v4l2_dev = &radio->v4l2_dev;
 397        radio->vdev.fops = &usb_ma901radio_fops;
 398        radio->vdev.ioctl_ops = &usb_ma901radio_ioctl_ops;
 399        radio->vdev.release = video_device_release_empty;
 400        radio->vdev.lock = &radio->lock;
 401
 402        radio->usbdev = interface_to_usbdev(intf);
 403        radio->intf = intf;
 404        usb_set_intfdata(intf, &radio->v4l2_dev);
 405        radio->curfreq = 95.21 * FREQ_MUL;
 406
 407        video_set_drvdata(&radio->vdev, radio);
 408
 409        /* TODO: we can get some statistics (freq, volume) from device
 410         * but it's not implemented yet. After insertion in usb-port radio
 411         * setups frequency and starts playing without any initialization.
 412         * So we don't call usb_ma901radio_init/get_stat() here.
 413         * retval = usb_ma901radio_init(radio);
 414         */
 415
 416        retval = video_register_device(&radio->vdev, VFL_TYPE_RADIO,
 417                                        radio_nr);
 418        if (retval < 0) {
 419                dev_err(&intf->dev, "could not register video device\n");
 420                goto err_vdev;
 421        }
 422
 423        return 0;
 424
 425err_vdev:
 426        v4l2_ctrl_handler_free(&radio->hdl);
 427err_ctrl:
 428        v4l2_device_unregister(&radio->v4l2_dev);
 429err_v4l2:
 430        kfree(radio->buffer);
 431err_nobuf:
 432        kfree(radio);
 433err:
 434        return retval;
 435}
 436
 437/* USB Device ID List */
 438static const struct usb_device_id usb_ma901radio_device_table[] = {
 439        { USB_DEVICE_AND_INTERFACE_INFO(USB_MA901_VENDOR, USB_MA901_PRODUCT,
 440                                                        USB_CLASS_HID, 0, 0) },
 441        { }                                             /* Terminating entry */
 442};
 443
 444MODULE_DEVICE_TABLE(usb, usb_ma901radio_device_table);
 445
 446/* USB subsystem interface */
 447static struct usb_driver usb_ma901radio_driver = {
 448        .name                   = MA901_DRIVER_NAME,
 449        .probe                  = usb_ma901radio_probe,
 450        .disconnect             = usb_ma901radio_disconnect,
 451        .suspend                = usb_ma901radio_suspend,
 452        .resume                 = usb_ma901radio_resume,
 453        .reset_resume           = usb_ma901radio_resume,
 454        .id_table               = usb_ma901radio_device_table,
 455};
 456
 457module_usb_driver(usb_ma901radio_driver);
 458