⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 radio-mr800.c

📁 trident tm5600的linux驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * A driver for the AverMedia MR 800 USB FM radio. This device plugs * into both the USB and an analog audio input, so this thing * only deals with initialization and frequency setting, the * audio data has to be handled by a sound driver. * * Copyright (c) 2008 Alexey Klimov <klimov.linux@gmail.com> * * 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 *//* * Big thanks to authors of dsbr100.c and radio-si470x.c * * When work was looked pretty good, i discover this: * http://av-usbradio.sourceforge.net/index.php * http://sourceforge.net/projects/av-usbradio/ * Latest release of theirs project was in 2005. * Probably, this driver could be improved trough using their * achievements (specifications given). * So, we have smth to begin with. * * History: * Version 0.01:	First working version. * 			It's required to blacklist AverMedia USB Radio * 			in usbhid/hid-quirks.c * * Many things to do: * 	- Correct power managment of device (suspend & resume) * 	- Make x86 independance (little-endian and big-endian stuff) * 	- Add code for scanning and smooth tuning * 	- Checked and add stereo&mono stuff * 	- Add code for sensitivity value * 	- Correct mistakes * 	- In Japan another FREQ_MIN and FREQ_MAX *//* 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-common.h>#include <media/v4l2-ioctl.h>#include <linux/usb.h>#include <linux/version.h>	/* for KERNEL_VERSION MACRO */#include "compat.h"/* driver and module definitions */#define DRIVER_AUTHOR "Alexey Klimov <klimov.linux@gmail.com>"#define DRIVER_DESC "AverMedia MR 800 USB FM radio driver"#define DRIVER_VERSION "0.01"#define RADIO_VERSION KERNEL_VERSION(0, 0, 1)MODULE_AUTHOR(DRIVER_AUTHOR);MODULE_DESCRIPTION(DRIVER_DESC);MODULE_LICENSE("GPL");#define USB_AMRADIO_VENDOR 0x07ca#define USB_AMRADIO_PRODUCT 0xb800/* Probably USB_TIMEOUT should be modified in module parameter */#define BUFFER_LENGTH 8#define USB_TIMEOUT 500/* Frequency limits in MHz -- these are European values.  For Japanesedevices, that would be 76 and 91.  */#define FREQ_MIN  87.5#define FREQ_MAX 108.0#define FREQ_MUL 16000/* module parameter */static int radio_nr = -1;module_param(radio_nr, int, 0);MODULE_PARM_DESC(radio_nr, "Radio Nr");static struct v4l2_queryctrl radio_qctrl[] = {	{		.id            = V4L2_CID_AUDIO_MUTE,		.name          = "Mute",		.minimum       = 0,		.maximum       = 1,		.step	       = 1,		.default_value = 1,		.type          = V4L2_CTRL_TYPE_BOOLEAN,	},/* HINT: the disabled controls are only here to satify kradio and such apps */	{	.id		= V4L2_CID_AUDIO_VOLUME,		.flags		= V4L2_CTRL_FLAG_DISABLED,	},	{		.id		= V4L2_CID_AUDIO_BALANCE,		.flags		= V4L2_CTRL_FLAG_DISABLED,	},	{		.id		= V4L2_CID_AUDIO_BASS,		.flags		= V4L2_CTRL_FLAG_DISABLED,	},	{		.id		= V4L2_CID_AUDIO_TREBLE,		.flags		= V4L2_CTRL_FLAG_DISABLED,	},	{		.id		= V4L2_CID_AUDIO_LOUDNESS,		.flags		= V4L2_CTRL_FLAG_DISABLED,	},};static int usb_amradio_probe(struct usb_interface *intf,			     const struct usb_device_id *id);static void usb_amradio_disconnect(struct usb_interface *intf);static int usb_amradio_open(struct inode *inode, struct file *file);static int usb_amradio_close(struct inode *inode, struct file *file);static int usb_amradio_suspend(struct usb_interface *intf,				pm_message_t message);static int usb_amradio_resume(struct usb_interface *intf);/* Data for one (physical) device */struct amradio_device {	/* reference to USB and video device */	struct usb_device *usbdev;	struct video_device *videodev;	unsigned char *buffer;	struct mutex lock;	/* buffer locking */	int curfreq;	int stereo;	int users;	int removed;	int muted;};/* USB Device ID List */static struct usb_device_id usb_amradio_device_table[] = {	{USB_DEVICE_AND_INTERFACE_INFO(USB_AMRADIO_VENDOR, USB_AMRADIO_PRODUCT,							USB_CLASS_HID, 0, 0) },	{ }						/* Terminating entry */};MODULE_DEVICE_TABLE(usb, usb_amradio_device_table);/* USB subsystem interface */static struct usb_driver usb_amradio_driver = {	.name			= "radio-mr800",	.probe			= usb_amradio_probe,	.disconnect		= usb_amradio_disconnect,	.suspend		= usb_amradio_suspend,	.resume			= usb_amradio_resume,#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23)	.reset_resume		= usb_amradio_resume,#endif	.id_table		= usb_amradio_device_table,	.supports_autosuspend	= 1,};/* switch on radio. Send 8 bytes to device. */static int amradio_start(struct amradio_device *radio){	int retval;	int size;	mutex_lock(&radio->lock);	radio->buffer[0] = 0x00;	radio->buffer[1] = 0x55;	radio->buffer[2] = 0xaa;	radio->buffer[3] = 0x00;	radio->buffer[4] = 0xab;	radio->buffer[5] = 0x00;	radio->buffer[6] = 0x00;	radio->buffer[7] = 0x00;	retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2),		(void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT);	if (retval) {		mutex_unlock(&radio->lock);		return retval;	}	mutex_unlock(&radio->lock);	radio->muted = 0;	return retval;}/* switch off radio */static int amradio_stop(struct amradio_device *radio){	int retval;	int size;	mutex_lock(&radio->lock);	radio->buffer[0] = 0x00;	radio->buffer[1] = 0x55;	radio->buffer[2] = 0xaa;	radio->buffer[3] = 0x00;	radio->buffer[4] = 0xab;	radio->buffer[5] = 0x01;	radio->buffer[6] = 0x00;	radio->buffer[7] = 0x00;	retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2),		(void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT);	if (retval) {		mutex_unlock(&radio->lock);		return retval;	}	mutex_unlock(&radio->lock);	radio->muted = 1;	return retval;}/* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */static int amradio_setfreq(struct amradio_device *radio, int freq){	int retval;	int size;	unsigned short freq_send = 0x13 + (freq >> 3) / 25;	mutex_lock(&radio->lock);	radio->buffer[0] = 0x00;	radio->buffer[1] = 0x55;	radio->buffer[2] = 0xaa;	radio->buffer[3] = 0x03;	radio->buffer[4] = 0xa4;	radio->buffer[5] = 0x00;	radio->buffer[6] = 0x00;	radio->buffer[7] = 0x08;	retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2),		(void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT);	if (retval) {		mutex_unlock(&radio->lock);		return retval;	}	/* frequency is calculated from freq_send and placed in first 2 bytes */	radio->buffer[0] = (freq_send >> 8) & 0xff;	radio->buffer[1] = freq_send & 0xff;	radio->buffer[2] = 0x01;	radio->buffer[3] = 0x00;	radio->buffer[4] = 0x00;	/* 5 and 6 bytes of buffer already = 0x00 */	radio->buffer[7] = 0x00;	retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2),		(void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT);	if (retval) {		mutex_unlock(&radio->lock);		return retval;	}	mutex_unlock(&radio->lock);	radio->stereo = 0;	return retval;}/* USB subsystem interface begins here *//* handle unplugging of the device, release data structuresif nothing keeps us from doing it.  If something is stillkeeping us busy, the release callback of v4l will take careof releasing it. */static void usb_amradio_disconnect(struct usb_interface *intf){	struct amradio_device *radio = usb_get_intfdata(intf);	usb_set_intfdata(intf, NULL);	if (radio) {		video_unregister_device(radio->videodev);		radio->videodev = NULL;		if (radio->users) {			kfree(radio->buffer);			kfree(radio);		} else {			radio->removed = 1;		}	}}/* vidioc_querycap - query device capabilities */static int vidioc_querycap(struct file *file, void *priv,					struct v4l2_capability *v){	strlcpy(v->driver, "radio-mr800", sizeof(v->driver));	strlcpy(v->card, "AverMedia MR 800 USB FM Radio", sizeof(v->card));	sprintf(v->bus_info, "USB");	v->version = RADIO_VERSION;	v->capabilities = V4L2_CAP_TUNER;	return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -