📄 hfc_usb.c
字号:
case LED_S0_OFF: led_state&=~vdata[hfc->vend_idx].led_bits[1]; break; case LED_B1_ON: hfc->led_b_active|=1; break; case LED_B1_OFF: hfc->led_b_active&=~1; break; case LED_B1_DATA: hfc->led_new_data|=1; break; case LED_B2_ON: hfc->led_b_active|=2; break; case LED_B2_OFF: hfc->led_b_active&=~2; break; case LED_B2_DATA: hfc->led_new_data|=2; break; } write_led(hfc,led_state);}/********************************//* called when timer t3 expires *//********************************/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");#endif hfc->l1_activated=FALSE; handle_led(hfc,LED_S0_OFF);}/********************************//* called when timer t4 expires *//********************************/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");#endif hfc->l1_activated=FALSE; handle_led(hfc,LED_S0_OFF);}/*****************************//* handle S0 state changes *//*****************************/static void state_handler(hfcusb_data * hfc,__u8 state){ __u8 old_state; old_state=hfc->l1_state; // 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);#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"); } if(state>=7) { if(timer_pending(&hfc->t4_timer)) del_timer(&hfc->t4_timer); //printk(KERN_INFO "HFC-USB: T4 deactivated\n"); } 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"); hfc->l1_activated=TRUE; handle_led(hfc,LED_S0_ON); } else if(state<=3 /* && activated*/) { 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); } else { hfc->d_if.ifc.l1l2(&hfc->d_if.ifc,PH_DEACTIVATE | INDICATION,NULL); //printk(KERN_INFO "HFC-USB: PH_DEACTIVATE | INDICATION sent\n"); hfc->l1_activated=FALSE; handle_led(hfc,LED_S0_OFF); } } hfc->l1_state=state;}/* prepare iso urb */static void fill_isoc_urb(struct urb *urb, struct usb_device *dev, unsigned int pipe, void *buf, int num_packets, int packet_size, int interval, usb_complete_t complete, void *context){ int k; spin_lock_init(&urb->lock); // do we really need spin_lock_init ? urb->dev = dev; urb->pipe = pipe; urb->complete = complete; urb->number_of_packets = num_packets; 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; for (k = 0; k < num_packets; k++) { urb->iso_frame_desc[k].offset = packet_size * k; urb->iso_frame_desc[k].length = packet_size; urb->iso_frame_desc[k].actual_length = 0; }}/* allocs urbs and start isoc transfer with two pending urbs to avoid gaps in the transfer chain */static int start_isoc_chain(usb_fifo * fifo, int num_packets_per_urb,usb_complete_t complete,int packet_size){ int i, k, errcode;#ifdef VERBOSE_USB_DEBUG printk(KERN_INFO "HFC-USB: starting ISO-chain for Fifo %i\n", fifo->fifonum);#endif // allocate Memory for Iso out Urbs for (i = 0; i < 2; i++) { if (!(fifo->iso[i].purb)) { fifo->iso[i].purb = usb_alloc_urb(num_packets_per_urb, GFP_KERNEL); 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)) { fill_isoc_urb(fifo->iso[i].purb, fifo->hfc->dev, fifo->pipe, fifo->iso[i].buffer, num_packets_per_urb, fifo->usb_packet_maxlen, fifo->intervall, complete, &fifo->iso[i]); memset(fifo->iso[i].buffer, 0, sizeof(fifo->iso[i].buffer)); // defining packet delimeters in fifo->buffer for(k = 0; k < num_packets_per_urb; k++) { fifo->iso[i].purb->iso_frame_desc[k].offset = k*packet_size; fifo->iso[i].purb->iso_frame_desc[k].length = packet_size; } } } fifo->bit_line = BITLINE_INF; errcode = usb_submit_urb(fifo->iso[i].purb, GFP_KERNEL); fifo->active = (errcode >= 0) ? 1 : 0; if(errcode < 0) { printk(KERN_INFO "HFC-USB: error submitting ISO URB: %i.%i \n", errcode, i); }; } // errcode = (usb_submit_urb(fifo->iso[0].purb, GFP_KERNEL)); return(fifo->active);}/* stops running iso chain and frees their pending urbs */static void stop_isoc_chain(usb_fifo * fifo){ int i; for(i = 0; i < 2; i++) { 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);#endif usb_unlink_urb(fifo->iso[i].purb); usb_free_urb(fifo->iso[i].purb); fifo->iso[i].purb = NULL; } } if (fifo->urb) { usb_unlink_urb(fifo->urb); usb_free_urb(fifo->urb); fifo->urb = NULL; } fifo->active = 0;}// defines how much ISO packets are handled in one URBstatic int iso_packets[8]={ISOC_PACKETS_B,ISOC_PACKETS_B,ISOC_PACKETS_B,ISOC_PACKETS_B, ISOC_PACKETS_D,ISOC_PACKETS_D,ISOC_PACKETS_D,ISOC_PACKETS_D};/*****************************************************//* transmit completion routine for all ISO tx fifos *//*****************************************************/static void tx_iso_complete(struct urb *urb, struct pt_regs *regs){ 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; __u8 threshbit; __u8 threshtable[8] = { 1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80}; fifon=fifo->fifonum; 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) { transp_mode=0; if(fifon<4 && hfc->b_mode[fifon/2]==L1_MODE_TRANS) transp_mode=TRUE; threshbit = threshtable[fifon] & hfc->threshold_mask; // is threshold set for our channel? num_isoc_packets=iso_packets[fifon]; if(fifon >= HFCUSB_D_TX) { sink = (threshbit) ? SINK_DMIN : SINK_DMAX; // how much bit go to the sink for D-channel? } else { sink = (threshbit) ? SINK_MIN : SINK_MAX; // how much bit go to the sink for B-channel? } // 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); memset(context_iso_urb->buffer, 0, sizeof(context_iso_urb->buffer)); frame_complete=FALSE; // Generate Iso Packets for(k = 0; k < num_isoc_packets; ++k) { if(fifo->skbuff) { len = fifo->skbuff->len; // remaining length fifo->bit_line -= sink; // we lower data margin every msec current_len = (0 - fifo->bit_line) / 8; if(current_len > 14) current_len = 14; // maximum 15 byte for every ISO packet makes our life easier current_len = (len <= current_len) ? len : current_len; fifo->bit_line += current_len * 8; // how much bit do we put on the line? context_iso_urb->buffer[tx_offset] = 0; if(current_len == len) { if(!transp_mode) { context_iso_urb->buffer[tx_offset] = 1; // here frame completion fifo->bit_line += 32; // add 2 byte flags and 16bit CRC at end of ISDN frame } frame_complete = TRUE; } // copy bytes from buffer into ISO_URB memcpy(context_iso_urb->buffer+tx_offset+1,fifo->skbuff->data,current_len); skb_pull(fifo->skbuff,current_len); // define packet delimeters within the URB buffer urb->iso_frame_desc[k].offset = tx_offset; 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); if(fifon==HFCUSB_B2_TX) handle_led(hfc,LED_B2_DATA); } } else { // we have no more data - generate 1 byte ISO packets urb->iso_frame_desc[k].offset = tx_offset++; urb->iso_frame_desc[k].length = 1; fifo->bit_line -= sink; // we lower data margin every msec if(fifo->bit_line < BITLINE_INF) { fifo->bit_line = BITLINE_INF; //printk (KERN_INFO "HFC-USB: BITLINE_INF underrun\n"); } } if(frame_complete) { // delete the buffer only once, here or in hfc_usb_l2l1() in a PH_DATA|REQUEST fifo->delete_flg=TRUE; fifo->hif->l1l2(fifo->hif,PH_DATA|CONFIRM,(void*)fifo->skbuff->truesize); 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); } } else { if(urb->status) { printk(KERN_INFO "HFC-USB: tx_iso_complete : urb->status %i, fifonum %i\n", urb->status,fifon); } }} /* tx_iso_complete *//*****************************************************//* receive completion routine for all ISO tx fifos *//*****************************************************/static void rx_iso_complete(struct urb *urb, struct pt_regs *regs){ 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; __u8 *buf; fifon=fifo->fifonum; // 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) { num_isoc_packets=iso_packets[fifon]; // Generate 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; 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); // 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); } else collect_rx_frame(fifo,buf,len,0); fifo->last_urblen=len; } // 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, rx_iso_complete, urb->context); errcode = usb_submit_urb(urb, GFP_ATOMIC); if(errcode < 0) { printk(KERN_INFO "HFC-USB: error submitting ISO URB: %i \n", errcode); } } else { if(urb->status) { printk(KERN_INFO "HFC-USB: rx_iso_complete : urb->status %i, fifonum %i\n", urb->status,fifon); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -