From: Karsten Keil This is an update of the HFC USB ISDN driver, the current one has some bugs and support not all HW. It was already tested as standalone patch for some time, so including it should be safe. Signed-off-by: Karsten Keil Signed-off-by: Andrew Morton --- 25-akpm/drivers/isdn/hisax/hfc_usb.c | 1067 +++++++++++++++++++++-------------- 1 files changed, 645 insertions(+), 422 deletions(-) diff -puN drivers/isdn/hisax/hfc_usb.c~i4l-new-hfc_usb-driver-version drivers/isdn/hisax/hfc_usb.c --- 25/drivers/isdn/hisax/hfc_usb.c~i4l-new-hfc_usb-driver-version 2005-01-22 18:35:06.001405192 -0800 +++ 25-akpm/drivers/isdn/hisax/hfc_usb.c 2005-01-22 18:35:06.016402912 -0800 @@ -1,9 +1,11 @@ /* * hfc_usb.c * - * modular HiSax ISDN driver for Colognechip HFC-USB chip + * $Id: hfc_usb.c,v 4.33 2004/11/26 07:54:01 martinb1 Exp $ * - * Authors : Peter Sprenger (sprenger@moving-byters.de) + * modular HiSax ISDN driver for Colognechip HFC-S USB chip + * + * Authors : Peter Sprenger (sprenger@moving-bytes.de) * Martin Bachem (info@colognechip.com) * based on the first hfc_usb driver of Werner Cornelius (werner@isdn-development.de) * @@ -21,6 +23,8 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * + * See Version Histroy at the bottom of this file + * */ @@ -38,16 +42,16 @@ #include #include "hisax_if.h" -static const char *hfcusb_revision = "4.0"; /* - to enable much mire debug messages in this driver, define - VERBOSE_USB_DEBUG and VERBOSE_ISDN_DEBUG - below -*/ + * Version Information + * (do not modify the CVS Makros $Revision: 4.33 $ and $Date: 2004/11/26 07:54:01 $ !) + */ +static const char *hfcusb_revision = "Revision: 4.33 $ Date: 2004/11/26 07:54:01 $ "; +#define DRIVER_AUTHOR "Peter Sprenger (sprenger@moving-byters.de) / Martin Bachem (info@colognechip.com)" +#define DRIVER_DESC "HFC-S USB based HiSAX ISDN driver" #define VERBOSE_USB_DEBUG -#define VERBOSE_ISDN_DEBUG #define INCLUDE_INLINE_FUNCS @@ -58,8 +62,7 @@ static const char *hfcusb_revision = "4. /***********/ /* defines */ /***********/ -#define HFC_CTRL_TIMEOUT 20 //(HZ * USB_CTRL_GET_TIMEOUT) -/* 5ms timeout writing/reading regs */ +#define HFC_CTRL_TIMEOUT 20 /* 5ms timeout writing/reading regs */ #define HFC_TIMER_T3 8000 /* timeout for l1 activation timer */ #define HFC_TIMER_T4 500 /* time for state change interval */ @@ -93,7 +96,7 @@ static const char *hfcusb_revision = "4. #define HFCUSB_INC_RES_F 0x0e #define HFCUSB_STATES 0x30 -#define HFCUSB_CHIPID 0x40 /* ID value of HFC-USB */ +#define HFCUSB_CHIPID 0x40 /* ID value of HFC-S USB */ /******************/ /* fifo registers */ @@ -112,12 +115,12 @@ static const char *hfcusb_revision = "4. * used to switch snd_transfer_mode for different TA modes e.g. the Billion USB TA just * supports ISO out, while the Cologne Chip EVAL TA just supports BULK out */ -#define USB_INT 0 -#define USB_BULK 1 -#define USB_ISOC 2 +#define USB_INT 0 +#define USB_BULK 1 +#define USB_ISOC 2 -#define ISOC_PACKETS_D 8 -#define ISOC_PACKETS_B 8 +#define ISOC_PACKETS_D 8 +#define ISOC_PACKETS_B 8 #define ISO_BUFFER_SIZE 128 // ISO send definitions @@ -128,14 +131,25 @@ static const char *hfcusb_revision = "4. #define BITLINE_INF (-64*8) - - /**********/ /* macros */ /**********/ -#define write_usb(a,b,c) usb_control_msg((a)->dev,(a)->ctrl_out_pipe,0,0x40,(c),(b),NULL,0,HFC_CTRL_TIMEOUT) +#define write_usb(a,b,c) usb_control_msg((a)->dev,(a)->ctrl_out_pipe,0,0x40,(c),(b),0,0,HFC_CTRL_TIMEOUT) #define read_usb(a,b,c) usb_control_msg((a)->dev,(a)->ctrl_in_pipe,1,0xC0,0,(b),(c),1,HFC_CTRL_TIMEOUT) +// Hisax debug support +// use "modprobe debug=x" where x is bitfield of USB_DBG & ISDN_DBG +#define USB_DBG 1 +#define ISDN_DBG 2 +#ifdef CONFIG_HISAX_DEBUG +#include +#define __debug_variable hfc_debug +#include "hisax_debug.h" +static u_int debug; +module_param(debug, uint, 0); +int hfc_debug; +#endif + /*************************************************/ /* entry and size of output/input control buffer */ /*************************************************/ @@ -154,8 +168,7 @@ typedef struct int prod_id; // product id char *vend_name; // vendor string __u8 led_scheme; // led display scheme - __u8 led_invert; // invert led aux port settings - __u8 led_bits[8]; // array of 8 possible LED bitmask settings + signed short led_bits[8]; // array of 8 possible LED bitmask settings } vendor_data; @@ -163,35 +176,35 @@ typedef struct /* structure defining input+output fifos (interrupt/bulk mode) */ /***************************************************************/ -struct usb_fifo; /* forward definition */ +struct usb_fifo; /* forward definition */ typedef struct iso_urb_struct { struct urb *purb; - __u8 buffer[ISO_BUFFER_SIZE]; /* buffer incoming/outgoing data */ + __u8 buffer[ISO_BUFFER_SIZE]; /* buffer incoming/outgoing data */ struct usb_fifo *owner_fifo; // pointer to owner fifo } iso_urb_struct; -struct hfcusb_data; /* forward definition */ +struct hfcusb_data; /* forward definition */ typedef struct usb_fifo { - int fifonum; /* fifo index attached to this structure */ - int active; /* fifo is currently active */ + int fifonum; /* fifo index attached to this structure */ + int active; /* fifo is currently active */ struct hfcusb_data *hfc; /* pointer to main structure */ - int pipe; /* address of endpoint */ + int pipe; /* address of endpoint */ __u8 usb_packet_maxlen; /* maximum length for usb transfer */ unsigned int max_size; /* maximum size of receive/send packet */ - __u8 intervall; /* interrupt interval */ + __u8 intervall; /* interrupt interval */ struct sk_buff *skbuff; /* actual used buffer */ - struct urb *urb; /* transfer structure for usb routines */ + struct urb *urb; /* transfer structure for usb routines */ __u8 buffer[128]; /* buffer incoming/outgoing data */ int bit_line; /* how much bits are in the fifo? */ - volatile __u8 usb_transfer_mode;/* switched between ISO and INT */ - iso_urb_struct iso[2]; /* need two urbs to have one always for pending */ + volatile __u8 usb_transfer_mode; /* switched between ISO and INT */ + iso_urb_struct iso[2]; /* need two urbs to have one always for pending */ struct hisax_if *hif; /* hisax interface */ - int delete_flg; /* only delete skbuff once */ - int last_urblen; /* remember length of last packet */ + int delete_flg; /* only delete skbuff once */ + int last_urblen; /* remember length of last packet */ } usb_fifo; @@ -202,44 +215,44 @@ typedef struct usb_fifo typedef struct hfcusb_data { // HiSax Interface for loadable Layer1 drivers - struct hisax_d_if d_if; /* see hisax_if.h */ - struct hisax_b_if b_if[2]; /* see hisax_if.h */ + struct hisax_d_if d_if; /* see hisax_if.h */ + struct hisax_b_if b_if[2]; /* see hisax_if.h */ int protocol; - - struct usb_device *dev; /* our device */ - int if_used; /* used interface number */ - int alt_used; /* used alternate config */ - int ctrl_paksize; /* control pipe packet size */ + + struct usb_device *dev; /* our device */ + int if_used; /* used interface number */ + int alt_used; /* used alternate config */ + int ctrl_paksize; /* control pipe packet size */ int ctrl_in_pipe, ctrl_out_pipe; /* handles for control pipe */ - int cfg_used; /* configuration index used */ - int vend_idx; // vendor found + int cfg_used; /* configuration index used */ + int vend_idx; // vendor found - int b_mode[2]; // B-channel mode + int b_mode[2]; // B-channel mode - int l1_activated; // layer 1 activated + int l1_activated; // layer 1 activated + int disc_flag; // TRUE if device was unplugged, so avoid some USB actions... - int packet_size,iso_packet_size; + int packet_size,iso_packet_size; /* control pipe background handling */ ctrl_buft ctrl_buff[HFC_CTRL_BUFSIZE]; /* buffer holding queued data */ - volatile int ctrl_in_idx, ctrl_out_idx, - ctrl_cnt; /* input/output pointer + count */ - struct urb *ctrl_urb; /* transfer structure for control channel */ + volatile int ctrl_in_idx, ctrl_out_idx, ctrl_cnt; /* input/output pointer + count */ + struct urb *ctrl_urb; /* transfer structure for control channel */ struct usb_ctrlrequest ctrl_write; /* buffer for control write request */ struct usb_ctrlrequest ctrl_read; /* same for read request */ - __u8 led_state,led_new_data,led_b_active; + __u8 old_led_state,led_state,led_new_data,led_b_active; - volatile __u8 threshold_mask; /* threshold actually reported */ - volatile __u8 bch_enables; /* or mask for sctrl_r and sctrl register values */ + volatile __u8 threshold_mask; /* threshold actually reported */ + volatile __u8 bch_enables; /* or mask for sctrl_r and sctrl register values */ usb_fifo fifos[HFCUSB_NUM_FIFOS]; /* structure holding all fifo data */ - volatile __u8 l1_state; /* actual l1 state */ - struct timer_list t3_timer; /* timer 3 for activation/deactivation */ - struct timer_list t4_timer; /* timer 4 for activation/deactivation */ - struct timer_list led_timer; /* timer flashing leds */ + volatile __u8 l1_state; /* actual l1 state */ + struct timer_list t3_timer; /* timer 3 for activation/deactivation */ + struct timer_list t4_timer; /* timer 4 for activation/deactivation */ + struct timer_list led_timer; /* timer flashing leds */ } hfcusb_data; @@ -247,13 +260,47 @@ typedef struct hfcusb_data static void collect_rx_frame(usb_fifo *fifo,__u8 *data,int len,int finish); +/* Used to represent a list of values and their respective symbolic names */ +struct hfcusb_symbolic_list { + const int num; + const char *name; +}; + +/* URB error codes: */ +static struct hfcusb_symbolic_list urb_errlist[] = { + { -ENOMEM, "No memory for allocation of internal structures" }, + { -ENOSPC, "The host controller's bandwidth is already consumed" }, + { -ENOENT, "URB was canceled by unlink_urb" }, + { -EXDEV, "ISO transfer only partially completed" }, + { -EAGAIN, "Too match scheduled for the future" }, + { -ENXIO, "URB already queued" }, + { -EFBIG, "Too much ISO frames requested" }, + { -ENOSR, "Buffer error (overrun)" }, + { -EPIPE, "Specified endpoint is stalled (device not responding)"}, + { -EOVERFLOW, "Babble (bad cable?)" }, + { -EPROTO, "Bit-stuff error (bad cable?)" }, + { -EILSEQ, "CRC/Timeout" }, + { -ETIMEDOUT, "NAK (device does not respond)" }, + { -ESHUTDOWN, "Device unplugged"}, + { -1, NULL } +}; + + +static inline const char * symbolic(struct hfcusb_symbolic_list list[], const int num) +{ + int i; + for (i = 0; list[i].name != NULL; i++) + if (list[i].num == num) + return (list[i].name); + return ""; +} + /******************************************************/ /* start next background transfer for control channel */ /******************************************************/ static void ctrl_start_transfer(hfcusb_data * hfc) { - int err; if(hfc->ctrl_cnt) { hfc->ctrl_urb->pipe = hfc->ctrl_out_pipe; @@ -262,8 +309,8 @@ static void ctrl_start_transfer(hfcusb_d hfc->ctrl_urb->transfer_buffer_length = 0; hfc->ctrl_write.wIndex = hfc->ctrl_buff[hfc->ctrl_out_idx].hfc_reg; hfc->ctrl_write.wValue = hfc->ctrl_buff[hfc->ctrl_out_idx].reg_val; - err = usb_submit_urb(hfc->ctrl_urb, GFP_ATOMIC); /* start transfer */ - printk(KERN_DEBUG "ctrl_start_transfer: submit %d\n", err); + + usb_submit_urb(hfc->ctrl_urb, GFP_ATOMIC); /* start transfer */ } } /* ctrl_start_transfer */ @@ -275,19 +322,13 @@ static int queue_control_request(hfcusb_ { ctrl_buft *buf; -#ifdef VERBOSE_USB_DEBUG - printk ("HFC_USB: queue_control_request reg: %x, val: %x\n", reg, val); -#endif - if(hfc->ctrl_cnt >= HFC_CTRL_BUFSIZE) return(1); /* no space left */ buf = &hfc->ctrl_buff[hfc->ctrl_in_idx]; /* pointer to new index */ buf->hfc_reg = reg; buf->reg_val = val; buf->action=action; - if (++hfc->ctrl_in_idx >= HFC_CTRL_BUFSIZE) - hfc->ctrl_in_idx = 0; /* pointer wrap */ - if (++hfc->ctrl_cnt == 1) - ctrl_start_transfer(hfc); + if(++hfc->ctrl_in_idx >= HFC_CTRL_BUFSIZE) hfc->ctrl_in_idx = 0; /* pointer wrap */ + if(++hfc->ctrl_cnt == 1) ctrl_start_transfer(hfc); return(0); } /* queue_control_request */ @@ -308,7 +349,6 @@ static void ctrl_complete(struct urb *ur hfcusb_data *hfc = (hfcusb_data *) urb->context; ctrl_buft *buf; - printk(KERN_DEBUG "ctrl_complete cnt %d\n", hfc->ctrl_cnt); urb->dev = hfc->dev; if(hfc->ctrl_cnt) { @@ -330,14 +370,14 @@ static void ctrl_complete(struct urb *ur #define LED_POWER_ON 1 #define LED_POWER_OFF 2 -#define LED_S0_ON 3 -#define LED_S0_OFF 4 -#define LED_B1_ON 5 -#define LED_B1_OFF 6 -#define LED_B1_DATA 7 -#define LED_B2_ON 8 -#define LED_B2_OFF 9 -#define LED_B2_DATA 10 +#define LED_S0_ON 3 +#define LED_S0_OFF 4 +#define LED_B1_ON 5 +#define LED_B1_OFF 6 +#define LED_B1_DATA 7 +#define LED_B2_ON 8 +#define LED_B2_OFF 9 +#define LED_B2_DATA 10 #define LED_NORMAL 0 // LEDs are normal #define LED_INVERTED 1 // LEDs are inverted @@ -347,24 +387,65 @@ static void ctrl_complete(struct urb *ur vendor_data vdata[]= { - {0x959, 0x2bd0, "ISDN USB TA (Cologne Chip HFC-S USB based)", LED_OFF,LED_NORMAL,{4,0,2,1}}, /* CologneChip Eval TA */ - {0x7b0, 0x0007, "Billion tiny USB ISDN TA 128", LED_SCHEME1, LED_INVERTED, {8,0x40,0x20,0x10}}, /* Billion TA */ - {0x742, 0x2008, "Stollmann USB TA", LED_SCHEME1, LED_NORMAL, {4,0,2,1}}, /* Stollmann TA */ - {0x8e3, 0x0301, "Olitec USB RNIS", LED_SCHEME1, LED_NORMAL, {2,0,1,4}}, /* Olitec TA */ - {0x675, 0x1688, "DrayTec USB ISDN TA", LED_SCHEME1, LED_NORMAL, {4,0,2,1}}, /* Draytec TA */ - {0x7fa, 0x0846, "Bewan Modem RNIS USB", LED_SCHEME1, LED_INVERTED, {8,0x40,0x20,0x10}}, /* Bewan TA */ - {0} // EOL element + // negative LED bit values mean inverted function + {0x0959, 0x2bd0, "ISDN USB TA (Cologne Chip HFC-S USB based)", LED_OFF, {4,0,2,1}}, /* CologneChip Eval TA */ + {0x0675, 0x1688, "DrayTek miniVigor 128 USB ISDN TA", LED_SCHEME1, {1,2,0,0}}, /* DrayTek miniVigor 128 USB ISDN TA */ + {0x07b0, 0x0007, "Billion tiny USB ISDN TA 128", LED_SCHEME1, {0x80,-64,-32,-16}}, /* Billion TA */ + {0x0742, 0x2008, "Stollmann USB TA", LED_SCHEME1, {4,0,2,1}}, /* Stollmann TA */ + {0x0742, 0x2009, "Aceex USB ISDN TA", LED_SCHEME1, {4,0,2,1}}, /* Aceex USB ISDN TA */ + {0x0742, 0x200A, "OEM USB ISDN TA", LED_SCHEME1, {4,0,2,1}}, /* OEM USB ISDN TA */ + {0x08e3, 0x0301, "Olitec USB RNIS", LED_SCHEME1, {2,0,1,4}}, /* Olitec TA */ + {0x07fa, 0x0846, "Bewan Modem RNIS USB", LED_SCHEME1, {0x80,-64,-32,-16}}, /* Bewan TA */ + {0x07fa, 0x0847, "Djinn Numeris USB", LED_SCHEME1, {0x80,-64,-32,-16}}, /* Bewan TA */ + {0x07b0, 0x0006, "Twister ISDN TA", LED_SCHEME1, {0x80,-64,-32,-16}}, /* Twister ISDN TA */ + {0,0,0} // EOL element }; - + +/****************************************/ +/* data defining the devices to be used */ +/****************************************/ +static struct usb_device_id hfc_usb_idtab[] = +{ + {USB_DEVICE(0x0959, 0x2bd0)}, /* Colognechip USB eval TA */ + {USB_DEVICE(0x0675, 0x1688)}, /* DrayTek miniVigor 128 USB ISDN TA */ + {USB_DEVICE(0x07b0, 0x0007)}, /* Billion USB TA 2 */ + {USB_DEVICE(0x0742, 0x2008)}, /* Stollmann USB TA */ + {USB_DEVICE(0x0742, 0x2009)}, /* Aceex USB ISDN TA */ + {USB_DEVICE(0x0742, 0x200A)}, /* OEM USB ISDN TA */ + {USB_DEVICE(0x08e3, 0x0301)}, /* OliTec ISDN USB */ + {USB_DEVICE(0x07fa, 0x0846)}, /* Bewan ISDN USB TA */ + {USB_DEVICE(0x07fa, 0x0847)}, /* Djinn Numeris USB */ + {USB_DEVICE(0x07b0, 0x0006)}, /* Twister ISDN USB TA */ + {} /* end with an all-zeroes entry */ +}; + + /***************************************************/ /* write led data to auxport & invert if necessary */ /***************************************************/ static void write_led(hfcusb_data * hfc,__u8 led_state) { - if(led_state!=hfc->led_state) + if(led_state!=hfc->old_led_state) + { + hfc->old_led_state=led_state; + queue_control_request(hfc, HFCUSB_P_DATA,led_state,1); + } +} + +/**************************/ +/* handle LED bits */ +/**************************/ +static void set_led_bit(hfcusb_data * hfc, signed short led_bits,int unset) +{ + if(unset) + { + if(led_bits<0) hfc->led_state|=abs(led_bits); + else hfc->led_state&=~led_bits; + } + else { - hfc->led_state=led_state; - queue_control_request(hfc, HFCUSB_P_DATA,(vdata[hfc->vend_idx].led_invert) ? ~led_state : led_state,1); + if(led_bits<0) hfc->led_state&=~abs(led_bits); + else hfc->led_state|=led_bits; } } @@ -374,26 +455,28 @@ static void write_led(hfcusb_data * hfc, static void led_timer(hfcusb_data * hfc) { static int cnt=0; - __u8 led_state=hfc->led_state; if(cnt) { - if(hfc->led_b_active&1) led_state|=vdata[hfc->vend_idx].led_bits[2]; - if(hfc->led_b_active&2) led_state|=vdata[hfc->vend_idx].led_bits[3]; + if(hfc->led_b_active&1) set_led_bit(hfc,vdata[hfc->vend_idx].led_bits[2],0); + if(hfc->led_b_active&2) set_led_bit(hfc,vdata[hfc->vend_idx].led_bits[3],0); } else { - if(!(hfc->led_b_active&1) || hfc->led_new_data&1) led_state&=~vdata[hfc->vend_idx].led_bits[2]; - if(!(hfc->led_b_active&2) || hfc->led_new_data&2) led_state&=~vdata[hfc->vend_idx].led_bits[3]; + if(!(hfc->led_b_active&1) || hfc->led_new_data&1) set_led_bit(hfc,vdata[hfc->vend_idx].led_bits[2],1); + if(!(hfc->led_b_active&2) || hfc->led_new_data&2) set_led_bit(hfc,vdata[hfc->vend_idx].led_bits[3],1); } - write_led(hfc,led_state); + write_led(hfc,hfc->led_state); hfc->led_new_data=0; cnt=!cnt; + // restart 4 hz timer - hfc->led_timer.expires = jiffies + (LED_TIME * HZ) / 1000; - if(!timer_pending(&hfc->led_timer)) add_timer(&hfc->led_timer); + if(!timer_pending(&hfc->led_timer)) { + add_timer(&hfc->led_timer); + hfc->led_timer.expires = jiffies + (LED_TIME * HZ) / 1000; + } } /**************************/ @@ -401,23 +484,24 @@ static void led_timer(hfcusb_data * hfc) /**************************/ static void handle_led(hfcusb_data * hfc,int event) { - __u8 led_state=hfc->led_state; - // if no scheme -> no LED action if(vdata[hfc->vend_idx].led_scheme==LED_OFF) return; switch(event) { case LED_POWER_ON: - led_state|=vdata[hfc->vend_idx].led_bits[0]; + set_led_bit(hfc,vdata[hfc->vend_idx].led_bits[0],0); + set_led_bit(hfc,vdata[hfc->vend_idx].led_bits[1],1); + set_led_bit(hfc,vdata[hfc->vend_idx].led_bits[2],1); + set_led_bit(hfc,vdata[hfc->vend_idx].led_bits[3],1); break; case LED_POWER_OFF: // no Power off handling break; case LED_S0_ON: - led_state|=vdata[hfc->vend_idx].led_bits[1]; + set_led_bit(hfc,vdata[hfc->vend_idx].led_bits[1],0); break; case LED_S0_OFF: - led_state&=~vdata[hfc->vend_idx].led_bits[1]; + set_led_bit(hfc,vdata[hfc->vend_idx].led_bits[1],1); break; case LED_B1_ON: hfc->led_b_active|=1; @@ -439,7 +523,7 @@ static void handle_led(hfcusb_data * hfc break; } - write_led(hfc,led_state); + write_led(hfc,hfc->led_state); } /********************************/ @@ -447,14 +531,14 @@ static void handle_led(hfcusb_data * hfc /********************************/ static void l1_timer_expire_t3(hfcusb_data * hfc) { - //printk (KERN_INFO "HFC-USB: l1_timer_expire_t3\n"); - hfc->d_if.ifc.l1l2(&hfc->d_if.ifc,PH_DEACTIVATE | INDICATION,NULL); -#ifdef VERBOSE_USB_DEBUG - printk(KERN_INFO "PH_DEACTIVATE | INDICATION sent\n"); +#ifdef CONFIG_HISAX_DEBUG + DBG(ISDN_DBG,"HFC-S USB: PH_DEACTIVATE | INDICATION sent (T3 expire)"); #endif hfc->l1_activated=FALSE; handle_led(hfc,LED_S0_OFF); + queue_control_request(hfc,HFCUSB_STATES,0x10,1); // deactivate + queue_control_request(hfc,HFCUSB_STATES,3,1); // deactivate } /********************************/ @@ -462,11 +546,9 @@ static void l1_timer_expire_t3(hfcusb_da /********************************/ static void l1_timer_expire_t4(hfcusb_data * hfc) { - //printk (KERN_INFO "HFC-USB: l1_timer_expire_t4\n"); - hfc->d_if.ifc.l1l2(&hfc->d_if.ifc,PH_DEACTIVATE | INDICATION,NULL); -#ifdef VERBOSE_USB_DEBUG - printk(KERN_INFO "PH_DEACTIVATE | INDICATION sent\n"); +#ifdef CONFIG_HISAX_DEBUG + DBG(ISDN_DBG,"HFC-S USB: PH_DEACTIVATE | INDICATION sent (T4 expire)"); #endif hfc->l1_activated=FALSE; handle_led(hfc,LED_S0_OFF); @@ -484,26 +566,30 @@ static void state_handler(hfcusb_data * // range check if(state==old_state || state<1 || state>8) return; -#ifdef VERBOSE_ISDN_DEBUG - printk(KERN_INFO "HFC-USB: new S0 state:%d old_state:%d\n",state,old_state); +#ifdef CONFIG_HISAX_DEBUG + DBG(ISDN_DBG,"HFC-S USB: new S0 state:%d old_state:%d",state,old_state); #endif - if(state<4 || state==7 || state==8) { if(timer_pending(&hfc->t3_timer)) del_timer(&hfc->t3_timer); - //printk(KERN_INFO "HFC-USB: T3 deactivated\n"); +#ifdef CONFIG_HISAX_DEBUG + DBG(ISDN_DBG,"HFC-S USB: T3 deactivated"); +#endif } - if(state>=7) { if(timer_pending(&hfc->t4_timer)) del_timer(&hfc->t4_timer); - //printk(KERN_INFO "HFC-USB: T4 deactivated\n"); +#ifdef CONFIG_HISAX_DEBUG + DBG(ISDN_DBG,"HFC-S USB: T4 deactivated"); +#endif } if(state==7 && !hfc->l1_activated) { hfc->d_if.ifc.l1l2(&hfc->d_if.ifc,PH_ACTIVATE | INDICATION,NULL); - //printk(KERN_INFO "HFC-USB: PH_ACTIVATE | INDICATION sent\n"); +#ifdef CONFIG_HISAX_DEBUG + DBG(ISDN_DBG,"HFC-S USB: PH_ACTIVATE | INDICATION sent"); +#endif hfc->l1_activated=TRUE; handle_led(hfc,LED_S0_ON); } @@ -512,14 +598,21 @@ static void state_handler(hfcusb_data * { if(old_state==7 || old_state==8) { - //printk(KERN_INFO "HFC-USB: T4 activated\n"); - hfc->t4_timer.expires = jiffies + (HFC_TIMER_T4 * HZ) / 1000; - if(!timer_pending(&hfc->t4_timer)) add_timer(&hfc->t4_timer); +#ifdef CONFIG_HISAX_DEBUG + DBG(ISDN_DBG,"HFC-S USB: T4 activated"); +#endif + + if(!timer_pending(&hfc->t4_timer)) { + hfc->t4_timer.expires = jiffies + (HFC_TIMER_T4 * HZ) / 1000; + add_timer(&hfc->t4_timer); + } } else { hfc->d_if.ifc.l1l2(&hfc->d_if.ifc,PH_DEACTIVATE | INDICATION,NULL); - //printk(KERN_INFO "HFC-USB: PH_DEACTIVATE | INDICATION sent\n"); +#ifdef CONFIG_HISAX_DEBUG + DBG(ISDN_DBG,"HFC-S USB: PH_DEACTIVATE | INDICATION sent"); +#endif hfc->l1_activated=FALSE; handle_led(hfc,LED_S0_OFF); } @@ -543,7 +636,6 @@ static void fill_isoc_urb(struct urb *ur urb->transfer_buffer_length = packet_size * num_packets; urb->context = context; urb->transfer_buffer = buf; - urb->transfer_flags = 0; urb->transfer_flags = URB_ISO_ASAP; urb->actual_length = 0; urb->interval = interval; @@ -559,19 +651,22 @@ static int start_isoc_chain(usb_fifo * f { int i, k, errcode; -#ifdef VERBOSE_USB_DEBUG - printk(KERN_INFO "HFC-USB: starting ISO-chain for Fifo %i\n", fifo->fifonum); -#endif - + printk (KERN_INFO "HFC-S USB: starting ISO-chain for Fifo %i\n", fifo->fifonum); // allocate Memory for Iso out Urbs - for (i = 0; i < 2; i++) { - if (!(fifo->iso[i].purb)) { + for(i = 0; i < 2; i++) + { + if(!(fifo->iso[i].purb)) + { fifo->iso[i].purb = usb_alloc_urb(num_packets_per_urb, GFP_KERNEL); + if (!(fifo->iso[i].purb)) { + printk (KERN_INFO "alloc urb for fifo %i failed!!!", fifo->fifonum); + } + fifo->iso[i].owner_fifo = (struct usb_fifo *) fifo; // Init the first iso - if (ISO_BUFFER_SIZE >= (fifo->usb_packet_maxlen * num_packets_per_urb)) + if(ISO_BUFFER_SIZE >= (fifo->usb_packet_maxlen * num_packets_per_urb)) { fill_isoc_urb(fifo->iso[i].purb, fifo->hfc->dev, fifo->pipe, fifo->iso[i].buffer, @@ -586,6 +681,8 @@ static int start_isoc_chain(usb_fifo * f fifo->iso[i].purb->iso_frame_desc[k].offset = k*packet_size; fifo->iso[i].purb->iso_frame_desc[k].length = packet_size; } + } else { + printk(KERN_INFO "HFC-S USB: ISO Buffer size to small!\n"); } } @@ -595,12 +692,11 @@ static int start_isoc_chain(usb_fifo * f fifo->active = (errcode >= 0) ? 1 : 0; if(errcode < 0) { - printk(KERN_INFO "HFC-USB: error submitting ISO URB: %i.%i \n", errcode, i); + printk(KERN_INFO "HFC-S USB: %s URB nr:%d\n", symbolic(urb_errlist, errcode), i); }; } - // errcode = (usb_submit_urb(fifo->iso[0].purb, GFP_KERNEL)); return(fifo->active); } @@ -613,8 +709,8 @@ static void stop_isoc_chain(usb_fifo * f { if(fifo->iso[i].purb) { -#ifdef VERBOSE_USB_DEBUG - printk(KERN_INFO "HFC-USB: Stopping iso chain for fifo %i.%i\n", fifo->fifonum, i); +#ifdef CONFIG_HISAX_DEBUG + DBG(USB_DBG,"HFC-S USB: Stopping iso chain for fifo %i.%i", fifo->fifonum, i); #endif usb_unlink_urb(fifo->iso[i].purb); usb_free_urb(fifo->iso[i].purb); @@ -641,22 +737,17 @@ static void tx_iso_complete(struct urb * iso_urb_struct *context_iso_urb = (iso_urb_struct *) urb->context; usb_fifo *fifo = context_iso_urb->owner_fifo; hfcusb_data *hfc = fifo->hfc; - int k, tx_offset, num_isoc_packets, sink, len, current_len,errcode,frame_complete,transp_mode,fifon; + int k, tx_offset, num_isoc_packets, sink, len, current_len,errcode; + int frame_complete,transp_mode,fifon,status; __u8 threshbit; __u8 threshtable[8] = { 1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80}; fifon=fifo->fifonum; + status=urb->status; + tx_offset=0; - // very weird error code when using ohci drivers, for now : ignore this error ... (MB) - if(urb->status == -EOVERFLOW) - { - urb->status = 0; -#ifdef VERBOSE_USB_DEBUG - printk(KERN_INFO "HFC-USB: ignoring USB DATAOVERRUN for fifo %i \n",fifon); -#endif - } - if(fifo->active && !urb->status) + if(fifo->active && !status) { transp_mode=0; if(fifon<4 && hfc->b_mode[fifon/2]==L1_MODE_TRANS) transp_mode=TRUE; @@ -675,7 +766,7 @@ static void tx_iso_complete(struct urb * // prepare ISO Urb fill_isoc_urb(urb, fifo->hfc->dev, fifo->pipe,context_iso_urb->buffer, num_isoc_packets, - fifo->usb_packet_maxlen, fifo->intervall, tx_iso_complete, urb->context); + fifo->usb_packet_maxlen, fifo->intervall, tx_iso_complete, urb->context); memset(context_iso_urb->buffer, 0, sizeof(context_iso_urb->buffer)); frame_complete=FALSE; @@ -713,7 +804,6 @@ static void tx_iso_complete(struct urb * urb->iso_frame_desc[k].length = current_len + 1; tx_offset += (current_len + 1); - // printk(KERN_INFO "HFC-USB: fifonum:%d,%d bytes to send, %d bytes ISO packet,bitline:%d,sink:%d,threshbit:%d,threshmask:%x\n",fifon,len,current_len,fifo->bit_line,sink,threshbit,hfc->threshold_mask); if(!transp_mode) { if(fifon==HFCUSB_B1_TX) handle_led(hfc,LED_B1_DATA); @@ -731,7 +821,7 @@ static void tx_iso_complete(struct urb * if(fifo->bit_line < BITLINE_INF) { fifo->bit_line = BITLINE_INF; - //printk (KERN_INFO "HFC-USB: BITLINE_INF underrun\n"); + //printk (KERN_INFO "HFC-S USB: BITLINE_INF underrun\n"); } } @@ -745,26 +835,25 @@ static void tx_iso_complete(struct urb * if(fifo->skbuff && fifo->delete_flg) { dev_kfree_skb_any(fifo->skbuff); - //printk(KERN_INFO "HFC-USB: skbuff=NULL on fifo:%d\n",fifo->fifonum); fifo->skbuff = NULL; fifo->delete_flg=FALSE; } frame_complete=FALSE; } - } + } errcode = usb_submit_urb(urb, GFP_ATOMIC); if(errcode < 0) { - printk(KERN_INFO "HFC-USB: error submitting ISO URB: %i \n", errcode); + printk(KERN_INFO "HFC-S USB: error submitting ISO URB: %d \n", errcode); } } else { - if(urb->status) + if(status && !hfc->disc_flag) { - printk(KERN_INFO "HFC-USB: tx_iso_complete : urb->status %i, fifonum %i\n", urb->status,fifon); + printk(KERN_INFO "HFC-S USB: tx_iso_complete : urb->status %s (%i), fifonum=%d\n", symbolic(urb_errlist, status), status, fifon); } } @@ -778,40 +867,68 @@ static void rx_iso_complete(struct urb * iso_urb_struct *context_iso_urb = (iso_urb_struct *) urb->context; usb_fifo *fifo = context_iso_urb->owner_fifo; hfcusb_data *hfc = fifo->hfc; - int k, len, errcode, offset, num_isoc_packets,fifon; + int k, len, errcode, offset, num_isoc_packets,fifon,maxlen,status; + unsigned int iso_status; __u8 *buf; + static __u8 eof[8]; +#ifdef CONFIG_HISAX_DEBUG + __u8 i; +#endif fifon=fifo->fifonum; + status=urb->status; // very weird error code when using ohci drivers, for now : ignore this error ... (MB) + // if(status == USB_ST_DATAOVERRUN || status == USB_ST_CRC) if(urb->status == -EOVERFLOW) { - urb->status = 0; -#ifdef VERBOSE_USB_DEBUG - printk(KERN_INFO "HFC-USB: ignoring USB DATAOVERRUN for fifo %i \n",fifon); +#ifdef CONFIG_HISAX_DEBUG + // DBG(USB_DBG,"HFC-S USB: ignoring USB_ST_DATAOVERRUN & USB_ST_CRC for fifo %d status:%d",fifon,status); + DBG(USB_DBG, "HFC-USB: ignoring USB DATAOVERRUN for fifo %i \n",fifon); #endif + status = 0; } - if(fifo->active && !urb->status) + if(fifo->active && !status) { num_isoc_packets=iso_packets[fifon]; + maxlen=fifo->usb_packet_maxlen; - // Generate D-Channel Iso Packets + // Analyse D-Channel Iso Packets for(k = 0; k < num_isoc_packets; ++k) { len=urb->iso_frame_desc[k].actual_length; offset=urb->iso_frame_desc[k].offset; buf=context_iso_urb->buffer+offset; + iso_status=urb->iso_frame_desc[k].status; +#ifdef CONFIG_HISAX_DEBUG + if(iso_status && !hfc->disc_flag) DBG(USB_DBG,"HFC-S USB: ISO packet failure - status:%x",iso_status); + + if ((fifon==5) && (debug>1)) { + printk (KERN_INFO "HFC-S USB: ISO-D-RX lst_urblen:%2d act_urblen:%2d max-urblen:%2d EOF:0x%0x DATA: ", fifo->last_urblen, len, maxlen, eof[5]); + for(i=0; ilast_urblen!=fifo->usb_packet_maxlen) + if(fifo->last_urblen!=maxlen) { // the threshold mask is in the 2nd status byte hfc->threshold_mask=buf[1]; - // the S0 state is in the upper half of the 1st status byte - state_handler(hfc,buf[0] >> 4); + + /* care for L1 state only for D-Channel to avoid overlapped iso completions */ + if (fifon==5) { + // the S0 state is in the upper half of the 1st status byte + state_handler(hfc,buf[0] >> 4); + } + + eof[fifon]=buf[0]&1; // if we have more than the 2 status bytes -> collect data - if(len>2) collect_rx_frame(fifo,buf+2,len-2,buf[0]&1); + if(len>2) collect_rx_frame(fifo,buf+2,len-2,(lenlast_urblen=len; @@ -824,14 +941,14 @@ static void rx_iso_complete(struct urb * errcode = usb_submit_urb(urb, GFP_ATOMIC); if(errcode < 0) { - printk(KERN_INFO "HFC-USB: error submitting ISO URB: %i \n", errcode); + printk(KERN_INFO "HFC-S USB: error submitting ISO URB: %d \n", errcode); } } else { - if(urb->status) + if(status && !hfc->disc_flag) { - printk(KERN_INFO "HFC-USB: rx_iso_complete : urb->status %i, fifonum %i\n", urb->status,fifon); + printk(KERN_INFO "HFC-S USB: rx_iso_complete : urb->status %d, fifonum %d\n", status,fifon); } } } /* rx_iso_complete */ @@ -844,29 +961,42 @@ static void collect_rx_frame(usb_fifo *f { hfcusb_data *hfc = fifo->hfc; int transp_mode,fifon; +#ifdef CONFIG_HISAX_DEBUG + int i; +#endif fifon=fifo->fifonum; transp_mode=0; if(fifon<4 && hfc->b_mode[fifon/2]==L1_MODE_TRANS) transp_mode=TRUE; - //printk(KERN_INFO "HFC-USB: got %d bytes finish:%d max_size:%d fifo:%d\n",len,finish,fifo->max_size,fifon); + //printk(KERN_INFO "HFC-S USB: got %d bytes finish:%d max_size:%d fifo:%d\n",len,finish,fifo->max_size,fifon); if(!fifo->skbuff) { // allocate sk buffer fifo->skbuff=dev_alloc_skb(fifo->max_size + 3); if(!fifo->skbuff) { - printk(KERN_INFO "HFC-USB: cannot allocate buffer (dev_alloc_skb) fifo:%d\n",fifon); + printk(KERN_INFO "HFC-S USB: cannot allocate buffer (dev_alloc_skb) fifo:%d\n",fifon); return; } - } - if(len && fifo->skbuff->len+lenmax_size) + if(len) { - memcpy(skb_put(fifo->skbuff,len),data,len); + if(fifo->skbuff->len+lenmax_size) + { + memcpy(skb_put(fifo->skbuff,len),data,len); + } + else + { +#ifdef CONFIG_HISAX_DEBUG + printk(KERN_INFO "HFC-S USB: "); + for(i=0;i<15;i++) printk("%.2x ",fifo->skbuff->data[fifo->skbuff->len-15+i]); + printk("\n"); +#endif + printk(KERN_INFO "HCF-USB: got frame exceeded fifo->max_size:%d on fifo:%d\n",fifo->max_size,fifon); + } } - else printk(KERN_INFO "HCF-USB: got frame exceeded fifo->max_size:%d\n",fifo->max_size); // give transparent data up, when 128 byte are available if(transp_mode && fifo->skbuff->len>=128) @@ -879,20 +1009,36 @@ static void collect_rx_frame(usb_fifo *f // we have a complete hdlc packet if(finish) { - if(!fifo->skbuff->data[fifo->skbuff->len-1]) + /* can CRC be valid, and is Frame of minimum length at least */ + if ((!fifo->skbuff->data[fifo->skbuff->len-1]) && (fifo->skbuff->len > 3)) { skb_trim(fifo->skbuff,fifo->skbuff->len-3); // remove CRC & status - //printk(KERN_INFO "HFC-USB: got frame %d bytes on fifo:%d\n",fifo->skbuff->len,fifon); - - if(fifon==HFCUSB_PCM_RX) fifo->hif->l1l2(fifo->hif,PH_DATA_E | INDICATION,fifo->skbuff); + if(fifon==HFCUSB_PCM_RX) + { + fifo->hif->l1l2(fifo->hif,PH_DATA_E | INDICATION,fifo->skbuff); + } else fifo->hif->l1l2(fifo->hif,PH_DATA | INDICATION,fifo->skbuff); fifo->skbuff = NULL; // buffer was freed from upper layer } else { - printk(KERN_INFO "HFC-USB: got frame %d bytes but CRC ERROR!!!\n",fifo->skbuff->len); + if (fifo->skbuff->len > 3) { + printk(KERN_INFO "HFC-S USB: got frame %d bytes but CRC ERROR on fifo:%d!!!\n",fifo->skbuff->len,fifon); +#ifdef CONFIG_HISAX_DEBUG + if (debug>1) { + printk(KERN_INFO "HFC-S USB: "); + for(i=0;i<15;i++) printk("%.2x ",fifo->skbuff->data[fifo->skbuff->len-15+i]); + printk("\n"); + } +#endif + } +#ifdef CONFIG_HISAX_DEBUG + else { + printk(KERN_INFO "HFC-S USB: frame to small (%d bytes)!!!\n",fifo->skbuff->len); + } +#endif skb_trim(fifo->skbuff,0); // clear whole buffer } @@ -912,18 +1058,27 @@ static void collect_rx_frame(usb_fifo *f static void rx_complete(struct urb *urb, struct pt_regs *regs) { int len; - __u8 *buf; + int status; + __u8 *buf,maxlen,fifon; usb_fifo *fifo = (usb_fifo *) urb->context; /* pointer to our fifo */ hfcusb_data *hfc = fifo->hfc; + static __u8 eof[8]; +#ifdef CONFIG_HISAX_DEBUG + __u8 i; +#endif + urb->dev = hfc->dev; /* security init */ - if((!fifo->active) || (urb->status)) { -#ifdef VERBOSE_USB_DEBUG - printk(KERN_INFO "HFC-USB: RX-Fifo %i is going down (%i)\n", fifo->fifonum, urb->status); + fifon=fifo->fifonum; + if((!fifo->active) || (urb->status)) + { +#ifdef CONFIG_HISAX_DEBUG + DBG(USB_DBG,"HFC-S USB: RX-Fifo %i is going down (%i)",fifon, urb->status); #endif fifo->urb->interval = 0; /* cancel automatic rescheduling */ - if(fifo->skbuff) { + if(fifo->skbuff) + { dev_kfree_skb_any(fifo->skbuff); fifo->skbuff = NULL; } @@ -932,24 +1087,43 @@ static void rx_complete(struct urb *urb, len=urb->actual_length; buf=fifo->buffer; + maxlen=fifo->usb_packet_maxlen; + + +#ifdef CONFIG_HISAX_DEBUG + if ((fifon==5) && (debug>1)) { + printk (KERN_INFO "HFC-S USB: INT-D-RX lst_urblen:%2d act_urblen:%2d max-urblen:%2d EOF:0x%0x DATA: ", fifo->last_urblen, len, maxlen, eof[5]); + for(i=0; ilast_urblen!=fifo->usb_packet_maxlen) { + } +#endif + + if(fifo->last_urblen!=fifo->usb_packet_maxlen) + { // the threshold mask is in the 2nd status byte hfc->threshold_mask=buf[1]; // the S0 state is in the upper half of the 1st status byte state_handler(hfc,buf[0] >> 4); + eof[fifon]=buf[0]&1; // if we have more than the 2 status bytes -> collect data - if(len>2) collect_rx_frame(fifo,buf+2,urb->actual_length-2,buf[0]&1); - } else - collect_rx_frame(fifo,buf,urb->actual_length,0); + if(len>2) collect_rx_frame(fifo,buf+2,urb->actual_length-2,(lenactual_length,(lenlast_urblen=urb->actual_length; + status = usb_submit_urb(urb, GFP_ATOMIC); + if (status) { + printk (KERN_INFO "HFC-S USB: error resubmitting URN at rx_complete...\n"); + } } /* rx_complete */ - /***************************************************/ /* start the interrupt transfer for the given fifo */ /***************************************************/ @@ -957,22 +1131,23 @@ static void start_int_fifo(usb_fifo * fi { int errcode; -#ifdef VERBOSE_USB_DEBUG - printk(KERN_INFO "HFC-USB: starting intr IN fifo:%d\n", fifo->fifonum); -#endif + printk(KERN_INFO "HFC-S USB: starting intr IN fifo:%d\n", fifo->fifonum); + if (!fifo->urb) { fifo->urb = usb_alloc_urb(0, GFP_KERNEL); if (!fifo->urb) return; } + usb_fill_int_urb(fifo->urb, fifo->hfc->dev, fifo->pipe, fifo->buffer, fifo->usb_packet_maxlen, rx_complete, fifo, fifo->intervall); fifo->active = 1; /* must be marked active */ + errcode = usb_submit_urb(fifo->urb, GFP_KERNEL); if(errcode) { - printk(KERN_INFO "HFC-USB: submit URB error(start_int_info): status:%i\n", errcode); + printk(KERN_INFO "HFC-S USB: submit URB error(start_int_info): status:%i\n", errcode); fifo->active = 0; fifo->skbuff = NULL; } @@ -985,10 +1160,13 @@ static void set_hfcmode(hfcusb_data *hfc { __u8 val,idx_table[2]={0,2}; -#ifdef VERBOSE_ISDN_DEBUG - printk (KERN_INFO "HFC-USB: setting channel %d to mode %d\n",channel,mode); -#endif + if (hfc->disc_flag) { + return; + } +#ifdef CONFIG_HISAX_DEBUG + DBG(ISDN_DBG,"HFC-S USB: setting channel %d to mode %d",channel,mode); +#endif hfc->b_mode[channel]=mode; // setup CON_HDLC @@ -1026,16 +1204,6 @@ static void set_hfcmode(hfcusb_data *hfc } } -/* - -------------------------------------------------------------------------------------- - from here : hisax_if callback routines : - - void hfc_usb_d_l2l1(struct hisax_if *hisax_d_if, int pr, void *arg) { - - l1 to l2 routines : - - static void hfc_usb_l1l2(hfcusb_data * hfc) - -*/ - void hfc_usb_l2l1(struct hisax_if *my_hisax_if, int pr, void *arg) { usb_fifo *fifo = my_hisax_if->priv; @@ -1045,17 +1213,41 @@ void hfc_usb_l2l1(struct hisax_if *my_hi case PH_ACTIVATE | REQUEST: if(fifo->fifonum==HFCUSB_D_TX) { -#ifdef VERBOSE_ISDN_DEBUG - printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 D-chan: PH_ACTIVATE | REQUEST\n"); +#ifdef CONFIG_HISAX_DEBUG + DBG(ISDN_DBG,"HFC_USB: hfc_usb_d_l2l1 D-chan: PH_ACTIVATE | REQUEST"); +#endif + if(hfc->l1_state!=3 && hfc->l1_state!=7) + { + hfc->d_if.ifc.l1l2(&hfc->d_if.ifc,PH_DEACTIVATE | INDICATION,NULL); +#ifdef CONFIG_HISAX_DEBUG + DBG(ISDN_DBG,"HFC-S USB: PH_DEACTIVATE | INDICATION sent (not state 3 or 7)"); #endif - queue_control_request(hfc, HFCUSB_STATES,0x60,1); /* make activation */ - hfc->t3_timer.expires = jiffies + (HFC_TIMER_T3 * HZ) / 1000; - if(!timer_pending(&hfc->t3_timer)) add_timer(&hfc->t3_timer); + } + else + { + if (hfc->l1_state==7) { /* l1 already active */ + hfc->d_if.ifc.l1l2(&hfc->d_if.ifc,PH_ACTIVATE | INDICATION,NULL); +#ifdef CONFIG_HISAX_DEBUG + DBG(ISDN_DBG,"HFC-S USB: PH_ACTIVATE | INDICATION sent again ;)"); +#endif + } else { + /* hfc->l1_state==3) */ + queue_control_request(hfc, HFCUSB_STATES,0x14,1); // force sending sending INFO1 + mdelay(1); + queue_control_request(hfc, HFCUSB_STATES,0x04,1); // start l1 activation + + if(!timer_pending(&hfc->t3_timer)) { + hfc->t3_timer.expires = jiffies + (HFC_TIMER_T3 * HZ) / 1000; + add_timer(&hfc->t3_timer); + } + } + } } else { -#ifdef VERBOSE_ISDN_DEBUG - printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 Bx-chan: PH_ACTIVATE | REQUEST\n"); + +#ifdef CONFIG_HISAX_DEBUG + DBG(ISDN_DBG,"HFC_USB: hfc_usb_d_l2l1 Bx-chan: PH_ACTIVATE | REQUEST"); #endif set_hfcmode(hfc,(fifo->fifonum==HFCUSB_B1_TX) ? 0 : 1 ,(int)arg); fifo->hif->l1l2(fifo->hif,PH_ACTIVATE | INDICATION, NULL); @@ -1064,15 +1256,15 @@ void hfc_usb_l2l1(struct hisax_if *my_hi case PH_DEACTIVATE | REQUEST: if(fifo->fifonum==HFCUSB_D_TX) { -#ifdef VERBOSE_ISDN_DEBUG - printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 D-chan: PH_DEACTIVATE | REQUEST\n"); +#ifdef CONFIG_HISAX_DEBUG + DBG(ISDN_DBG,"HFC_USB: hfc_usb_d_l2l1 D-chan: PH_DEACTIVATE | REQUEST"); #endif - printk (KERN_INFO "HFC-USB: ISDN TE device should not deativate...\n"); + printk (KERN_INFO "HFC-S USB: ISDN TE device should not deativate...\n"); } else { -#ifdef VERBOSE_ISDN_DEBUG - printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 Bx-chan: PH_DEACTIVATE | REQUEST\n"); +#ifdef CONFIG_HISAX_DEBUG + DBG(ISDN_DBG,"HFC_USB: hfc_usb_d_l2l1 Bx-chan: PH_DEACTIVATE | REQUEST"); #endif set_hfcmode(hfc,(fifo->fifonum==HFCUSB_B1_TX) ? 0 : 1 ,(int)L1_MODE_NULL); fifo->hif->l1l2(fifo->hif,PH_DEACTIVATE | INDICATION, NULL); @@ -1082,15 +1274,11 @@ void hfc_usb_l2l1(struct hisax_if *my_hi if(fifo->skbuff && fifo->delete_flg) { dev_kfree_skb_any(fifo->skbuff); - //printk(KERN_INFO "skbuff=NULL on fifo:%d\n",fifo->fifonum); fifo->skbuff = NULL; fifo->delete_flg=FALSE; } fifo->skbuff=arg; // we have a new buffer - - //if(fifo->fifonum==HFCUSB_D_TX) printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 D-chan: PH_DATA | REQUEST\n"); - //else printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 Bx-chan: PH_DATA | REQUEST\n"); break; default: printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1: unkown state : %#x\n", pr); @@ -1102,43 +1290,9 @@ void hfc_usb_l2l1(struct hisax_if *my_hi #define CNF_4INT3ISO 1 // 4 INT IN, 3 ISO OUT #define CNF_3INT3ISO 2 // 3 INT IN, 3 ISO OUT #define CNF_4ISO3ISO 3 // 4 ISO IN, 3 ISO OUT -#define CNF_3ISO3ISO 4 // 3 ISO IN, 3 ISO OUT +#define CNF_3ISO3ISO 4 // 3 ISO IN, 3 ISO OUT -/* - -------------------------------------------------------------------------------------- - From here on USB initialization and deactivation related routines are implemented : - - - hfc_usb_init : - is the main Entry Point for the USB Subsystem when the device get plugged - in. This function calls usb_register with usb_driver as parameter. - Here, further entry points for probing (hfc_usb_probe) and disconnecting - the device (hfc_usb_disconnect) are published, as the id_table - - - hfc_usb_probe - this function is called by the usb subsystem, and steps through the alternate - settings of the currently plugged in device to detect all Endpoints needed to - run an ISDN TA. - Needed EndPoints are - 3 (+1) IntIn EndPoints (D-in, E-in, B1-in, B2-in, (E-in)) or - 3 (+1) Isochron In Endpoints (D-out, B1-out, B2-out) and 3 IsoOut Endpoints - The currently used transfer mode of on the Out-Endpoints will be stored in - hfc->usb_transfer_mode and is either USB_INT or USB_ISO - When a valid alternate setting could be found, the usb_init (see blow) - function is called - - - usb_init - Here, the HFC_USB Chip itself gets initialized and the USB framework to send/receive - Data to/from the several EndPoints are initialized: - The E- and D-Channel Int-In chain gets started - The IsoChain for the Iso-Out traffic get started - - - hfc_usb_disconnect - this function is called by the usb subsystem and has to free all resources - and stop all usb traffic to allow a proper hotplugging disconnect. - -*/ - /***************************************************************************/ /* usb_init is called once when a new matching device is detected to setup */ /* main parameters. It registers the driver at the main hisax module. */ @@ -1152,23 +1306,18 @@ static int usb_init(hfcusb_data * hfc) struct hisax_b_if *p_b_if[2]; /* check the chip id */ - printk(KERN_INFO "HFCUSB_CHIP_ID begin\n"); if (read_usb(hfc, HFCUSB_CHIP_ID, &b) != 1) { printk(KERN_INFO "HFC-USB: cannot read chip id\n"); - return(1); + return(1); } - printk(KERN_INFO "HFCUSB_CHIP_ID %x\n", b); if (b != HFCUSB_CHIPID) { - printk(KERN_INFO "HFC-USB: Invalid chip id 0x%02x\n", b); + printk(KERN_INFO "HFC-S USB: Invalid chip id 0x%02x\n", b); return(1); } /* first set the needed config, interface and alternate */ - printk(KERN_INFO "usb_init 1\n"); -// usb_set_configuration(hfc->dev, 1); - printk(KERN_INFO "usb_init 2\n"); err = usb_set_interface(hfc->dev, hfc->if_used, hfc->alt_used); - printk(KERN_INFO "usb_init usb_set_interface return %d\n", err); + /* now we initialize the chip */ write_usb(hfc, HFCUSB_CIRM, 8); // do reset write_usb(hfc, HFCUSB_CIRM, 0x10); // aux = output, reset off @@ -1210,24 +1359,31 @@ static int usb_init(hfcusb_data * hfc) hfc->b_mode[1]=L1_MODE_NULL; hfc->l1_activated=FALSE; + hfc->disc_flag=FALSE; hfc->led_state=0; hfc->led_new_data=0; + hfc->old_led_state=0; - /* init the t3 timer */ + // init the t3 timer init_timer(&hfc->t3_timer); hfc->t3_timer.data = (long) hfc; hfc->t3_timer.function = (void *) l1_timer_expire_t3; - /* init the t4 timer */ + + // init the t4 timer init_timer(&hfc->t4_timer); hfc->t4_timer.data = (long) hfc; hfc->t4_timer.function = (void *) l1_timer_expire_t4; - /* init the led timer */ + + // init the led timer init_timer(&hfc->led_timer); hfc->led_timer.data = (long) hfc; hfc->led_timer.function = (void *) led_timer; + // trigger 4 hz led timer - hfc->led_timer.expires = jiffies + (LED_TIME * HZ) / 1000; - if(!timer_pending(&hfc->led_timer)) add_timer(&hfc->led_timer); + if(!timer_pending(&hfc->led_timer)) { + hfc->led_timer.expires = jiffies + (LED_TIME * HZ) / 1000; + add_timer(&hfc->led_timer); + } // init the background machinery for control requests hfc->ctrl_read.bRequestType = 0xc0; @@ -1236,8 +1392,15 @@ static int usb_init(hfcusb_data * hfc) hfc->ctrl_write.bRequestType = 0x40; hfc->ctrl_write.bRequest = 0; hfc->ctrl_write.wLength = 0; - usb_fill_control_urb(hfc->ctrl_urb, hfc->dev, hfc->ctrl_out_pipe,(u_char *) & hfc->ctrl_write, NULL, 0, ctrl_complete, hfc); - + usb_fill_control_urb(hfc->ctrl_urb, + hfc->dev, + hfc->ctrl_out_pipe, + (u_char *) & hfc->ctrl_write, + NULL, + 0, + ctrl_complete, + hfc); + /* Init All Fifos */ for(i = 0; i < HFCUSB_NUM_FIFOS; i++) { @@ -1260,14 +1423,16 @@ static int usb_init(hfcusb_data * hfc) hfc->protocol = 2; /* default EURO ISDN, should be a module_param */ hisax_register(&hfc->d_if, p_b_if, "hfc_usb", hfc->protocol); - - for (i=0; i<4; i++) - hfc->fifos[i].hif=&p_b_if[i/2]->ifc; - for (i=4; i<8; i++) - hfc->fifos[i].hif=&hfc->d_if.ifc; + +#ifdef CONFIG_HISAX_DEBUG + hfc_debug=debug; +#endif + + for (i=0; i<4; i++) hfc->fifos[i].hif=&p_b_if[i/2]->ifc; + for (i=4; i<8; i++) hfc->fifos[i].hif=&hfc->d_if.ifc; // 3 (+1) INT IN + 3 ISO OUT - if(hfc->cfg_used == CNF_3INT3ISO || hfc->cfg_used == CNF_4INT3ISO) + if(hfc->cfg_used==CNF_3INT3ISO || hfc->cfg_used==CNF_4INT3ISO) { start_int_fifo(hfc->fifos + HFCUSB_D_RX); // Int IN D-fifo if(hfc->fifos[HFCUSB_PCM_RX].pipe) start_int_fifo(hfc->fifos + HFCUSB_PCM_RX); // E-fifo @@ -1284,9 +1449,9 @@ static int usb_init(hfcusb_data * hfc) start_isoc_chain(hfc->fifos + HFCUSB_B2_RX, ISOC_PACKETS_B, rx_iso_complete,16); } - start_isoc_chain(hfc->fifos + HFCUSB_D_TX, ISOC_PACKETS_D, tx_iso_complete,1); - start_isoc_chain(hfc->fifos + HFCUSB_B1_TX, ISOC_PACKETS_B, tx_iso_complete,1); - start_isoc_chain(hfc->fifos + HFCUSB_B2_TX, ISOC_PACKETS_B, tx_iso_complete,1); + start_isoc_chain(hfc->fifos + HFCUSB_D_TX, ISOC_PACKETS_D, tx_iso_complete, 1); + start_isoc_chain(hfc->fifos + HFCUSB_B1_TX, ISOC_PACKETS_B, tx_iso_complete, 1); + start_isoc_chain(hfc->fifos + HFCUSB_B2_TX, ISOC_PACKETS_B, tx_iso_complete, 1); handle_led(hfc,LED_POWER_ON); @@ -1294,25 +1459,6 @@ static int usb_init(hfcusb_data * hfc) } /* usb_init */ -/****************************************/ -/* data defining the devices to be used */ -/****************************************/ -// static __devinitdata const struct usb_device_id hfc_usb_idtab[3] = { -static struct usb_device_id hfc_usb_idtab[] = { - {USB_DEVICE(0x7b0, 0x0007)}, /* Billion USB TA 2 */ - {USB_DEVICE(0x742, 0x2008)}, /* Stollmann USB TA */ - {USB_DEVICE(0x959, 0x2bd0)}, /* Colognechip USB eval TA */ - {USB_DEVICE(0x8e3, 0x0301)}, /* OliTec ISDN USB */ - {USB_DEVICE(0x675, 0x1688)}, /* DrayTec ISDN USB */ - {USB_DEVICE(0x7fa, 0x0846)}, /* Bewan ISDN USB TA */ - {} /* end with an all-zeroes entry */ -}; - -MODULE_AUTHOR("Peter Sprenger (sprenger@moving-byters.de)/Martin Bachem (info@colognechip.com)"); -MODULE_DESCRIPTION("HFC I4L USB driver"); -MODULE_DEVICE_TABLE(usb, hfc_usb_idtab); -MODULE_LICENSE("GPL"); - #define EP_NUL 1 // Endpoint at this position not allowed #define EP_NOP 2 // all type of endpoints allowed at this position #define EP_ISO 3 // Isochron endpoint mandatory at this position @@ -1320,15 +1466,15 @@ MODULE_LICENSE("GPL"); #define EP_INT 5 // Interrupt endpoint mandatory at this position // this array represents all endpoints possible in the HCF-USB -// the last 2 entries are the configuration number and the minimum interval for Interrupt endpoints -int validconf[][18]= +// the last 3 entries are the configuration number, the minimum interval for Interrupt endpoints & boolean if E-channel logging possible +int validconf[][19]= { // INT in, ISO out config - {EP_NUL,EP_INT,EP_NUL,EP_INT,EP_NUL,EP_INT,EP_NOP,EP_INT,EP_ISO,EP_NUL,EP_ISO,EP_NUL,EP_ISO,EP_NUL,EP_NUL,EP_NUL,CNF_4INT3ISO,2}, - {EP_NUL,EP_INT,EP_NUL,EP_INT,EP_NUL,EP_INT,EP_NUL,EP_NUL,EP_ISO,EP_NUL,EP_ISO,EP_NUL,EP_ISO,EP_NUL,EP_NUL,EP_NUL,CNF_3INT3ISO,2}, + {EP_NUL,EP_INT,EP_NUL,EP_INT,EP_NUL,EP_INT,EP_NOP,EP_INT,EP_ISO,EP_NUL,EP_ISO,EP_NUL,EP_ISO,EP_NUL,EP_NUL,EP_NUL,CNF_4INT3ISO,2,1}, + {EP_NUL,EP_INT,EP_NUL,EP_INT,EP_NUL,EP_INT,EP_NUL,EP_NUL,EP_ISO,EP_NUL,EP_ISO,EP_NUL,EP_ISO,EP_NUL,EP_NUL,EP_NUL,CNF_3INT3ISO,2,0}, // ISO in, ISO out config - {EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_NOP,EP_ISO,CNF_4ISO3ISO,2}, - {EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_NUL,EP_NUL,CNF_3ISO3ISO,2}, + {EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_NOP,EP_ISO,CNF_4ISO3ISO,2,1}, + {EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_NUL,EP_NUL,CNF_3ISO3ISO,2,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} // EOL element }; @@ -1356,25 +1502,26 @@ static int hfc_usb_probe(struct usb_inte int i, idx, alt_idx, probe_alt_setting, vend_idx, cfg_used, *vcf, attr, cfg_found, cidx, ep_addr; int cmptbl[16],small_match,iso_packet_size,packet_size,alt_used=0; -// usb_show_device(dev); -// usb_show_device_descriptor(&dev->descriptor); -// usb_show_interface_descriptor(&iface->desc); vend_idx=0xffff; - for(i=0;vdata[i].vendor;i++) { - if (le16_to_cpu(dev->descriptor.idVendor) == vdata[i].vendor && - le16_to_cpu(dev->descriptor.idProduct) == vdata[i].prod_id) - vend_idx = i; + for(i=0;vdata[i].vendor;i++) + { + if(dev->descriptor.idVendor==vdata[i].vendor && dev->descriptor.idProduct==vdata[i].prod_id) vend_idx=i; } - -#ifdef VERBOSE_USB_DEBUG - printk(KERN_INFO "HFC-USB: probing interface(%d) actalt(%d) minor(%d)\n", +#ifdef CONFIG_HISAX_DEBUG + DBG(USB_DBG, "HFC-USB: probing interface(%d) actalt(%d) minor(%d)\n", ifnum, iface->desc.bAlternateSetting, intf->minor); #endif - if (vend_idx != 0xffff) { -#ifdef VERBOSE_USB_DEBUG - printk(KERN_INFO "HFC-USB: found vendor idx:%d name:%s\n",vend_idx,vdata[vend_idx].vend_name); + + printk (KERN_INFO "HFC-S USB: probing interface(%d) actalt(%d) minor(%d)\n", + ifnum, iface->desc.bAlternateSetting, intf->minor); + + + if(vend_idx!=0xffff) + { +#ifdef CONFIG_HISAX_DEBUG + DBG(USB_DBG,"HFC-S USB: found vendor idx:%d name:%s",vend_idx,vdata[vend_idx].vend_name); #endif /* if vendor and product ID is OK, start probing a matching alternate setting ... */ alt_idx = 0; @@ -1388,24 +1535,26 @@ static int hfc_usb_probe(struct usb_inte probe_alt_setting = iface->desc.bAlternateSetting; cfg_used=0; -#ifdef VERBOSE_USB_DEBUG - printk(KERN_INFO "HFC-USB: test alt_setting %d\n", probe_alt_setting); -#endif + //printk(KERN_INFO "HFC-S USB: if=%d alt=%d\n",interface, ifp->act_altsetting); + // check for config EOL element - while (validconf[cfg_used][0]) { + while(validconf[cfg_used][0]) + { cfg_found=TRUE; vcf=validconf[cfg_used]; ep = iface->endpoint; /* first endpoint descriptor */ -#ifdef VERBOSE_USB_DEBUG - printk(KERN_INFO "HFC-USB: (if=%d alt=%d cfg_used=%d)\n", +#ifdef CONFIG_HISAX_DEBUG + DBG(USB_DBG, "HFC-USB: (if=%d alt=%d cfg_used=%d)\n", ifnum, probe_alt_setting, cfg_used); #endif + // copy table memcpy(cmptbl,vcf,16*sizeof(int)); // check for all endpoints in this alternate setting - for (i=0; i < iface->desc.bNumEndpoints; i++) { + for (i=0; i < iface->desc.bNumEndpoints; i++) + { ep_addr = ep->desc.bEndpointAddress; idx = ((ep_addr & 0x7f)-1)*2; /* get endpoint base */ if (ep_addr & 0x80) @@ -1413,49 +1562,46 @@ static int hfc_usb_probe(struct usb_inte attr = ep->desc.bmAttributes; if (cmptbl[idx] == EP_NUL) { - printk(KERN_INFO "HFC-USB: cfg_found=FALSE in idx:%d attr:%d cmptbl[%d]:%d\n", - idx, attr, idx, cmptbl[idx]); + /* printk(KERN_INFO "HFC-USB: cfg_found=FALSE in idx:%d attr:%d cmptbl[%d]:%d\n", + idx, attr, idx, cmptbl[idx]); */ cfg_found = FALSE; } - if (attr == USB_ENDPOINT_XFER_INT && cmptbl[idx] == EP_INT) - cmptbl[idx] = EP_NUL; - if (attr == USB_ENDPOINT_XFER_BULK && cmptbl[idx] == EP_BLK) - cmptbl[idx] = EP_NUL; - if (attr == USB_ENDPOINT_XFER_ISOC && cmptbl[idx] == EP_ISO) - cmptbl[idx] = EP_NUL; + if(attr==USB_ENDPOINT_XFER_INT && cmptbl[idx]==EP_INT) cmptbl[idx]=EP_NUL; + if(attr==USB_ENDPOINT_XFER_BULK && cmptbl[idx]==EP_BLK) cmptbl[idx]=EP_NUL; + if(attr==USB_ENDPOINT_XFER_ISOC && cmptbl[idx]==EP_ISO) cmptbl[idx]=EP_NUL; // check if all INT endpoints match minimum interval - if (attr == USB_ENDPOINT_XFER_INT && ep->desc.bInterval < vcf[17]) { -#ifdef VERBOSE_USB_DEBUG - if (cfg_found) - printk(KERN_INFO "HFC-USB: Interrupt Endpoint interval < %d found - skipping config\n", - vcf[17]); + if(attr==USB_ENDPOINT_XFER_INT && ep->desc.bInterval < vcf[17]) + { +#ifdef CONFIG_HISAX_DEBUG + if(cfg_found) DBG(USB_DBG,"HFC-S USB: Interrupt Endpoint interval < %d found - skipping config",vcf[17]); #endif - cfg_found = FALSE; + + cfg_found=FALSE; } ep++; } - for (i = 0; i < 16; i++) { - // printk(KERN_INFO "HFC-USB: cmptbl[%d]:%d\n", i, cmptbl[i]); - + for(i=0;i<16;i++) + { // all entries must be EP_NOP or EP_NUL for a valid config - if (cmptbl[i] != EP_NOP && cmptbl[i] != EP_NUL) - cfg_found = FALSE; + if(cmptbl[i]!=EP_NOP && cmptbl[i]!=EP_NUL) cfg_found=FALSE; } // we check for smallest match, to provide configuration priority // configurations with smaller index have higher priority - if (cfg_found) { - if (cfg_used < small_match) { - small_match = cfg_used; - alt_used = probe_alt_setting; + if(cfg_found) + { + if(cfg_usednum_altsetting) */ -#ifdef VERBOSE_USB_DEBUG - printk(KERN_INFO "HFC-USB: final small_match=%x alt_used=%x\n",small_match, alt_used); -#endif + +// printk (KERN_INFO "HFC-S USB: final small_match=%x alt_used=%x\n",small_match, alt_used); + // yiipiee, we found a valid config - if (small_match != 0xffff) { + if(small_match!=0xffff) + { iface = iface_used; if (!(context = kmalloc(sizeof(hfcusb_data), GFP_KERNEL))) @@ -1478,79 +1625,68 @@ static int hfc_usb_probe(struct usb_inte ep = iface->endpoint; /* first endpoint descriptor */ vcf = validconf[small_match]; - for (i = 0; i < iface->desc.bNumEndpoints; i++) { + for (i = 0; i < iface->desc.bNumEndpoints; i++) + { ep_addr = ep->desc.bEndpointAddress; idx = ((ep_addr & 0x7f)-1)*2; /* get endpoint base */ - if (ep_addr & 0x80) - idx++; + if (ep_addr & 0x80) idx++; cidx = idx & 7; attr = ep->desc.bmAttributes; // only initialize used endpoints - if (vcf[idx] != EP_NOP && vcf[idx] != EP_NUL) { - switch (attr) { + if(vcf[idx]!=EP_NOP && vcf[idx]!=EP_NUL) + { + switch(attr) + { case USB_ENDPOINT_XFER_INT: context->fifos[cidx].pipe = usb_rcvintpipe(dev, ep->desc.bEndpointAddress); context->fifos[cidx].usb_transfer_mode = USB_INT; - packet_size = le16_to_cpu(ep->desc.wMaxPacketSize); // remember max packet size -#ifdef VERBOSE_USB_DEBUG - printk (KERN_INFO "HFC-USB: Interrupt-In Endpoint found %d ms(idx:%d cidx:%d)!\n", - ep->desc.bInterval, idx, cidx); -#endif + packet_size=ep->desc.wMaxPacketSize; // remember max packet size +// printk(KERN_INFO "HFC-S USB: Interrupt-In Endpoint found %d ms(idx:%d cidx:%d)!\n", ep->desc.bInterval, idx, cidx); break; + case USB_ENDPOINT_XFER_BULK: - if (ep_addr & 0x80) - context->fifos[cidx].pipe = usb_rcvbulkpipe(dev, ep->desc.bEndpointAddress); - else - context->fifos[cidx].pipe = usb_sndbulkpipe(dev, ep->desc.bEndpointAddress); + if(ep_addr & 0x80) context->fifos[cidx].pipe = usb_rcvbulkpipe(dev, ep->desc.bEndpointAddress); + else context->fifos[cidx].pipe = usb_sndbulkpipe(dev, ep->desc.bEndpointAddress); context->fifos[cidx].usb_transfer_mode = USB_BULK; - packet_size = le16_to_cpu(ep->desc.wMaxPacketSize); // remember max packet size -#ifdef VERBOSE_USB_DEBUG - printk (KERN_INFO "HFC-USB: Bulk Endpoint found (idx:%d cidx:%d)!\n", - idx, cidx); -#endif + packet_size=ep->desc.wMaxPacketSize; // remember max packet size +// printk(KERN_INFO "HFC-S USB: Bulk Endpoint found (idx:%d cidx:%d)!\n", idx,cidx); break; + case USB_ENDPOINT_XFER_ISOC: - if (ep_addr & 0x80) - context->fifos[cidx].pipe = usb_rcvisocpipe(dev, ep->desc.bEndpointAddress); - else - context->fifos[cidx].pipe = usb_sndisocpipe(dev, ep->desc.bEndpointAddress); + if(ep_addr & 0x80) context->fifos[cidx].pipe = usb_rcvisocpipe(dev, ep->desc.bEndpointAddress); + else context->fifos[cidx].pipe = usb_sndisocpipe(dev, ep->desc.bEndpointAddress); context->fifos[cidx].usb_transfer_mode = USB_ISOC; - iso_packet_size = le16_to_cpu(ep->desc.wMaxPacketSize); // remember max packet size -#ifdef VERBOSE_USB_DEBUG - printk (KERN_INFO "HFC-USB: ISO Endpoint found (idx:%d cidx:%d)!\n", - idx, cidx); -#endif + iso_packet_size=ep->desc.wMaxPacketSize; // remember max packet size +// printk (KERN_INFO "HFC-S USB: ISO Endpoint found (idx:%d cidx:%d)!\n", idx,cidx); break; + default: context->fifos[cidx].pipe = 0; /* reset data */ } /* switch attribute */ - if (context->fifos[cidx].pipe) { + if(context->fifos[cidx].pipe) + { context->fifos[cidx].fifonum = cidx; context->fifos[cidx].hfc = context; - context->fifos[cidx].usb_packet_maxlen = le16_to_cpu(ep->desc.wMaxPacketSize); + context->fifos[cidx].usb_packet_maxlen = ep->desc.wMaxPacketSize; context->fifos[cidx].intervall = ep->desc.bInterval; context->fifos[cidx].skbuff = NULL; -#ifdef VERBOSE_USB_DEBUG - printk (KERN_INFO "HFC-USB: fifo%d pktlen %d interval %d\n", - context->fifos[cidx].fifonum, - context->fifos[cidx].usb_packet_maxlen, - context->fifos[cidx].intervall); -#endif } } ep++; } + + // now share our luck - context->dev = dev; /* save device */ - context->if_used = ifnum; /* save used interface */ - context->alt_used = alt_used; /* and alternate config */ + context->dev = dev; /* save device */ + context->if_used = ifnum; /* save used interface */ + context->alt_used = alt_used; /* and alternate config */ context->ctrl_paksize = dev->descriptor.bMaxPacketSize0; /* control size */ - context->cfg_used=vcf[16]; // store used config - context->vend_idx=vend_idx; // store found vendor + context->cfg_used=vcf[16]; // store used config + context->vend_idx=vend_idx; // store found vendor context->packet_size=packet_size; context->iso_packet_size=iso_packet_size; @@ -1559,11 +1695,16 @@ static int hfc_usb_probe(struct usb_inte context->ctrl_out_pipe = usb_sndctrlpipe(context->dev, 0); context->ctrl_urb = usb_alloc_urb(0, GFP_KERNEL); - printk(KERN_INFO "HFC-USB: detected \"%s\" configuration: %s (if=%d alt=%d)\n", + printk(KERN_INFO "HFC-S USB: detected \"%s\" configuration: %s (if=%d alt=%d)\n", vdata[vend_idx].vend_name, conf_str[small_match], context->if_used, context->alt_used); + + printk(KERN_INFO "E-channel (\"ECHO:\") logging "); + if(validconf[small_match][18]) printk(" possible\n"); + else printk("NOT possible\n"); + /* init the chip and register the driver */ - if (usb_init(context)) + if(usb_init(context)) { if (context->ctrl_urb) { usb_unlink_urb(context->ctrl_urb); @@ -1573,10 +1714,16 @@ static int hfc_usb_probe(struct usb_inte kfree(context); return(-EIO); } + usb_set_intfdata(intf, context); return(0); - } + } + } + else + { + printk(KERN_INFO "HFC-S USB: no valid vendor found in USB descriptor\n"); } + return(-EIO); } @@ -1588,34 +1735,36 @@ static void hfc_usb_disconnect(struct us hfcusb_data *context = usb_get_intfdata(intf); int i; - printk(KERN_INFO "HFC-USB: device disconnect\n"); + printk(KERN_INFO "HFC-S USB: device disconnect\n"); - usb_set_intfdata(intf, NULL); - if (!context) - return; - if (timer_pending(&context->t3_timer)) - del_timer(&context->t3_timer); - if (timer_pending(&context->t4_timer)) - del_timer(&context->t4_timer); - if (timer_pending(&context->led_timer)) - del_timer(&context->led_timer); + context->disc_flag=TRUE; - hisax_unregister(&context->d_if); + usb_set_intfdata(intf, NULL); + if (!context) return; + if (timer_pending(&context->t3_timer)) del_timer(&context->t3_timer); + if (timer_pending(&context->t4_timer)) del_timer(&context->t4_timer); + if (timer_pending(&context->led_timer)) del_timer(&context->led_timer); /* tell all fifos to terminate */ - for(i = 0; i < HFCUSB_NUM_FIFOS; i++) { - if(context->fifos[i].usb_transfer_mode == USB_ISOC) { - if(context->fifos[i].active > 0) { - stop_isoc_chain(&context->fifos[i]); -#ifdef VERBOSE_USB_DEBUG - printk (KERN_INFO "HFC-USB: hfc_usb_disconnect: stopping ISOC chain Fifo no %i\n", i); -#endif - } - } else { - if(context->fifos[i].active > 0) { + for(i = 0; i < HFCUSB_NUM_FIFOS; i++) + { + if(context->fifos[i].usb_transfer_mode == USB_ISOC) + { + if(context->fifos[i].active > 0) + { + stop_isoc_chain(&context->fifos[i]); +#ifdef CONFIG_HISAX_DEBUG + DBG(USB_DBG,"HFC-S USB: hfc_usb_disconnect: stopping ISOC chain Fifo no %i", i); +#endif + } + } + else + { + if(context->fifos[i].active > 0) + { context->fifos[i].active = 0; -#ifdef VERBOSE_USB_DEBUG - printk (KERN_INFO "HFC-USB: hfc_usb_disconnect: unlinking URB for Fifo no %i\n", i); +#ifdef CONFIG_HISAX_DEBUG + DBG(USB_DBG,"HFC-S USB: hfc_usb_disconnect: unlinking URB for Fifo no %i", i); #endif } if (context->fifos[i].urb) { @@ -1623,15 +1772,24 @@ static void hfc_usb_disconnect(struct us usb_free_urb(context->fifos[i].urb); context->fifos[i].urb = NULL; } + } context->fifos[i].active = 0; } + + + // wait for all URBS to terminate + mdelay(10); + if (context->ctrl_urb) { usb_unlink_urb(context->ctrl_urb); usb_free_urb(context->ctrl_urb); context->ctrl_urb = NULL; } + + hisax_unregister(&context->d_if); kfree(context); /* free our structure again */ + } /* hfc_usb_disconnect */ @@ -1648,20 +1806,27 @@ static struct usb_driver hfc_drv = { static void __exit hfc_usb_exit(void) { -#ifdef VERBOSE_USB_DEBUG - printk ("HFC-USB: calling \"hfc_usb_exit\" ...\n"); +#ifdef CONFIG_HISAX_DEBUG + DBG(USB_DBG,"HFC-S USB: calling \"hfc_usb_exit\" ..."); #endif usb_deregister(&hfc_drv); /* release our driver */ - printk(KERN_INFO "HFC-USB module removed\n"); + printk(KERN_INFO "HFC-S USB: module removed\n"); } static int __init hfc_usb_init(void) { - printk ("HFC-USB: driver module revision %s loaded\n", hfcusb_revision); +#ifndef CONFIG_HISAX_DEBUG + unsigned int debug = -1; +#endif + + char revstr[30],datestr[30],dummy[30]; + + sscanf(hfcusb_revision,"%s %s $ %s %s %s $ ",dummy,revstr,dummy,datestr,dummy); + printk(KERN_INFO "HFC-S USB: driver module revision %s date %s loaded, (debug=%i)\n",revstr,datestr,debug); if(usb_register(&hfc_drv)) { - printk(KERN_INFO "HFC-USB: Unable to register HFC-USB module at usb stack\n"); + printk(KERN_INFO "HFC-S USB: Unable to register HFC-S USB module at usb stack\n"); return(-1); /* unable to register */ } return(0); @@ -1669,3 +1834,61 @@ static int __init hfc_usb_init(void) module_init(hfc_usb_init); module_exit(hfc_usb_exit); + + +MODULE_AUTHOR (DRIVER_AUTHOR); +MODULE_DESCRIPTION (DRIVER_DESC); +MODULE_LICENSE ("GPL"); +MODULE_DEVICE_TABLE(usb, hfc_usb_idtab); + + +/********************************************************************************************************************** +* +* History of changes : + +$Log: hfc_usb.c,v $ +Revision 4.33 2004/11/26 07:54:01 martinb1 +removed dublicate MODULE_AUTHOR, switched deprecated MODULE_PARAM + +Revision 4.32 2004/11/24 16:03:33 martinb1 +- ISO-in now cares for S0-state info from D-Channel (Fifo 5) only +- L1 activation forces INFO1 for at least 1ms before writing state 4 +- improved L1 activation when L1 was already activated + +Revision 4.31 2004/09/13 11:09:49 martinb1 +using dummy var 'debug' to fake its content when Hisax-Debugging is disabled + +Revision 4.30 2004/07/19 14:06:16 martinb1 + +ported to kernel 2.6 + +Revision 4.29 2004/04/01 11:18:33 martinb1 +added "Aceex USB ISDN TA" (0x0742,0x2009) +added "OEM USB ISDN TA" (0x0742,0x200A) + +Revision 4.28 2004/03/11 15:14:49 martinb1 +call function DBG() only if CONFIG_HISAX_DEBUG is enabled in kernel config + + +- rev 4.22-4.26 : 07.01.2004 (Peter Sprenger, sprenger@moving-bytes.de): + - every LED bit can now be used inverted + +- rev 4.22-4.25 : 02.12.2003 (Peter Sprenger, sprenger@moving-bytes.de): + - using now hisax_debug.h scheme + - added MODULE(...) information + - some internal CVS revisions + +- rev 4.21 : 27.11.2003 (Peter Sprenger, sprenger@moving-bytes.de): + - added Twister idtab[] entry + - fixed debug output + +- rev 4.20 : 21.11.2003 (Peter Sprenger, sprenger@moving-bytes.de): + - small l1 statehandler fixes - layer 1 now passed TBR3 Layer 1 Appendix B2 tests at german test lab (TUV Cologne) + + +- rev 4.10 : 17.11.2003 (Peter Sprenger, sprenger@moving-bytes.de): + - fixed a bug in eof of ISDN frames when frame==max_packet_size + - status messages for every ISO frame in URBs + +*/ + _