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 >
*
* This software may be used and distributed according to the terms
* of the GNU General Public License , incorporated herein by reference .
*
*/
# include <linux/init.h>
# include <linux/usb.h>
# include <linux/slab.h>
# include <linux/netdevice.h>
# include "st5481.h"
static void ph_connect ( struct st5481_adapter * adapter ) ;
static void ph_disconnect ( struct st5481_adapter * adapter ) ;
static struct Fsm l1fsm ;
static char * strL1State [ ] =
{
" ST_L1_F3 " ,
" ST_L1_F4 " ,
" ST_L1_F6 " ,
" ST_L1_F7 " ,
" ST_L1_F8 " ,
} ;
static char * strL1Event [ ] =
{
" EV_IND_DP " ,
" EV_IND_1 " ,
" EV_IND_2 " ,
" EV_IND_3 " ,
" EV_IND_RSY " ,
" EV_IND_5 " ,
" EV_IND_6 " ,
" EV_IND_7 " ,
" EV_IND_AP " ,
" EV_IND_9 " ,
" EV_IND_10 " ,
" EV_IND_11 " ,
" EV_IND_AI8 " ,
" EV_IND_AI10 " ,
" EV_IND_AIL " ,
" EV_IND_DI " ,
" EV_PH_ACTIVATE_REQ " ,
" EV_PH_DEACTIVATE_REQ " ,
" EV_TIMER3 " ,
} ;
static inline void D_L1L2 ( struct st5481_adapter * adapter , int pr , void * arg )
{
struct hisax_if * ifc = ( struct hisax_if * ) & adapter - > hisax_d_if ;
ifc - > l1l2 ( ifc , pr , arg ) ;
}
static void
l1_go_f3 ( struct FsmInst * fi , int event , void * arg )
{
struct st5481_adapter * adapter = fi - > userdata ;
if ( fi - > state = = ST_L1_F7 )
ph_disconnect ( adapter ) ;
FsmChangeState ( fi , ST_L1_F3 ) ;
D_L1L2 ( adapter , PH_DEACTIVATE | INDICATION , NULL ) ;
}
static void
l1_go_f6 ( struct FsmInst * fi , int event , void * arg )
{
struct st5481_adapter * adapter = fi - > userdata ;
if ( fi - > state = = ST_L1_F7 )
ph_disconnect ( adapter ) ;
FsmChangeState ( fi , ST_L1_F6 ) ;
}
static void
l1_go_f7 ( struct FsmInst * fi , int event , void * arg )
{
struct st5481_adapter * adapter = fi - > userdata ;
FsmDelTimer ( & adapter - > timer , 0 ) ;
ph_connect ( adapter ) ;
FsmChangeState ( fi , ST_L1_F7 ) ;
D_L1L2 ( adapter , PH_ACTIVATE | INDICATION , NULL ) ;
}
static void
l1_go_f8 ( struct FsmInst * fi , int event , void * arg )
{
struct st5481_adapter * adapter = fi - > userdata ;
if ( fi - > state = = ST_L1_F7 )
ph_disconnect ( adapter ) ;
FsmChangeState ( fi , ST_L1_F8 ) ;
}
static void
l1_timer3 ( struct FsmInst * fi , int event , void * arg )
{
struct st5481_adapter * adapter = fi - > userdata ;
st5481_ph_command ( adapter , ST5481_CMD_DR ) ;
FsmChangeState ( fi , ST_L1_F3 ) ;
D_L1L2 ( adapter , PH_DEACTIVATE | INDICATION , NULL ) ;
}
static void
l1_ignore ( struct FsmInst * fi , int event , void * arg )
{
}
static void
l1_activate ( struct FsmInst * fi , int event , void * arg )
{
struct st5481_adapter * adapter = fi - > userdata ;
st5481_ph_command ( adapter , ST5481_CMD_DR ) ;
st5481_ph_command ( adapter , ST5481_CMD_PUP ) ;
FsmRestartTimer ( & adapter - > timer , TIMER3_VALUE , EV_TIMER3 , NULL , 2 ) ;
st5481_ph_command ( adapter , ST5481_CMD_AR8 ) ;
FsmChangeState ( fi , ST_L1_F4 ) ;
}
static struct FsmNode L1FnList [ ] __initdata =
{
{ ST_L1_F3 , EV_IND_DP , l1_ignore } ,
{ ST_L1_F3 , EV_IND_AP , l1_go_f6 } ,
{ ST_L1_F3 , EV_IND_AI8 , l1_go_f7 } ,
{ ST_L1_F3 , EV_IND_AI10 , l1_go_f7 } ,
{ ST_L1_F3 , EV_PH_ACTIVATE_REQ , l1_activate } ,
{ ST_L1_F4 , EV_TIMER3 , l1_timer3 } ,
{ ST_L1_F4 , EV_IND_DP , l1_go_f3 } ,
{ ST_L1_F4 , EV_IND_AP , l1_go_f6 } ,
{ ST_L1_F4 , EV_IND_AI8 , l1_go_f7 } ,
{ ST_L1_F4 , EV_IND_AI10 , l1_go_f7 } ,
{ ST_L1_F6 , EV_TIMER3 , l1_timer3 } ,
{ ST_L1_F6 , EV_IND_DP , l1_go_f3 } ,
{ ST_L1_F6 , EV_IND_AP , l1_ignore } ,
{ ST_L1_F6 , EV_IND_AI8 , l1_go_f7 } ,
{ ST_L1_F6 , EV_IND_AI10 , l1_go_f7 } ,
{ ST_L1_F7 , EV_IND_RSY , l1_go_f8 } ,
{ ST_L1_F7 , EV_IND_DP , l1_go_f3 } ,
{ ST_L1_F7 , EV_IND_AP , l1_go_f6 } ,
{ ST_L1_F7 , EV_IND_AI8 , l1_ignore } ,
{ ST_L1_F7 , EV_IND_AI10 , l1_ignore } ,
{ ST_L1_F7 , EV_IND_RSY , l1_go_f8 } ,
{ ST_L1_F8 , EV_TIMER3 , l1_timer3 } ,
{ ST_L1_F8 , EV_IND_DP , l1_go_f3 } ,
{ ST_L1_F8 , EV_IND_AP , l1_go_f6 } ,
{ ST_L1_F8 , EV_IND_AI8 , l1_go_f8 } ,
{ ST_L1_F8 , EV_IND_AI10 , l1_go_f8 } ,
{ ST_L1_F8 , EV_IND_RSY , l1_ignore } ,
} ;
static void l1m_debug ( struct FsmInst * fi , char * fmt , . . . )
{
va_list args ;
char buf [ 256 ] ;
va_start ( args , fmt ) ;
vsprintf ( buf , fmt , args ) ;
DBG ( 8 , " %s " , buf ) ;
va_end ( args ) ;
}
/* ======================================================================
* D - Channel out
*/
/*
D OUT state machine :
= = = = = = = = = = = = = = = = = = = =
Transmit short frame ( < 16 bytes of encoded data ) :
L1 FRAME D_OUT_STATE USB D CHANNEL
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FIXME
- > [ xx . . xx ] SHORT_INIT - > [ 7 Exx . . xxC1C27EFF ]
SHORT_WAIT_DEN < > OUT_D_COUNTER = 16
END_OF_SHORT < - DEN_EVENT - > 7 Exx
xxxx
xxxx
xxxx
xxxx
xxxx
C1C1
7 EFF
WAIT_FOR_RESET_IDLE < - D_UNDERRUN < - ( 8 ms )
IDLE < > Reset pipe
Transmit long frame ( > = 16 bytes of encoded data ) :
L1 FRAME D_OUT_STATE USB D CHANNEL
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- > [ xx . . . xx ] IDLE
WAIT_FOR_STOP < > OUT_D_COUNTER = 0
WAIT_FOR_RESET < > Reset pipe
STOP
INIT_LONG_FRAME - > [ 7 Exx . . xx ]
WAIT_DEN < > OUT_D_COUNTER = 16
OUT_NORMAL < - DEN_EVENT - > 7 Exx
END_OF_FRAME_BUSY - > [ xxxx ] xxxx
END_OF_FRAME_NOT_BUSY - > [ xxxx ] xxxx
- > [ xxxx ] xxxx
- > [ C1C2 ] xxxx
- > [ 7 EFF ] xxxx
xxxx
xxxx
. . . .
xxxx
C1C2
7 EFF
< - D_UNDERRUN < - ( > 8 ms )
WAIT_FOR_STOP < > OUT_D_COUNTER = 0
WAIT_FOR_RESET < > Reset pipe
STOP
*/
static struct Fsm dout_fsm ;
static char * strDoutState [ ] =
{
" ST_DOUT_NONE " ,
" ST_DOUT_SHORT_INIT " ,
" ST_DOUT_SHORT_WAIT_DEN " ,
" ST_DOUT_LONG_INIT " ,
" ST_DOUT_LONG_WAIT_DEN " ,
" ST_DOUT_NORMAL " ,
" ST_DOUT_WAIT_FOR_UNDERRUN " ,
" ST_DOUT_WAIT_FOR_NOT_BUSY " ,
" ST_DOUT_WAIT_FOR_STOP " ,
" ST_DOUT_WAIT_FOR_RESET " ,
} ;
static char * strDoutEvent [ ] =
{
" EV_DOUT_START_XMIT " ,
" EV_DOUT_COMPLETE " ,
" EV_DOUT_DEN " ,
" EV_DOUT_RESETED " ,
" EV_DOUT_STOPPED " ,
" EV_DOUT_COLL " ,
" EV_DOUT_UNDERRUN " ,
} ;
static void dout_debug ( struct FsmInst * fi , char * fmt , . . . )
{
va_list args ;
char buf [ 256 ] ;
va_start ( args , fmt ) ;
vsprintf ( buf , fmt , args ) ;
DBG ( 0x2 , " %s " , buf ) ;
va_end ( args ) ;
}
static void dout_stop_event ( void * context )
{
struct st5481_adapter * adapter = context ;
FsmEvent ( & adapter - > d_out . fsm , EV_DOUT_STOPPED , NULL ) ;
}
/*
* Start the transfer of a D channel frame .
*/
static void usb_d_out ( struct st5481_adapter * adapter , int buf_nr )
{
struct st5481_d_out * d_out = & adapter - > d_out ;
struct urb * urb ;
unsigned int num_packets , packet_offset ;
int len , buf_size , bytes_sent ;
struct sk_buff * skb ;
struct usb_iso_packet_descriptor * desc ;
if ( d_out - > fsm . state ! = ST_DOUT_NORMAL )
return ;
if ( test_and_set_bit ( buf_nr , & d_out - > busy ) ) {
DBG ( 2 , " ep %d urb %d busy %#lx " , EP_D_OUT , buf_nr , d_out - > busy ) ;
return ;
}
urb = d_out - > urb [ buf_nr ] ;
skb = d_out - > tx_skb ;
buf_size = NUM_ISO_PACKETS_D * SIZE_ISO_PACKETS_D_OUT ;
if ( skb ) {
len = isdnhdlc_encode ( & d_out - > hdlc_state ,
skb - > data , skb - > len , & bytes_sent ,
urb - > transfer_buffer , buf_size ) ;
skb_pull ( skb , bytes_sent ) ;
} else {
// Send flags or idle
len = isdnhdlc_encode ( & d_out - > hdlc_state ,
NULL , 0 , & bytes_sent ,
urb - > transfer_buffer , buf_size ) ;
}
if ( len < buf_size ) {
FsmChangeState ( & d_out - > fsm , ST_DOUT_WAIT_FOR_UNDERRUN ) ;
}
if ( skb & & ! skb - > len ) {
d_out - > tx_skb = NULL ;
D_L1L2 ( adapter , PH_DATA | CONFIRM , NULL ) ;
dev_kfree_skb_any ( skb ) ;
}
// Prepare the URB
urb - > transfer_buffer_length = len ;
num_packets = 0 ;
packet_offset = 0 ;
while ( packet_offset < len ) {
desc = & urb - > iso_frame_desc [ num_packets ] ;
desc - > offset = packet_offset ;
desc - > length = SIZE_ISO_PACKETS_D_OUT ;
if ( len - packet_offset < desc - > length )
desc - > length = len - packet_offset ;
num_packets + + ;
packet_offset + = desc - > length ;
}
urb - > number_of_packets = num_packets ;
// Prepare the URB
urb - > dev = adapter - > usb_dev ;
// Need to transmit the next buffer 2ms after the DEN_EVENT
urb - > transfer_flags = 0 ;
urb - > start_frame = usb_get_current_frame_number ( adapter - > usb_dev ) + 2 ;
DBG_ISO_PACKET ( 0x20 , urb ) ;
if ( usb_submit_urb ( urb , GFP_KERNEL ) < 0 ) {
// There is another URB queued up
urb - > transfer_flags = URB_ISO_ASAP ;
SUBMIT_URB ( urb , GFP_KERNEL ) ;
}
}
static void fifo_reseted ( void * context )
{
struct st5481_adapter * adapter = context ;
FsmEvent ( & adapter - > d_out . fsm , EV_DOUT_RESETED , NULL ) ;
}
static void usb_d_out_complete ( struct urb * urb , struct pt_regs * regs )
{
struct st5481_adapter * adapter = urb - > context ;
struct st5481_d_out * d_out = & adapter - > d_out ;
int buf_nr ;
DBG ( 2 , " " ) ;
buf_nr = get_buf_nr ( d_out - > urb , urb ) ;
test_and_clear_bit ( buf_nr , & d_out - > busy ) ;
if ( unlikely ( urb - > status < 0 ) ) {
2005-09-17 23:52:42 +02:00
switch ( urb - > status ) {
case - ENOENT :
case - ESHUTDOWN :
case - ECONNRESET :
DBG ( 1 , " urb killed status %d " , urb - > status ) ;
break ;
default :
WARN ( " urb status %d " , urb - > status ) ;
if ( d_out - > busy = = 0 ) {
st5481_usb_pipe_reset ( adapter , EP_D_OUT | USB_DIR_OUT , fifo_reseted , adapter ) ;
}
break ;
2005-04-16 15:20:36 -07:00
}
2005-09-17 23:52:42 +02:00
return ; // Give up
2005-04-16 15:20:36 -07:00
}
FsmEvent ( & adapter - > d_out . fsm , EV_DOUT_COMPLETE , ( void * ) buf_nr ) ;
}
/* ====================================================================== */
static void dout_start_xmit ( struct FsmInst * fsm , int event , void * arg )
{
// FIXME unify?
struct st5481_adapter * adapter = fsm - > userdata ;
struct st5481_d_out * d_out = & adapter - > d_out ;
struct urb * urb ;
int len , bytes_sent ;
struct sk_buff * skb ;
int buf_nr = 0 ;
skb = d_out - > tx_skb ;
DBG ( 2 , " len=%d " , skb - > len ) ;
isdnhdlc_out_init ( & d_out - > hdlc_state , 1 , 0 ) ;
if ( test_and_set_bit ( buf_nr , & d_out - > busy ) ) {
WARN ( " ep %d urb %d busy %#lx " , EP_D_OUT , buf_nr , d_out - > busy ) ;
return ;
}
urb = d_out - > urb [ buf_nr ] ;
DBG_SKB ( 0x10 , skb ) ;
len = isdnhdlc_encode ( & d_out - > hdlc_state ,
skb - > data , skb - > len , & bytes_sent ,
urb - > transfer_buffer , 16 ) ;
skb_pull ( skb , bytes_sent ) ;
if ( len < 16 )
FsmChangeState ( & d_out - > fsm , ST_DOUT_SHORT_INIT ) ;
else
FsmChangeState ( & d_out - > fsm , ST_DOUT_LONG_INIT ) ;
if ( skb - > len = = 0 ) {
d_out - > tx_skb = NULL ;
D_L1L2 ( adapter , PH_DATA | CONFIRM , NULL ) ;
dev_kfree_skb_any ( skb ) ;
}
// Prepare the URB
urb - > transfer_buffer_length = len ;
urb - > iso_frame_desc [ 0 ] . offset = 0 ;
urb - > iso_frame_desc [ 0 ] . length = len ;
urb - > number_of_packets = 1 ;
// Prepare the URB
urb - > dev = adapter - > usb_dev ;
urb - > transfer_flags = URB_ISO_ASAP ;
DBG_ISO_PACKET ( 0x20 , urb ) ;
SUBMIT_URB ( urb , GFP_KERNEL ) ;
}
static void dout_short_fifo ( struct FsmInst * fsm , int event , void * arg )
{
struct st5481_adapter * adapter = fsm - > userdata ;
struct st5481_d_out * d_out = & adapter - > d_out ;
FsmChangeState ( & d_out - > fsm , ST_DOUT_SHORT_WAIT_DEN ) ;
st5481_usb_device_ctrl_msg ( adapter , OUT_D_COUNTER , 16 , NULL , NULL ) ;
}
static void dout_end_short_frame ( struct FsmInst * fsm , int event , void * arg )
{
struct st5481_adapter * adapter = fsm - > userdata ;
struct st5481_d_out * d_out = & adapter - > d_out ;
FsmChangeState ( & d_out - > fsm , ST_DOUT_WAIT_FOR_UNDERRUN ) ;
}
static void dout_long_enable_fifo ( struct FsmInst * fsm , int event , void * arg )
{
struct st5481_adapter * adapter = fsm - > userdata ;
struct st5481_d_out * d_out = & adapter - > d_out ;
st5481_usb_device_ctrl_msg ( adapter , OUT_D_COUNTER , 16 , NULL , NULL ) ;
FsmChangeState ( & d_out - > fsm , ST_DOUT_LONG_WAIT_DEN ) ;
}
static void dout_long_den ( struct FsmInst * fsm , int event , void * arg )
{
struct st5481_adapter * adapter = fsm - > userdata ;
struct st5481_d_out * d_out = & adapter - > d_out ;
FsmChangeState ( & d_out - > fsm , ST_DOUT_NORMAL ) ;
usb_d_out ( adapter , 0 ) ;
usb_d_out ( adapter , 1 ) ;
}
static void dout_reset ( struct FsmInst * fsm , int event , void * arg )
{
struct st5481_adapter * adapter = fsm - > userdata ;
struct st5481_d_out * d_out = & adapter - > d_out ;
FsmChangeState ( & d_out - > fsm , ST_DOUT_WAIT_FOR_RESET ) ;
st5481_usb_pipe_reset ( adapter , EP_D_OUT | USB_DIR_OUT , fifo_reseted , adapter ) ;
}
static void dout_stop ( struct FsmInst * fsm , int event , void * arg )
{
struct st5481_adapter * adapter = fsm - > userdata ;
struct st5481_d_out * d_out = & adapter - > d_out ;
FsmChangeState ( & d_out - > fsm , ST_DOUT_WAIT_FOR_STOP ) ;
st5481_usb_device_ctrl_msg ( adapter , OUT_D_COUNTER , 0 , dout_stop_event , adapter ) ;
}
static void dout_underrun ( struct FsmInst * fsm , int event , void * arg )
{
struct st5481_adapter * adapter = fsm - > userdata ;
struct st5481_d_out * d_out = & adapter - > d_out ;
if ( test_bit ( 0 , & d_out - > busy ) | | test_bit ( 1 , & d_out - > busy ) ) {
FsmChangeState ( & d_out - > fsm , ST_DOUT_WAIT_FOR_NOT_BUSY ) ;
} else {
dout_stop ( fsm , event , arg ) ;
}
}
static void dout_check_busy ( struct FsmInst * fsm , int event , void * arg )
{
struct st5481_adapter * adapter = fsm - > userdata ;
struct st5481_d_out * d_out = & adapter - > d_out ;
if ( ! test_bit ( 0 , & d_out - > busy ) & & ! test_bit ( 1 , & d_out - > busy ) )
dout_stop ( fsm , event , arg ) ;
}
static void dout_reseted ( struct FsmInst * fsm , int event , void * arg )
{
struct st5481_adapter * adapter = fsm - > userdata ;
struct st5481_d_out * d_out = & adapter - > d_out ;
FsmChangeState ( & d_out - > fsm , ST_DOUT_NONE ) ;
// FIXME locking
if ( d_out - > tx_skb )
FsmEvent ( & d_out - > fsm , EV_DOUT_START_XMIT , NULL ) ;
}
static void dout_complete ( struct FsmInst * fsm , int event , void * arg )
{
struct st5481_adapter * adapter = fsm - > userdata ;
int buf_nr = ( int ) arg ;
usb_d_out ( adapter , buf_nr ) ;
}
static void dout_ignore ( struct FsmInst * fsm , int event , void * arg )
{
}
static struct FsmNode DoutFnList [ ] __initdata =
{
{ ST_DOUT_NONE , EV_DOUT_START_XMIT , dout_start_xmit } ,
{ ST_DOUT_SHORT_INIT , EV_DOUT_COMPLETE , dout_short_fifo } ,
{ ST_DOUT_SHORT_WAIT_DEN , EV_DOUT_DEN , dout_end_short_frame } ,
{ ST_DOUT_SHORT_WAIT_DEN , EV_DOUT_UNDERRUN , dout_underrun } ,
{ ST_DOUT_LONG_INIT , EV_DOUT_COMPLETE , dout_long_enable_fifo } ,
{ ST_DOUT_LONG_WAIT_DEN , EV_DOUT_DEN , dout_long_den } ,
{ ST_DOUT_LONG_WAIT_DEN , EV_DOUT_UNDERRUN , dout_underrun } ,
{ ST_DOUT_NORMAL , EV_DOUT_UNDERRUN , dout_underrun } ,
{ ST_DOUT_NORMAL , EV_DOUT_COMPLETE , dout_complete } ,
{ ST_DOUT_WAIT_FOR_UNDERRUN , EV_DOUT_UNDERRUN , dout_underrun } ,
{ ST_DOUT_WAIT_FOR_UNDERRUN , EV_DOUT_COMPLETE , dout_ignore } ,
{ ST_DOUT_WAIT_FOR_NOT_BUSY , EV_DOUT_COMPLETE , dout_check_busy } ,
{ ST_DOUT_WAIT_FOR_STOP , EV_DOUT_STOPPED , dout_reset } ,
{ ST_DOUT_WAIT_FOR_RESET , EV_DOUT_RESETED , dout_reseted } ,
} ;
void st5481_d_l2l1 ( struct hisax_if * hisax_d_if , int pr , void * arg )
{
struct st5481_adapter * adapter = hisax_d_if - > priv ;
struct sk_buff * skb = arg ;
switch ( pr ) {
case PH_ACTIVATE | REQUEST :
FsmEvent ( & adapter - > l1m , EV_PH_ACTIVATE_REQ , NULL ) ;
break ;
case PH_DEACTIVATE | REQUEST :
FsmEvent ( & adapter - > l1m , EV_PH_DEACTIVATE_REQ , NULL ) ;
break ;
case PH_DATA | REQUEST :
DBG ( 2 , " PH_DATA REQUEST len %d " , skb - > len ) ;
if ( adapter - > d_out . tx_skb )
BUG ( ) ;
adapter - > d_out . tx_skb = skb ;
FsmEvent ( & adapter - > d_out . fsm , EV_DOUT_START_XMIT , NULL ) ;
break ;
default :
WARN ( " pr %#x \n " , pr ) ;
break ;
}
}
/* ======================================================================
*/
/*
* Start receiving on the D channel since entered state F7 .
*/
static void ph_connect ( struct st5481_adapter * adapter )
{
struct st5481_d_out * d_out = & adapter - > d_out ;
struct st5481_in * d_in = & adapter - > d_in ;
DBG ( 8 , " " ) ;
FsmChangeState ( & d_out - > fsm , ST_DOUT_NONE ) ;
// st5481_usb_device_ctrl_msg(adapter, FFMSK_D, OUT_UNDERRUN, NULL, NULL);
st5481_usb_device_ctrl_msg ( adapter , FFMSK_D , 0xfc , NULL , NULL ) ;
st5481_in_mode ( d_in , L1_MODE_HDLC ) ;
# ifdef LOOPBACK
// Turn loopback on (data sent on B and D looped back)
st5481_usb_device_ctrl_msg ( cs , LBB , 0x04 , NULL , NULL ) ;
# endif
st5481_usb_pipe_reset ( adapter , EP_D_OUT | USB_DIR_OUT , NULL , NULL ) ;
// Turn on the green LED to tell that we are in state F7
adapter - > leds | = GREEN_LED ;
st5481_usb_device_ctrl_msg ( adapter , GPIO_OUT , adapter - > leds , NULL , NULL ) ;
}
/*
* Stop receiving on the D channel since not in state F7 .
*/
static void ph_disconnect ( struct st5481_adapter * adapter )
{
DBG ( 8 , " " ) ;
st5481_in_mode ( & adapter - > d_in , L1_MODE_NULL ) ;
// Turn off the green LED to tell that we left state F7
adapter - > leds & = ~ GREEN_LED ;
st5481_usb_device_ctrl_msg ( adapter , GPIO_OUT , adapter - > leds , NULL , NULL ) ;
}
static int st5481_setup_d_out ( struct st5481_adapter * adapter )
{
struct usb_device * dev = adapter - > usb_dev ;
struct usb_interface * intf ;
struct usb_host_interface * altsetting = NULL ;
struct usb_host_endpoint * endpoint ;
struct st5481_d_out * d_out = & adapter - > d_out ;
DBG ( 2 , " " ) ;
intf = usb_ifnum_to_if ( dev , 0 ) ;
if ( intf )
altsetting = usb_altnum_to_altsetting ( intf , 3 ) ;
if ( ! altsetting )
return - ENXIO ;
// Allocate URBs and buffers for the D channel out
endpoint = & altsetting - > endpoint [ EP_D_OUT - 1 ] ;
DBG ( 2 , " endpoint address=%02x,packet size=%d " ,
endpoint - > desc . bEndpointAddress , le16_to_cpu ( endpoint - > desc . wMaxPacketSize ) ) ;
return st5481_setup_isocpipes ( d_out - > urb , dev ,
usb_sndisocpipe ( dev , endpoint - > desc . bEndpointAddress ) ,
NUM_ISO_PACKETS_D , SIZE_ISO_PACKETS_D_OUT ,
NUM_ISO_PACKETS_D * SIZE_ISO_PACKETS_D_OUT ,
usb_d_out_complete , adapter ) ;
}
static void st5481_release_d_out ( struct st5481_adapter * adapter )
{
struct st5481_d_out * d_out = & adapter - > d_out ;
DBG ( 2 , " " ) ;
st5481_release_isocpipes ( d_out - > urb ) ;
}
int st5481_setup_d ( struct st5481_adapter * adapter )
{
int retval ;
DBG ( 2 , " " ) ;
retval = st5481_setup_d_out ( adapter ) ;
if ( retval )
goto err ;
adapter - > d_in . bufsize = MAX_DFRAME_LEN_L1 ;
adapter - > d_in . num_packets = NUM_ISO_PACKETS_D ;
adapter - > d_in . packet_size = SIZE_ISO_PACKETS_D_IN ;
adapter - > d_in . ep = EP_D_IN | USB_DIR_IN ;
adapter - > d_in . counter = IN_D_COUNTER ;
adapter - > d_in . adapter = adapter ;
adapter - > d_in . hisax_if = & adapter - > hisax_d_if . ifc ;
retval = st5481_setup_in ( & adapter - > d_in ) ;
if ( retval )
goto err_d_out ;
adapter - > l1m . fsm = & l1fsm ;
adapter - > l1m . state = ST_L1_F3 ;
2005-09-17 23:52:42 +02:00
adapter - > l1m . debug = st5481_debug & 0x100 ;
2005-04-16 15:20:36 -07:00
adapter - > l1m . userdata = adapter ;
adapter - > l1m . printdebug = l1m_debug ;
FsmInitTimer ( & adapter - > l1m , & adapter - > timer ) ;
adapter - > d_out . fsm . fsm = & dout_fsm ;
adapter - > d_out . fsm . state = ST_DOUT_NONE ;
2005-09-17 23:52:42 +02:00
adapter - > d_out . fsm . debug = st5481_debug & 0x100 ;
2005-04-16 15:20:36 -07:00
adapter - > d_out . fsm . userdata = adapter ;
adapter - > d_out . fsm . printdebug = dout_debug ;
return 0 ;
err_d_out :
st5481_release_d_out ( adapter ) ;
err :
return retval ;
}
void st5481_release_d ( struct st5481_adapter * adapter )
{
DBG ( 2 , " " ) ;
st5481_release_in ( & adapter - > d_in ) ;
st5481_release_d_out ( adapter ) ;
}
/* ======================================================================
* init / exit
*/
int __init st5481_d_init ( void )
{
int retval ;
l1fsm . state_count = L1_STATE_COUNT ;
l1fsm . event_count = L1_EVENT_COUNT ;
l1fsm . strEvent = strL1Event ;
l1fsm . strState = strL1State ;
retval = FsmNew ( & l1fsm , L1FnList , ARRAY_SIZE ( L1FnList ) ) ;
if ( retval )
goto err ;
dout_fsm . state_count = DOUT_STATE_COUNT ;
dout_fsm . event_count = DOUT_EVENT_COUNT ;
dout_fsm . strEvent = strDoutEvent ;
dout_fsm . strState = strDoutState ;
retval = FsmNew ( & dout_fsm , DoutFnList , ARRAY_SIZE ( DoutFnList ) ) ;
if ( retval )
goto err_l1 ;
return 0 ;
err_l1 :
FsmFree ( & l1fsm ) ;
err :
return retval ;
}
// can't be __exit
void st5481_d_exit ( void )
{
FsmFree ( & l1fsm ) ;
FsmFree ( & dout_fsm ) ;
}