Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Driver for the MasterKit MA901 USB FM radio. This device plugs
0004  * into the USB port and an analog audio input or headphones, so this thing
0005  * only deals with initialization, frequency setting, volume.
0006  *
0007  * Copyright (c) 2012 Alexey Klimov <klimov.linux@gmail.com>
0008  */
0009 
0010 #include <linux/kernel.h>
0011 #include <linux/module.h>
0012 #include <linux/init.h>
0013 #include <linux/slab.h>
0014 #include <linux/input.h>
0015 #include <linux/videodev2.h>
0016 #include <media/v4l2-device.h>
0017 #include <media/v4l2-ioctl.h>
0018 #include <media/v4l2-ctrls.h>
0019 #include <media/v4l2-event.h>
0020 #include <linux/usb.h>
0021 #include <linux/mutex.h>
0022 
0023 #define DRIVER_AUTHOR "Alexey Klimov <klimov.linux@gmail.com>"
0024 #define DRIVER_DESC "Masterkit MA901 USB FM radio driver"
0025 #define DRIVER_VERSION "0.0.1"
0026 
0027 MODULE_AUTHOR(DRIVER_AUTHOR);
0028 MODULE_DESCRIPTION(DRIVER_DESC);
0029 MODULE_LICENSE("GPL");
0030 MODULE_VERSION(DRIVER_VERSION);
0031 
0032 #define USB_MA901_VENDOR  0x16c0
0033 #define USB_MA901_PRODUCT 0x05df
0034 
0035 /* dev_warn macro with driver name */
0036 #define MA901_DRIVER_NAME "radio-ma901"
0037 #define ma901radio_dev_warn(dev, fmt, arg...)               \
0038         dev_warn(dev, MA901_DRIVER_NAME " - " fmt, ##arg)
0039 
0040 #define ma901radio_dev_err(dev, fmt, arg...) \
0041         dev_err(dev, MA901_DRIVER_NAME " - " fmt, ##arg)
0042 
0043 /* Probably USB_TIMEOUT should be modified in module parameter */
0044 #define BUFFER_LENGTH 8
0045 #define USB_TIMEOUT 500
0046 
0047 #define FREQ_MIN  87.5
0048 #define FREQ_MAX 108.0
0049 #define FREQ_MUL 16000
0050 
0051 #define MA901_VOLUME_MAX 16
0052 #define MA901_VOLUME_MIN 0
0053 
0054 /* Commands that device should understand
0055  * List isn't full and will be updated with implementation of new functions
0056  */
0057 #define MA901_RADIO_SET_FREQ        0x03
0058 #define MA901_RADIO_SET_VOLUME      0x04
0059 #define MA901_RADIO_SET_MONO_STEREO 0x05
0060 
0061 /* Comfortable defines for ma901radio_set_stereo */
0062 #define MA901_WANT_STEREO       0x50
0063 #define MA901_WANT_MONO         0xd0
0064 
0065 /* module parameter */
0066 static int radio_nr = -1;
0067 module_param(radio_nr, int, 0);
0068 MODULE_PARM_DESC(radio_nr, "Radio file number");
0069 
0070 /* Data for one (physical) device */
0071 struct ma901radio_device {
0072     /* reference to USB and video device */
0073     struct usb_device *usbdev;
0074     struct usb_interface *intf;
0075     struct video_device vdev;
0076     struct v4l2_device v4l2_dev;
0077     struct v4l2_ctrl_handler hdl;
0078 
0079     u8 *buffer;
0080     struct mutex lock;  /* buffer locking */
0081     int curfreq;
0082     u16 volume;
0083     int stereo;
0084     bool muted;
0085 };
0086 
0087 static inline struct ma901radio_device *to_ma901radio_dev(struct v4l2_device *v4l2_dev)
0088 {
0089     return container_of(v4l2_dev, struct ma901radio_device, v4l2_dev);
0090 }
0091 
0092 /* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */
0093 static int ma901radio_set_freq(struct ma901radio_device *radio, int freq)
0094 {
0095     unsigned int freq_send = 0x300 + (freq >> 5) / 25;
0096     int retval;
0097 
0098     radio->buffer[0] = 0x0a;
0099     radio->buffer[1] = MA901_RADIO_SET_FREQ;
0100     radio->buffer[2] = ((freq_send >> 8) & 0xff) + 0x80;
0101     radio->buffer[3] = freq_send & 0xff;
0102     radio->buffer[4] = 0x00;
0103     radio->buffer[5] = 0x00;
0104     radio->buffer[6] = 0x00;
0105     radio->buffer[7] = 0x00;
0106 
0107     retval = usb_control_msg(radio->usbdev, usb_sndctrlpipe(radio->usbdev, 0),
0108                 9, 0x21, 0x0300, 0,
0109                 radio->buffer, BUFFER_LENGTH, USB_TIMEOUT);
0110     if (retval < 0)
0111         return retval;
0112 
0113     radio->curfreq = freq;
0114     return 0;
0115 }
0116 
0117 static int ma901radio_set_volume(struct ma901radio_device *radio, u16 vol_to_set)
0118 {
0119     int retval;
0120 
0121     radio->buffer[0] = 0x0a;
0122     radio->buffer[1] = MA901_RADIO_SET_VOLUME;
0123     radio->buffer[2] = 0xc2;
0124     radio->buffer[3] = vol_to_set + 0x20;
0125     radio->buffer[4] = 0x00;
0126     radio->buffer[5] = 0x00;
0127     radio->buffer[6] = 0x00;
0128     radio->buffer[7] = 0x00;
0129 
0130     retval = usb_control_msg(radio->usbdev, usb_sndctrlpipe(radio->usbdev, 0),
0131                 9, 0x21, 0x0300, 0,
0132                 radio->buffer, BUFFER_LENGTH, USB_TIMEOUT);
0133     if (retval < 0)
0134         return retval;
0135 
0136     radio->volume = vol_to_set;
0137     return retval;
0138 }
0139 
0140 static int ma901_set_stereo(struct ma901radio_device *radio, u8 stereo)
0141 {
0142     int retval;
0143 
0144     radio->buffer[0] = 0x0a;
0145     radio->buffer[1] = MA901_RADIO_SET_MONO_STEREO;
0146     radio->buffer[2] = stereo;
0147     radio->buffer[3] = 0x00;
0148     radio->buffer[4] = 0x00;
0149     radio->buffer[5] = 0x00;
0150     radio->buffer[6] = 0x00;
0151     radio->buffer[7] = 0x00;
0152 
0153     retval = usb_control_msg(radio->usbdev, usb_sndctrlpipe(radio->usbdev, 0),
0154                 9, 0x21, 0x0300, 0,
0155                 radio->buffer, BUFFER_LENGTH, USB_TIMEOUT);
0156 
0157     if (retval < 0)
0158         return retval;
0159 
0160     if (stereo == MA901_WANT_STEREO)
0161         radio->stereo = V4L2_TUNER_MODE_STEREO;
0162     else
0163         radio->stereo = V4L2_TUNER_MODE_MONO;
0164 
0165     return retval;
0166 }
0167 
0168 /* Handle unplugging the device.
0169  * We call video_unregister_device in any case.
0170  * The last function called in this procedure is
0171  * usb_ma901radio_device_release.
0172  */
0173 static void usb_ma901radio_disconnect(struct usb_interface *intf)
0174 {
0175     struct ma901radio_device *radio = to_ma901radio_dev(usb_get_intfdata(intf));
0176 
0177     mutex_lock(&radio->lock);
0178     video_unregister_device(&radio->vdev);
0179     usb_set_intfdata(intf, NULL);
0180     v4l2_device_disconnect(&radio->v4l2_dev);
0181     mutex_unlock(&radio->lock);
0182     v4l2_device_put(&radio->v4l2_dev);
0183 }
0184 
0185 /* vidioc_querycap - query device capabilities */
0186 static int vidioc_querycap(struct file *file, void *priv,
0187                     struct v4l2_capability *v)
0188 {
0189     struct ma901radio_device *radio = video_drvdata(file);
0190 
0191     strscpy(v->driver, "radio-ma901", sizeof(v->driver));
0192     strscpy(v->card, "Masterkit MA901 USB FM Radio", sizeof(v->card));
0193     usb_make_path(radio->usbdev, v->bus_info, sizeof(v->bus_info));
0194     return 0;
0195 }
0196 
0197 /* vidioc_g_tuner - get tuner attributes */
0198 static int vidioc_g_tuner(struct file *file, void *priv,
0199                 struct v4l2_tuner *v)
0200 {
0201     struct ma901radio_device *radio = video_drvdata(file);
0202 
0203     if (v->index > 0)
0204         return -EINVAL;
0205 
0206     v->signal = 0;
0207 
0208     /* TODO: the same words like in _probe() goes here.
0209      * When receiving of stats will be implemented then we can call
0210      * ma901radio_get_stat().
0211      * retval = ma901radio_get_stat(radio, &is_stereo, &v->signal);
0212      */
0213 
0214     strscpy(v->name, "FM", sizeof(v->name));
0215     v->type = V4L2_TUNER_RADIO;
0216     v->rangelow = FREQ_MIN * FREQ_MUL;
0217     v->rangehigh = FREQ_MAX * FREQ_MUL;
0218     v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
0219     /* v->rxsubchans = is_stereo ? V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO; */
0220     v->audmode = radio->stereo ?
0221         V4L2_TUNER_MODE_STEREO : V4L2_TUNER_MODE_MONO;
0222     return 0;
0223 }
0224 
0225 /* vidioc_s_tuner - set tuner attributes */
0226 static int vidioc_s_tuner(struct file *file, void *priv,
0227                 const struct v4l2_tuner *v)
0228 {
0229     struct ma901radio_device *radio = video_drvdata(file);
0230 
0231     if (v->index > 0)
0232         return -EINVAL;
0233 
0234     /* mono/stereo selector */
0235     switch (v->audmode) {
0236     case V4L2_TUNER_MODE_MONO:
0237         return ma901_set_stereo(radio, MA901_WANT_MONO);
0238     default:
0239         return ma901_set_stereo(radio, MA901_WANT_STEREO);
0240     }
0241 }
0242 
0243 /* vidioc_s_frequency - set tuner radio frequency */
0244 static int vidioc_s_frequency(struct file *file, void *priv,
0245                 const struct v4l2_frequency *f)
0246 {
0247     struct ma901radio_device *radio = video_drvdata(file);
0248 
0249     if (f->tuner != 0)
0250         return -EINVAL;
0251 
0252     return ma901radio_set_freq(radio, clamp_t(unsigned, f->frequency,
0253                 FREQ_MIN * FREQ_MUL, FREQ_MAX * FREQ_MUL));
0254 }
0255 
0256 /* vidioc_g_frequency - get tuner radio frequency */
0257 static int vidioc_g_frequency(struct file *file, void *priv,
0258                 struct v4l2_frequency *f)
0259 {
0260     struct ma901radio_device *radio = video_drvdata(file);
0261 
0262     if (f->tuner != 0)
0263         return -EINVAL;
0264     f->frequency = radio->curfreq;
0265 
0266     return 0;
0267 }
0268 
0269 static int usb_ma901radio_s_ctrl(struct v4l2_ctrl *ctrl)
0270 {
0271     struct ma901radio_device *radio =
0272         container_of(ctrl->handler, struct ma901radio_device, hdl);
0273 
0274     switch (ctrl->id) {
0275     case V4L2_CID_AUDIO_VOLUME:     /* set volume */
0276         return ma901radio_set_volume(radio, (u16)ctrl->val);
0277     }
0278 
0279     return -EINVAL;
0280 }
0281 
0282 /* TODO: Should we really need to implement suspend and resume functions?
0283  * Radio has it's own memory and will continue playing if power is present
0284  * on usb port and on resume it will start to play again based on freq, volume
0285  * values in device memory.
0286  */
0287 static int usb_ma901radio_suspend(struct usb_interface *intf, pm_message_t message)
0288 {
0289     return 0;
0290 }
0291 
0292 static int usb_ma901radio_resume(struct usb_interface *intf)
0293 {
0294     return 0;
0295 }
0296 
0297 static const struct v4l2_ctrl_ops usb_ma901radio_ctrl_ops = {
0298     .s_ctrl = usb_ma901radio_s_ctrl,
0299 };
0300 
0301 /* File system interface */
0302 static const struct v4l2_file_operations usb_ma901radio_fops = {
0303     .owner      = THIS_MODULE,
0304     .open       = v4l2_fh_open,
0305     .release    = v4l2_fh_release,
0306     .poll       = v4l2_ctrl_poll,
0307     .unlocked_ioctl = video_ioctl2,
0308 };
0309 
0310 static const struct v4l2_ioctl_ops usb_ma901radio_ioctl_ops = {
0311     .vidioc_querycap    = vidioc_querycap,
0312     .vidioc_g_tuner     = vidioc_g_tuner,
0313     .vidioc_s_tuner     = vidioc_s_tuner,
0314     .vidioc_g_frequency = vidioc_g_frequency,
0315     .vidioc_s_frequency = vidioc_s_frequency,
0316     .vidioc_log_status  = v4l2_ctrl_log_status,
0317     .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
0318     .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
0319 };
0320 
0321 static void usb_ma901radio_release(struct v4l2_device *v4l2_dev)
0322 {
0323     struct ma901radio_device *radio = to_ma901radio_dev(v4l2_dev);
0324 
0325     v4l2_ctrl_handler_free(&radio->hdl);
0326     v4l2_device_unregister(&radio->v4l2_dev);
0327     kfree(radio->buffer);
0328     kfree(radio);
0329 }
0330 
0331 /* check if the device is present and register with v4l and usb if it is */
0332 static int usb_ma901radio_probe(struct usb_interface *intf,
0333                 const struct usb_device_id *id)
0334 {
0335     struct usb_device *dev = interface_to_usbdev(intf);
0336     struct ma901radio_device *radio;
0337     int retval = 0;
0338 
0339     /* Masterkit MA901 usb radio has the same USB ID as many others
0340      * Atmel V-USB devices. Let's make additional checks to be sure
0341      * that this is our device.
0342      */
0343 
0344     if (dev->product && dev->manufacturer &&
0345         (strncmp(dev->product, "MA901", 5) != 0
0346         || strncmp(dev->manufacturer, "www.masterkit.ru", 16) != 0))
0347         return -ENODEV;
0348 
0349     radio = kzalloc(sizeof(struct ma901radio_device), GFP_KERNEL);
0350     if (!radio) {
0351         dev_err(&intf->dev, "kzalloc for ma901radio_device failed\n");
0352         retval = -ENOMEM;
0353         goto err;
0354     }
0355 
0356     radio->buffer = kmalloc(BUFFER_LENGTH, GFP_KERNEL);
0357     if (!radio->buffer) {
0358         dev_err(&intf->dev, "kmalloc for radio->buffer failed\n");
0359         retval = -ENOMEM;
0360         goto err_nobuf;
0361     }
0362 
0363     retval = v4l2_device_register(&intf->dev, &radio->v4l2_dev);
0364     if (retval < 0) {
0365         dev_err(&intf->dev, "couldn't register v4l2_device\n");
0366         goto err_v4l2;
0367     }
0368 
0369     v4l2_ctrl_handler_init(&radio->hdl, 1);
0370 
0371     /* TODO:It looks like this radio doesn't have mute/unmute control
0372      * and windows program just emulate it using volume control.
0373      * Let's plan to do the same in this driver.
0374      *
0375      * v4l2_ctrl_new_std(&radio->hdl, &usb_ma901radio_ctrl_ops,
0376      *        V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
0377      */
0378 
0379     v4l2_ctrl_new_std(&radio->hdl, &usb_ma901radio_ctrl_ops,
0380               V4L2_CID_AUDIO_VOLUME, MA901_VOLUME_MIN,
0381               MA901_VOLUME_MAX, 1, MA901_VOLUME_MAX);
0382 
0383     if (radio->hdl.error) {
0384         retval = radio->hdl.error;
0385         dev_err(&intf->dev, "couldn't register control\n");
0386         goto err_ctrl;
0387     }
0388     mutex_init(&radio->lock);
0389 
0390     radio->v4l2_dev.ctrl_handler = &radio->hdl;
0391     radio->v4l2_dev.release = usb_ma901radio_release;
0392     strscpy(radio->vdev.name, radio->v4l2_dev.name,
0393         sizeof(radio->vdev.name));
0394     radio->vdev.v4l2_dev = &radio->v4l2_dev;
0395     radio->vdev.fops = &usb_ma901radio_fops;
0396     radio->vdev.ioctl_ops = &usb_ma901radio_ioctl_ops;
0397     radio->vdev.release = video_device_release_empty;
0398     radio->vdev.lock = &radio->lock;
0399     radio->vdev.device_caps = V4L2_CAP_RADIO | V4L2_CAP_TUNER;
0400 
0401     radio->usbdev = interface_to_usbdev(intf);
0402     radio->intf = intf;
0403     usb_set_intfdata(intf, &radio->v4l2_dev);
0404     radio->curfreq = 95.21 * FREQ_MUL;
0405 
0406     video_set_drvdata(&radio->vdev, radio);
0407 
0408     /* TODO: we can get some statistics (freq, volume) from device
0409      * but it's not implemented yet. After insertion in usb-port radio
0410      * setups frequency and starts playing without any initialization.
0411      * So we don't call usb_ma901radio_init/get_stat() here.
0412      * retval = usb_ma901radio_init(radio);
0413      */
0414 
0415     retval = video_register_device(&radio->vdev, VFL_TYPE_RADIO,
0416                     radio_nr);
0417     if (retval < 0) {
0418         dev_err(&intf->dev, "could not register video device\n");
0419         goto err_vdev;
0420     }
0421 
0422     return 0;
0423 
0424 err_vdev:
0425     v4l2_ctrl_handler_free(&radio->hdl);
0426 err_ctrl:
0427     v4l2_device_unregister(&radio->v4l2_dev);
0428 err_v4l2:
0429     kfree(radio->buffer);
0430 err_nobuf:
0431     kfree(radio);
0432 err:
0433     return retval;
0434 }
0435 
0436 /* USB Device ID List */
0437 static const struct usb_device_id usb_ma901radio_device_table[] = {
0438     { USB_DEVICE_AND_INTERFACE_INFO(USB_MA901_VENDOR, USB_MA901_PRODUCT,
0439                             USB_CLASS_HID, 0, 0) },
0440     { }                     /* Terminating entry */
0441 };
0442 
0443 MODULE_DEVICE_TABLE(usb, usb_ma901radio_device_table);
0444 
0445 /* USB subsystem interface */
0446 static struct usb_driver usb_ma901radio_driver = {
0447     .name           = MA901_DRIVER_NAME,
0448     .probe          = usb_ma901radio_probe,
0449     .disconnect     = usb_ma901radio_disconnect,
0450     .suspend        = usb_ma901radio_suspend,
0451     .resume         = usb_ma901radio_resume,
0452     .reset_resume       = usb_ma901radio_resume,
0453     .id_table       = usb_ma901radio_device_table,
0454 };
0455 
0456 module_usb_driver(usb_ma901radio_driver);