Hi Devin, Devin Heitmueller wrote: > Hello Mauro, > > Please PULL from > http://kernellabs.com/hg/~dheitmueller/v4l-dvb-as102-2 for the > following: > > as102: import initial as102 driver > as102: checkpatch fixes > as102: checkpatch fixes > as102: checkpatch fixes > as102: checkpatch fixes > as102: checkpatch fixes > as102: checkpatch fixes > as102: checkpatch fixes > as102: Add Elgato EyeTV DTT Deluxe > as102: properly handle multiple product names > as102: fix compile warning about unused function > > Thanks to Rainer Miethling from PCTV Systems for working to get the > driver released (for use with the PCTV 74e) and Pierrick Hascoet from > Abilis for authoring the original driver. > > Devin I have several comments about this. I've folded all patches into one for a better review. This driver requires several fixes for it to be accepted, including the license, since, on some files, it says: All rights reserved, instead of a GPL compatible licensing. > diff --git a/drivers/media/dvb/Kconfig b/drivers/media/dvb/Kconfig > index 161ccfd..9bb7b31 100644 > --- a/drivers/media/dvb/Kconfig > +++ b/drivers/media/dvb/Kconfig > @@ -47,6 +47,7 @@ source "drivers/media/dvb/dvb-usb/Kconfig" > source "drivers/media/dvb/ttusb-budget/Kconfig" > source "drivers/media/dvb/ttusb-dec/Kconfig" > source "drivers/media/dvb/siano/Kconfig" > +source "drivers/media/dvb/as102/Kconfig" > > comment "Supported FlexCopII (B2C2) Adapters" > depends on DVB_CORE && (PCI || USB) && I2C > diff --git a/drivers/media/dvb/Makefile b/drivers/media/dvb/Makefile > index a1a0875..def029b 100644 > --- a/drivers/media/dvb/Makefile > +++ b/drivers/media/dvb/Makefile > @@ -15,6 +15,7 @@ obj-y := dvb-core/ \ > dm1105/ \ > pt1/ \ > mantis/ \ > - ngene/ > + ngene/ \ > + as102/ > > obj-$(CONFIG_DVB_FIREDTV) += firewire/ > diff --git a/drivers/media/dvb/as102/Kconfig b/drivers/media/dvb/as102/Kconfig > new file mode 100644 > index 0000000..5865029 > --- /dev/null > +++ b/drivers/media/dvb/as102/Kconfig > @@ -0,0 +1,7 @@ > +config DVB_AS102 > + tristate "Abilis AS102 DVB receiver" > + depends on DVB_CORE && USB && I2C && INPUT > + help > + Choose Y or M here if you have a device containing an AS102 > + > + To compile this driver as a module, choose M here > diff --git a/drivers/media/dvb/as102/Makefile b/drivers/media/dvb/as102/Makefile > new file mode 100644 > index 0000000..c2334c6 > --- /dev/null > +++ b/drivers/media/dvb/as102/Makefile > @@ -0,0 +1,5 @@ > +dvb-as102-objs := as102_drv.o as102_fw.o as10x_cmd.o as10x_cmd_stream.o as102_fe.o as102_usb_drv.o as10x_cmd_cfg.o > + > +obj-$(CONFIG_DVB_AS102) += dvb-as102.o > + > +EXTRA_CFLAGS += -DLINUX -DCONFIG_AS102_USB -Idrivers/media/dvb/dvb-core Huh? You shouldn't be passing "LINUX" and "CONFIG_AS102_USB" parameters here... it will always be LINUX, and, if the driver supports USB and SPI (CONFIG_AS102_SPI), you should have those items at Kconfig. > diff --git a/drivers/media/dvb/as102/as102_drv.c b/drivers/media/dvb/as102/as102_drv.c > new file mode 100644 > index 0000000..e1e32be > --- /dev/null > +++ b/drivers/media/dvb/as102/as102_drv.c > @@ -0,0 +1,360 @@ > +/* > + * Abilis Systems Single DVB-T Receiver > + * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@xxxxxxxxxx> > + * Copyright (C) 2010 Devin Heitmueller <dheitmueller@xxxxxxxxxxxxxx> > + * > + * 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. > + */ > +#include <linux/kernel.h> > +#include <linux/errno.h> > +#include <linux/init.h> > +#include <linux/slab.h> > +#include <linux/module.h> > +#include <linux/mm.h> > +#include <linux/kref.h> > +#include <asm/uaccess.h> asm/uaccess.h? Is this arch-dependent, or it could use, instead linux/uaccess.h? > +#include <linux/usb.h> > + > +/* header file for Usb device driver*/ > +#include "as102_drv.h" > +#include "as102_fw.h" > + > +#if defined(CONFIG_DVB_CORE) || defined(CONFIG_DVB_CORE_MODULE) > +#include "dvbdev.h" > +#else > +#warning >>> DVB_CORE not defined !!! <<< > +#endif This is not needed, as it is checked at Kconfig: #if defined(CONFIG_DVB_CORE) || defined(CONFIG_DVB_CORE_MODULE) #include "dvbdev.h" #else #warning >>> DVB_CORE not defined !!! <<< #endif You should just remove all those tests for CONFIG_DVB > + > +int debug; > +module_param_named(debug, debug, int, 0644); > +MODULE_PARM_DESC(debug, "Turn on/off debugging (default: off)"); > + > +int dual_tuner; > +module_param_named(dual_tuner, dual_tuner, int, 0644); > +MODULE_PARM_DESC(dual_tuner, "Activate Dual-Tuner config (default: off)"); > + > +static int fw_upload = 1; > +module_param_named(fw_upload, fw_upload, int, 0644); > +MODULE_PARM_DESC(fw_upload, "Turn on/off default FW upload (default: on)"); > + > +static int pid_filtering; > +module_param_named(pid_filtering, pid_filtering, int, 0644); > +MODULE_PARM_DESC(pid_filtering, "Activate HW PID filtering (default: off)"); > + > +static int ts_auto_disable; > +module_param_named(ts_auto_disable, ts_auto_disable, int, 0644); > +MODULE_PARM_DESC(ts_auto_disable, "Stream Auto Enable on FW (default: off)"); > + > +int elna_enable = 1; > +module_param_named(elna_enable, elna_enable, int, 0644); > +MODULE_PARM_DESC(elna_enable, "Activate eLNA (default: on)"); > + > +#ifdef DVB_DEFINE_MOD_OPT_ADAPTER_NR > +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); > +#endif > + > +#if defined(CONFIG_DVB_CORE) || defined(CONFIG_DVB_CORE_MODULE) > +static void as102_stop_stream(struct as102_dev_t *dev) > +{ > + struct as102_bus_adapter_t *bus_adap; > + > + if (dev != NULL) > + bus_adap = &dev->bus_adap; > + else > + return; > + > + if (bus_adap->ops->stop_stream != NULL) > + bus_adap->ops->stop_stream(dev); > + > + if (ts_auto_disable) { > + if (mutex_lock_interruptible(&dev->bus_adap.lock)) > + return; > + > + if (as10x_cmd_stop_streaming(bus_adap) < 0) > + dprintk(debug, "as10x_cmd_stop_streaming failed\n"); > + > + mutex_unlock(&dev->bus_adap.lock); > + } > +} > + > +static int as102_start_stream(struct as102_dev_t *dev) > +{ > + struct as102_bus_adapter_t *bus_adap; > + int ret = -EFAULT; > + > + if (dev != NULL) > + bus_adap = &dev->bus_adap; > + else > + return ret; > + > + if (bus_adap->ops->start_stream != NULL) > + ret = bus_adap->ops->start_stream(dev); > + > + if (ts_auto_disable) { > + if (mutex_lock_interruptible(&dev->bus_adap.lock)) > + return -EFAULT; > + > + ret = as10x_cmd_start_streaming(bus_adap); > + > + mutex_unlock(&dev->bus_adap.lock); > + } > + > + return ret; > +} > + > +static int as10x_pid_filter(struct as102_dev_t *dev, > + int index, u16 pid, int onoff) { > + > + struct as102_bus_adapter_t *bus_adap = &dev->bus_adap; > + int ret = -EFAULT; > + > + ENTER(); ENTER() is a very bad name for a debug macro. If this is really needed, please use something better. > + > + if (mutex_lock_interruptible(&dev->bus_adap.lock)) { > + dprintk(debug, "mutex_lock_interruptible(lock) failed !\n"); > + return -EBUSY; > + } > + > + switch (onoff) { > + case 0: > + ret = as10x_cmd_del_PID_filter(bus_adap, (uint16_t) pid); > + dprintk(debug, "DEL_PID_FILTER([%02d] 0x%04x) ret = %d\n", > + index, pid, ret); > + break; > + case 1: > + { > + struct as10x_ts_filter filter; > + > + filter.type = TS_PID_TYPE_TS; > + filter.idx = 0xFF; > + filter.pid = pid; > + > + ret = as10x_cmd_add_PID_filter(bus_adap, &filter); > + dprintk(debug, "ADD_PID_FILTER([%02d -> %02d], 0x%04x) ret = %d\n", > + index, filter.idx, filter.pid, ret); > + break; > + } > + } > + > + mutex_unlock(&dev->bus_adap.lock); > + > + LEAVE(); LEAVE() is a very bad name for a debug macro. If this is really needed, please use something better. > + return ret; > +} > + > +static int as102_dvb_dmx_start_feed(struct dvb_demux_feed *dvbdmxfeed) > +{ > + int ret = 0; > + struct dvb_demux *demux = dvbdmxfeed->demux; > + struct as102_dev_t *as102_dev = demux->priv; > + > + ENTER(); > + > + if (mutex_lock_interruptible(&as102_dev->sem)) > + return -ERESTARTSYS; > + > + if (pid_filtering) { > + as10x_pid_filter(as102_dev, > + dvbdmxfeed->index, dvbdmxfeed->pid, 1); > + } > + > + if (as102_dev->streaming++ == 0) > + ret = as102_start_stream(as102_dev); > + > + mutex_unlock(&as102_dev->sem); > + LEAVE(); > + return ret; > +} > + > +static int as102_dvb_dmx_stop_feed(struct dvb_demux_feed *dvbdmxfeed) > +{ > + struct dvb_demux *demux = dvbdmxfeed->demux; > + struct as102_dev_t *as102_dev = demux->priv; > + > + ENTER(); > + > + if (mutex_lock_interruptible(&as102_dev->sem)) > + return -ERESTARTSYS; > + > + if (--as102_dev->streaming == 0) > + as102_stop_stream(as102_dev); > + > + if (pid_filtering) { > + as10x_pid_filter(as102_dev, > + dvbdmxfeed->index, dvbdmxfeed->pid, 0); > + } > + > + mutex_unlock(&as102_dev->sem); > + LEAVE(); > + return 0; > +} > +#endif > + > +int as102_dvb_register(struct as102_dev_t *as102_dev) > +{ > + int ret = 0; > + ENTER(); > + > +#if defined(CONFIG_DVB_CORE) || defined(CONFIG_DVB_CORE_MODULE) > + ret = dvb_register_adapter(&as102_dev->dvb_adap, > + as102_dev->name, > + THIS_MODULE, > +#if defined(CONFIG_AS102_USB) > + &as102_dev->bus_adap.usb_dev->dev > +#elif defined(CONFIG_AS102_SPI) > + &as102_dev->bus_adap.spi_dev->dev > +#else > +#error >>> dvb_register_adapter <<< > +#endif What would happen if both USB and SPI were enabled? I suspect that you need to add some way to identify that a board is using USB or SPI bus, and have a logic there to check for this information at the board struct, in order to use one or the other bus address. > +#ifdef DVB_DEFINE_MOD_OPT_ADAPTER_NR > + , adapter_nr > +#endif > + ); > + if (ret < 0) { > + err("%s: dvb_register_adapter() failed (errno = %d)", > + __func__, ret); > + goto failed; > + } > + > + as102_dev->dvb_dmx.priv = as102_dev; > + as102_dev->dvb_dmx.filternum = pid_filtering ? 16 : 256; > + as102_dev->dvb_dmx.feednum = 256; > + as102_dev->dvb_dmx.start_feed = as102_dvb_dmx_start_feed; > + as102_dev->dvb_dmx.stop_feed = as102_dvb_dmx_stop_feed; > + > + as102_dev->dvb_dmx.dmx.capabilities = DMX_TS_FILTERING | > + DMX_SECTION_FILTERING; > + > + as102_dev->dvb_dmxdev.filternum = as102_dev->dvb_dmx.filternum; > + as102_dev->dvb_dmxdev.demux = &as102_dev->dvb_dmx.dmx; > + as102_dev->dvb_dmxdev.capabilities = 0; > + > + ret = dvb_dmx_init(&as102_dev->dvb_dmx); > + if (ret < 0) { > + err("%s: dvb_dmx_init() failed (errno = %d)", __func__, ret); > + goto failed; > + } > + > + ret = dvb_dmxdev_init(&as102_dev->dvb_dmxdev, &as102_dev->dvb_adap); > + if (ret < 0) { > + err("%s: dvb_dmxdev_init() failed (errno = %d)", __func__, > + ret); > + goto failed; > + } > + > + ret = as102_dvb_register_fe(as102_dev, &as102_dev->dvb_fe); > + if (ret < 0) { > + err("%s: as102_dvb_register_frontend() failed (errno = %d)", > + __func__, ret); > + goto failed; > + } > +#endif > + > + /* init bus mutex for token locking */ > + mutex_init(&as102_dev->bus_adap.lock); > + > + /* init start / stop stream mutex */ > + mutex_init(&as102_dev->sem); > + > +#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE) > + /* > + * try to load as102 firmware. If firmware upload failed, we'll be > + * able to upload it later. > + */ > + if (fw_upload) > + try_then_request_module(as102_fw_upload(&as102_dev->bus_adap), > + "firmware_class"); > +#endif > + > +failed: > + LEAVE(); > + /* FIXME: free dvb_XXX */ Better to add some release functions here. > + return ret; > +} > + > +void as102_dvb_unregister(struct as102_dev_t *as102_dev) > +{ > + ENTER(); > + > +#if defined(CONFIG_DVB_CORE) || defined(CONFIG_DVB_CORE_MODULE) > + /* unregister as102 frontend */ > + as102_dvb_unregister_fe(&as102_dev->dvb_fe); > + > + /* unregister demux device */ > + dvb_dmxdev_release(&as102_dev->dvb_dmxdev); > + dvb_dmx_release(&as102_dev->dvb_dmx); > + > + /* unregister dvb adapter */ > + dvb_unregister_adapter(&as102_dev->dvb_adap); > +#endif > + LEAVE(); > +} > + > +static int __init as102_driver_init(void) > +{ > + int ret = 0; > + > + ENTER(); > + > + /* register this driver with the low level subsystem */ > +#if defined(CONFIG_AS102_USB) > + ret = usb_register(&as102_usb_driver); > + if (ret) > + err("usb_register failed (ret = %d)", ret); > +#endif > +#if defined(CONFIG_AS102_SPI) > + ret = spi_register_driver(&as102_spi_driver); > + if (ret) > + printk(KERN_ERR "spi_register failed (ret = %d)", ret); > +#endif It should be one or another register, depending on the board model. > + > + LEAVE(); > + return ret; > +} > + > +/* > + * Mandatory function : Adds a special section to the module indicating > + * where initialisation function is defined > + */ > +module_init(as102_driver_init); > + > +/** > + * \brief as102 driver exit point. This function is called when device has > + * to be removed. > + */ > +static void __exit as102_driver_exit(void) > +{ > + ENTER(); > + /* deregister this driver with the low level bus subsystem */ > +#if defined(CONFIG_AS102_USB) > + usb_deregister(&as102_usb_driver); > +#endif > +#if defined(CONFIG_AS102_SPI) > + spi_unregister_driver(&as102_spi_driver); > +#endif > + LEAVE(); > +} > + > +/* > + * required function for unload: Adds a special section to the module > + * indicating where unload function is defined > + */ > +module_exit(as102_driver_exit); > +/* modinfo details */ > +MODULE_DESCRIPTION(DRIVER_FULL_NAME); > +MODULE_LICENSE("GPL"); > +MODULE_AUTHOR("Pierrick Hascoet <pierrick.hascoet@xxxxxxxxxx>"); > + > +/* EOF - vim: set textwidth=80 ts=8 sw=8 sts=8 noet: */ Please, don't keep editor-dependent tags on the source code. > diff --git a/drivers/media/dvb/as102/as102_drv.h b/drivers/media/dvb/as102/as102_drv.h > new file mode 100644 > index 0000000..cd11b16 > --- /dev/null > +++ b/drivers/media/dvb/as102/as102_drv.h > @@ -0,0 +1,147 @@ > +/* > + * Abilis Systems Single DVB-T Receiver > + * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@xxxxxxxxxx> > + * > + * 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. > + */ > + > +#if defined(CONFIG_AS102_USB) > +#include <linux/usb.h> > +extern struct usb_driver as102_usb_driver; > +#endif > + > +#if defined(CONFIG_AS102_SPI) > +#include <linux/platform_device.h> > +#include <linux/spi/spi.h> > +#include <linux/cdev.h> > + > +extern struct spi_driver as102_spi_driver; > +#endif > + > +#if defined(CONFIG_DVB_CORE) || defined(CONFIG_DVB_CORE_MODULE) > +#include "dvb_demux.h" > +#include "dvb_frontend.h" > +#include "dmxdev.h" > +#endif Test is not needed. > + > +#define DRIVER_FULL_NAME "Abilis Systems as10x usb driver" > +#define DRIVER_NAME "as10x_usb" > + > +extern int debug; > + > +#define dprintk(debug, args...) \ > + do { if (debug) { \ > + printk(KERN_DEBUG "%s: ",__FUNCTION__); \ > + printk(args); \ > + } } while (0) > + > +#ifdef TRACE > +#define ENTER() printk(">> enter %s\n", __FUNCTION__) > +#define LEAVE() printk("<< leave %s\n", __FUNCTION__) KERN_DEBUG is missing here. Also, as already commented, ENTER/LEAVE is a bad name, and it should be using __func__ instead. > +#else > +#define ENTER() > +#define LEAVE() > +#endif > + > +#define AS102_DEVICE_MAJOR 192 Huh? Why is it declaring a major here, instead using the DVB definition? > + > +#define AS102_USB_BUF_SIZE 512 > +#define MAX_STREAM_URB 32 > + > +#include "as10x_cmd.h" > + > +#if defined(CONFIG_AS102_USB) > +#include "as102_usb_drv.h" > +#endif > + > +#if defined(CONFIG_AS102_SPI) > +#include "as10x_spi_drv.h" > +#endif > + > + > +struct as102_bus_adapter_t { > +#if defined(CONFIG_AS102_USB) > + struct usb_device *usb_dev; > +#elif defined(CONFIG_AS102_SPI) > + struct spi_device *spi_dev; Why elif? maybe the better is to use an union for the above, and just add the spi-specific vars, if SPI is enabled. > + struct cdev cdev; /* spidev raw device */ > + > + struct timer_list timer; > + struct completion xfer_done; > +#endif > + /* bus token lock */ > + struct mutex lock; > + /* low level interface for bus adapter */ > + union as10x_bus_token_t { > +#if defined(CONFIG_AS102_USB) > + /* usb token */ > + struct as10x_usb_token_cmd_t usb; > +#endif > +#if defined(CONFIG_AS102_SPI) > + /* spi token */ > + struct as10x_spi_token_cmd_t spi; > +#endif > + } token; > + > + /* token cmd xfer id */ > + uint16_t cmd_xid; > + > + /* as10x command and response for dvb interface*/ > + struct as10x_cmd_t *cmd, *rsp; > + > + /* bus adapter private ops callback */ > + struct as102_priv_ops_t *ops; > +}; > + > +struct as102_dev_t { > + const char *name; > + struct as102_bus_adapter_t bus_adap; > + struct list_head device_entry; > + struct kref kref; > + unsigned long minor; > + > +#if defined(CONFIG_DVB_CORE) || defined(CONFIG_DVB_CORE_MODULE) > + struct dvb_adapter dvb_adap; > + struct dvb_frontend dvb_fe; > + struct dvb_demux dvb_dmx; > + struct dmxdev dvb_dmxdev; > +#endif If is not needed here. There's no sense of compiling a DVB module without DVB core support enabled. > + > + /* demodulator stats */ > + struct as10x_demod_stats demod_stats; > + /* signal strength */ > + uint16_t signal_strength; > + /* bit error rate */ > + uint32_t ber; > + > + /* timer handle to trig ts stream download */ > + struct timer_list timer_handle; > + > + struct mutex sem; > + dma_addr_t dma_addr; > + void *stream; > + int streaming; > + struct urb *stream_urb[MAX_STREAM_URB]; > +}; > + > +int as102_dvb_register(struct as102_dev_t *dev); > +void as102_dvb_unregister(struct as102_dev_t *dev); > + > +#if defined(CONFIG_DVB_CORE) || defined(CONFIG_DVB_CORE_MODULE) > +int as102_dvb_register_fe(struct as102_dev_t *dev, struct dvb_frontend *fe); > +int as102_dvb_unregister_fe(struct dvb_frontend *dev); > +#endif > + > +/* EOF - vim: set textwidth=80 ts=8 sw=8 sts=8 noet: */ > diff --git a/drivers/media/dvb/as102/as102_fe.c b/drivers/media/dvb/as102/as102_fe.c > new file mode 100644 > index 0000000..603de38 > --- /dev/null > +++ b/drivers/media/dvb/as102/as102_fe.c > @@ -0,0 +1,601 @@ > +/* > + * Abilis Systems Single DVB-T Receiver > + * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@xxxxxxxxxx> > + * Copyright (C) 2010 Devin Heitmueller <dheitmueller@xxxxxxxxxxxxxx> > + * > + * 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. > + */ > +#include <linux/version.h> > + > +#include "as102_drv.h" > +#include "as10x_types.h" > +#include "as10x_cmd.h" > + > +extern int elna_enable; Don't use extern's at .c files. Please put them at the headers. > + > +#if defined(CONFIG_DVB_CORE) || defined(CONFIG_DVB_CORE_MODULE) > +static void as10x_fe_copy_tps_parameters(struct dvb_frontend_parameters *dst, > + struct as10x_tps *src); > + > +static void as102_fe_copy_tune_parameters(struct as10x_tune_args *dst, > + struct dvb_frontend_parameters *src); > + > + > +static int as102_fe_set_frontend(struct dvb_frontend *fe, > + struct dvb_frontend_parameters *params) > +{ > + int ret = 0; > + struct as102_dev_t *dev; > + struct as10x_tune_args tune_args = { 0 }; > + > + ENTER(); > + > + dev = (struct as102_dev_t *) fe->tuner_priv; > + if (dev == NULL) > + return -ENODEV; > + > + if (mutex_lock_interruptible(&dev->bus_adap.lock)) > + return -EBUSY; > + > + as102_fe_copy_tune_parameters(&tune_args, params); > + > + /* send abilis command: SET_TUNE */ > + ret = as10x_cmd_set_tune(&dev->bus_adap, &tune_args); > + if (ret != 0) > + dprintk(debug, "as10x_cmd_set_tune failed. (err = %d)\n", ret); > + > + mutex_unlock(&dev->bus_adap.lock); > + > + LEAVE(); > + return (ret < 0) ? -EINVAL : 0; > +} > + > +static int as102_fe_get_frontend(struct dvb_frontend *fe, > + struct dvb_frontend_parameters *p) { > + int ret = 0; > + struct as102_dev_t *dev; > + struct as10x_tps tps = { 0 }; > + > + ENTER(); > + > + dev = (struct as102_dev_t *) fe->tuner_priv; > + if (dev == NULL) > + return -EINVAL; > + > + if (mutex_lock_interruptible(&dev->bus_adap.lock)) > + return -EBUSY; > + > + /* send abilis command: GET_TPS */ > + ret = as10x_cmd_get_tps(&dev->bus_adap, &tps); > + > + if (ret == 0) > + as10x_fe_copy_tps_parameters(p, &tps); > + > + mutex_unlock(&dev->bus_adap.lock); > + > + LEAVE(); > + return (ret < 0) ? -EINVAL : 0; > +} > + > +static int as102_fe_get_tune_settings(struct dvb_frontend *fe, > + struct dvb_frontend_tune_settings *settings) { > + ENTER(); > + > + > + settings->min_delay_ms = 1000; > + > + LEAVE(); > + return 0; > +} > + > + > +static int as102_fe_read_status(struct dvb_frontend *fe, fe_status_t *status) > +{ > + int ret = 0; > + struct as102_dev_t *dev; > + struct as10x_tune_status tstate = { 0 }; > + > + ENTER(); > + > + dev = (struct as102_dev_t *) fe->tuner_priv; > + if (dev == NULL) > + return -ENODEV; > + > + if (mutex_lock_interruptible(&dev->bus_adap.lock)) > + return -EBUSY; > + > + /* send abilis command: GET_TUNE_STATUS */ > + ret = as10x_cmd_get_tune_status(&dev->bus_adap, &tstate); > + if (ret < 0) { > + dprintk(debug, "as10x_cmd_get_tune_status failed (err = %d)\n", > + ret); > + goto out; > + } > + > + dev->signal_strength = tstate.signal_strength; > + dev->ber = tstate.BER; > + > + switch (tstate.tune_state) { > + case TUNE_STATUS_SIGNAL_DVB_OK: > + *status = FE_HAS_SIGNAL | FE_HAS_CARRIER; > + break; > + case TUNE_STATUS_STREAM_DETECTED: > + *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_SYNC; > + break; > + case TUNE_STATUS_STREAM_TUNED: > + *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_SYNC | > + FE_HAS_LOCK; > + break; > + default: > + *status = TUNE_STATUS_NOT_TUNED; > + } > + > + dprintk(debug, "tuner status: 0x%02x, strength %d, per: %d, ber: %d\n", > + tstate.tune_state, tstate.signal_strength, > + tstate.PER, tstate.BER); > + > + if (*status & FE_HAS_LOCK) { > + if (as10x_cmd_get_demod_stats(&dev->bus_adap, > + (struct as10x_demod_stats *) &dev->demod_stats) < 0) { > + memset(&dev->demod_stats, 0, sizeof(dev->demod_stats)); > + dprintk(debug, "as10x_cmd_get_demod_stats failed " > + "(probably not tuned)\n"); > + } else { > + dprintk(debug, > + "demod status: fc: 0x%08x, bad fc: 0x%08x, " > + "bytes corrected: 0x%08x , MER: 0x%04x\n", > + dev->demod_stats.frame_count, > + dev->demod_stats.bad_frame_count, > + dev->demod_stats.bytes_fixed_by_rs, > + dev->demod_stats.mer); > + } > + } else { > + memset(&dev->demod_stats, 0, sizeof(dev->demod_stats)); > + } > + > +out: > + mutex_unlock(&dev->bus_adap.lock); > + LEAVE(); > + return ret; > +} > + > +/* > + * Note: > + * - in AS102 SNR=MER > + * - the SNR will be returned in linear terms, i.e. not in dB > + * - the accuracy equals ±2dB for a SNR range from 4dB to 30dB > + * - the accuracy is >2dB for SNR values outside this range > + */ > +static int as102_fe_read_snr(struct dvb_frontend *fe, u16 *snr) > +{ > + struct as102_dev_t *dev; > + > + ENTER(); > + > + dev = (struct as102_dev_t *) fe->tuner_priv; > + if (dev == NULL) > + return -ENODEV; > + > + *snr = dev->demod_stats.mer; > + > + LEAVE(); > + return 0; > +} > + > +static int as102_fe_read_ber(struct dvb_frontend *fe, u32 *ber) > +{ > + struct as102_dev_t *dev; > + > + ENTER(); > + > + dev = (struct as102_dev_t *) fe->tuner_priv; > + if (dev == NULL) > + return -ENODEV; > + > + *ber = dev->ber; > + > + LEAVE(); > + return 0; > +} > + > +static int as102_fe_read_signal_strength(struct dvb_frontend *fe, > + u16 *strength) > +{ > + struct as102_dev_t *dev; > + > + ENTER(); > + > + dev = (struct as102_dev_t *) fe->tuner_priv; > + if (dev == NULL) > + return -ENODEV; > + > + *strength = (((0xffff * 400) * dev->signal_strength + 41000) * 2); > + > + LEAVE(); > + return 0; > +} > + > +static int as102_fe_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) > +{ > + struct as102_dev_t *dev; > + > + ENTER(); > + > + dev = (struct as102_dev_t *) fe->tuner_priv; > + if (dev == NULL) > + return -ENODEV; > + > + if (dev->demod_stats.has_started) > + *ucblocks = dev->demod_stats.bad_frame_count; > + else > + *ucblocks = 0; > + > + LEAVE(); > + return 0; > +} It would be nice if you could put some comments about the scale of the above error parameters. > + > +static int as102_fe_ts_bus_ctrl(struct dvb_frontend *fe, int acquire) > +{ > + struct as102_dev_t *dev; > + int ret; > + > + ENTER(); > + > + dev = (struct as102_dev_t *) fe->tuner_priv; > + if (dev == NULL) > + return -ENODEV; > + > + if (mutex_lock_interruptible(&dev->bus_adap.lock)) > + return -EBUSY; > + > + if (acquire) { > + if (elna_enable) > + as10x_cmd_set_context(&dev->bus_adap, 1010, 0xC0); > + > + ret = as10x_cmd_turn_on(&dev->bus_adap); > + } else { > + ret = as10x_cmd_turn_off(&dev->bus_adap); > + } > + > + mutex_unlock(&dev->bus_adap.lock); > + > + LEAVE(); > + return ret; > +} > + > +static struct dvb_frontend_ops as102_fe_ops = { > + .info = { > + .name = "Unknown AS102 device", > + .type = FE_OFDM, > + .frequency_min = 174000000, > + .frequency_max = 862000000, > + .frequency_stepsize = 166667, > + .caps = FE_CAN_INVERSION_AUTO > + | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 > + | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO > + | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QPSK > + | FE_CAN_QAM_AUTO > + | FE_CAN_TRANSMISSION_MODE_AUTO > + | FE_CAN_GUARD_INTERVAL_AUTO > + | FE_CAN_HIERARCHY_AUTO > + | FE_CAN_RECOVER > + | FE_CAN_MUTE_TS > + }, > + > + .set_frontend = as102_fe_set_frontend, > + .get_frontend = as102_fe_get_frontend, > + .get_tune_settings = as102_fe_get_tune_settings, > + > + > + .read_status = as102_fe_read_status, > + .read_snr = as102_fe_read_snr, > + .read_ber = as102_fe_read_ber, > + .read_signal_strength = as102_fe_read_signal_strength, > + .read_ucblocks = as102_fe_read_ucblocks, > + > + .ts_bus_ctrl = as102_fe_ts_bus_ctrl, > +}; > + > +int as102_dvb_unregister_fe(struct dvb_frontend *fe) > +{ > + /* unregister frontend */ > + dvb_unregister_frontend(fe); > + > + /* detach frontend */ > + dvb_frontend_detach(fe); > + return 0; > +} > + > +int as102_dvb_register_fe(struct as102_dev_t *as102_dev, > + struct dvb_frontend *dvb_fe) > +{ > + int errno; > + struct dvb_adapter *dvb_adap; > + > + if (as102_dev == NULL) > + return -EINVAL; > + > + /* extract dvb_adapter */ > + dvb_adap = &as102_dev->dvb_adap; > + > + /* init frontend callback ops */ > + memcpy(&dvb_fe->ops, &as102_fe_ops, sizeof(struct dvb_frontend_ops)); > + strncpy(dvb_fe->ops.info.name, as102_dev->name, > + sizeof(dvb_fe->ops.info.name)); > + > + /* register dbvb frontend */ > + errno = dvb_register_frontend(dvb_adap, dvb_fe); > + if (errno == 0) > + dvb_fe->tuner_priv = as102_dev; > + > + return errno; > +} > + > +static void as10x_fe_copy_tps_parameters(struct dvb_frontend_parameters *dst, > + struct as10x_tps *as10x_tps) > +{ > + > + struct dvb_ofdm_parameters *fe_tps = &dst->u.ofdm; > + > + /* extract consteallation */ > + switch (as10x_tps->constellation) { > + case CONST_QPSK: > + fe_tps->constellation = QPSK; > + break; > + case CONST_QAM16: > + fe_tps->constellation = QAM_16; > + break; > + case CONST_QAM64: > + fe_tps->constellation = QAM_64; > + break; > + } > + > + /* extract hierarchy */ > + switch (as10x_tps->hierarchy) { > + case HIER_NONE: > + fe_tps->hierarchy_information = HIERARCHY_NONE; > + break; > + case HIER_ALPHA_1: > + fe_tps->hierarchy_information = HIERARCHY_1; > + break; > + case HIER_ALPHA_2: > + fe_tps->hierarchy_information = HIERARCHY_2; > + break; > + case HIER_ALPHA_4: > + fe_tps->hierarchy_information = HIERARCHY_4; > + break; > + } > + > + /* extract code rate HP */ > + switch (as10x_tps->code_rate_HP) { > + case CODE_RATE_1_2: > + fe_tps->code_rate_HP = FEC_1_2; > + break; > + case CODE_RATE_2_3: > + fe_tps->code_rate_HP = FEC_2_3; > + break; > + case CODE_RATE_3_4: > + fe_tps->code_rate_HP = FEC_3_4; > + break; > + case CODE_RATE_5_6: > + fe_tps->code_rate_HP = FEC_5_6; > + break; > + case CODE_RATE_7_8: > + fe_tps->code_rate_HP = FEC_7_8; > + break; > + } > + > + /* extract code rate LP */ > + switch (as10x_tps->code_rate_LP) { > + case CODE_RATE_1_2: > + fe_tps->code_rate_LP = FEC_1_2; > + break; > + case CODE_RATE_2_3: > + fe_tps->code_rate_LP = FEC_2_3; > + break; > + case CODE_RATE_3_4: > + fe_tps->code_rate_LP = FEC_3_4; > + break; > + case CODE_RATE_5_6: > + fe_tps->code_rate_LP = FEC_5_6; > + break; > + case CODE_RATE_7_8: > + fe_tps->code_rate_LP = FEC_7_8; > + break; > + } > + > + /* extract guard interval */ > + switch (as10x_tps->guard_interval) { > + case GUARD_INT_1_32: > + fe_tps->guard_interval = GUARD_INTERVAL_1_32; > + break; > + case GUARD_INT_1_16: > + fe_tps->guard_interval = GUARD_INTERVAL_1_16; > + break; > + case GUARD_INT_1_8: > + fe_tps->guard_interval = GUARD_INTERVAL_1_8; > + break; > + case GUARD_INT_1_4: > + fe_tps->guard_interval = GUARD_INTERVAL_1_4; > + break; > + } > + > + /* extract transmission mode */ > + switch (as10x_tps->transmission_mode) { > + case TRANS_MODE_2K: > + fe_tps->transmission_mode = TRANSMISSION_MODE_2K; > + break; > + case TRANS_MODE_8K: > + fe_tps->transmission_mode = TRANSMISSION_MODE_8K; > + break; > + } > +} > + > +static uint8_t as102_fe_get_code_rate(fe_code_rate_t arg) > +{ > + uint8_t c; > + > + switch (arg) { > + case FEC_1_2: > + c = CODE_RATE_1_2; > + break; > + case FEC_2_3: > + c = CODE_RATE_2_3; > + break; > + case FEC_3_4: > + c = CODE_RATE_3_4; > + break; > + case FEC_5_6: > + c = CODE_RATE_5_6; > + break; > + case FEC_7_8: > + c = CODE_RATE_7_8; > + break; > + default: > + c = CODE_RATE_UNKNOWN; > + break; > + } > + > + return c; > +} > + > +static void as102_fe_copy_tune_parameters(struct as10x_tune_args *tune_args, > + struct dvb_frontend_parameters *params) > +{ > + > + /* set frequency */ > + tune_args->freq = params->frequency / 1000; > + > + /* fix interleaving_mode */ > + tune_args->interleaving_mode = INTLV_NATIVE; > + > + switch (params->u.ofdm.bandwidth) { > + case BANDWIDTH_8_MHZ: > + tune_args->bandwidth = BW_8_MHZ; > + break; > + case BANDWIDTH_7_MHZ: > + tune_args->bandwidth = BW_7_MHZ; > + break; > + case BANDWIDTH_6_MHZ: > + tune_args->bandwidth = BW_6_MHZ; > + break; > + default: > + tune_args->bandwidth = BW_8_MHZ; > + } > + > + switch (params->u.ofdm.guard_interval) { > + case GUARD_INTERVAL_1_32: > + tune_args->guard_interval = GUARD_INT_1_32; > + break; > + case GUARD_INTERVAL_1_16: > + tune_args->guard_interval = GUARD_INT_1_16; > + break; > + case GUARD_INTERVAL_1_8: > + tune_args->guard_interval = GUARD_INT_1_8; > + break; > + case GUARD_INTERVAL_1_4: > + tune_args->guard_interval = GUARD_INT_1_4; > + break; > + case GUARD_INTERVAL_AUTO: > + default: > + tune_args->guard_interval = GUARD_UNKNOWN; > + break; > + } > + > + switch (params->u.ofdm.constellation) { > + case QPSK: > + tune_args->constellation = CONST_QPSK; > + break; > + case QAM_16: > + tune_args->constellation = CONST_QAM16; > + break; > + case QAM_64: > + tune_args->constellation = CONST_QAM64; > + break; > + default: > + tune_args->constellation = CONST_UNKNOWN; > + break; > + } > + > + switch (params->u.ofdm.transmission_mode) { > + case TRANSMISSION_MODE_2K: > + tune_args->transmission_mode = TRANS_MODE_2K; > + break; > + case TRANSMISSION_MODE_8K: > + tune_args->transmission_mode = TRANS_MODE_8K; > + break; > + default: > + tune_args->transmission_mode = TRANS_MODE_UNKNOWN; > + } > + > + switch (params->u.ofdm.hierarchy_information) { > + case HIERARCHY_NONE: > + tune_args->hierarchy = HIER_NONE; > + break; > + case HIERARCHY_1: > + tune_args->hierarchy = HIER_ALPHA_1; > + break; > + case HIERARCHY_2: > + tune_args->hierarchy = HIER_ALPHA_2; > + break; > + case HIERARCHY_4: > + tune_args->hierarchy = HIER_ALPHA_4; > + break; > + case HIERARCHY_AUTO: > + tune_args->hierarchy = HIER_UNKNOWN; > + break; > + } > + > + dprintk(debug, "tuner parameters: freq: %d bw: 0x%02x gi: 0x%02x\n", > + params->frequency, > + tune_args->bandwidth, > + tune_args->guard_interval); > + > + /* > + * Detect a hierarchy selection > + * if HP/LP are both set to FEC_NONE, HP will be selected. > + */ > + if ((tune_args->hierarchy != HIER_NONE) && > + ((params->u.ofdm.code_rate_LP == FEC_NONE) || > + (params->u.ofdm.code_rate_HP == FEC_NONE))) { > + > + if (params->u.ofdm.code_rate_LP == FEC_NONE) { > + tune_args->hier_select = HIER_HIGH_PRIORITY; > + tune_args->code_rate = > + as102_fe_get_code_rate(params->u.ofdm.code_rate_HP); > + } > + > + if (params->u.ofdm.code_rate_HP == FEC_NONE) { > + tune_args->hier_select = HIER_LOW_PRIORITY; > + tune_args->code_rate = > + as102_fe_get_code_rate(params->u.ofdm.code_rate_LP); > + } > + > + dprintk(debug, "\thierarchy: 0x%02x " > + "selected: %s code_rate_%s: 0x%02x\n", > + tune_args->hierarchy, > + tune_args->hier_select == HIER_HIGH_PRIORITY ? > + "HP" : "LP", > + tune_args->hier_select == HIER_HIGH_PRIORITY ? > + "HP" : "LP", > + tune_args->code_rate); > + } else { > + tune_args->code_rate = > + as102_fe_get_code_rate(params->u.ofdm.code_rate_HP); > + } > +} > +#endif > + > +/* EOF - vim: set textwidth=80 ts=8 sw=8 sts=8 noet: */ > diff --git a/drivers/media/dvb/as102/as102_fw.c b/drivers/media/dvb/as102/as102_fw.c > new file mode 100644 > index 0000000..c019df9 > --- /dev/null > +++ b/drivers/media/dvb/as102/as102_fw.c > @@ -0,0 +1,251 @@ > +/* > + * Abilis Systems Single DVB-T Receiver > + * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@xxxxxxxxxx> > + * Copyright (C) 2010 Devin Heitmueller <dheitmueller@xxxxxxxxxxxxxx> > + * > + * 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. > + */ > +#include <linux/kernel.h> > +#include <linux/errno.h> > +#include <linux/ctype.h> > +#include <linux/delay.h> > +#include <linux/firmware.h> > + > +#include "as102_drv.h" > +#include "as102_fw.h" > + > +#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE) > +char as102_st_fw1[] = "as102_data1_st.hex"; > +char as102_st_fw2[] = "as102_data2_st.hex"; > +char as102_dt_fw1[] = "as102_data1_dt.hex"; > +char as102_dt_fw2[] = "as102_data2_dt.hex"; > + > +static unsigned char atohx(unsigned char *dst, char *src) > +{ > + unsigned char value = 0; > + > + char msb = tolower(*src) - '0'; > + char lsb = tolower(*(src + 1)) - '0'; > + > + if (msb > 9) > + msb -= 7; > + if (lsb > 9) > + lsb -= 7; > + > + *dst = value = ((msb & 0xF) << 4) | (lsb & 0xF); > + return value; > +} > + > +/* > + * Parse INTEL HEX firmware file to extract address and data. > + */ > +static int parse_hex_line(unsigned char *fw_data, unsigned char *addr, > + unsigned char *data, int *dataLength, > + unsigned char *addr_has_changed) { > + > + int count = 0; > + unsigned char *src, dst; > + > + if (*fw_data++ != ':') { > + printk(KERN_ERR "invalid firmware file\n"); > + return -EFAULT; > + } > + > + /* locate end of line */ > + for (src = fw_data; *src != '\n'; src += 2) { > + atohx(&dst, src); > + /* parse line to split addr / data */ > + switch (count) { > + case 0: > + *dataLength = dst; > + break; > + case 1: > + addr[2] = dst; > + break; > + case 2: > + addr[3] = dst; > + break; > + case 3: > + /* check if data is an address */ > + if (dst == 0x04) > + *addr_has_changed = 1; > + else > + *addr_has_changed = 0; > + break; > + case 4: > + case 5: > + if (*addr_has_changed) > + addr[(count - 4)] = dst; > + else > + data[(count - 4)] = dst; > + break; > + default: > + data[(count - 4)] = dst; > + break; > + } > + count++; > + } > + > + /* return read value + ':' + '\n' */ > + return (count * 2) + 2; > +} > + > +static int as102_firmware_upload(struct as102_bus_adapter_t *bus_adap, > + unsigned char *cmd, > + const struct firmware *firmware) { > + > + struct as10x_fw_pkt_t fw_pkt; > + int total_read_bytes = 0, errno = 0; > + unsigned char addr_has_changed = 0; > + > + ENTER(); > + > + for (total_read_bytes = 0; total_read_bytes < firmware->size; ) { > + int read_bytes = 0, data_len = 0; > + > + /* parse intel hex line */ > + read_bytes = parse_hex_line( > + (u8 *) (firmware->data + total_read_bytes), > + fw_pkt.raw.address, > + fw_pkt.raw.data, > + &data_len, > + &addr_has_changed); > + > + if (read_bytes <= 0) > + goto error; > + > + /* detect the end of file */ > + total_read_bytes += read_bytes; > + if (total_read_bytes == firmware->size) { > + fw_pkt.u.request[0] = 0x00; > + fw_pkt.u.request[1] = 0x03; > + > + /* send EOF command */ > + errno = bus_adap->ops->upload_fw_pkt(bus_adap, > + (uint8_t *) > + &fw_pkt, 2, 0); > + if (errno < 0) > + goto error; > + } else { > + if (!addr_has_changed) { > + /* prepare command to send */ > + fw_pkt.u.request[0] = 0x00; > + fw_pkt.u.request[1] = 0x01; > + > + data_len += sizeof(fw_pkt.u.request); > + data_len += sizeof(fw_pkt.raw.address); > + > + /* send cmd to device */ > + errno = bus_adap->ops->upload_fw_pkt(bus_adap, > + (uint8_t *) > + &fw_pkt, > + data_len, > + 0); > + if (errno < 0) > + goto error; > + } > + } > + } > +error: > + LEAVE(); > + return (errno == 0) ? total_read_bytes : errno; > +} > + > +int as102_fw_upload(struct as102_bus_adapter_t *bus_adap) > +{ > + int errno = -EFAULT; > + const struct firmware *firmware; > + unsigned char *cmd_buf = NULL; > + char *fw1, *fw2; > + > +#if defined(CONFIG_AS102_USB) > + struct usb_device *dev = bus_adap->usb_dev; > +#endif > +#if defined(CONFIG_AS102_SPI) > + struct spi_device *dev = bus_adap->spi_dev; > +#endif If both options are enabled, the above will generate a compilation error. Maybe the better is to use void *dev. > + ENTER(); > + > + /* select fw file to upload */ > + if (dual_tuner) { > + fw1 = as102_dt_fw1; > + fw2 = as102_dt_fw2; > + } else { > + fw1 = as102_st_fw1; > + fw2 = as102_st_fw2; > + } > + > +#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE) > + /* allocate buffer to store firmware upload command and data */ > + cmd_buf = kzalloc(MAX_FW_PKT_SIZE, GFP_KERNEL); > + if (cmd_buf == NULL) { > + errno = -ENOMEM; > + goto error; > + } > + > + /* request kernel to locate firmware file: part1 */ > + errno = request_firmware(&firmware, fw1, &dev->dev); > + if (errno < 0) { > + printk(KERN_ERR "%s: unable to locate firmware file: %s\n", > + DRIVER_NAME, fw1); > + goto error; > + } > + > + /* initiate firmware upload */ > + errno = as102_firmware_upload(bus_adap, cmd_buf, firmware); > + if (errno < 0) { > + printk(KERN_ERR "%s: error during firmware upload part1\n", > + DRIVER_NAME); > + goto error; > + } > + > + printk(KERN_INFO "%s: fimrware: %s loaded with success\n", > + DRIVER_NAME, fw1); > + release_firmware(firmware); > + > + /* wait for boot to complete */ > + mdelay(100); better to use msleep(). > + > + /* request kernel to locate firmware file: part2 */ > + errno = request_firmware(&firmware, fw2, &dev->dev); > + if (errno < 0) { > + printk(KERN_ERR "%s: unable to locate firmware file: %s\n", > + DRIVER_NAME, fw2); > + goto error; > + } > + > + /* initiate firmware upload */ > + errno = as102_firmware_upload(bus_adap, cmd_buf, firmware); > + if (errno < 0) { > + printk(KERN_ERR "%s: error during firmware upload part2\n", > + DRIVER_NAME); > + goto error; > + } > + > + printk(KERN_INFO "%s: fimrware: %s loaded with success\n", > + DRIVER_NAME, fw2); > +error: > + /* free data buffer */ > + kfree(cmd_buf); > + /* release firmware if needed */ > + if (firmware != NULL) > + release_firmware(firmware); > +#endif > + LEAVE(); > + return errno; > +} > +#endif > + > +/* EOF - vim: set textwidth=80 ts=8 sw=8 sts=8 noet: */ > diff --git a/drivers/media/dvb/as102/as102_fw.h b/drivers/media/dvb/as102/as102_fw.h > new file mode 100644 > index 0000000..27e5347 > --- /dev/null > +++ b/drivers/media/dvb/as102/as102_fw.h > @@ -0,0 +1,42 @@ > +/* > + * Abilis Systems Single DVB-T Receiver > + * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@xxxxxxxxxx> > + * > + * 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. > + */ > +#define MAX_FW_PKT_SIZE 64 > + > +extern int dual_tuner; > + > +#pragma pack(1) > +struct as10x_raw_fw_pkt { > + unsigned char address[4]; > + unsigned char data[MAX_FW_PKT_SIZE - 6]; > +}; > + > +struct as10x_fw_pkt_t { > + union { > + unsigned char request[2]; > + unsigned char length[2]; > + } u; > + struct as10x_raw_fw_pkt raw; > +}; > +#pragma pack() Huh? Why do you need a pragma here? Just use __attribute__ ((packed)); at the structs you need to be packed. > + > +#ifdef __KERNEL__ > +int as102_fw_upload(struct as102_bus_adapter_t *bus_adap); > +#endif Don't check for __KERNEL__. This header is for kernel-only usage. > + > +/* EOF - vim: set textwidth=80 ts=8 sw=8 sts=8 noet: */ > diff --git a/drivers/media/dvb/as102/as102_usb_drv.c b/drivers/media/dvb/as102/as102_usb_drv.c > new file mode 100644 > index 0000000..3bdbc37 > --- /dev/null > +++ b/drivers/media/dvb/as102/as102_usb_drv.c > @@ -0,0 +1,480 @@ > +/* > + * Abilis Systems Single DVB-T Receiver > + * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@xxxxxxxxxx> > + * Copyright (C) 2010 Devin Heitmueller <dheitmueller@xxxxxxxxxxxxxx> > + * > + * 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. > + */ > +#include <linux/kernel.h> > +#include <linux/errno.h> > +#include <linux/slab.h> > +#include <linux/mm.h> > +#include <linux/usb.h> > + > +#include "as102_drv.h" > +#include "as102_usb_drv.h" > +#include "as102_fw.h" > + > +static void as102_usb_disconnect(struct usb_interface *interface); > +static int as102_usb_probe(struct usb_interface *interface, > + const struct usb_device_id *id); > + > +static int as102_usb_start_stream(struct as102_dev_t *dev); > +static void as102_usb_stop_stream(struct as102_dev_t *dev); > + > +static int as102_open(struct inode *inode, struct file *file); > +static int as102_release(struct inode *inode, struct file *file); > + > +static struct usb_device_id as102_usb_id_table[] = { > + { USB_DEVICE(AS102_USB_DEVICE_VENDOR_ID, AS102_USB_DEVICE_PID_0001) }, > + { USB_DEVICE(PCTV_74E_USB_VID, PCTV_74E_USB_PID) }, > + { USB_DEVICE(ELGATO_EYETV_DTT_USB_VID, ELGATO_EYETV_DTT_USB_PID) }, > + { } /* Terminating entry */ > +}; > + > +/* Note that this table must always have the same number of entries as the > + as102_usb_id_table struct */ > +static const char *as102_device_names[] = { > + AS102_REFERENCE_DESIGN, > + AS102_PCTV_74E, > + AS102_ELGATO_EYETV_DTT_NAME, > + NULL /* Terminating entry */ > +}; Better to use usb_device_id::driver_into to associate names (and eventually other info) to the board. > + > +struct usb_driver as102_usb_driver = { > + .name = DRIVER_FULL_NAME, > + .probe = as102_usb_probe, > + .disconnect = as102_usb_disconnect, > + .id_table = as102_usb_id_table > +}; > + > +static const struct file_operations as102_dev_fops = { > + .owner = THIS_MODULE, > + .open = as102_open, > + .release = as102_release, > +}; > + > +static struct usb_class_driver as102_usb_class_driver = { > + .name = "aton2-%d", > + .fops = &as102_dev_fops, > + .minor_base = AS102_DEVICE_MAJOR, > +}; > + > +static int as102_usb_xfer_cmd(struct as102_bus_adapter_t *bus_adap, > + unsigned char *send_buf, int send_buf_len, > + unsigned char *recv_buf, int recv_buf_len) > +{ > + int ret = 0; > + ENTER(); > + It should be noticed that the buffers used for usb need to be on an area where DMA is allowed. That means that you cannot use any stack-based buffer. So, it is very likely that you'll need to allocate some temporary buffer here. > + if (send_buf != NULL) { > + ret = usb_control_msg(bus_adap->usb_dev, > + usb_sndctrlpipe(bus_adap->usb_dev, 0), > + AS102_USB_DEVICE_TX_CTRL_CMD, > + USB_DIR_OUT | USB_TYPE_VENDOR | > + USB_RECIP_DEVICE, > + bus_adap->cmd_xid, /* value */ > + 0, /* index */ > + send_buf, send_buf_len, > + USB_CTRL_SET_TIMEOUT /* 200 */); > + if (ret < 0) { > + dprintk(debug, "usb_control_msg(send) failed, err %i\n", > + ret); > + return ret; > + } > + > + if (ret != send_buf_len) { > + dprintk(debug, "only wrote %d of %d bytes\n", > + ret, send_buf_len); > + return -1; > + } > + } > + > + if (recv_buf != NULL) { > +#ifdef TRACE > + dprintk(debug, "want to read: %d bytes\n", recv_buf_len); > +#endif > + ret = usb_control_msg(bus_adap->usb_dev, > + usb_rcvctrlpipe(bus_adap->usb_dev, 0), > + AS102_USB_DEVICE_RX_CTRL_CMD, > + USB_DIR_IN | USB_TYPE_VENDOR | > + USB_RECIP_DEVICE, > + bus_adap->cmd_xid, /* value */ > + 0, /* index */ > + recv_buf, recv_buf_len, > + USB_CTRL_GET_TIMEOUT /* 200 */); > + if (ret < 0) { > + dprintk(debug, "usb_control_msg(recv) failed, err %i\n", > + ret); > + return ret; > + } > +#ifdef TRACE > + dprintk(debug, "read %d bytes\n", recv_buf_len); > +#endif > + } > + > + LEAVE(); > + return ret; > +} > + > +static int as102_send_ep1(struct as102_bus_adapter_t *bus_adap, > + unsigned char *send_buf, > + int send_buf_len, > + int swap32) > +{ > + int ret = 0, actual_len; > + > + ret = usb_bulk_msg(bus_adap->usb_dev, > + usb_sndbulkpipe(bus_adap->usb_dev, 1), > + send_buf, send_buf_len, &actual_len, 200); > + if (ret) { > + dprintk(debug, "usb_bulk_msg(send) failed, err %i\n", ret); > + return ret; > + } > + > + if (actual_len != send_buf_len) { > + dprintk(debug, "only wrote %d of %d bytes\n", > + actual_len, send_buf_len); > + return -1; > + } > + return ret ? ret : actual_len; > +} > + > +static int as102_read_ep2(struct as102_bus_adapter_t *bus_adap, > + unsigned char *recv_buf, int recv_buf_len) > +{ > + int ret = 0, actual_len; > + > + if (recv_buf == NULL) > + return -EINVAL; > + > + ret = usb_bulk_msg(bus_adap->usb_dev, > + usb_rcvbulkpipe(bus_adap->usb_dev, 2), > + recv_buf, recv_buf_len, &actual_len, 200); > + if (ret) { > + dprintk(debug, "usb_bulk_msg(recv) failed, err %i\n", ret); > + return ret; > + } > + > + if (actual_len != recv_buf_len) { > + dprintk(debug, "only read %d of %d bytes\n", > + actual_len, recv_buf_len); > + return -1; > + } > + return ret ? ret : actual_len; > +} > + > +struct as102_priv_ops_t as102_priv_ops = { > + .upload_fw_pkt = as102_send_ep1, > + .xfer_cmd = as102_usb_xfer_cmd, > + .as102_read_ep2 = as102_read_ep2, > + .start_stream = as102_usb_start_stream, > + .stop_stream = as102_usb_stop_stream, > +}; > + > +static int as102_submit_urb_stream(struct as102_dev_t *dev, struct urb *urb) > +{ > + int err; > + > + usb_fill_bulk_urb(urb, > + dev->bus_adap.usb_dev, > + usb_rcvbulkpipe(dev->bus_adap.usb_dev, 0x2), > + urb->transfer_buffer, > + AS102_USB_BUF_SIZE, > + as102_urb_stream_irq, > + dev); > + > + err = usb_submit_urb(urb, GFP_ATOMIC); > + if (err) > + dprintk(debug, "%s: usb_submit_urb failed\n", __func__); > + > + return err; > +} > + > +void as102_urb_stream_irq(struct urb *urb) > +{ > + struct as102_dev_t *as102_dev = urb->context; > + > + if (urb->actual_length > 0) { > +#if defined(CONFIG_DVB_CORE) || defined(CONFIG_DVB_CORE_MODULE) > + dvb_dmx_swfilter(&as102_dev->dvb_dmx, > + urb->transfer_buffer, > + urb->actual_length); > +#else > + /* do nothing ? */ > +#endif Same here: shouldn't check for DVB_CORE. > + } else { > + if (urb->actual_length == 0) > + memset(urb->transfer_buffer, 0, AS102_USB_BUF_SIZE); > + } > + > + /* is not stopped, re-submit urb */ > + if (as102_dev->streaming) > + as102_submit_urb_stream(as102_dev, urb); > +} > + > +static void as102_free_usb_stream_buffer(struct as102_dev_t *dev) > +{ > + int i; > + > + ENTER(); > + > + for (i = 0; i < MAX_STREAM_URB; i++) > + usb_free_urb(dev->stream_urb[i]); > + > + usb_buffer_free(dev->bus_adap.usb_dev, > + MAX_STREAM_URB * AS102_USB_BUF_SIZE, > + dev->stream, > + dev->dma_addr); > + LEAVE(); > +} > + > +static int as102_alloc_usb_stream_buffer(struct as102_dev_t *dev) > +{ > + int i, ret = 0; > + > + ENTER(); > + > + dev->stream = usb_buffer_alloc(dev->bus_adap.usb_dev, > + MAX_STREAM_URB * AS102_USB_BUF_SIZE, > + GFP_KERNEL, > + &dev->dma_addr); > + if (!dev->stream) { > + dprintk(debug, "%s: usb_buffer_alloc failed\n", __func__); > + return -ENOMEM; > + } > + > + memset(dev->stream, 0, MAX_STREAM_URB * AS102_USB_BUF_SIZE); > + > + /* init urb buffers */ > + for (i = 0; i < MAX_STREAM_URB; i++) { > + struct urb *urb; > + > + urb = usb_alloc_urb(0, GFP_ATOMIC); > + if (urb == NULL) { > + dprintk(debug, "%s: usb_alloc_urb failed\n", __func__); > + as102_free_usb_stream_buffer(dev); > + return -ENOMEM; > + } > + > + urb->transfer_buffer = dev->stream + (i * AS102_USB_BUF_SIZE); > + urb->transfer_buffer_length = AS102_USB_BUF_SIZE; > + > + dev->stream_urb[i] = urb; > + } > + LEAVE(); > + return ret; > +} > + > +static void as102_usb_stop_stream(struct as102_dev_t *dev) > +{ > + int i; > + > + for (i = 0; i < MAX_STREAM_URB; i++) > + usb_kill_urb(dev->stream_urb[i]); > +} > + > +static int as102_usb_start_stream(struct as102_dev_t *dev) > +{ > + int i, ret = 0; > + > + for (i = 0; i < MAX_STREAM_URB; i++) { > + ret = as102_submit_urb_stream(dev, dev->stream_urb[i]); > + if (ret) { > + as102_usb_stop_stream(dev); > + return ret; > + } > + } > + > + return 0; > +} > + > +static void as102_usb_release(struct kref *kref) > +{ > + struct as102_dev_t *as102_dev; > + > + ENTER(); > + > + as102_dev = container_of(kref, struct as102_dev_t, kref); > + if (as102_dev != NULL) { > + usb_put_dev(as102_dev->bus_adap.usb_dev); > + kfree(as102_dev); > + } > + > + LEAVE(); > +} > + > +static void as102_usb_disconnect(struct usb_interface *intf) > +{ > + struct as102_dev_t *as102_dev; > + > + ENTER(); > + > + /* extract as102_dev_t from usb_device private data */ > + as102_dev = usb_get_intfdata(intf); > + > + /* unregister dvb layer */ > + as102_dvb_unregister(as102_dev); > + > + /* free usb buffers */ > + as102_free_usb_stream_buffer(as102_dev); > + > + usb_set_intfdata(intf, NULL); > + > + /* usb unregister device */ > + usb_deregister_dev(intf, &as102_usb_class_driver); > + > + /* decrement usage counter */ > + kref_put(&as102_dev->kref, as102_usb_release); > + > + printk(KERN_INFO "%s: device has been disconnected\n", DRIVER_NAME); > + > + LEAVE(); > +} > + > +static int as102_usb_probe(struct usb_interface *intf, > + const struct usb_device_id *id) > +{ > + int ret; > + struct as102_dev_t *as102_dev; > + int i; > + > + ENTER(); > + > + as102_dev = kzalloc(sizeof(struct as102_dev_t), GFP_KERNEL); > + if (as102_dev == NULL) { > + err("%s: kzalloc failed", __func__); > + return -ENOMEM; > + } > + > + /* This should never actually happen */ > + if ((sizeof(as102_usb_id_table) / sizeof(struct usb_device_id)) != > + (sizeof(as102_device_names) / sizeof(const char *))) { > + printk(KERN_ERR "Device names table invalid size"); > + return -EINVAL; > + } > + > + /* Assign the user-friendly device name */ > + for (i = 0; i < (sizeof(as102_usb_id_table) / > + sizeof(struct usb_device_id)); i++) { > + if (id == &as102_usb_id_table[i]) > + as102_dev->name = as102_device_names[i]; > + } > + > + if (as102_dev->name == NULL) > + as102_dev->name = "Unknown AS102 device"; > + > + /* set private callback functions */ > + as102_dev->bus_adap.ops = &as102_priv_ops; > + > + /* init cmd token for usb bus */ > + as102_dev->bus_adap.cmd = &as102_dev->bus_adap.token.usb.c; > + as102_dev->bus_adap.rsp = &as102_dev->bus_adap.token.usb.r; > + > + /* init kernel device reference */ > + kref_init(&as102_dev->kref); > + > + /* store as102 device to usb_device private data */ > + usb_set_intfdata(intf, (void *) as102_dev); > + > + /* store in as102 device the usb_device pointer */ > + as102_dev->bus_adap.usb_dev = usb_get_dev(interface_to_usbdev(intf)); > + > + /* we can register the device now, as it is ready */ > + ret = usb_register_dev(intf, &as102_usb_class_driver); > + if (ret < 0) { > + /* something prevented us from registering this driver */ > + err("%s: usb_register_dev() failed (errno = %d)", > + __func__, ret); > + goto failed; > + } > + > + printk(KERN_INFO "%s: device has been detected\n", DRIVER_NAME); > + > + /* request buffer allocation for streaming */ > + ret = as102_alloc_usb_stream_buffer(as102_dev); > + if (ret != 0) > + goto failed; > + > + /* register dvb layer */ > + ret = as102_dvb_register(as102_dev); > + > + LEAVE(); > + return ret; > + > +failed: > + usb_set_intfdata(intf, NULL); > + kfree(as102_dev); > + return ret; > +} > + > +static int as102_open(struct inode *inode, struct file *file) > +{ > + int ret = 0, minor = 0; > + struct usb_interface *intf = NULL; > + struct as102_dev_t *dev = NULL; > + > + ENTER(); > + > + /* read minor from inode */ > + minor = iminor(inode); > + > + /* fetch device from usb interface */ > + intf = usb_find_interface(&as102_usb_driver, minor); > + if (intf == NULL) { > + printk(KERN_ERR "%s: can't find device for minor %d\n", > + __func__, minor); > + ret = -ENODEV; > + goto exit; > + } > + > + /* get our device */ > + dev = usb_get_intfdata(intf); > + if (dev == NULL) { > + ret = -EFAULT; > + goto exit; > + } > + > + /* save our device object in the file's private structure */ > + file->private_data = dev; > + > + /* increment our usage count for the device */ > + kref_get(&dev->kref); > + > +exit: > + LEAVE(); > + return ret; > +} > + > +static int as102_release(struct inode *inode, struct file *file) > +{ > + int ret = 0; > + struct as102_dev_t *dev = NULL; > + > + ENTER(); > + > + dev = file->private_data; > + if (dev != NULL) { > + /* decrement the count on our device */ > + kref_put(&dev->kref, as102_usb_release); > + } > + > + LEAVE(); > + return ret; > +} > + > +MODULE_DEVICE_TABLE(usb, as102_usb_id_table); > + > +/* EOF - vim: set textwidth=80 ts=8 sw=8 sts=8 noet: */ > diff --git a/drivers/media/dvb/as102/as102_usb_drv.h b/drivers/media/dvb/as102/as102_usb_drv.h > new file mode 100644 > index 0000000..db47a70 > --- /dev/null > +++ b/drivers/media/dvb/as102/as102_usb_drv.h > @@ -0,0 +1,55 @@ > +/* > + * Abilis Systems Single DVB-T Receiver > + * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@xxxxxxxxxx> > + * Copyright (C) 2010 Devin Heitmueller <dheitmueller@xxxxxxxxxxxxxx> > + * > + * 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. > + */ > +#include <linux/version.h> > + > +#ifndef _AS102_USB_DRV_H_ > +#define _AS102_USB_DRV_H_ > + > +#define AS102_USB_DEVICE_TX_CTRL_CMD 0xF1 > +#define AS102_USB_DEVICE_RX_CTRL_CMD 0xF2 > + > +/* define these values to match the supported devices */ > + > +/* Abilis system: "TITAN" */ > +#define AS102_REFERENCE_DESIGN "Abilis Systems DVB-Titan" > +#define AS102_USB_DEVICE_VENDOR_ID 0x1BA6 > +#define AS102_USB_DEVICE_PID_0001 0x0001 > + > +/* PCTV Systems: PCTV picoStick (74e) */ > +#define AS102_PCTV_74E "PCTV Systems picoStick (74e)" > +#define PCTV_74E_USB_VID 0x2013 > +#define PCTV_74E_USB_PID 0x0246 > + > +/* Elgato: EyeTV DTT Deluxe */ > +#define AS102_ELGATO_EYETV_DTT_NAME "Elgato EyeTV DTT Deluxe" > +#define ELGATO_EYETV_DTT_USB_VID 0x0fd9 > +#define ELGATO_EYETV_DTT_USB_PID 0x002c Better to put the addresses at drivers/media/dvb/dvb-usb/dvb-usb-ids.h > + > +void as102_urb_stream_irq(struct urb *urb); > + > + > +struct as10x_usb_token_cmd_t { > + /* token cmd */ > + struct as10x_cmd_t c; > + /* token response */ > + struct as10x_cmd_t r; > +}; > +#endif > +/* EOF - vim: set textwidth=80 ts=8 sw=8 sts=8 noet: */ > diff --git a/drivers/media/dvb/as102/as10x_cmd.c b/drivers/media/dvb/as102/as10x_cmd.c > new file mode 100644 > index 0000000..222e703 > --- /dev/null > +++ b/drivers/media/dvb/as102/as10x_cmd.c > @@ -0,0 +1,481 @@ > +/* > + * Abilis Systems Single DVB-T Receiver > + * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@xxxxxxxxxx> > + * Copyright (C) 2010 Devin Heitmueller <dheitmueller@xxxxxxxxxxxxxx> > + * > + * 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. > + */ > + > +#if defined(LINUX) && defined(__KERNEL__) /* linux kernel implementation */ Why test it? It will always be true. > +#include <linux/kernel.h> > +#include "as102_drv.h" > +#elif defined(WIN32) NO!!! Just strip any code for any other OS. > + #if defined(__BUILDMACHINE__) && (__BUILDMACHINE__ == WinDDK) > + /* win32 ddk implementation */ > + #include "wdm.h" > + #include "Device.h" > + #include "endian_mgmt.h" /* FIXME */ > + #else /* win32 sdk implementation */ > + #include <windows.h> > + #include "types.h" > + #include "util.h" > + #include "as10x_handle.h" > + #include "endian_mgmt.h" > + #endif > +#else /* all other cases */ > + #include <string.h> > + #include "types.h" > + #include "util.h" > + #include "as10x_handle.h" > + #include "endian_mgmt.h" /* FIXME */ > +#endif /* __KERNEL__ */ > + > +#include "as10x_types.h" > +#include "as10x_cmd.h" > + > +/** > + \brief send turn on command to AS10x > + \param phandle: pointer to AS10x handle > + \return 0 when no error, < 0 in case of error. > + \callgraph > +*/ This comment is out of the format. It should be following Documentation/kernel-doc-nano-HOWTO.txt > +int as10x_cmd_turn_on(as10x_handle_t *phandle) > +{ > + int error; > + struct as10x_cmd_t *pcmd, *prsp; > + > + ENTER(); > + > + pcmd = phandle->cmd; > + prsp = phandle->rsp; > + > + /* prepare command */ > + as10x_cmd_build(pcmd, (++phandle->cmd_xid), > + sizeof(pcmd->body.turn_on.req)); > + > + /* fill command */ > + pcmd->body.turn_on.req.proc_id = cpu_to_le16(CONTROL_PROC_TURNON); > + > + /* send command */ > + if (phandle->ops->xfer_cmd) { > + error = phandle->ops->xfer_cmd(phandle, (uint8_t *) pcmd, > + sizeof(pcmd->body.turn_on.req) + > + HEADER_SIZE, > + (uint8_t *) prsp, > + sizeof(prsp->body.turn_on.rsp) + > + HEADER_SIZE); > + } else { > + error = AS10X_CMD_ERROR; > + } > + > + if (error < 0) > + goto out; > + > + /* parse response */ > + error = as10x_rsp_parse(prsp, CONTROL_PROC_TURNON_RSP); > + > +out: > + LEAVE(); > + return error; > +} > + > +/** > + \brief send turn off command to AS10x > + \param phandle: pointer to AS10x handle > + \return 0 when no error, < 0 in case of error. > + \callgraph > +*/ This comment is out of the format. It should be following Documentation/kernel-doc-nano-HOWTO.txt > +int as10x_cmd_turn_off(as10x_handle_t *phandle) > +{ > + int error; > + struct as10x_cmd_t *pcmd, *prsp; > + > + ENTER(); > + > + pcmd = phandle->cmd; > + prsp = phandle->rsp; > + > + /* prepare command */ > + as10x_cmd_build(pcmd, (++phandle->cmd_xid), > + sizeof(pcmd->body.turn_off.req)); > + > + /* fill command */ > + pcmd->body.turn_off.req.proc_id = cpu_to_le16(CONTROL_PROC_TURNOFF); > + > + /* send command */ > + if (phandle->ops->xfer_cmd) { > + error = phandle->ops->xfer_cmd( > + phandle, (uint8_t *) pcmd, > + sizeof(pcmd->body.turn_off.req) + HEADER_SIZE, > + (uint8_t *) prsp, > + sizeof(prsp->body.turn_off.rsp) + HEADER_SIZE); > + } else { > + error = AS10X_CMD_ERROR; > + } > + > + if (error < 0) > + goto out; > + > + /* parse response */ > + error = as10x_rsp_parse(prsp, CONTROL_PROC_TURNOFF_RSP); > + > +out: > + LEAVE(); > + return error; > +} > + > +/** > + \brief send set tune command to AS10x > + \param phandle: pointer to AS10x handle > + \param ptune: tune parameters > + \return 0 when no error, < 0 in case of error. > + \callgraph > + */ This comment is out of the format. It should be following Documentation/kernel-doc-nano-HOWTO.txt > +int as10x_cmd_set_tune(as10x_handle_t *phandle, struct as10x_tune_args *ptune) > +{ > + int error; > + struct as10x_cmd_t *preq, *prsp; > + > + ENTER(); > + > + preq = phandle->cmd; > + prsp = phandle->rsp; > + > + /* prepare command */ > + as10x_cmd_build(preq, (++phandle->cmd_xid), > + sizeof(preq->body.set_tune.req)); > + > + /* fill command */ > + preq->body.set_tune.req.proc_id = cpu_to_le16(CONTROL_PROC_SETTUNE); > + preq->body.set_tune.req.args.freq = cpu_to_le32(ptune->freq); > + preq->body.set_tune.req.args.bandwidth = ptune->bandwidth; > + preq->body.set_tune.req.args.hier_select = ptune->hier_select; > + preq->body.set_tune.req.args.constellation = ptune->constellation; > + preq->body.set_tune.req.args.hierarchy = ptune->hierarchy; > + preq->body.set_tune.req.args.interleaving_mode = > + ptune->interleaving_mode; > + preq->body.set_tune.req.args.code_rate = ptune->code_rate; > + preq->body.set_tune.req.args.guard_interval = ptune->guard_interval; > + preq->body.set_tune.req.args.transmission_mode = > + ptune->transmission_mode; > + > + /* send command */ > + if (phandle->ops->xfer_cmd) { > + error = phandle->ops->xfer_cmd(phandle, > + (uint8_t *) preq, > + sizeof(preq->body.set_tune.req) > + + HEADER_SIZE, > + (uint8_t *) prsp, > + sizeof(prsp->body.set_tune.rsp) > + + HEADER_SIZE); > + } else { > + error = AS10X_CMD_ERROR; > + } > + > + if (error < 0) > + goto out; > + > + /* parse response */ > + error = as10x_rsp_parse(prsp, CONTROL_PROC_SETTUNE_RSP); > + > +out: > + LEAVE(); > + return error; > +} > + > +/** > + \brief send get tune status command to AS10x > + \param phandle: pointer to AS10x handle > + \param pstatus: pointer to updated status structure of the current tune > + \return 0 when no error, < 0 in case of error. > + \callgraph > + */ This comment is out of the format. It should be following Documentation/kernel-doc-nano-HOWTO.txt > +int as10x_cmd_get_tune_status(as10x_handle_t *phandle, > + struct as10x_tune_status *pstatus) > +{ > + int error; > + struct as10x_cmd_t *preq, *prsp; > + > + ENTER(); > + > + preq = phandle->cmd; > + prsp = phandle->rsp; > + > + /* prepare command */ > + as10x_cmd_build(preq, (++phandle->cmd_xid), > + sizeof(preq->body.get_tune_status.req)); > + > + /* fill command */ > + preq->body.get_tune_status.req.proc_id = > + cpu_to_le16(CONTROL_PROC_GETTUNESTAT); > + > + /* send command */ > + if (phandle->ops->xfer_cmd) { > + error = phandle->ops->xfer_cmd( > + phandle, > + (uint8_t *) preq, > + sizeof(preq->body.get_tune_status.req) + HEADER_SIZE, > + (uint8_t *) prsp, > + sizeof(prsp->body.get_tune_status.rsp) + HEADER_SIZE); > + } else { > + error = AS10X_CMD_ERROR; > + } > + > + if (error < 0) > + goto out; > + > + /* parse response */ > + error = as10x_rsp_parse(prsp, CONTROL_PROC_GETTUNESTAT_RSP); > + if (error < 0) > + goto out; > + > + /* Response OK -> get response data */ > + pstatus->tune_state = prsp->body.get_tune_status.rsp.sts.tune_state; > + pstatus->signal_strength = > + le16_to_cpu(prsp->body.get_tune_status.rsp.sts.signal_strength); > + pstatus->PER = le16_to_cpu(prsp->body.get_tune_status.rsp.sts.PER); > + pstatus->BER = le16_to_cpu(prsp->body.get_tune_status.rsp.sts.BER); > + > +out: > + LEAVE(); > + return error; > +} > + > +/** > + \brief send get TPS command to AS10x > + \param phandle: pointer to AS10x handle > + \param ptps: pointer to TPS parameters structure > + \return 0 when no error, < 0 in case of error. > + \callgraph > + */ This comment is out of the format. It should be following Documentation/kernel-doc-nano-HOWTO.txt > +int as10x_cmd_get_tps(as10x_handle_t *phandle, struct as10x_tps *ptps) > +{ > + int error; > + struct as10x_cmd_t *pcmd, *prsp; > + > + ENTER(); > + > + pcmd = phandle->cmd; > + prsp = phandle->rsp; > + > + /* prepare command */ > + as10x_cmd_build(pcmd, (++phandle->cmd_xid), > + sizeof(pcmd->body.get_tps.req)); > + > + /* fill command */ > + pcmd->body.get_tune_status.req.proc_id = > + cpu_to_le16(CONTROL_PROC_GETTPS); > + > + /* send command */ > + if (phandle->ops->xfer_cmd) { > + error = phandle->ops->xfer_cmd(phandle, > + (uint8_t *) pcmd, > + sizeof(pcmd->body.get_tps.req) + > + HEADER_SIZE, > + (uint8_t *) prsp, > + sizeof(prsp->body.get_tps.rsp) + > + HEADER_SIZE); > + } else { > + error = AS10X_CMD_ERROR; > + } > + > + if (error < 0) > + goto out; > + > + /* parse response */ > + error = as10x_rsp_parse(prsp, CONTROL_PROC_GETTPS_RSP); > + if (error < 0) > + goto out; > + > + /* Response OK -> get response data */ > + ptps->constellation = prsp->body.get_tps.rsp.tps.constellation; > + ptps->hierarchy = prsp->body.get_tps.rsp.tps.hierarchy; > + ptps->interleaving_mode = prsp->body.get_tps.rsp.tps.interleaving_mode; > + ptps->code_rate_HP = prsp->body.get_tps.rsp.tps.code_rate_HP; > + ptps->code_rate_LP = prsp->body.get_tps.rsp.tps.code_rate_LP; > + ptps->guard_interval = prsp->body.get_tps.rsp.tps.guard_interval; > + ptps->transmission_mode = prsp->body.get_tps.rsp.tps.transmission_mode; > + ptps->DVBH_mask_HP = prsp->body.get_tps.rsp.tps.DVBH_mask_HP; > + ptps->DVBH_mask_LP = prsp->body.get_tps.rsp.tps.DVBH_mask_LP; > + ptps->cell_ID = le16_to_cpu(prsp->body.get_tps.rsp.tps.cell_ID); > + > +out: > + LEAVE(); > + return error; > +} > + > +/** > + \brief send get demod stats command to AS10x > + \param phandle: pointer to AS10x handle > + \param pdemod_stats: pointer to demod stats parameters structure > + \return 0 when no error, < 0 in case of error. > + \callgraph > +*/ This comment is out of the format. It should be following Documentation/kernel-doc-nano-HOWTO.txt > +int as10x_cmd_get_demod_stats(as10x_handle_t *phandle, > + struct as10x_demod_stats *pdemod_stats) > +{ > + int error; > + struct as10x_cmd_t *pcmd, *prsp; > + > + ENTER(); > + > + pcmd = phandle->cmd; > + prsp = phandle->rsp; > + > + /* prepare command */ > + as10x_cmd_build(pcmd, (++phandle->cmd_xid), > + sizeof(pcmd->body.get_demod_stats.req)); > + > + /* fill command */ > + pcmd->body.get_demod_stats.req.proc_id = > + cpu_to_le16(CONTROL_PROC_GET_DEMOD_STATS); > + > + /* send command */ > + if (phandle->ops->xfer_cmd) { > + error = phandle->ops->xfer_cmd(phandle, > + (uint8_t *) pcmd, > + sizeof(pcmd->body.get_demod_stats.req) > + + HEADER_SIZE, > + (uint8_t *) prsp, > + sizeof(prsp->body.get_demod_stats.rsp) > + + HEADER_SIZE); > + } else { > + error = AS10X_CMD_ERROR; > + } > + > + if (error < 0) > + goto out; > + > + /* parse response */ > + error = as10x_rsp_parse(prsp, CONTROL_PROC_GET_DEMOD_STATS_RSP); > + if (error < 0) > + goto out; > + > + /* Response OK -> get response data */ > + pdemod_stats->frame_count = > + le32_to_cpu(prsp->body.get_demod_stats.rsp.stats.frame_count); > + pdemod_stats->bad_frame_count = > + le32_to_cpu(prsp->body.get_demod_stats.rsp.stats.bad_frame_count); > + pdemod_stats->bytes_fixed_by_rs = > + le32_to_cpu(prsp->body.get_demod_stats.rsp.stats.bytes_fixed_by_rs); > + pdemod_stats->mer = > + le16_to_cpu(prsp->body.get_demod_stats.rsp.stats.mer); > + pdemod_stats->has_started = > + prsp->body.get_demod_stats.rsp.stats.has_started; > + > +out: > + LEAVE(); > + return error; > +} > + > +/** > + \brief send get impulse response command to AS10x > + \param phandle: pointer to AS10x handle > + \param is_ready: pointer to value indicating when impulse > + response data is ready > + \return 0 when no error, < 0 in case of error. > + \callgraph > +*/ This comment is out of the format. It should be following Documentation/kernel-doc-nano-HOWTO.txt > +int as10x_cmd_get_impulse_resp(as10x_handle_t *phandle, > + uint8_t *is_ready) Hmm.... lots of non-static functions... I suspect that several of those functions are, in fact, static. Please review and add the static tag where pertinent. > +{ > + int error; > + struct as10x_cmd_t *pcmd, *prsp; > + > + ENTER(); > + > + pcmd = phandle->cmd; > + prsp = phandle->rsp; > + > + /* prepare command */ > + as10x_cmd_build(pcmd, (++phandle->cmd_xid), > + sizeof(pcmd->body.get_impulse_rsp.req)); > + > + /* fill command */ > + pcmd->body.get_impulse_rsp.req.proc_id = > + cpu_to_le16(CONTROL_PROC_GET_IMPULSE_RESP); > + > + /* send command */ > + if (phandle->ops->xfer_cmd) { > + error = phandle->ops->xfer_cmd(phandle, > + (uint8_t *) pcmd, > + sizeof(pcmd->body.get_impulse_rsp.req) > + + HEADER_SIZE, > + (uint8_t *) prsp, > + sizeof(prsp->body.get_impulse_rsp.rsp) > + + HEADER_SIZE); > + } else { > + error = AS10X_CMD_ERROR; > + } > + > + if (error < 0) > + goto out; > + > + /* parse response */ > + error = as10x_rsp_parse(prsp, CONTROL_PROC_GET_IMPULSE_RESP_RSP); > + if (error < 0) > + goto out; > + > + /* Response OK -> get response data */ > + *is_ready = prsp->body.get_impulse_rsp.rsp.is_ready; > + > +out: > + LEAVE(); > + return error; > +} > + > + > + > +/** > + \brief build AS10x command header > + \param pcmd: pointer to AS10x command buffer > + \param xid: sequence id of the command > + \param cmd_len: lenght of the command > + \return - > + \callgraph > +*/ This comment is out of the format. It should be following Documentation/kernel-doc-nano-HOWTO.txt > +void as10x_cmd_build(struct as10x_cmd_t *pcmd, > + uint16_t xid, uint16_t cmd_len) > +{ > + pcmd->header.req_id = cpu_to_le16(xid); > + pcmd->header.prog = cpu_to_le16(SERVICE_PROG_ID); > + pcmd->header.version = cpu_to_le16(SERVICE_PROG_VERSION); > + pcmd->header.data_len = cpu_to_le16(cmd_len); > +} > + > +/** > + \brief Parse command response > + \param pcmd: pointer to AS10x command buffer > + \param cmd_seqid: sequence id of the command > + \param cmd_len: lenght of the command > + \return 0 when no error, < 0 in case of error > + \callgraph > +*/ This comment is out of the format. It should be following Documentation/kernel-doc-nano-HOWTO.txt > +int as10x_rsp_parse(struct as10x_cmd_t *prsp, uint16_t proc_id) > +{ > + int error; > + > + /* extract command error code */ > + error = prsp->body.common.rsp.error; > + > + if ((error == 0) && > + (le16_to_cpu(prsp->body.common.rsp.proc_id) == proc_id)) { > + return 0; > + } > + > + return AS10X_CMD_ERROR; > +} > + > + > diff --git a/drivers/media/dvb/as102/as10x_cmd.h b/drivers/media/dvb/as102/as10x_cmd.h > new file mode 100644 > index 0000000..01a7163 > --- /dev/null > +++ b/drivers/media/dvb/as102/as10x_cmd.h > @@ -0,0 +1,540 @@ > +/* > + * Abilis Systems Single DVB-T Receiver > + * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@xxxxxxxxxx> > + * > + * 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. > + */ > +#ifndef _AS10X_CMD_H_ > +#define _AS10X_CMD_H_ > + > +#ifdef __KERNEL__ > +#include <linux/kernel.h> > +#endif > + > +#include "as10x_types.h" > + > +/*********************************/ > +/* MACRO DEFINITIONS */ > +/*********************************/ > +#define AS10X_CMD_ERROR -1 > + > +#define SERVICE_PROG_ID 0x0002 > +#define SERVICE_PROG_VERSION 0x0001 > + > +#define HIER_NONE 0x00 > +#define HIER_LOW_PRIORITY 0x01 > + > +#define HEADER_SIZE (sizeof(struct as10x_cmd_header_t)) > + > +/* context request types */ > +#define GET_CONTEXT_DATA 1 > +#define SET_CONTEXT_DATA 2 > + > +/* ODSP suspend modes */ > +#define CFG_MODE_ODSP_RESUME 0 > +#define CFG_MODE_ODSP_SUSPEND 1 > + > +/* Dump memory size */ > +#define DUMP_BLOCK_SIZE_MAX 0x20 > + > +/*********************************/ > +/* TYPE DEFINITION */ > +/*********************************/ > +typedef enum { Please, don't use typedef. > + CONTROL_PROC_TURNON = 0x0001, Please use tab instead of spaces for indentation. > + CONTROL_PROC_TURNON_RSP = 0x0100, > + CONTROL_PROC_SET_REGISTER = 0x0002, > + CONTROL_PROC_SET_REGISTER_RSP = 0x0200, > + CONTROL_PROC_GET_REGISTER = 0x0003, > + CONTROL_PROC_GET_REGISTER_RSP = 0x0300, > + CONTROL_PROC_SETTUNE = 0x000A, > + CONTROL_PROC_SETTUNE_RSP = 0x0A00, > + CONTROL_PROC_GETTUNESTAT = 0x000B, > + CONTROL_PROC_GETTUNESTAT_RSP = 0x0B00, > + CONTROL_PROC_GETTPS = 0x000D, > + CONTROL_PROC_GETTPS_RSP = 0x0D00, > + CONTROL_PROC_SETFILTER = 0x000E, > + CONTROL_PROC_SETFILTER_RSP = 0x0E00, > + CONTROL_PROC_REMOVEFILTER = 0x000F, > + CONTROL_PROC_REMOVEFILTER_RSP = 0x0F00, > + CONTROL_PROC_GET_IMPULSE_RESP = 0x0012, > + CONTROL_PROC_GET_IMPULSE_RESP_RSP = 0x1200, > + CONTROL_PROC_START_STREAMING = 0x0013, > + CONTROL_PROC_START_STREAMING_RSP = 0x1300, > + CONTROL_PROC_STOP_STREAMING = 0x0014, > + CONTROL_PROC_STOP_STREAMING_RSP = 0x1400, > + CONTROL_PROC_GET_DEMOD_STATS = 0x0015, > + CONTROL_PROC_GET_DEMOD_STATS_RSP = 0x1500, > + CONTROL_PROC_ELNA_CHANGE_MODE = 0x0016, > + CONTROL_PROC_ELNA_CHANGE_MODE_RSP = 0x1600, > + CONTROL_PROC_ODSP_CHANGE_MODE = 0x0017, > + CONTROL_PROC_ODSP_CHANGE_MODE_RSP = 0x1700, > + CONTROL_PROC_AGC_CHANGE_MODE = 0x0018, > + CONTROL_PROC_AGC_CHANGE_MODE_RSP = 0x1800, > + > + CONTROL_PROC_CONTEXT = 0x00FC, > + CONTROL_PROC_CONTEXT_RSP = 0xFC00, > + CONTROL_PROC_DUMP_MEMORY = 0x00FD, > + CONTROL_PROC_DUMP_MEMORY_RSP = 0xFD00, > + CONTROL_PROC_DUMPLOG_MEMORY = 0x00FE, > + CONTROL_PROC_DUMPLOG_MEMORY_RSP = 0xFE00, > + CONTROL_PROC_TURNOFF = 0x00FF, > + CONTROL_PROC_TURNOFF_RSP = 0xFF00 > +} control_proc; > + > + > +#pragma pack(1) > +typedef union { > + /* request */ > + struct { > + /* request identifier */ > + uint16_t proc_id; > + } req; > + /* response */ > + struct { > + /* response identifier */ > + uint16_t proc_id; > + /* error */ > + uint8_t error; > + } rsp; > +} TURN_ON; Don't use pack nor typedef. > + > +typedef union { > + /* request */ > + struct { > + /* request identifier */ > + uint16_t proc_id; > + } req; > + /* response */ > + struct { > + /* response identifier */ > + uint16_t proc_id; > + /* error */ > + uint8_t err; > + } rsp; > +} TURN_OFF; Don't use typedef. > + > +typedef union { > + /* request */ > + struct { > + /* request identifier */ > + uint16_t proc_id; > + /* tune params */ > + struct as10x_tune_args args; > + } req; > + /* response */ > + struct { > + /* response identifier */ > + uint16_t proc_id; > + /* response error */ > + uint8_t error; > + } rsp; > +} SET_TUNE; Don't use typedef. > + > +typedef union { > + /* request */ > + struct { > + /* request identifier */ > + uint16_t proc_id; > + } req; > + /* response */ > + struct { > + /* response identifier */ > + uint16_t proc_id; > + /* response error */ > + uint8_t error; > + /* tune status */ > + struct as10x_tune_status sts; > + } rsp; > +} GET_TUNE_STATUS; Don't use typedef. > + > +typedef union { > + /* request */ > + struct { > + /* request identifier */ > + uint16_t proc_id; > + } req; > + /* response */ > + struct { > + /* response identifier */ > + uint16_t proc_id; > + /* response error */ > + uint8_t error; > + /* tps details */ > + struct as10x_tps tps; > + } rsp; > +} GET_TPS; Don't use typedef. > + > +typedef union { > + /* request */ > + struct { > + /* request identifier */ > + uint16_t proc_id; > + } req; > + /* response */ > + struct { > + /* response identifier */ > + uint16_t proc_id; > + /* response error */ > + uint8_t error; > + } rsp; > +} COMMON; Don't use typedef. > + > +typedef union { > + /* request */ > + struct { > + /* request identifier */ > + uint16_t proc_id; > + /* PID to filter */ > + uint16_t pid; > + /* stream type (MPE, PSI/SI or PES )*/ > + uint8_t stream_type; > + /* PID index in filter table */ > + uint8_t idx; > + } req; > + /* response */ > + struct { > + /* response identifier */ > + uint16_t proc_id; > + /* response error */ > + uint8_t error; > + /* Filter id */ > + uint8_t filter_id; > + } rsp; > +} ADD_PID_FILTER; > + Don't use typedef. > +typedef union { > + /* request */ > + struct { > + /* request identifier */ > + uint16_t proc_id; > + /* PID to remove */ > + uint16_t pid; > + } req; > + /* response */ > + struct { > + /* response identifier */ > + uint16_t proc_id; > + /* response error */ > + uint8_t error; > + } rsp; > +} DEL_PID_FILTER; Don't use typedef. > + > +typedef union { > + /* request */ > + struct { > + /* request identifier */ > + uint16_t proc_id; > + } req; > + /* response */ > + struct { > + /* response identifier */ > + uint16_t proc_id; > + /* error */ > + uint8_t error; > + } rsp; > +} START_STREAMING; Don't use typedef. > + > +typedef union { > + /* request */ > + struct { > + /* request identifier */ > + uint16_t proc_id; > + } req; > + /* response */ > + struct { > + /* response identifier */ > + uint16_t proc_id; > + /* error */ > + uint8_t error; > + } rsp; > +} STOP_STREAMING; > + > +typedef union { > + /* request */ > + struct { > + /* request identifier */ > + uint16_t proc_id; > + } req; > + /* response */ > + struct { > + /* response identifier */ > + uint16_t proc_id; > + /* error */ > + uint8_t error; > + /* demod stats */ > + struct as10x_demod_stats stats; > + } rsp; > +} GET_DEMOD_STATS; > + > +typedef union { > + /* request */ > + struct { > + /* request identifier */ > + uint16_t proc_id; > + } req; > + /* response */ > + struct { > + /* response identifier */ > + uint16_t proc_id; > + /* error */ > + uint8_t error; > + /* impulse response ready */ > + uint8_t is_ready; > + } rsp; > +} GET_IMPULSE_RESP; > + > +typedef union { > + /* request */ > + struct { > + /* request identifier */ > + uint16_t proc_id; > + /* value to write (for set context)*/ > + struct as10x_register_value reg_val; > + /* context tag */ > + uint16_t tag; > + /* context request type */ > + uint16_t type; > + } req; > + /* response */ > + struct { > + /* response identifier */ > + uint16_t proc_id; > + /* value read (for get context) */ > + struct as10x_register_value reg_val; > + /* context request type */ > + uint16_t type; > + /* error */ > + uint8_t error; > + } rsp; > +} FW_CONTEXT; > + > +typedef union { > + /* request */ > + struct { > + /* response identifier */ > + uint16_t proc_id; > + /* register description */ > + struct as10x_register_addr reg_addr; > + /* register content */ > + struct as10x_register_value reg_val; > + } req; > + /* response */ > + struct { > + /* response identifier */ > + uint16_t proc_id; > + /* error */ > + uint8_t error; > + } rsp; > +} SET_REGISTER; > + > +typedef union { > + /* request */ > + struct { > + /* response identifier */ > + uint16_t proc_id; > + /* register description */ > + struct as10x_register_addr reg_addr; > + } req; > + /* response */ > + struct { > + /* response identifier */ > + uint16_t proc_id; > + /* error */ > + uint8_t error; > + /* register content */ > + struct as10x_register_value reg_val; > + } rsp; > +} GET_REGISTER; > + > +typedef union { > + /* request */ > + struct { > + /* request identifier */ > + uint16_t proc_id; > + /* mode */ > + uint8_t mode; > + } req; > + /* response */ > + struct { > + /* response identifier */ > + uint16_t proc_id; > + /* error */ > + uint8_t error; > + } rsp; > +} CFG_CHANGE_MODE; Don't use typedef on the above. > + > +struct as10x_cmd_header_t { > + uint16_t req_id; > + uint16_t prog; > + uint16_t version; > + uint16_t data_len; > +}; Use tab instead os spaces. > + > +#define DUMP_BLOCK_SIZE 16 > +typedef union { > + /* request */ > + struct { > + /* request identifier */ > + uint16_t proc_id; > + /* dump memory type request */ > + uint8_t dump_req; > + /* register description */ > + struct as10x_register_addr reg_addr; > + /* nb blocks to read */ > + uint16_t num_blocks; > + } req; > + /* response */ > + struct { > + /* response identifier */ > + uint16_t proc_id; > + /* error */ > + uint8_t error; > + /* dump response */ > + uint8_t dump_rsp; > + /* data */ > + union { > + uint8_t data8[DUMP_BLOCK_SIZE]; > + uint16_t data16[DUMP_BLOCK_SIZE / sizeof(uint16_t)]; > + uint32_t data32[DUMP_BLOCK_SIZE / sizeof(uint32_t)]; > + } u; > + } rsp; > +} DUMP_MEMORY; > + > +typedef union { > + struct { > + /* request identifier */ > + uint16_t proc_id; > + /* dump memory type request */ > + uint8_t dump_req; > + } req; > + struct { > + /* request identifier */ > + uint16_t proc_id; > + /* error */ > + uint8_t error; > + /* dump response */ > + uint8_t dump_rsp; > + /* dump data */ > + uint8_t data[DUMP_BLOCK_SIZE]; > + } rsp; > +} DUMPLOG_MEMORY; > + > +typedef union { > + /* request */ > + struct { > + uint16_t proc_id; > + uint8_t data[64 - sizeof(struct as10x_cmd_header_t) -2 /* proc_id */]; > + } req; > + /* response */ > + struct { > + uint16_t proc_id; > + uint8_t error; > + uint8_t data[64 - sizeof(struct as10x_cmd_header_t) /* header */ > + - 2 /* proc_id */ - 1 /* rc */]; > + } rsp; > +} RAW_DATA; > + > +struct as10x_cmd_t { > + /* header */ > + struct as10x_cmd_header_t header; > + /* body */ > + union { > + TURN_ON turn_on; > + TURN_OFF turn_off; > + SET_TUNE set_tune; > + GET_TUNE_STATUS get_tune_status; > + GET_TPS get_tps; > + COMMON common; > + ADD_PID_FILTER add_pid_filter; > + DEL_PID_FILTER del_pid_filter; > + START_STREAMING start_streaming; > + STOP_STREAMING stop_streaming; > + GET_DEMOD_STATS get_demod_stats; > + GET_IMPULSE_RESP get_impulse_rsp; > + FW_CONTEXT context; > + SET_REGISTER set_register; > + GET_REGISTER get_register; > + CFG_CHANGE_MODE cfg_change_mode; > + DUMP_MEMORY dump_memory; > + DUMPLOG_MEMORY dumplog_memory; > + RAW_DATA raw_data; > + } body; > +}; > + > +struct as10x_token_cmd_t { > + /* token cmd */ > + struct as10x_cmd_t c; > + /* token response */ > + struct as10x_cmd_t r; > +}; > +#pragma pack() Samme comments: don't use spaces for indent, don't use typedef. > + > + > +/**************************/ > +/* FUNCTION DECLARATION */ > +/**************************/ > + > +void as10x_cmd_build(struct as10x_cmd_t *pcmd, uint16_t proc_id, > + uint16_t cmd_len); > +int as10x_rsp_parse(struct as10x_cmd_t *r, uint16_t proc_id); > + > +#ifdef __cplusplus > +extern "C" { > +#endif Always false. Kernel is in c, not c++. > + > +/* as10x cmd */ > +int as10x_cmd_turn_on(as10x_handle_t *phandle); > +int as10x_cmd_turn_off(as10x_handle_t *phandle); > + > +int as10x_cmd_set_tune(as10x_handle_t *phandle, > + struct as10x_tune_args *ptune); > + > +int as10x_cmd_get_tune_status(as10x_handle_t *phandle, > + struct as10x_tune_status *pstatus); > + > +int as10x_cmd_get_tps(as10x_handle_t *phandle, > + struct as10x_tps *ptps); > + > +int as10x_cmd_get_demod_stats(as10x_handle_t *phandle, > + struct as10x_demod_stats *pdemod_stats); > + > +int as10x_cmd_get_impulse_resp(as10x_handle_t *phandle, > + uint8_t *is_ready); > + > +/* as10x cmd stream */ > +int as10x_cmd_add_PID_filter(as10x_handle_t *phandle, > + struct as10x_ts_filter *filter); > +int as10x_cmd_del_PID_filter(as10x_handle_t *phandle, > + uint16_t pid_value); > + > +int as10x_cmd_start_streaming(as10x_handle_t *phandle); > +int as10x_cmd_stop_streaming(as10x_handle_t *phandle); > + > +/* as10x cmd cfg */ > +int as10x_cmd_set_context(as10x_handle_t *phandle, > + uint16_t tag, > + uint32_t value); > +int as10x_cmd_get_context(as10x_handle_t *phandle, > + uint16_t tag, > + uint32_t *pvalue); > + > +int as10x_cmd_eLNA_change_mode(as10x_handle_t *phandle, uint8_t mode); > +int as10x_context_rsp_parse(struct as10x_cmd_t *prsp, uint16_t proc_id); > +#ifdef __cplusplus > +} > +#endif > +#endif > +/* EOF - vim: set textwidth=80 ts=3 sw=3 sts=3 et: */ > diff --git a/drivers/media/dvb/as102/as10x_cmd_cfg.c b/drivers/media/dvb/as102/as10x_cmd_cfg.c > new file mode 100644 > index 0000000..7b22e19 > --- /dev/null > +++ b/drivers/media/dvb/as102/as10x_cmd_cfg.c > @@ -0,0 +1,237 @@ > +/** > + > + \file as10x_cmd_cfg.c > + > + \author: S. Martinelli > + > + ----------------------------------------------------------------------------\n > + (c) Copyright Abilis Systems SARL 2005-2009 All rigths reserved \n Incompatible license. Header format also doesn't seem ok. > + www.abilis.com \n > + ----------------------------------------------------------------------------\n > + > + \brief AS10x API, configuration services > + > + AS10x cmd management: build command buffer, send command through > + selected port and wait for the response when required. > + > +*/ > + > +#if defined(LINUX) && defined(__KERNEL__) /* linux kernel implementation */ > +#include <linux/kernel.h> > +#include "as102_drv.h" > +#elif defined(WIN32) > + #if defined(__BUILDMACHINE__) && (__BUILDMACHINE__ == WinDDK) > + /* win32 ddk implementation */ > + #include "wdm.h" > + #include "Device.h" > + #include "endian_mgmt.h" /* FIXME */ > + #else /* win32 sdk implementation */ > + #include <windows.h> > + #include "types.h" > + #include "util.h" > + #include "as10x_handle.h" > + #include "endian_mgmt.h" > + #endif > +#else /* all other cases */ > + #include <string.h> > + #include "types.h" > + #include "util.h" > + #include "as10x_handle.h" > + #include "endian_mgmt.h" /* FIXME */ > +#endif /* __KERNEL__ */ Argh! No windows here. > + > +#include "as10x_types.h" > +#include "as10x_cmd.h" > + > +/***************************/ > +/* FUNCTION DEFINITION */ > +/***************************/ > + > +/** > + \brief send get context command to AS10x > + \param phandle: pointer to AS10x handle > + \param tag: context tag > + \param pvalue: pointer where to store context value read > + \return 0 when no error, < 0 in case of error. > + \callgraph > +*/ Format is wrong. > +int as10x_cmd_get_context(as10x_handle_t *phandle, uint16_t tag, > + uint32_t *pvalue) > +{ > + int error; > + struct as10x_cmd_t *pcmd, *prsp; > + > + ENTER(); > + > + pcmd = phandle->cmd; > + prsp = phandle->rsp; > + > + /* prepare command */ > + as10x_cmd_build(pcmd, (++phandle->cmd_xid), > + sizeof(pcmd->body.context.req)); > + > + /* fill command */ > + pcmd->body.context.req.proc_id = cpu_to_le16(CONTROL_PROC_CONTEXT); > + pcmd->body.context.req.tag = cpu_to_le16(tag); > + pcmd->body.context.req.type = cpu_to_le16(GET_CONTEXT_DATA); > + > + /* send command */ > + if (phandle->ops->xfer_cmd) { > + error = phandle->ops->xfer_cmd(phandle, > + (uint8_t *) pcmd, > + sizeof(pcmd->body.context.req) > + + HEADER_SIZE, > + (uint8_t *) prsp, > + sizeof(prsp->body.context.rsp) > + + HEADER_SIZE); > + } else { > + error = AS10X_CMD_ERROR; > + } > + > + if (error < 0) > + goto out; > + > + /* parse response: context command do not follow the common response */ > + /* structure -> specific handling response parse required */ > + error = as10x_context_rsp_parse(prsp, CONTROL_PROC_CONTEXT_RSP); > + > + if (error == 0) { > + /* Response OK -> get response data */ > + *pvalue = le32_to_cpu(prsp->body.context.rsp.reg_val.u.value32); > + /* value returned is always a 32-bit value */ > + } > + > +out: > + LEAVE(); > + return error; > +} > + > +/** > + \brief send set context command to AS10x > + \param phandle: pointer to AS10x handle > + \param tag: context tag > + \param value: value to set in context > + \return 0 when no error, < 0 in case of error. > + \callgraph > +*/ Format is wrong. > +int as10x_cmd_set_context(as10x_handle_t *phandle, uint16_t tag, > + uint32_t value) > +{ > + int error; > + struct as10x_cmd_t *pcmd, *prsp; > + > + ENTER(); > + > + pcmd = phandle->cmd; > + prsp = phandle->rsp; > + > + /* prepare command */ > + as10x_cmd_build(pcmd, (++phandle->cmd_xid), > + sizeof(pcmd->body.context.req)); > + > + /* fill command */ > + pcmd->body.context.req.proc_id = cpu_to_le16(CONTROL_PROC_CONTEXT); > + /* pcmd->body.context.req.reg_val.mode initialization is not required */ > + pcmd->body.context.req.reg_val.u.value32 = cpu_to_le32(value); > + pcmd->body.context.req.tag = cpu_to_le16(tag); > + pcmd->body.context.req.type = cpu_to_le16(SET_CONTEXT_DATA); > + > + /* send command */ > + if (phandle->ops->xfer_cmd) { > + error = phandle->ops->xfer_cmd(phandle, > + (uint8_t *) pcmd, > + sizeof(pcmd->body.context.req) > + + HEADER_SIZE, > + (uint8_t *) prsp, > + sizeof(prsp->body.context.rsp) > + + HEADER_SIZE); > + } else { > + error = AS10X_CMD_ERROR; > + } > + > + if (error < 0) > + goto out; > + > + /* parse response: context command do not follow the common response */ > + /* structure -> specific handling response parse required */ > + error = as10x_context_rsp_parse(prsp, CONTROL_PROC_CONTEXT_RSP); > + > +out: > + LEAVE(); > + return error; > +} > + > +/** > + \brief send eLNA change mode command to AS10x > + \param phandle: pointer to AS10x handle > + \param tag: context tag > + \param mode: mode selected: > + - ON : 0x0 => eLNA always ON > + - OFF : 0x1 => eLNA always OFF > + - AUTO : 0x2 => eLNA follow hysteresis parameters to be > + ON or OFF > + \return 0 when no error, < 0 in case of error. > + \callgraph > +*/ Format is wrong. > +int as10x_cmd_eLNA_change_mode(as10x_handle_t *phandle, uint8_t mode) > +{ > + int error; > + struct as10x_cmd_t *pcmd, *prsp; > + > + ENTER(); > + > + pcmd = phandle->cmd; > + prsp = phandle->rsp; > + > + /* prepare command */ > + as10x_cmd_build(pcmd, (++phandle->cmd_xid), > + sizeof(pcmd->body.cfg_change_mode.req)); > + > + /* fill command */ > + pcmd->body.cfg_change_mode.req.proc_id = > + cpu_to_le16(CONTROL_PROC_ELNA_CHANGE_MODE); > + pcmd->body.cfg_change_mode.req.mode = mode; > + > + /* send command */ > + if (phandle->ops->xfer_cmd) { > + error = phandle->ops->xfer_cmd(phandle, (uint8_t *) pcmd, > + sizeof(pcmd->body.cfg_change_mode.req) > + + HEADER_SIZE, (uint8_t *) prsp, > + sizeof(prsp->body.cfg_change_mode.rsp) > + + HEADER_SIZE); > + } else { > + error = AS10X_CMD_ERROR; > + } > + > + if (error < 0) > + goto out; > + > + /* parse response */ > + error = as10x_rsp_parse(prsp, CONTROL_PROC_ELNA_CHANGE_MODE_RSP); > + > +out: > + LEAVE(); > + return error; > +} > + > +/** > + \brief Parse context command response. Since this command does not follow > + the common response, a specific parse function is required. > + \param prsp: pointer to AS10x command response buffer > + \param proc_id: id of the command > + \return 0 when no error, < 0 in case of error. > + ABILIS_RC_NOK > + \callgraph > +*/ idem. > +int as10x_context_rsp_parse(struct as10x_cmd_t *prsp, uint16_t proc_id) > +{ > + int err; > + > + err = prsp->body.context.rsp.error; > + > + if ((err == 0) && > + (le16_to_cpu(prsp->body.context.rsp.proc_id) == proc_id)) { > + return 0; > + } > + return AS10X_CMD_ERROR; > +} > diff --git a/drivers/media/dvb/as102/as10x_cmd_stream.c b/drivers/media/dvb/as102/as10x_cmd_stream.c > new file mode 100644 > index 0000000..8705894 > --- /dev/null > +++ b/drivers/media/dvb/as102/as10x_cmd_stream.c > @@ -0,0 +1,248 @@ > +/** > + > + \file as10x_cmd_stream.c > + > + \author: S. Martinelli > + > + ----------------------------------------------------------------------------\n > + (c) Copyright Abilis Systems SARL 2005-2009 All rigths reserved \n > + www.abilis.com \n > + ----------------------------------------------------------------------------\n > + > + \brief AS10x CMD, stream services > + > + AS10x CMD management: build command buffer, send command through > + selected port and wait for the response when required. > + > +*/ format is wrong. License is not GPL. > + > + > +#if defined(LINUX) && defined(__KERNEL__) /* linux kernel implementation */ > +#include <linux/kernel.h> > +#include "as102_drv.h" > +#elif defined(WIN32) > + #if defined(DDK) /* win32 ddk implementation */ > + #include "wdm.h" > + #include "Device.h" > + #include "endian_mgmt.h" /* FIXME */ > + #else /* win32 sdk implementation */ > + #include <windows.h> > + #include "types.h" > + #include "util.h" > + #include "as10x_handle.h" > + #include "endian_mgmt.h" > + #endif > +#else /* all other cases */ > + #include <string.h> > + #include "types.h" > + #include "util.h" > + #include "as10x_handle.h" > + #include "endian_mgmt.h" /* FIXME */ > +#endif /* __KERNEL__ */ Only kernel applies here. > + > +#include "as10x_cmd.h" > + > + > +/** > + \brief send add filter command to AS10x > + \param phandle: pointer to AS10x handle > + \param filter: TSFilter filter for DVB-T > + \param pfilter_handle: pointer where to store filter handle > + \return 0 when no error, < 0 in case of error. > + \callgraph > +*/ Wrong format. > +int as10x_cmd_add_PID_filter(as10x_handle_t *phandle, > + struct as10x_ts_filter *filter) > +{ > + int error; > + struct as10x_cmd_t *pcmd, *prsp; > + > + ENTER(); > + > + pcmd = phandle->cmd; > + prsp = phandle->rsp; > + > + /* prepare command */ > + as10x_cmd_build(pcmd, (++phandle->cmd_xid), > + sizeof(pcmd->body.add_pid_filter.req)); > + > + /* fill command */ > + pcmd->body.add_pid_filter.req.proc_id = > + cpu_to_le16(CONTROL_PROC_SETFILTER); > + pcmd->body.add_pid_filter.req.pid = cpu_to_le16(filter->pid); > + pcmd->body.add_pid_filter.req.stream_type = filter->type; > + > + if (filter->idx < 16) > + pcmd->body.add_pid_filter.req.idx = filter->idx; > + else > + pcmd->body.add_pid_filter.req.idx = 0xFF; > + > + /* send command */ > + if (phandle->ops->xfer_cmd) { > + error = phandle->ops->xfer_cmd(phandle, (uint8_t *) pcmd, > + sizeof(pcmd->body.add_pid_filter.req) > + + HEADER_SIZE, (uint8_t *) prsp, > + sizeof(prsp->body.add_pid_filter.rsp) > + + HEADER_SIZE); > + } else { > + error = AS10X_CMD_ERROR; > + } > + > + if (error < 0) > + goto out; > + > + /* parse response */ > + error = as10x_rsp_parse(prsp, CONTROL_PROC_SETFILTER_RSP); > + > + if (error == 0) { > + /* Response OK -> get response data */ > + filter->idx = prsp->body.add_pid_filter.rsp.filter_id; > + } > + > +out: > + LEAVE(); > + return error; > +} > + > +/** > + \brief Send delete filter command to AS10x > + \param phandle: pointer to AS10x handle > + \param filter_handle: filter handle > + \return 0 when no error, < 0 in case of error. > + \callgraph > +*/ idem. > +int as10x_cmd_del_PID_filter(as10x_handle_t *phandle, > + uint16_t pid_value) > +{ > + int error; > + struct as10x_cmd_t *pcmd, *prsp; > + > + ENTER(); > + > + pcmd = phandle->cmd; > + prsp = phandle->rsp; > + > + /* prepare command */ > + as10x_cmd_build(pcmd, (++phandle->cmd_xid), > + sizeof(pcmd->body.del_pid_filter.req)); > + > + /* fill command */ > + pcmd->body.del_pid_filter.req.proc_id = > + cpu_to_le16(CONTROL_PROC_REMOVEFILTER); > + pcmd->body.del_pid_filter.req.pid = cpu_to_le16(pid_value); > + > + /* send command */ > + if (phandle->ops->xfer_cmd) { > + error = phandle->ops->xfer_cmd(phandle, (uint8_t *) pcmd, > + sizeof(pcmd->body.del_pid_filter.req) > + + HEADER_SIZE, (uint8_t *) prsp, > + sizeof(prsp->body.del_pid_filter.rsp) > + + HEADER_SIZE); > + } else { > + error = AS10X_CMD_ERROR; > + } > + > + if (error < 0) > + goto out; > + > + /* parse response */ > + error = as10x_rsp_parse(prsp, CONTROL_PROC_REMOVEFILTER_RSP); > + > +out: > + LEAVE(); > + return error; > +} > + > +/** > + \brief Send start streaming command to AS10x > + \param phandle: pointer to AS10x handle > + \return 0 when no error, < 0 in case of error. > + \callgraph > +*/ idem > +int as10x_cmd_start_streaming(as10x_handle_t *phandle) > +{ > + int error; > + struct as10x_cmd_t *pcmd, *prsp; > + > + ENTER(); > + > + pcmd = phandle->cmd; > + prsp = phandle->rsp; > + > + /* prepare command */ > + as10x_cmd_build(pcmd, (++phandle->cmd_xid), > + sizeof(pcmd->body.start_streaming.req)); > + > + /* fill command */ > + pcmd->body.start_streaming.req.proc_id = > + cpu_to_le16(CONTROL_PROC_START_STREAMING); > + > + /* send command */ > + if (phandle->ops->xfer_cmd) { > + error = phandle->ops->xfer_cmd(phandle, (uint8_t *) pcmd, > + sizeof(pcmd->body.start_streaming.req) > + + HEADER_SIZE, (uint8_t *) prsp, > + sizeof(prsp->body.start_streaming.rsp) > + + HEADER_SIZE); > + } else { > + error = AS10X_CMD_ERROR; > + } > + > + if (error < 0) > + goto out; > + > + /* parse response */ > + error = as10x_rsp_parse(prsp, CONTROL_PROC_START_STREAMING_RSP); > + > +out: > + LEAVE(); > + return error; > +} > + > +/** > + \brief Send stop streaming command to AS10x > + \param phandle: pointer to AS10x handle > + \return 0 when no error, < 0 in case of error. > + \callgraph > +*/ idem. > +int as10x_cmd_stop_streaming(as10x_handle_t *phandle) > +{ > + int8_t error; > + struct as10x_cmd_t *pcmd, *prsp; > + > + ENTER(); > + > + pcmd = phandle->cmd; > + prsp = phandle->rsp; > + > + /* prepare command */ > + as10x_cmd_build(pcmd, (++phandle->cmd_xid), > + sizeof(pcmd->body.stop_streaming.req)); > + > + /* fill command */ > + pcmd->body.stop_streaming.req.proc_id = > + cpu_to_le16(CONTROL_PROC_STOP_STREAMING); > + > + /* send command */ > + if (phandle->ops->xfer_cmd) { > + error = phandle->ops->xfer_cmd(phandle, (uint8_t *) pcmd, > + sizeof(pcmd->body.stop_streaming.req) > + + HEADER_SIZE, (uint8_t *) prsp, > + sizeof(prsp->body.stop_streaming.rsp) > + + HEADER_SIZE); > + } else { > + error = AS10X_CMD_ERROR; > + } > + > + if (error < 0) > + goto out; > + > + /* parse response */ > + error = as10x_rsp_parse(prsp, CONTROL_PROC_STOP_STREAMING_RSP); > + > +out: > + LEAVE(); > + return error; > +} > + > + > diff --git a/drivers/media/dvb/as102/as10x_handle.h b/drivers/media/dvb/as102/as10x_handle.h > new file mode 100644 > index 0000000..4f01a76 > --- /dev/null > +++ b/drivers/media/dvb/as102/as10x_handle.h > @@ -0,0 +1,58 @@ > +/* > + * Abilis Systems Single DVB-T Receiver > + * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@xxxxxxxxxx> > + * > + * 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. > + */ > +#ifdef __KERNEL__ Always true. Just remove the test. > +struct as102_bus_adapter_t; > +struct as102_dev_t; > + > +#define as10x_handle_t struct as102_bus_adapter_t > +#include "as10x_cmd.h" > + > +/* values for "mode" field */ > +#define REGMODE8 8 > +#define REGMODE16 16 > +#define REGMODE32 32 > + > +struct as102_priv_ops_t { > + int (*upload_fw_pkt) (struct as102_bus_adapter_t *bus_adap, > + unsigned char *buf, int buflen, int swap32); > + > + int (*send_cmd) (struct as102_bus_adapter_t *bus_adap, > + unsigned char *buf, int buflen); > + > + int (*xfer_cmd) (struct as102_bus_adapter_t *bus_adap, > + unsigned char *send_buf, int send_buf_len, > + unsigned char *recv_buf, int recv_buf_len); > +/* > + int (*pid_filter) (struct as102_bus_adapter_t *bus_adap, > + int index, u16 pid, int onoff); > +*/ > + int (*start_stream) (struct as102_dev_t *dev); > + void (*stop_stream) (struct as102_dev_t *dev); > + > + int (*reset_target) (struct as102_bus_adapter_t *bus_adap); > + > + int (*read_write)(struct as102_bus_adapter_t *bus_adap, uint8_t mode, > + uint32_t rd_addr, uint16_t rd_len, > + uint32_t wr_addr, uint16_t wr_len); > + > + int (*as102_read_ep2) (struct as102_bus_adapter_t *bus_adap, > + unsigned char *recv_buf, > + int recv_buf_len); > +}; > +#endif > diff --git a/drivers/media/dvb/as102/as10x_types.h b/drivers/media/dvb/as102/as10x_types.h > new file mode 100644 > index 0000000..3dedb3c > --- /dev/null > +++ b/drivers/media/dvb/as102/as10x_types.h > @@ -0,0 +1,198 @@ > +/* > + * Abilis Systems Single DVB-T Receiver > + * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@xxxxxxxxxx> > + * > + * 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. > + */ > +#ifndef _AS10X_TYPES_H_ > +#define _AS10X_TYPES_H_ > + > +#include "as10x_handle.h" > + > +/*********************************/ > +/* MACRO DEFINITIONS */ > +/*********************************/ > + > +/* bandwidth constant values */ > +#define BW_5_MHZ 0x00 > +#define BW_6_MHZ 0x01 > +#define BW_7_MHZ 0x02 > +#define BW_8_MHZ 0x03 > + > +/* hierarchy priority selection values */ > +#define HIER_NO_PRIORITY 0x00 > +#define HIER_LOW_PRIORITY 0x01 > +#define HIER_HIGH_PRIORITY 0x02 > + > +/* constellation available values */ > +#define CONST_QPSK 0x00 > +#define CONST_QAM16 0x01 > +#define CONST_QAM64 0x02 > +#define CONST_UNKNOWN 0xFF > + > +/* hierarchy available values */ > +#define HIER_NONE 0x00 > +#define HIER_ALPHA_1 0x01 > +#define HIER_ALPHA_2 0x02 > +#define HIER_ALPHA_4 0x03 > +#define HIER_UNKNOWN 0xFF > + > +/* interleaving available values */ > +#define INTLV_NATIVE 0x00 > +#define INTLV_IN_DEPTH 0x01 > +#define INTLV_UNKNOWN 0xFF > + > +/* code rate available values */ > +#define CODE_RATE_1_2 0x00 > +#define CODE_RATE_2_3 0x01 > +#define CODE_RATE_3_4 0x02 > +#define CODE_RATE_5_6 0x03 > +#define CODE_RATE_7_8 0x04 > +#define CODE_RATE_UNKNOWN 0xFF > + > +/* guard interval available values */ > +#define GUARD_INT_1_32 0x00 > +#define GUARD_INT_1_16 0x01 > +#define GUARD_INT_1_8 0x02 > +#define GUARD_INT_1_4 0x03 > +#define GUARD_UNKNOWN 0xFF > + > +/* transmission mode available values */ > +#define TRANS_MODE_2K 0x00 > +#define TRANS_MODE_8K 0x01 > +#define TRANS_MODE_4K 0x02 > +#define TRANS_MODE_UNKNOWN 0xFF > + > +/* DVBH signalling available values */ > +#define TIMESLICING_PRESENT 0x01 > +#define MPE_FEC_PRESENT 0x02 > + > +/* tune state available */ > +#define TUNE_STATUS_NOT_TUNED 0x00 > +#define TUNE_STATUS_IDLE 0x01 > +#define TUNE_STATUS_LOCKING 0x02 > +#define TUNE_STATUS_SIGNAL_DVB_OK 0x03 > +#define TUNE_STATUS_STREAM_DETECTED 0x04 > +#define TUNE_STATUS_STREAM_TUNED 0x05 > +#define TUNE_STATUS_ERROR 0xFF > + > +/* available TS FID filter types */ > +#define TS_PID_TYPE_TS 0 > +#define TS_PID_TYPE_PSI_SI 1 > +#define TS_PID_TYPE_MPE 2 > + > +/* number of echos available */ > +#define MAX_ECHOS 15 > + > +/* Context types */ > +#define CONTEXT_LNA 1010 > +#define CONTEXT_ELNA_HYSTERESIS 4003 > +#define CONTEXT_ELNA_GAIN 4004 > +#define CONTEXT_MER_THRESHOLD 5005 > +#define CONTEXT_MER_OFFSET 5006 > +#define CONTEXT_IR_STATE 7000 > +#define CONTEXT_TSOUT_MSB_FIRST 7004 > +#define CONTEXT_TSOUT_FALLING_EDGE 7005 > + > +/* Configuration modes */ > +#define CFG_MODE_ON 0 > +#define CFG_MODE_OFF 1 > +#define CFG_MODE_AUTO 2 > + > +#pragma pack(1) > +struct as10x_tps { > + uint8_t constellation; > + uint8_t hierarchy; > + uint8_t interleaving_mode; > + uint8_t code_rate_HP; > + uint8_t code_rate_LP; > + uint8_t guard_interval; > + uint8_t transmission_mode; > + uint8_t DVBH_mask_HP; > + uint8_t DVBH_mask_LP; > + uint16_t cell_ID; > +}; > + > +struct as10x_tune_args { > + /* frequency */ > + uint32_t freq; > + /* bandwidth */ > + uint8_t bandwidth; > + /* hierarchy selection */ > + uint8_t hier_select; > + /* constellation */ > + uint8_t constellation; > + /* hierarchy */ > + uint8_t hierarchy; > + /* interleaving mode */ > + uint8_t interleaving_mode; > + /* code rate */ > + uint8_t code_rate; > + /* guard interval */ > + uint8_t guard_interval; > + /* transmission mode */ > + uint8_t transmission_mode; > +}; > + > +struct as10x_tune_status { > + /* tune status */ > + uint8_t tune_state; > + /* signal strength */ > + int16_t signal_strength; > + /* packet error rate 10^-4 */ > + uint16_t PER; > + /* bit error rate 10^-4 */ > + uint16_t BER; > +}; > + > +struct as10x_demod_stats { > + /* frame counter */ > + uint32_t frame_count; > + /* Bad frame counter */ > + uint32_t bad_frame_count; > + /* Number of wrong bytes fixed by Reed-Solomon */ > + uint32_t bytes_fixed_by_rs; > + /* Averaged MER */ > + uint16_t mer; > + /* statistics calculation state indicator (started or not) */ > + uint8_t has_started; > +}; > + > +struct as10x_ts_filter { > + uint16_t pid; /** valid PID value 0x00 : 0x2000 */ > + uint8_t type; /** Red TS_PID_TYPE_<N> values */ > + uint8_t idx; /** index in filtering table */ > +}; > + > +struct as10x_register_value { > + uint8_t mode; > + union { > + uint8_t value8; /* 8 bit value */ > + uint16_t value16; /* 16 bit value */ > + uint32_t value32; /* 32 bit value */ > + }u; > +}; > + > +#pragma pack() Use tabs, don't use pragma. > + > +struct as10x_register_addr { > + /* register addr */ > + uint32_t addr; > + /* register mode access */ > + uint8_t mode; > +}; Use tabs. > + > + > +#endif There are also some checkpatch errors (see enclosed). I probably pointed some of the comments bellow when reviewing the code itself. Cheers, Mauro --- WARNING: Use #include <linux/uaccess.h> instead of <asm/uaccess.h> #27: FILE: media/dvb/as102/as102_drv.c:27: +#include <asm/uaccess.h> total: 0 errors, 1 warnings, 360 lines checked drivers/media/dvb/as102/as102_drv.c has style problems, please review. If any of these errors are false positives report them to the maintainer, see CHECKPATCH in MAINTAINERS. ERROR: space required after that ',' (ctx:VxV) #46: FILE: media/dvb/as102/as102_drv.h:46: + printk(KERN_DEBUG "%s: ",__FUNCTION__); \ ^ WARNING: __func__ should be used instead of gcc specific __FUNCTION__ #46: FILE: media/dvb/as102/as102_drv.h:46: + printk(KERN_DEBUG "%s: ",__FUNCTION__); \ WARNING: __func__ should be used instead of gcc specific __FUNCTION__ #51: FILE: media/dvb/as102/as102_drv.h:51: +#define ENTER() printk(">> enter %s\n", __FUNCTION__) WARNING: printk() should include KERN_ facility level #52: FILE: media/dvb/as102/as102_drv.h:52: +#define LEAVE() printk("<< leave %s\n", __FUNCTION__) WARNING: __func__ should be used instead of gcc specific __FUNCTION__ #52: FILE: media/dvb/as102/as102_drv.h:52: +#define LEAVE() printk("<< leave %s\n", __FUNCTION__) total: 1 errors, 4 warnings, 147 lines checked drivers/media/dvb/as102/as102_drv.h has style problems, please review. If any of these errors are false positives report them to the maintainer, see CHECKPATCH in MAINTAINERS. WARNING: externs should be avoided in .c files #26: FILE: media/dvb/as102/as102_fe.c:26: +extern int elna_enable; total: 0 errors, 1 warnings, 601 lines checked drivers/media/dvb/as102/as102_fe.c has style problems, please review. If any of these errors are false positives report them to the maintainer, see CHECKPATCH in MAINTAINERS. total: 0 errors, 0 warnings, 251 lines checked drivers/media/dvb/as102/as102_fw.c has no obvious style problems and is ready for submission. total: 0 errors, 0 warnings, 42 lines checked drivers/media/dvb/as102/as102_fw.h has no obvious style problems and is ready for submission. total: 0 errors, 0 warnings, 480 lines checked drivers/media/dvb/as102/as102_usb_drv.c has no obvious style problems and is ready for submission. total: 0 errors, 0 warnings, 55 lines checked drivers/media/dvb/as102/as102_usb_drv.h has no obvious style problems and is ready for submission. WARNING: line over 80 characters #370: FILE: media/dvb/as102/as10x_cmd.c:370: + le32_to_cpu(prsp->body.get_demod_stats.rsp.stats.bad_frame_count); WARNING: line over 80 characters #372: FILE: media/dvb/as102/as10x_cmd.c:372: + le32_to_cpu(prsp->body.get_demod_stats.rsp.stats.bytes_fixed_by_rs); total: 0 errors, 2 warnings, 481 lines checked drivers/media/dvb/as102/as10x_cmd.c has style problems, please review. If any of these errors are false positives report them to the maintainer, see CHECKPATCH in MAINTAINERS. total: 0 errors, 0 warnings, 237 lines checked drivers/media/dvb/as102/as10x_cmd_cfg.c has no obvious style problems and is ready for submission. WARNING: do not add new typedefs #55: FILE: media/dvb/as102/as10x_cmd.h:55: +typedef enum { WARNING: do not add new typedefs #99: FILE: media/dvb/as102/as10x_cmd.h:99: +typedef union { WARNING: do not add new typedefs #114: FILE: media/dvb/as102/as10x_cmd.h:114: +typedef union { WARNING: do not add new typedefs #129: FILE: media/dvb/as102/as10x_cmd.h:129: +typedef union { WARNING: do not add new typedefs #146: FILE: media/dvb/as102/as10x_cmd.h:146: +typedef union { WARNING: do not add new typedefs #163: FILE: media/dvb/as102/as10x_cmd.h:163: +typedef union { WARNING: do not add new typedefs #180: FILE: media/dvb/as102/as10x_cmd.h:180: +typedef union { WARNING: do not add new typedefs #195: FILE: media/dvb/as102/as10x_cmd.h:195: +typedef union { WARNING: do not add new typedefs #218: FILE: media/dvb/as102/as10x_cmd.h:218: +typedef union { WARNING: do not add new typedefs #235: FILE: media/dvb/as102/as10x_cmd.h:235: +typedef union { WARNING: do not add new typedefs #250: FILE: media/dvb/as102/as10x_cmd.h:250: +typedef union { WARNING: do not add new typedefs #265: FILE: media/dvb/as102/as10x_cmd.h:265: +typedef union { WARNING: do not add new typedefs #282: FILE: media/dvb/as102/as10x_cmd.h:282: +typedef union { WARNING: do not add new typedefs #299: FILE: media/dvb/as102/as10x_cmd.h:299: +typedef union { WARNING: do not add new typedefs #324: FILE: media/dvb/as102/as10x_cmd.h:324: +typedef union { WARNING: do not add new typedefs #343: FILE: media/dvb/as102/as10x_cmd.h:343: +typedef union { WARNING: do not add new typedefs #362: FILE: media/dvb/as102/as10x_cmd.h:362: +typedef union { WARNING: do not add new typedefs #387: FILE: media/dvb/as102/as10x_cmd.h:387: +typedef union { WARNING: do not add new typedefs #416: FILE: media/dvb/as102/as10x_cmd.h:416: +typedef union { WARNING: do not add new typedefs #435: FILE: media/dvb/as102/as10x_cmd.h:435: +typedef union { ERROR: need consistent spacing around '-' (ctx:WxV) #439: FILE: media/dvb/as102/as10x_cmd.h:439: + uint8_t data[64 - sizeof(struct as10x_cmd_header_t) -2 /* proc_id */]; ^ total: 1 errors, 20 warnings, 540 lines checked drivers/media/dvb/as102/as10x_cmd.h has style problems, please review. If any of these errors are false positives report them to the maintainer, see CHECKPATCH in MAINTAINERS. total: 0 errors, 0 warnings, 248 lines checked drivers/media/dvb/as102/as10x_cmd_stream.c has no obvious style problems and is ready for submission. total: 0 errors, 0 warnings, 58 lines checked drivers/media/dvb/as102/as10x_handle.h has no obvious style problems and is ready for submission. ERROR: space required after that close brace '}' #185: FILE: media/dvb/as102/as10x_types.h:185: + }u; total: 1 errors, 0 warnings, 198 lines checked drivers/media/dvb/as102/as10x_types.h has style problems, please review. If any of these errors are false positives report them to the maintainer, see CHECKPATCH in MAINTAINERS. -- Cheers, Mauro -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html