* [RFC PATCH 0/3] New driver for the Keene USB FM Transmitter @ 2012-01-16 12:29 Hans Verkuil 2012-01-16 12:29 ` [RFC PATCH 1/3] v4l2-ctrls: fix ugly control name Hans Verkuil 0 siblings, 1 reply; 13+ messages in thread From: Hans Verkuil @ 2012-01-16 12:29 UTC (permalink / raw) To: linux-media; +Cc: linux-input, Jiri Kosina Hi all, Here is a V4L2 driver for the Keene USB FM Transmitter: http://www.amazon.co.uk/Keene-Electronics-USB-FM-Transmitter/dp/B003GCHPDY It's been very useful to test V4L2 FM radio receivers. Note that the Keene FM transmitter USB device has the same USB ID as the Logitech AudioHub Speaker. Since the radio-keene driver needs to hijack the HID something needed to be done to differentiate the two. So hid-core was modified to decide this based on the product name. I have tested that this works with both a Keene device and a Logitech AudioHub device hooked up at the same time. Jiri, can you look at the last patch and let me know if it is OK from a HID point of view? Regards, Hans ^ permalink raw reply [flat|nested] 13+ messages in thread
* [RFC PATCH 1/3] v4l2-ctrls: fix ugly control name. 2012-01-16 12:29 [RFC PATCH 0/3] New driver for the Keene USB FM Transmitter Hans Verkuil @ 2012-01-16 12:29 ` Hans Verkuil 2012-01-16 12:29 ` [RFC PATCH 2/3] radio-keene: add a driver for the Keene FM Transmitter Hans Verkuil ` (2 more replies) 0 siblings, 3 replies; 13+ messages in thread From: Hans Verkuil @ 2012-01-16 12:29 UTC (permalink / raw) To: linux-media; +Cc: linux-input, Jiri Kosina, Hans Verkuil From: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> --- drivers/media/video/v4l2-ctrls.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c index da1f4c2..35316f9 100644 --- a/drivers/media/video/v4l2-ctrls.c +++ b/drivers/media/video/v4l2-ctrls.c @@ -588,7 +588,7 @@ const char *v4l2_ctrl_get_name(u32 id) case V4L2_CID_PILOT_TONE_ENABLED: return "Pilot Tone Feature Enabled"; case V4L2_CID_PILOT_TONE_DEVIATION: return "Pilot Tone Deviation"; case V4L2_CID_PILOT_TONE_FREQUENCY: return "Pilot Tone Frequency"; - case V4L2_CID_TUNE_PREEMPHASIS: return "Pre-emphasis settings"; + case V4L2_CID_TUNE_PREEMPHASIS: return "Pre-Emphasis"; case V4L2_CID_TUNE_POWER_LEVEL: return "Tune Power Level"; case V4L2_CID_TUNE_ANTENNA_CAPACITOR: return "Tune Antenna Capacitor"; -- 1.7.7.3 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* [RFC PATCH 2/3] radio-keene: add a driver for the Keene FM Transmitter. 2012-01-16 12:29 ` [RFC PATCH 1/3] v4l2-ctrls: fix ugly control name Hans Verkuil @ 2012-01-16 12:29 ` Hans Verkuil 2012-01-16 12:44 ` Oliver Neukum 2012-01-16 12:46 ` Oliver Neukum 2012-01-16 12:29 ` [RFC PATCH 3/3] hid-core: ignore the Keene FM transmitter Hans Verkuil 2012-01-16 13:00 ` [RFC PATCH 1/3] v4l2-ctrls: fix ugly control name Oliver Neukum 2 siblings, 2 replies; 13+ messages in thread From: Hans Verkuil @ 2012-01-16 12:29 UTC (permalink / raw) To: linux-media; +Cc: linux-input, Jiri Kosina, Hans Verkuil From: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> --- drivers/media/radio/Kconfig | 10 + drivers/media/radio/Makefile | 1 + drivers/media/radio/radio-keene.c | 419 +++++++++++++++++++++++++++++++++++++ 3 files changed, 430 insertions(+), 0 deletions(-) create mode 100644 drivers/media/radio/radio-keene.c diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig index e954781..48747df 100644 --- a/drivers/media/radio/Kconfig +++ b/drivers/media/radio/Kconfig @@ -80,6 +80,16 @@ config RADIO_SI4713 To compile this driver as a module, choose M here: the module will be called radio-si4713. +config USB_KEENE + tristate "Keene FM Transmitter USB support" + depends on USB && VIDEO_V4L2 + ---help--- + Say Y here if you want to connect this type of FM transmitter + to your computer's USB port. + + To compile this driver as a module, choose M here: the + module will be called radio-keene. + config RADIO_TEA5764 tristate "TEA5764 I2C FM radio support" depends on I2C && VIDEO_V4L2 diff --git a/drivers/media/radio/Makefile b/drivers/media/radio/Makefile index 390daf9..aec5f6f 100644 --- a/drivers/media/radio/Makefile +++ b/drivers/media/radio/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_RADIO_MIROPCM20) += radio-miropcm20.o obj-$(CONFIG_USB_DSBR) += dsbr100.o obj-$(CONFIG_RADIO_SI470X) += si470x/ obj-$(CONFIG_USB_MR800) += radio-mr800.o +obj-$(CONFIG_USB_KEENE) += radio-keene.o obj-$(CONFIG_RADIO_TEA5764) += radio-tea5764.o obj-$(CONFIG_RADIO_SAA7706H) += saa7706h.o obj-$(CONFIG_RADIO_TEF6862) += tef6862.o diff --git a/drivers/media/radio/radio-keene.c b/drivers/media/radio/radio-keene.c new file mode 100644 index 0000000..1647a7f --- /dev/null +++ b/drivers/media/radio/radio-keene.c @@ -0,0 +1,419 @@ +/* + * Copyright (c) 2012 Hans Verkuil <hverkuil@xs4all.nl> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* kernel includes */ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/input.h> +#include <linux/videodev2.h> +#include <media/v4l2-device.h> +#include <media/v4l2-ioctl.h> +#include <media/v4l2-ctrls.h> +#include <media/v4l2-event.h> +#include <linux/usb.h> +#include <linux/version.h> +#include <linux/mutex.h> + +/* driver and module definitions */ +MODULE_AUTHOR("Hans Verkuil <hverkuil@xs4all.nl>"); +MODULE_DESCRIPTION("Keene FM Transmitter driver"); +MODULE_LICENSE("GPL"); + +/* Actually, it advertises itself as a Logitech */ +#define USB_KEENE_VENDOR 0x046d +#define USB_KEENE_PRODUCT 0x0a0e + +/* Probably USB_TIMEOUT should be modified in module parameter */ +#define BUFFER_LENGTH 8 +#define USB_TIMEOUT 500 + +/* Frequency limits in MHz */ +#define FREQ_MIN 76U +#define FREQ_MAX 108U +#define FREQ_MUL 16000U + +/* USB Device ID List */ +static struct usb_device_id usb_keene_device_table[] = { + {USB_DEVICE_AND_INTERFACE_INFO(USB_KEENE_VENDOR, USB_KEENE_PRODUCT, + USB_CLASS_HID, 0, 0) }, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE(usb, usb_keene_device_table); + +struct keene_device { + struct usb_device *usbdev; + struct usb_interface *intf; + struct video_device vdev; + struct v4l2_device v4l2_dev; + struct v4l2_ctrl_handler hdl; + struct mutex lock; + + u8 buffer[BUFFER_LENGTH]; + unsigned curfreq; + u8 tx; + u8 pa; + bool stereo; + bool muted; + bool preemph_75_us; +}; + +static inline struct keene_device *to_keene_dev(struct v4l2_device *v4l2_dev) +{ + return container_of(v4l2_dev, struct keene_device, v4l2_dev); +} + +/* Set frequency (if non-0), PA, mute and turn on/off the FM transmitter. */ +static int keene_cmd_main(struct keene_device *radio, unsigned freq, bool play) +{ + unsigned short freq_send = freq ? (freq - 76 * 16000) / 800 : 0; + int ret; + + radio->buffer[0] = 0x00; + radio->buffer[1] = 0x50; + radio->buffer[2] = (freq_send >> 8) & 0xff; + radio->buffer[3] = freq_send & 0xff; + radio->buffer[4] = radio->pa; + /* If bit 4 is set, then tune to the frequency. + If bit 3 is set, then unmute; if bit 2 is set, then mute. + If bit 1 is set, then enter idle mode; if bit 0 is set, + then enter transit mode. + */ + radio->buffer[5] = (radio->muted ? 4 : 8) | (play ? 1 : 2) | + (freq ? 0x10 : 0); + radio->buffer[6] = 0x00; + radio->buffer[7] = 0x00; + + ret = usb_control_msg(radio->usbdev, usb_sndctrlpipe(radio->usbdev, 0), + 9, 0x21, 0x200, 2, radio->buffer, BUFFER_LENGTH, USB_TIMEOUT); + + if (ret < 0) { + dev_warn(&radio->vdev.dev, "%s failed (%d)\n", __func__, ret); + return ret; + } + if (freq) + radio->curfreq = freq; + return 0; +} + +/* Set TX, stereo and preemphasis mode (50 us vs 75 us). */ +static int keene_cmd_set(struct keene_device *radio) +{ + int ret; + + radio->buffer[0] = 0x00; + radio->buffer[1] = 0x51; + radio->buffer[2] = radio->tx; + /* If bit 0 is set, then transmit mono, otherwise stereo. + If bit 2 is set, then enable 75 us preemphasis, otherwise + it is 50 us. */ + radio->buffer[3] = (!radio->stereo) | (radio->preemph_75_us ? 4 : 0); + radio->buffer[4] = 0x00; + radio->buffer[5] = 0x00; + radio->buffer[6] = 0x00; + radio->buffer[7] = 0x00; + + ret = usb_control_msg(radio->usbdev, usb_sndctrlpipe(radio->usbdev, 0), + 9, 0x21, 0x200, 2, radio->buffer, BUFFER_LENGTH, USB_TIMEOUT); + + if (ret < 0) { + dev_warn(&radio->vdev.dev, "%s failed (%d)\n", __func__, ret); + return ret; + } + return 0; +} + +/* Handle unplugging the device. + * We call video_unregister_device in any case. + * The last function called in this procedure is + * usb_keene_device_release. + */ +static void usb_keene_disconnect(struct usb_interface *intf) +{ + struct keene_device *radio = to_keene_dev(usb_get_intfdata(intf)); + + v4l2_device_get(&radio->v4l2_dev); + mutex_lock(&radio->lock); + usb_set_intfdata(intf, NULL); + video_unregister_device(&radio->vdev); + v4l2_device_disconnect(&radio->v4l2_dev); + mutex_unlock(&radio->lock); + v4l2_device_put(&radio->v4l2_dev); +} + +static int vidioc_querycap(struct file *file, void *priv, + struct v4l2_capability *v) +{ + struct keene_device *radio = video_drvdata(file); + + strlcpy(v->driver, "radio-keene", sizeof(v->driver)); + strlcpy(v->card, "Keene FM Transmitter", sizeof(v->card)); + usb_make_path(radio->usbdev, v->bus_info, sizeof(v->bus_info)); + v->capabilities = V4L2_CAP_RADIO | V4L2_CAP_MODULATOR; + return 0; +} + +static int vidioc_g_modulator(struct file *file, void *priv, + struct v4l2_modulator *v) +{ + struct keene_device *radio = video_drvdata(file); + + if (v->index > 0) + return -EINVAL; + + strlcpy(v->name, "FM", sizeof(v->name)); + v->rangelow = FREQ_MIN * FREQ_MUL; + v->rangehigh = FREQ_MAX * FREQ_MUL; + v->txsubchans = radio->stereo ? V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO; + v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; + return 0; +} + +static int vidioc_s_modulator(struct file *file, void *priv, + struct v4l2_modulator *v) +{ + struct keene_device *radio = video_drvdata(file); + + if (v->index > 0) + return -EINVAL; + + radio->stereo = (v->txsubchans == V4L2_TUNER_SUB_STEREO); + return keene_cmd_set(radio); +} + +static int vidioc_s_frequency(struct file *file, void *priv, + struct v4l2_frequency *f) +{ + struct keene_device *radio = video_drvdata(file); + + if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) + return -EINVAL; + f->frequency = clamp(f->frequency, + FREQ_MIN * FREQ_MUL, FREQ_MAX * FREQ_MUL); + return keene_cmd_main(radio, f->frequency, true); +} + +static int vidioc_g_frequency(struct file *file, void *priv, + struct v4l2_frequency *f) +{ + struct keene_device *radio = video_drvdata(file); + + if (f->tuner != 0) + return -EINVAL; + f->type = V4L2_TUNER_RADIO; + f->frequency = radio->curfreq; + return 0; +} + +static int keene_s_ctrl(struct v4l2_ctrl *ctrl) +{ + static const u8 db2tx[] = { + /* -15, -12, -9, -6, -3, 0 dB */ + 0x03, 0x13, 0x02, 0x12, 0x22, 0x32, + /* 3, 6, 9, 12, 15, 18 dB */ + 0x21, 0x31, 0x20, 0x30, 0x40, 0x50 + }; + struct keene_device *radio = + container_of(ctrl->handler, struct keene_device, hdl); + + switch (ctrl->id) { + case V4L2_CID_AUDIO_MUTE: + radio->muted = ctrl->val; + return keene_cmd_main(radio, 0, true); + + case V4L2_CID_TUNE_POWER_LEVEL: + /* To go from dBuV to the register value we apply the + following formula: */ + radio->pa = (ctrl->val - 71) * 100 / 62; + return keene_cmd_main(radio, 0, true); + + case V4L2_CID_TUNE_PREEMPHASIS: + radio->preemph_75_us = ctrl->val == V4L2_PREEMPHASIS_75_uS; + return keene_cmd_set(radio); + + case V4L2_CID_AUDIO_COMPRESSION_GAIN: + radio->tx = db2tx[(ctrl->val - ctrl->minimum) / ctrl->step]; + return keene_cmd_set(radio); + } + return -EINVAL; +} + +static int vidioc_subscribe_event(struct v4l2_fh *fh, + struct v4l2_event_subscription *sub) +{ + switch (sub->type) { + case V4L2_EVENT_CTRL: + return v4l2_event_subscribe(fh, sub, 0); + default: + return -EINVAL; + } +} + +static unsigned int keene_poll(struct file *file, struct poll_table_struct *wait) +{ + struct v4l2_fh *fh = file->private_data; + unsigned int res = 0; + + if (v4l2_event_pending(fh)) + res |= POLLPRI; + else + poll_wait(file, &fh->wait, wait); + return res; +} + + +/* File system interface */ +static const struct v4l2_file_operations usb_keene_fops = { + .owner = THIS_MODULE, + .open = v4l2_fh_open, + .release = v4l2_fh_release, + .poll = keene_poll, + .unlocked_ioctl = video_ioctl2, +}; + +static const struct v4l2_ctrl_ops keene_ctrl_ops = { + .s_ctrl = keene_s_ctrl, +}; + +static const struct v4l2_ioctl_ops usb_keene_ioctl_ops = { + .vidioc_querycap = vidioc_querycap, + .vidioc_g_modulator = vidioc_g_modulator, + .vidioc_s_modulator = vidioc_s_modulator, + .vidioc_g_frequency = vidioc_g_frequency, + .vidioc_s_frequency = vidioc_s_frequency, + .vidioc_subscribe_event = vidioc_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, +}; + +static void usb_keene_video_device_release(struct v4l2_device *v4l2_dev) +{ + struct keene_device *radio = to_keene_dev(v4l2_dev); + + /* free rest memory */ + v4l2_ctrl_handler_free(&radio->hdl); + kfree(radio); +} + +/* check if the device is present and register with v4l and usb if it is */ +static int usb_keene_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct keene_device *radio; + struct v4l2_ctrl_handler *hdl; + int retval = 0; + + radio = kzalloc(sizeof(struct keene_device), GFP_KERNEL); + + if (!radio) { + dev_err(&intf->dev, "kmalloc for keene_device failed\n"); + retval = -ENOMEM; + goto err; + } + + hdl = &radio->hdl; + v4l2_ctrl_handler_init(hdl, 4); + v4l2_ctrl_new_std(hdl, &keene_ctrl_ops, V4L2_CID_AUDIO_MUTE, + 0, 1, 1, 0); + v4l2_ctrl_new_std_menu(hdl, &keene_ctrl_ops, V4L2_CID_TUNE_PREEMPHASIS, + V4L2_PREEMPHASIS_75_uS, 1, V4L2_PREEMPHASIS_50_uS); + v4l2_ctrl_new_std(hdl, &keene_ctrl_ops, V4L2_CID_TUNE_POWER_LEVEL, + 84, 118, 1, 118); + v4l2_ctrl_new_std(hdl, &keene_ctrl_ops, V4L2_CID_AUDIO_COMPRESSION_GAIN, + -15, 18, 3, 0); + radio->pa = 118; + radio->tx = 0x32; + radio->stereo = true; + radio->curfreq = 95.16 * FREQ_MUL; + if (hdl->error) { + retval = hdl->error; + + v4l2_ctrl_handler_free(hdl); + goto err_v4l2; + } + retval = v4l2_device_register(&intf->dev, &radio->v4l2_dev); + if (retval < 0) { + dev_err(&intf->dev, "couldn't register v4l2_device\n"); + goto err_v4l2; + } + + mutex_init(&radio->lock); + + radio->v4l2_dev.ctrl_handler = hdl; + radio->v4l2_dev.release = usb_keene_video_device_release; + strlcpy(radio->vdev.name, radio->v4l2_dev.name, + sizeof(radio->vdev.name)); + radio->vdev.v4l2_dev = &radio->v4l2_dev; + radio->vdev.fops = &usb_keene_fops; + radio->vdev.ioctl_ops = &usb_keene_ioctl_ops; + radio->vdev.lock = &radio->lock; + radio->vdev.release = video_device_release_empty; + + radio->usbdev = interface_to_usbdev(intf); + radio->intf = intf; + usb_set_intfdata(intf, &radio->v4l2_dev); + + video_set_drvdata(&radio->vdev, radio); + set_bit(V4L2_FL_USE_FH_PRIO, &radio->vdev.flags); + + retval = video_register_device(&radio->vdev, VFL_TYPE_RADIO, -1); + if (retval < 0) { + dev_err(&intf->dev, "could not register video device\n"); + goto err_vdev; + } + v4l2_ctrl_handler_setup(hdl); + dev_info(&intf->dev, "V4L2 device registered as %s\n", + video_device_node_name(&radio->vdev)); + return 0; + +err_vdev: + v4l2_device_unregister(&radio->v4l2_dev); +err_v4l2: + kfree(radio); +err: + return retval; +} + +/* USB subsystem interface */ +static struct usb_driver usb_keene_driver = { + .name = "radio-keene", + .probe = usb_keene_probe, + .disconnect = usb_keene_disconnect, + .id_table = usb_keene_device_table, +}; + +static int __init keene_init(void) +{ + int retval = usb_register(&usb_keene_driver); + + if (retval) + pr_err(KBUILD_MODNAME + ": usb_register failed. Error number %d\n", retval); + + return retval; +} + +static void __exit keene_exit(void) +{ + usb_deregister(&usb_keene_driver); +} + +module_init(keene_init); +module_exit(keene_exit); + -- 1.7.7.3 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [RFC PATCH 2/3] radio-keene: add a driver for the Keene FM Transmitter. 2012-01-16 12:29 ` [RFC PATCH 2/3] radio-keene: add a driver for the Keene FM Transmitter Hans Verkuil @ 2012-01-16 12:44 ` Oliver Neukum 2012-01-16 13:02 ` Hans Verkuil 2012-01-16 12:46 ` Oliver Neukum 1 sibling, 1 reply; 13+ messages in thread From: Oliver Neukum @ 2012-01-16 12:44 UTC (permalink / raw) To: Hans Verkuil; +Cc: linux-media, linux-input, Jiri Kosina, Hans Verkuil Am Montag, 16. Januar 2012, 13:29:19 schrieb Hans Verkuil: > From: Hans Verkuil <hans.verkuil@cisco.com> > +MODULE_DEVICE_TABLE(usb, usb_keene_device_table); > + > +struct keene_device { > + struct usb_device *usbdev; > + struct usb_interface *intf; > + struct video_device vdev; > + struct v4l2_device v4l2_dev; > + struct v4l2_ctrl_handler hdl; > + struct mutex lock; > + > + u8 buffer[BUFFER_LENGTH]; This is a violation of the DMA API. You need to alocate the buffer with a separate kmalloc. > + unsigned curfreq; > + u8 tx; > + u8 pa; > + bool stereo; > + bool muted; > + bool preemph_75_us; > +}; > + > +static inline struct keene_device *to_keene_dev(struct v4l2_device *v4l2_dev) > +{ > + return container_of(v4l2_dev, struct keene_device, v4l2_dev); > +} > + > +/* Set frequency (if non-0), PA, mute and turn on/off the FM transmitter. */ > +static int keene_cmd_main(struct keene_device *radio, unsigned freq, bool play) > +{ > + unsigned short freq_send = freq ? (freq - 76 * 16000) / 800 : 0; > + int ret; > + > + radio->buffer[0] = 0x00; > + radio->buffer[1] = 0x50; > + radio->buffer[2] = (freq_send >> 8) & 0xff; > + radio->buffer[3] = freq_send & 0xff; Please use the endianness macro appropriate here Regards Oliver ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [RFC PATCH 2/3] radio-keene: add a driver for the Keene FM Transmitter. 2012-01-16 12:44 ` Oliver Neukum @ 2012-01-16 13:02 ` Hans Verkuil 2012-01-16 13:11 ` Oliver Neukum 0 siblings, 1 reply; 13+ messages in thread From: Hans Verkuil @ 2012-01-16 13:02 UTC (permalink / raw) To: Oliver Neukum; +Cc: linux-media, linux-input, Jiri Kosina, Hans Verkuil On Monday 16 January 2012 13:44:37 Oliver Neukum wrote: > Am Montag, 16. Januar 2012, 13:29:19 schrieb Hans Verkuil: > > From: Hans Verkuil <hans.verkuil@cisco.com> > > > > +MODULE_DEVICE_TABLE(usb, usb_keene_device_table); > > + > > +struct keene_device { > > + struct usb_device *usbdev; > > + struct usb_interface *intf; > > + struct video_device vdev; > > + struct v4l2_device v4l2_dev; > > + struct v4l2_ctrl_handler hdl; > > + struct mutex lock; > > + > > + u8 buffer[BUFFER_LENGTH]; > > This is a violation of the DMA API. You need to alocate the buffer with > a separate kmalloc. OK. > > + unsigned curfreq; > > + u8 tx; > > + u8 pa; > > + bool stereo; > > + bool muted; > > + bool preemph_75_us; > > +}; > > + > > +static inline struct keene_device *to_keene_dev(struct v4l2_device > > *v4l2_dev) +{ > > + return container_of(v4l2_dev, struct keene_device, v4l2_dev); > > +} > > + > > +/* Set frequency (if non-0), PA, mute and turn on/off the FM > > transmitter. */ +static int keene_cmd_main(struct keene_device *radio, > > unsigned freq, bool play) +{ > > + unsigned short freq_send = freq ? (freq - 76 * 16000) / 800 : 0; > > + int ret; > > + > > + radio->buffer[0] = 0x00; > > + radio->buffer[1] = 0x50; > > + radio->buffer[2] = (freq_send >> 8) & 0xff; > > + radio->buffer[3] = freq_send & 0xff; > > Please use the endianness macro appropriate here I don't see any endianness issues here, but perhaps I missed something. Regards, Hans ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [RFC PATCH 2/3] radio-keene: add a driver for the Keene FM Transmitter. 2012-01-16 13:02 ` Hans Verkuil @ 2012-01-16 13:11 ` Oliver Neukum 2012-01-16 17:28 ` Alan Cox 0 siblings, 1 reply; 13+ messages in thread From: Oliver Neukum @ 2012-01-16 13:11 UTC (permalink / raw) To: Hans Verkuil; +Cc: linux-media, linux-input, Jiri Kosina, Hans Verkuil Am Montag, 16. Januar 2012, 14:02:05 schrieb Hans Verkuil: > > > +/* Set frequency (if non-0), PA, mute and turn on/off the FM > > > transmitter. */ +static int keene_cmd_main(struct keene_device *radio, > > > unsigned freq, bool play) +{ > > > + unsigned short freq_send = freq ? (freq - 76 * 16000) / 800 : 0; > > > + int ret; > > > + > > > + radio->buffer[0] = 0x00; > > > + radio->buffer[1] = 0x50; > > > + radio->buffer[2] = (freq_send >> 8) & 0xff; > > > + radio->buffer[3] = freq_send & 0xff; > > > > Please use the endianness macro appropriate here > > I don't see any endianness issues here, but perhaps I missed something. You are doing the endianness conversion by hand. We have a nice macro for that that assures that special swapping cpu instructions will be used. Regards Oliver ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [RFC PATCH 2/3] radio-keene: add a driver for the Keene FM Transmitter. 2012-01-16 13:11 ` Oliver Neukum @ 2012-01-16 17:28 ` Alan Cox 0 siblings, 0 replies; 13+ messages in thread From: Alan Cox @ 2012-01-16 17:28 UTC (permalink / raw) To: Oliver Neukum Cc: Hans Verkuil, linux-media, linux-input, Jiri Kosina, Hans Verkuil On Mon, 16 Jan 2012 14:11:20 +0100 Oliver Neukum <oneukum@suse.de> wrote: > Am Montag, 16. Januar 2012, 14:02:05 schrieb Hans Verkuil: > > > > +/* Set frequency (if non-0), PA, mute and turn on/off the FM > > > > transmitter. */ +static int keene_cmd_main(struct keene_device *radio, > > > > unsigned freq, bool play) +{ > > > > + unsigned short freq_send = freq ? (freq - 76 * 16000) / 800 : 0; > > > > + int ret; > > > > + > > > > + radio->buffer[0] = 0x00; > > > > + radio->buffer[1] = 0x50; > > > > + radio->buffer[2] = (freq_send >> 8) & 0xff; > > > > + radio->buffer[3] = freq_send & 0xff; > > > > > > Please use the endianness macro appropriate here > > > > I don't see any endianness issues here, but perhaps I missed something. > > You are doing the endianness conversion by hand. We have a nice macro No - it's packing bytes into a buffer from a u16. That doesn't have a macro. Alan ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [RFC PATCH 2/3] radio-keene: add a driver for the Keene FM Transmitter. 2012-01-16 12:29 ` [RFC PATCH 2/3] radio-keene: add a driver for the Keene FM Transmitter Hans Verkuil 2012-01-16 12:44 ` Oliver Neukum @ 2012-01-16 12:46 ` Oliver Neukum 2012-01-16 13:03 ` Hans Verkuil 1 sibling, 1 reply; 13+ messages in thread From: Oliver Neukum @ 2012-01-16 12:46 UTC (permalink / raw) To: Hans Verkuil; +Cc: linux-media, linux-input, Jiri Kosina, Hans Verkuil Am Montag, 16. Januar 2012, 13:29:19 schrieb Hans Verkuil: > +/* check if the device is present and register with v4l and usb if it is */ > +static int usb_keene_probe(struct usb_interface *intf, > + const struct usb_device_id *id) > +{ > + struct keene_device *radio; > + struct v4l2_ctrl_handler *hdl; > + int retval = 0; > + > + radio = kzalloc(sizeof(struct keene_device), GFP_KERNEL); > + > + if (!radio) { > + dev_err(&intf->dev, "kmalloc for keene_device failed\n"); > + retval = -ENOMEM; > + goto err; > + } Oh, I forgot. You have no guarantee the hid driver is already loaded. This driver needs to also gracefully handle being called for a HID device. Regards Oliver ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [RFC PATCH 2/3] radio-keene: add a driver for the Keene FM Transmitter. 2012-01-16 12:46 ` Oliver Neukum @ 2012-01-16 13:03 ` Hans Verkuil 2012-01-16 13:15 ` Oliver Neukum 0 siblings, 1 reply; 13+ messages in thread From: Hans Verkuil @ 2012-01-16 13:03 UTC (permalink / raw) To: Oliver Neukum; +Cc: linux-media, linux-input, Jiri Kosina, Hans Verkuil On Monday 16 January 2012 13:46:46 Oliver Neukum wrote: > Am Montag, 16. Januar 2012, 13:29:19 schrieb Hans Verkuil: > > +/* check if the device is present and register with v4l and usb if it is > > */ +static int usb_keene_probe(struct usb_interface *intf, > > + const struct usb_device_id *id) > > +{ > > + struct keene_device *radio; > > + struct v4l2_ctrl_handler *hdl; > > + int retval = 0; > > + > > + radio = kzalloc(sizeof(struct keene_device), GFP_KERNEL); > > + > > + if (!radio) { > > + dev_err(&intf->dev, "kmalloc for keene_device failed\n"); > > + retval = -ENOMEM; > > + goto err; > > + } > > Oh, I forgot. You have no guarantee the hid driver is already loaded. > This driver needs to also gracefully handle being called for a HID > device. And how do I do that? Do you have a pointer to another driver for me? Regards, Hans ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [RFC PATCH 2/3] radio-keene: add a driver for the Keene FM Transmitter. 2012-01-16 13:03 ` Hans Verkuil @ 2012-01-16 13:15 ` Oliver Neukum 0 siblings, 0 replies; 13+ messages in thread From: Oliver Neukum @ 2012-01-16 13:15 UTC (permalink / raw) To: Hans Verkuil; +Cc: linux-media, linux-input, Jiri Kosina, Hans Verkuil Am Montag, 16. Januar 2012, 14:03:07 schrieb Hans Verkuil: > > Oh, I forgot. You have no guarantee the hid driver is already loaded. > > This driver needs to also gracefully handle being called for a HID > > device. > > And how do I do that? Do you have a pointer to another driver for me? As you've tested that rejecting the device in usbhid works, I suggest you do it as usbhid does it. Which reminds me, have you tested that it works the second time also? The behavior is different if both drivers are resident in memory. Regards Oliver ^ permalink raw reply [flat|nested] 13+ messages in thread
* [RFC PATCH 3/3] hid-core: ignore the Keene FM transmitter. 2012-01-16 12:29 ` [RFC PATCH 1/3] v4l2-ctrls: fix ugly control name Hans Verkuil 2012-01-16 12:29 ` [RFC PATCH 2/3] radio-keene: add a driver for the Keene FM Transmitter Hans Verkuil @ 2012-01-16 12:29 ` Hans Verkuil 2012-01-16 13:00 ` [RFC PATCH 1/3] v4l2-ctrls: fix ugly control name Oliver Neukum 2 siblings, 0 replies; 13+ messages in thread From: Hans Verkuil @ 2012-01-16 12:29 UTC (permalink / raw) To: linux-media; +Cc: linux-input, Jiri Kosina, Hans Verkuil From: Hans Verkuil <hans.verkuil@cisco.com> The Keene FM transmitter USB device has the same USB ID as the Logitech AudioHub Speaker, but it should ignore the hid. Check if the name is that of the Keene device. Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> --- drivers/hid/hid-core.c | 10 ++++++++++ drivers/hid/hid-ids.h | 1 + 2 files changed, 11 insertions(+), 0 deletions(-) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index af35384..f02d197 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1973,6 +1973,16 @@ static bool hid_ignore(struct hid_device *hdev) if (hdev->product >= USB_DEVICE_ID_LOGITECH_HARMONY_FIRST && hdev->product <= USB_DEVICE_ID_LOGITECH_HARMONY_LAST) return true; + /* + * The Keene FM transmitter USB device has the same USB ID as + * the Logitech AudioHub Speaker, but it should ignore the hid. + * Check if the name is that of the Keene device. + * For reference: the name of the AudioHub is + * "HOLTEK AudioHub Speaker". + */ + if (hdev->product == USB_DEVICE_ID_LOGITECH_AUDIOHUB && + !strcmp(hdev->name, "HOLTEK B-LINK USB Audio ")) + return true; break; case USB_VENDOR_ID_SOUNDGRAPH: if (hdev->product >= USB_DEVICE_ID_SOUNDGRAPH_IMON_FIRST && diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 4a441a6..2f6dc92 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -440,6 +440,7 @@ #define USB_DEVICE_ID_LG_MULTITOUCH 0x0064 #define USB_VENDOR_ID_LOGITECH 0x046d +#define USB_DEVICE_ID_LOGITECH_AUDIOHUB 0x0a0e #define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101 #define USB_DEVICE_ID_LOGITECH_HARMONY_FIRST 0xc110 #define USB_DEVICE_ID_LOGITECH_HARMONY_LAST 0xc14f -- 1.7.7.3 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [RFC PATCH 1/3] v4l2-ctrls: fix ugly control name. 2012-01-16 12:29 ` [RFC PATCH 1/3] v4l2-ctrls: fix ugly control name Hans Verkuil 2012-01-16 12:29 ` [RFC PATCH 2/3] radio-keene: add a driver for the Keene FM Transmitter Hans Verkuil 2012-01-16 12:29 ` [RFC PATCH 3/3] hid-core: ignore the Keene FM transmitter Hans Verkuil @ 2012-01-16 13:00 ` Oliver Neukum 2012-01-16 13:04 ` Hans Verkuil 2 siblings, 1 reply; 13+ messages in thread From: Oliver Neukum @ 2012-01-16 13:00 UTC (permalink / raw) To: Hans Verkuil; +Cc: linux-media, linux-input, Jiri Kosina, Hans Verkuil Am Montag, 16. Januar 2012, 13:29:18 schrieb Hans Verkuil: > From: Hans Verkuil <hans.verkuil@cisco.com> > > Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> > --- > drivers/media/video/v4l2-ctrls.c | 2 +- > 1 files changed, 1 insertions(+), 1 deletions(-) > > diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c > index da1f4c2..35316f9 100644 > --- a/drivers/media/video/v4l2-ctrls.c > +++ b/drivers/media/video/v4l2-ctrls.c > @@ -588,7 +588,7 @@ const char *v4l2_ctrl_get_name(u32 id) > case V4L2_CID_PILOT_TONE_ENABLED: return "Pilot Tone Feature Enabled"; > case V4L2_CID_PILOT_TONE_DEVIATION: return "Pilot Tone Deviation"; > case V4L2_CID_PILOT_TONE_FREQUENCY: return "Pilot Tone Frequency"; > - case V4L2_CID_TUNE_PREEMPHASIS: return "Pre-emphasis settings"; > + case V4L2_CID_TUNE_PREEMPHASIS: return "Pre-Emphasis"; > case V4L2_CID_TUNE_POWER_LEVEL: return "Tune Power Level"; > case V4L2_CID_TUNE_ANTENNA_CAPACITOR: return "Tune Antenna Capacitor"; > This looks like generic code. What happens if a programm is looking for this string? Regards Oliver ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [RFC PATCH 1/3] v4l2-ctrls: fix ugly control name. 2012-01-16 13:00 ` [RFC PATCH 1/3] v4l2-ctrls: fix ugly control name Oliver Neukum @ 2012-01-16 13:04 ` Hans Verkuil 0 siblings, 0 replies; 13+ messages in thread From: Hans Verkuil @ 2012-01-16 13:04 UTC (permalink / raw) To: Oliver Neukum; +Cc: linux-media, linux-input, Jiri Kosina, Hans Verkuil On Monday 16 January 2012 14:00:00 Oliver Neukum wrote: > Am Montag, 16. Januar 2012, 13:29:18 schrieb Hans Verkuil: > > From: Hans Verkuil <hans.verkuil@cisco.com> > > > > Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> > > --- > > > > drivers/media/video/v4l2-ctrls.c | 2 +- > > 1 files changed, 1 insertions(+), 1 deletions(-) > > > > diff --git a/drivers/media/video/v4l2-ctrls.c > > b/drivers/media/video/v4l2-ctrls.c index da1f4c2..35316f9 100644 > > --- a/drivers/media/video/v4l2-ctrls.c > > +++ b/drivers/media/video/v4l2-ctrls.c > > @@ -588,7 +588,7 @@ const char *v4l2_ctrl_get_name(u32 id) > > > > case V4L2_CID_PILOT_TONE_ENABLED: return "Pilot Tone Feature Enabled"; > > case V4L2_CID_PILOT_TONE_DEVIATION: return "Pilot Tone Deviation"; > > case V4L2_CID_PILOT_TONE_FREQUENCY: return "Pilot Tone Frequency"; > > > > - case V4L2_CID_TUNE_PREEMPHASIS: return "Pre-emphasis settings"; > > + case V4L2_CID_TUNE_PREEMPHASIS: return "Pre-Emphasis"; > > > > case V4L2_CID_TUNE_POWER_LEVEL: return "Tune Power Level"; > > case V4L2_CID_TUNE_ANTENNA_CAPACITOR: return "Tune Antenna Capacitor"; > > This looks like generic code. What happens if a programm is looking for > this string? User space can't rely on the name being constant. Perhaps in the future they can but not at the moment. Regards, Hans ^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2012-01-16 17:26 UTC | newest] Thread overview: 13+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2012-01-16 12:29 [RFC PATCH 0/3] New driver for the Keene USB FM Transmitter Hans Verkuil 2012-01-16 12:29 ` [RFC PATCH 1/3] v4l2-ctrls: fix ugly control name Hans Verkuil 2012-01-16 12:29 ` [RFC PATCH 2/3] radio-keene: add a driver for the Keene FM Transmitter Hans Verkuil 2012-01-16 12:44 ` Oliver Neukum 2012-01-16 13:02 ` Hans Verkuil 2012-01-16 13:11 ` Oliver Neukum 2012-01-16 17:28 ` Alan Cox 2012-01-16 12:46 ` Oliver Neukum 2012-01-16 13:03 ` Hans Verkuil 2012-01-16 13:15 ` Oliver Neukum 2012-01-16 12:29 ` [RFC PATCH 3/3] hid-core: ignore the Keene FM transmitter Hans Verkuil 2012-01-16 13:00 ` [RFC PATCH 1/3] v4l2-ctrls: fix ugly control name Oliver Neukum 2012-01-16 13:04 ` Hans Verkuil
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.