2005-04-16 15:20:36 -07:00
/*
* Driver for ST5481 USB ISDN modem
*
* Author Frode Isaksen
* Copyright 2001 by Frode Isaksen < fisaksen @ bewan . com >
* 2001 by Kai Germaschewski < kai . germaschewski @ gmx . de >
2012-02-19 19:52:38 -08:00
*
2005-04-16 15:20:36 -07:00
* This software may be used and distributed according to the terms
* of the GNU General Public License , incorporated herein by reference .
*
*/
2012-02-19 19:52:38 -08:00
/*
2005-04-16 15:20:36 -07:00
* TODO :
*
* b layer1 delay ?
* hotplug / unregister issues
* mod_inc / dec_use_count
* unify parts of d / b channel usb handling
* file header
* avoid copy to isoc buffer ?
* improve usb delay ?
* merge l1 state machines ?
* clean up debug
*/
# include <linux/module.h>
# include <linux/init.h>
# include <linux/usb.h>
# include <linux/slab.h>
# include "st5481.h"
MODULE_DESCRIPTION ( " ISDN4Linux: driver for ST5481 USB ISDN adapter " ) ;
MODULE_AUTHOR ( " Frode Isaksen " ) ;
MODULE_LICENSE ( " GPL " ) ;
static int protocol = 2 ; /* EURO-ISDN Default */
module_param ( protocol , int , 0 ) ;
static int number_of_leds = 2 ; /* 2 LEDs on the adpater default */
module_param ( number_of_leds , int , 0 ) ;
# ifdef CONFIG_HISAX_DEBUG
2005-09-17 23:52:42 +02:00
static int debug = 0 ;
2005-04-16 15:20:36 -07:00
module_param ( debug , int , 0 ) ;
# endif
2005-09-17 23:52:42 +02:00
int st5481_debug ;
2005-04-16 15:20:36 -07:00
/* ======================================================================
* registration / deregistration with the USB layer
*/
/*
* This function will be called when the adapter is plugged
* into the USB bus .
*/
static int probe_st5481 ( struct usb_interface * intf ,
const struct usb_device_id * id )
{
struct usb_device * dev = interface_to_usbdev ( intf ) ;
struct st5481_adapter * adapter ;
struct hisax_b_if * b_if [ 2 ] ;
int retval , i ;
printk ( KERN_INFO " st541: found adapter VendorId %04x, ProductId %04x, LEDs %d \n " ,
2012-02-19 19:52:38 -08:00
le16_to_cpu ( dev - > descriptor . idVendor ) ,
le16_to_cpu ( dev - > descriptor . idProduct ) ,
number_of_leds ) ;
2005-04-16 15:20:36 -07:00
2006-12-08 02:39:35 -08:00
adapter = kzalloc ( sizeof ( struct st5481_adapter ) , GFP_KERNEL ) ;
2005-04-16 15:20:36 -07:00
if ( ! adapter )
return - ENOMEM ;
adapter - > number_of_leds = number_of_leds ;
adapter - > usb_dev = dev ;
adapter - > hisax_d_if . owner = THIS_MODULE ;
adapter - > hisax_d_if . ifc . priv = adapter ;
adapter - > hisax_d_if . ifc . l2l1 = st5481_d_l2l1 ;
for ( i = 0 ; i < 2 ; i + + ) {
adapter - > bcs [ i ] . adapter = adapter ;
adapter - > bcs [ i ] . channel = i ;
adapter - > bcs [ i ] . b_if . ifc . priv = & adapter - > bcs [ i ] ;
adapter - > bcs [ i ] . b_if . ifc . l2l1 = st5481_b_l2l1 ;
}
retval = st5481_setup_usb ( adapter ) ;
if ( retval < 0 )
goto err ;
retval = st5481_setup_d ( adapter ) ;
if ( retval < 0 )
goto err_usb ;
retval = st5481_setup_b ( & adapter - > bcs [ 0 ] ) ;
if ( retval < 0 )
goto err_d ;
retval = st5481_setup_b ( & adapter - > bcs [ 1 ] ) ;
if ( retval < 0 )
goto err_b ;
for ( i = 0 ; i < 2 ; i + + )
b_if [ i ] = & adapter - > bcs [ i ] . b_if ;
2007-05-23 13:58:12 -07:00
if ( hisax_register ( & adapter - > hisax_d_if , b_if , " st5481_usb " ,
2012-02-19 19:52:38 -08:00
protocol ) ! = 0 )
2007-05-23 13:58:12 -07:00
goto err_b1 ;
2005-04-16 15:20:36 -07:00
st5481_start ( adapter ) ;
usb_set_intfdata ( intf , adapter ) ;
return 0 ;
2012-02-19 19:52:38 -08:00
err_b1 :
2007-05-23 13:58:12 -07:00
st5481_release_b ( & adapter - > bcs [ 1 ] ) ;
2012-02-19 19:52:38 -08:00
err_b :
2005-04-16 15:20:36 -07:00
st5481_release_b ( & adapter - > bcs [ 0 ] ) ;
2012-02-19 19:52:38 -08:00
err_d :
2005-04-16 15:20:36 -07:00
st5481_release_d ( adapter ) ;
2012-02-19 19:52:38 -08:00
err_usb :
2005-04-16 15:20:36 -07:00
st5481_release_usb ( adapter ) ;
2012-02-19 19:52:38 -08:00
err :
2011-05-13 04:15:39 +00:00
kfree ( adapter ) ;
2005-04-16 15:20:36 -07:00
return - EIO ;
}
/*
* This function will be called when the adapter is removed
* from the USB bus .
*/
static void disconnect_st5481 ( struct usb_interface * intf )
{
struct st5481_adapter * adapter = usb_get_intfdata ( intf ) ;
2012-02-19 19:52:38 -08:00
DBG ( 1 , " " ) ;
2005-04-16 15:20:36 -07:00
usb_set_intfdata ( intf , NULL ) ;
if ( ! adapter )
return ;
2012-02-19 19:52:38 -08:00
2005-04-16 15:20:36 -07:00
st5481_stop ( adapter ) ;
st5481_release_b ( & adapter - > bcs [ 1 ] ) ;
st5481_release_b ( & adapter - > bcs [ 0 ] ) ;
st5481_release_d ( adapter ) ;
// we would actually better wait for completion of outstanding urbs
mdelay ( 2 ) ;
st5481_release_usb ( adapter ) ;
hisax_unregister ( & adapter - > hisax_d_if ) ;
kfree ( adapter ) ;
}
/*
* The last 4 bits in the Product Id is set with 4 pins on the chip .
*/
static struct usb_device_id st5481_ids [ ] = {
2012-02-19 19:52:38 -08:00
{ USB_DEVICE ( ST_VENDOR_ID , ST5481_PRODUCT_ID + 0x0 ) } ,
{ USB_DEVICE ( ST_VENDOR_ID , ST5481_PRODUCT_ID + 0x1 ) } ,
{ USB_DEVICE ( ST_VENDOR_ID , ST5481_PRODUCT_ID + 0x2 ) } ,
{ USB_DEVICE ( ST_VENDOR_ID , ST5481_PRODUCT_ID + 0x3 ) } ,
{ USB_DEVICE ( ST_VENDOR_ID , ST5481_PRODUCT_ID + 0x4 ) } ,
{ USB_DEVICE ( ST_VENDOR_ID , ST5481_PRODUCT_ID + 0x5 ) } ,
{ USB_DEVICE ( ST_VENDOR_ID , ST5481_PRODUCT_ID + 0x6 ) } ,
{ USB_DEVICE ( ST_VENDOR_ID , ST5481_PRODUCT_ID + 0x7 ) } ,
{ USB_DEVICE ( ST_VENDOR_ID , ST5481_PRODUCT_ID + 0x8 ) } ,
{ USB_DEVICE ( ST_VENDOR_ID , ST5481_PRODUCT_ID + 0x9 ) } ,
{ USB_DEVICE ( ST_VENDOR_ID , ST5481_PRODUCT_ID + 0xA ) } ,
{ USB_DEVICE ( ST_VENDOR_ID , ST5481_PRODUCT_ID + 0xB ) } ,
{ USB_DEVICE ( ST_VENDOR_ID , ST5481_PRODUCT_ID + 0xC ) } ,
{ USB_DEVICE ( ST_VENDOR_ID , ST5481_PRODUCT_ID + 0xD ) } ,
{ USB_DEVICE ( ST_VENDOR_ID , ST5481_PRODUCT_ID + 0xE ) } ,
{ USB_DEVICE ( ST_VENDOR_ID , ST5481_PRODUCT_ID + 0xF ) } ,
2005-04-16 15:20:36 -07:00
{ }
} ;
2012-02-19 19:52:38 -08:00
MODULE_DEVICE_TABLE ( usb , st5481_ids ) ;
2005-04-16 15:20:36 -07:00
static struct usb_driver st5481_usb_driver = {
. name = " st5481_usb " ,
. probe = probe_st5481 ,
. disconnect = disconnect_st5481 ,
. id_table = st5481_ids ,
2012-04-23 10:08:51 -07:00
. disable_hub_initiated_lpm = 1 ,
2005-04-16 15:20:36 -07:00
} ;
static int __init st5481_usb_init ( void )
{
int retval ;
# ifdef CONFIG_HISAX_DEBUG
st5481_debug = debug ;
# endif
printk ( KERN_INFO " hisax_st5481: ST5481 USB ISDN driver $Revision: 2.4.2.3 $ \n " ) ;
retval = st5481_d_init ( ) ;
if ( retval < 0 )
goto out ;
retval = usb_register ( & st5481_usb_driver ) ;
if ( retval < 0 )
goto out_d_exit ;
return 0 ;
2012-02-19 19:52:38 -08:00
out_d_exit :
2005-04-16 15:20:36 -07:00
st5481_d_exit ( ) ;
2012-02-19 19:52:38 -08:00
out :
2005-04-16 15:20:36 -07:00
return retval ;
}
static void __exit st5481_usb_exit ( void )
{
usb_deregister ( & st5481_usb_driver ) ;
st5481_d_exit ( ) ;
}
module_init ( st5481_usb_init ) ;
module_exit ( st5481_usb_exit ) ;