2005-06-23 22:02:35 -07:00
/*
* DVB USB library - provides a generic interface for a DVB USB device driver .
*
* dvb - usb - init . c
*
2016-01-24 12:56:58 -02:00
* Copyright ( C ) 2004 - 6 Patrick Boettcher ( patrick . boettcher @ posteo . de )
2005-06-23 22:02:35 -07:00
*
* 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 , version 2.
*
* see Documentation / dvb / README . dvb - usb for more information
*/
# include "dvb-usb-common.h"
/* debug */
int dvb_usb_debug ;
2010-07-01 01:50:04 -03:00
module_param_named ( debug , dvb_usb_debug , int , 0644 ) ;
2006-09-30 06:53:48 -03:00
MODULE_PARM_DESC ( debug , " set debugging level (1=info,xfer=2,pll=4,ts=8,err=16,rc=32,fw=64,mem=128,uxfer=256 (or-able)). " DVB_USB_DEBUG_STATUS ) ;
2005-06-23 22:02:35 -07:00
2005-07-07 17:58:11 -07:00
int dvb_usb_disable_rc_polling ;
module_param_named ( disable_rc_polling , dvb_usb_disable_rc_polling , int , 0644 ) ;
MODULE_PARM_DESC ( disable_rc_polling , " disable remote control polling (default: 0). " ) ;
2006-09-30 06:53:48 -03:00
static int dvb_usb_force_pid_filter_usage ;
module_param_named ( force_pid_filter_usage , dvb_usb_force_pid_filter_usage , int , 0444 ) ;
2007-08-18 18:02:31 -03:00
MODULE_PARM_DESC ( force_pid_filter_usage , " force all dvb-usb-devices to use a PID filter, if any (default: 0). " ) ;
2006-09-30 06:53:48 -03:00
2008-04-09 19:13:13 -03:00
static int dvb_usb_adapter_init ( struct dvb_usb_device * d , short * adapter_nrs )
2006-09-30 06:53:48 -03:00
{
struct dvb_usb_adapter * adap ;
2011-09-06 09:31:57 -03:00
int ret , n , o ;
2006-09-30 06:53:48 -03:00
for ( n = 0 ; n < d - > props . num_adapters ; n + + ) {
adap = & d - > adapter [ n ] ;
adap - > dev = d ;
adap - > id = n ;
memcpy ( & adap - > props , & d - > props . adapter [ n ] , sizeof ( struct dvb_usb_adapter_properties ) ) ;
2012-12-10 17:37:09 -03:00
for ( o = 0 ; o < adap - > props . num_frontends ; o + + ) {
struct dvb_usb_adapter_fe_properties * props = & adap - > props . fe [ o ] ;
/* speed - when running at FULL speed we need a HW PID filter */
if ( d - > udev - > speed = = USB_SPEED_FULL & & ! ( props - > caps & DVB_USB_ADAP_HAS_PID_FILTER ) ) {
err ( " This USB2.0 device cannot be run on a USB1.1 port. (it lacks a hardware PID filter) " ) ;
return - ENODEV ;
}
2006-09-30 06:53:48 -03:00
2012-12-10 17:37:09 -03:00
if ( ( d - > udev - > speed = = USB_SPEED_FULL & & props - > caps & DVB_USB_ADAP_HAS_PID_FILTER ) | |
( props - > caps & DVB_USB_ADAP_NEED_PID_FILTERING ) ) {
info ( " will use the device's hardware PID filter (table count: %d). " , props - > pid_filter_count ) ;
adap - > fe_adap [ o ] . pid_filtering = 1 ;
adap - > fe_adap [ o ] . max_feed_count = props - > pid_filter_count ;
} else {
info ( " will pass the complete MPEG2 transport stream to the software demuxer. " ) ;
adap - > fe_adap [ o ] . pid_filtering = 0 ;
adap - > fe_adap [ o ] . max_feed_count = 255 ;
}
2006-09-30 06:53:48 -03:00
2012-12-10 17:37:09 -03:00
if ( ! adap - > fe_adap [ o ] . pid_filtering & &
dvb_usb_force_pid_filter_usage & &
props - > caps & DVB_USB_ADAP_HAS_PID_FILTER ) {
info ( " pid filter enabled by module option. " ) ;
adap - > fe_adap [ o ] . pid_filtering = 1 ;
adap - > fe_adap [ o ] . max_feed_count = props - > pid_filter_count ;
}
2006-09-30 06:53:48 -03:00
2012-12-10 17:37:09 -03:00
if ( props - > size_of_priv > 0 ) {
adap - > fe_adap [ o ] . priv = kzalloc ( props - > size_of_priv , GFP_KERNEL ) ;
if ( adap - > fe_adap [ o ] . priv = = NULL ) {
err ( " no memory for priv for adapter %d fe %d. " , n , o ) ;
return - ENOMEM ;
}
2011-09-06 09:31:57 -03:00
}
}
2006-09-30 06:53:48 -03:00
if ( adap - > props . size_of_priv > 0 ) {
2010-07-01 01:50:04 -03:00
adap - > priv = kzalloc ( adap - > props . size_of_priv , GFP_KERNEL ) ;
2006-09-30 06:53:48 -03:00
if ( adap - > priv = = NULL ) {
2010-07-01 01:50:04 -03:00
err ( " no memory for priv for adapter %d. " , n ) ;
2006-09-30 06:53:48 -03:00
return - ENOMEM ;
}
}
if ( ( ret = dvb_usb_adapter_stream_init ( adap ) ) | |
2008-04-09 19:13:13 -03:00
( ret = dvb_usb_adapter_dvb_init ( adap , adapter_nrs ) ) | |
2006-09-30 06:53:48 -03:00
( ret = dvb_usb_adapter_frontend_init ( adap ) ) ) {
return ret ;
}
2011-07-25 20:16:13 -03:00
/* use exclusive FE lock if there is multiple shared FEs */
2011-09-06 09:31:57 -03:00
if ( adap - > fe_adap [ 1 ] . fe )
2011-07-25 20:16:13 -03:00
adap - > dvb_adap . mfe_shared = 1 ;
2006-09-30 06:53:48 -03:00
d - > num_adapters_initialized + + ;
d - > state | = DVB_USB_STATE_DVB ;
}
/*
* when reloading the driver w / o replugging the device
* sometimes a timeout occures , this helps
*/
if ( d - > props . generic_bulk_ctrl_endpoint ! = 0 ) {
2010-07-01 01:50:04 -03:00
usb_clear_halt ( d - > udev , usb_sndbulkpipe ( d - > udev , d - > props . generic_bulk_ctrl_endpoint ) ) ;
usb_clear_halt ( d - > udev , usb_rcvbulkpipe ( d - > udev , d - > props . generic_bulk_ctrl_endpoint ) ) ;
2006-09-30 06:53:48 -03:00
}
return 0 ;
}
static int dvb_usb_adapter_exit ( struct dvb_usb_device * d )
{
int n ;
2010-07-01 01:50:04 -03:00
2006-09-30 06:53:48 -03:00
for ( n = 0 ; n < d - > num_adapters_initialized ; n + + ) {
dvb_usb_adapter_frontend_exit ( & d - > adapter [ n ] ) ;
dvb_usb_adapter_dvb_exit ( & d - > adapter [ n ] ) ;
dvb_usb_adapter_stream_exit ( & d - > adapter [ n ] ) ;
kfree ( d - > adapter [ n ] . priv ) ;
}
d - > num_adapters_initialized = 0 ;
d - > state & = ~ DVB_USB_STATE_DVB ;
return 0 ;
}
2005-06-23 22:02:35 -07:00
/* general initialization functions */
2005-12-01 00:51:53 -08:00
static int dvb_usb_exit ( struct dvb_usb_device * d )
2005-06-23 22:02:35 -07:00
{
2010-07-01 01:50:04 -03:00
deb_info ( " state before exiting everything: %x \n " , d - > state ) ;
2005-06-23 22:02:35 -07:00
dvb_usb_remote_exit ( d ) ;
2006-09-30 06:53:48 -03:00
dvb_usb_adapter_exit ( d ) ;
2005-06-23 22:02:35 -07:00
dvb_usb_i2c_exit ( d ) ;
2010-07-01 01:50:04 -03:00
deb_info ( " state should be zero now: %x \n " , d - > state ) ;
2005-06-23 22:02:35 -07:00
d - > state = DVB_USB_STATE_INIT ;
kfree ( d - > priv ) ;
kfree ( d ) ;
return 0 ;
}
2008-04-09 19:13:13 -03:00
static int dvb_usb_init ( struct dvb_usb_device * d , short * adapter_nums )
2005-06-23 22:02:35 -07:00
{
int ret = 0 ;
2016-11-12 12:46:26 -02:00
mutex_init ( & d - > data_mutex ) ;
2006-02-07 06:49:14 -02:00
mutex_init ( & d - > usb_mutex ) ;
mutex_init ( & d - > i2c_mutex ) ;
2005-06-23 22:02:35 -07:00
d - > state = DVB_USB_STATE_INIT ;
2006-09-30 06:53:48 -03:00
if ( d - > props . size_of_priv > 0 ) {
2010-07-01 01:50:04 -03:00
d - > priv = kzalloc ( d - > props . size_of_priv , GFP_KERNEL ) ;
2006-09-30 06:53:48 -03:00
if ( d - > priv = = NULL ) {
err ( " no memory for priv in 'struct dvb_usb_device' " ) ;
return - ENOMEM ;
2006-09-20 06:06:11 -03:00
}
2005-06-23 22:02:35 -07:00
}
2010-07-01 01:50:04 -03:00
/* check the capabilities and set appropriate variables */
2006-09-30 06:53:48 -03:00
dvb_usb_device_power_ctrl ( d , 1 ) ;
2005-06-23 22:02:35 -07:00
2006-09-30 06:53:48 -03:00
if ( ( ret = dvb_usb_i2c_init ( d ) ) | |
2008-04-09 19:13:13 -03:00
( ret = dvb_usb_adapter_init ( d , adapter_nums ) ) ) {
2005-06-23 22:02:35 -07:00
dvb_usb_exit ( d ) ;
return ret ;
}
if ( ( ret = dvb_usb_remote_init ( d ) ) )
err ( " could not initialize remote control. " ) ;
2006-09-30 06:53:48 -03:00
dvb_usb_device_power_ctrl ( d , 0 ) ;
2005-06-23 22:02:35 -07:00
return 0 ;
}
/* determine the name and the state of the just found USB device */
2010-07-01 01:50:04 -03:00
static struct dvb_usb_device_description * dvb_usb_find_device ( struct usb_device * udev , struct dvb_usb_device_properties * props , int * cold )
2005-06-23 22:02:35 -07:00
{
2010-07-01 01:50:04 -03:00
int i , j ;
2005-06-23 22:02:35 -07:00
struct dvb_usb_device_description * desc = NULL ;
2010-07-01 01:50:04 -03:00
2005-06-23 22:02:35 -07:00
* cold = - 1 ;
for ( i = 0 ; i < props - > num_device_descs ; i + + ) {
for ( j = 0 ; j < DVB_USB_ID_MAX_NUM & & props - > devices [ i ] . cold_ids [ j ] ! = NULL ; j + + ) {
2010-07-01 01:50:04 -03:00
deb_info ( " check for cold %x %x \n " , props - > devices [ i ] . cold_ids [ j ] - > idVendor , props - > devices [ i ] . cold_ids [ j ] - > idProduct ) ;
2005-06-23 22:02:35 -07:00
if ( props - > devices [ i ] . cold_ids [ j ] - > idVendor = = le16_to_cpu ( udev - > descriptor . idVendor ) & &
props - > devices [ i ] . cold_ids [ j ] - > idProduct = = le16_to_cpu ( udev - > descriptor . idProduct ) ) {
* cold = 1 ;
desc = & props - > devices [ i ] ;
break ;
}
}
if ( desc ! = NULL )
break ;
for ( j = 0 ; j < DVB_USB_ID_MAX_NUM & & props - > devices [ i ] . warm_ids [ j ] ! = NULL ; j + + ) {
2010-07-01 01:50:04 -03:00
deb_info ( " check for warm %x %x \n " , props - > devices [ i ] . warm_ids [ j ] - > idVendor , props - > devices [ i ] . warm_ids [ j ] - > idProduct ) ;
2005-06-23 22:02:35 -07:00
if ( props - > devices [ i ] . warm_ids [ j ] - > idVendor = = le16_to_cpu ( udev - > descriptor . idVendor ) & &
props - > devices [ i ] . warm_ids [ j ] - > idProduct = = le16_to_cpu ( udev - > descriptor . idProduct ) ) {
* cold = 0 ;
desc = & props - > devices [ i ] ;
break ;
}
}
}
if ( desc ! = NULL & & props - > identify_state ! = NULL )
2010-07-01 01:50:04 -03:00
props - > identify_state ( udev , props , & desc , cold ) ;
2005-06-23 22:02:35 -07:00
return desc ;
}
2006-09-30 06:53:48 -03:00
int dvb_usb_device_power_ctrl ( struct dvb_usb_device * d , int onoff )
{
2006-09-20 06:06:11 -03:00
if ( onoff )
d - > powered + + ;
else
d - > powered - - ;
2010-07-01 01:50:04 -03:00
if ( d - > powered = = 0 | | ( onoff & & d - > powered = = 1 ) ) { /* when switching from 1 to 0 or from 0 to 1 */
2006-09-20 06:06:11 -03:00
deb_info ( " power control: %d \n " , onoff ) ;
2006-09-30 06:53:48 -03:00
if ( d - > props . power_ctrl )
return d - > props . power_ctrl ( d , onoff ) ;
}
return 0 ;
}
2005-06-23 22:02:35 -07:00
/*
* USB
*/
2008-04-09 19:13:13 -03:00
int dvb_usb_device_init ( struct usb_interface * intf ,
struct dvb_usb_device_properties * props ,
struct module * owner , struct dvb_usb_device * * du ,
short * adapter_nums )
2005-06-23 22:02:35 -07:00
{
struct usb_device * udev = interface_to_usbdev ( intf ) ;
struct dvb_usb_device * d = NULL ;
struct dvb_usb_device_description * desc = NULL ;
2010-07-01 01:50:04 -03:00
int ret = - ENOMEM , cold = 0 ;
2005-06-23 22:02:35 -07:00
2006-01-09 15:25:33 -02:00
if ( du ! = NULL )
* du = NULL ;
2010-07-01 01:50:04 -03:00
if ( ( desc = dvb_usb_find_device ( udev , props , & cold ) ) = = NULL ) {
2005-06-23 22:02:35 -07:00
deb_err ( " something went very wrong, device was not found in current device list - let's see what comes next. \n " ) ;
return - ENODEV ;
}
if ( cold ) {
2010-07-01 01:50:04 -03:00
info ( " found a '%s' in cold state, will try to load a firmware " , desc - > name ) ;
ret = dvb_usb_download_firmware ( udev , props ) ;
2006-09-19 12:51:46 -03:00
if ( ! props - > no_reconnect | | ret ! = 0 )
2005-06-23 22:02:35 -07:00
return ret ;
2006-01-09 15:25:04 -02:00
}
2010-07-01 01:50:04 -03:00
info ( " found a '%s' in warm state. " , desc - > name ) ;
d = kzalloc ( sizeof ( struct dvb_usb_device ) , GFP_KERNEL ) ;
2006-01-09 15:25:04 -02:00
if ( d = = NULL ) {
err ( " no memory for 'struct dvb_usb_device' " ) ;
2010-02-02 11:29:46 -03:00
return - ENOMEM ;
2006-01-09 15:25:04 -02:00
}
d - > udev = udev ;
2010-07-01 01:50:04 -03:00
memcpy ( & d - > props , props , sizeof ( struct dvb_usb_device_properties ) ) ;
2006-01-09 15:25:04 -02:00
d - > desc = desc ;
d - > owner = owner ;
usb_set_intfdata ( intf , d ) ;
2005-06-23 22:02:35 -07:00
2006-01-09 15:25:04 -02:00
if ( du ! = NULL )
* du = d ;
2005-09-09 13:02:47 -07:00
2008-04-09 19:13:13 -03:00
ret = dvb_usb_init ( d , adapter_nums ) ;
2005-06-23 22:02:35 -07:00
if ( ret = = 0 )
2010-07-01 01:50:04 -03:00
info ( " %s successfully initialized and connected. " , desc - > name ) ;
2005-06-23 22:02:35 -07:00
else
2010-07-01 01:50:04 -03:00
info ( " %s error while loading driver (%d) " , desc - > name , ret ) ;
2005-06-23 22:02:35 -07:00
return ret ;
}
EXPORT_SYMBOL ( dvb_usb_device_init ) ;
void dvb_usb_device_exit ( struct usb_interface * intf )
{
struct dvb_usb_device * d = usb_get_intfdata ( intf ) ;
const char * name = " generic DVB-USB module " ;
2010-07-01 01:50:04 -03:00
usb_set_intfdata ( intf , NULL ) ;
2005-06-23 22:02:35 -07:00
if ( d ! = NULL & & d - > desc ! = NULL ) {
name = d - > desc - > name ;
dvb_usb_exit ( d ) ;
}
2010-07-01 01:50:04 -03:00
info ( " %s successfully deinitialized and disconnected. " , name ) ;
2005-06-23 22:02:35 -07:00
}
EXPORT_SYMBOL ( dvb_usb_device_exit ) ;
2006-09-30 06:53:48 -03:00
MODULE_VERSION ( " 1.0 " ) ;
2016-01-24 12:56:58 -02:00
MODULE_AUTHOR ( " Patrick Boettcher <patrick.boettcher@posteo.de> " ) ;
2005-06-23 22:02:35 -07:00
MODULE_DESCRIPTION ( " A library module containing commonly used USB and DVB function USB DVB devices " ) ;
MODULE_LICENSE ( " GPL " ) ;