📄 st5481_usb.c
字号:
DBG(1,""); // Stop and free Control and Interrupt URBs usb_kill_urb(ctrl->urb); kfree(ctrl->urb->transfer_buffer); usb_free_urb(ctrl->urb); ctrl->urb = NULL; usb_kill_urb(intr->urb); kfree(intr->urb->transfer_buffer); usb_free_urb(intr->urb); ctrl->urb = NULL;}/* * Initialize the adapter. */void st5481_start(struct st5481_adapter *adapter){ static const u8 init_cmd_table[]={ SET_DEFAULT,0, STT,0, SDA_MIN,0x0d, SDA_MAX,0x29, SDELAY_VALUE,0x14, GPIO_DIR,0x01, GPIO_OUT,RED_LED,// FFCTRL_OUT_D,4,// FFCTRH_OUT_D,12, FFCTRL_OUT_B1,6, FFCTRH_OUT_B1,20, FFCTRL_OUT_B2,6, FFCTRH_OUT_B2,20, MPMSK,RXCI_INT+DEN_INT+DCOLL_INT, 0 }; struct st5481_intr *intr = &adapter->intr; int i = 0; u8 request,value; DBG(8,""); adapter->leds = RED_LED; // Start receiving on the interrupt endpoint SUBMIT_URB(intr->urb, GFP_KERNEL); while ((request = init_cmd_table[i++])) { value = init_cmd_table[i++]; st5481_usb_device_ctrl_msg(adapter, request, value, NULL, NULL); } st5481_ph_command(adapter, ST5481_CMD_PUP);}/* * Reset the adapter to default values. */void st5481_stop(struct st5481_adapter *adapter){ DBG(8,""); st5481_usb_device_ctrl_msg(adapter, SET_DEFAULT, 0, NULL, NULL);}/* ====================================================================== * isochronous USB helpers */static voidfill_isoc_urb(struct urb *urb, struct usb_device *dev, unsigned int pipe, void *buf, int num_packets, int packet_size, usb_complete_t complete, void *context) { int k; spin_lock_init(&urb->lock); urb->dev=dev; urb->pipe=pipe; urb->interval = 1; urb->transfer_buffer=buf; urb->number_of_packets = num_packets; urb->transfer_buffer_length=num_packets*packet_size; urb->actual_length = 0; urb->complete=complete; urb->context=context; urb->transfer_flags=URB_ISO_ASAP; 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; }}intst5481_setup_isocpipes(struct urb* urb[2], struct usb_device *dev, unsigned int pipe, int num_packets, int packet_size, int buf_size, usb_complete_t complete, void *context){ int j, retval; unsigned char *buf; for (j = 0; j < 2; j++) { retval = -ENOMEM; urb[j] = usb_alloc_urb(num_packets, GFP_KERNEL); if (!urb[j]) goto err; // Allocate memory for 2000bytes/sec (16Kb/s) buf = kmalloc(buf_size, GFP_KERNEL); if (!buf) goto err; // Fill the isochronous URB fill_isoc_urb(urb[j], dev, pipe, buf, num_packets, packet_size, complete, context); } return 0; err: for (j = 0; j < 2; j++) { if (urb[j]) { kfree(urb[j]->transfer_buffer); urb[j]->transfer_buffer = NULL; usb_free_urb(urb[j]); urb[j] = NULL; } } return retval;}void st5481_release_isocpipes(struct urb* urb[2]){ int j; for (j = 0; j < 2; j++) { usb_kill_urb(urb[j]); kfree(urb[j]->transfer_buffer); usb_free_urb(urb[j]); urb[j] = NULL; }}/* * Decode frames received on the B/D channel. * Note that this function will be called continously * with 64Kbit/s / 16Kbit/s of data and hence it will be * called 50 times per second with 20 ISOC descriptors. * Called at interrupt. */static void usb_in_complete(struct urb *urb, struct pt_regs *regs){ struct st5481_in *in = urb->context; unsigned char *ptr; struct sk_buff *skb; int len, count, status; if (unlikely(urb->status < 0)) { switch (urb->status) { case -ENOENT: case -ESHUTDOWN: case -ECONNRESET: DBG(1,"urb killed status %d", urb->status); return; // Give up default: WARN("urb status %d",urb->status); break; } } DBG_ISO_PACKET(0x80,urb); len = st5481_isoc_flatten(urb); ptr = urb->transfer_buffer; while (len > 0) { if (in->mode == L1_MODE_TRANS) { memcpy(in->rcvbuf, ptr, len); status = len; len = 0; } else { status = isdnhdlc_decode(&in->hdlc_state, ptr, len, &count, in->rcvbuf, in->bufsize); ptr += count; len -= count; } if (status > 0) { // Good frame received DBG(4,"count=%d",status); DBG_PACKET(0x400, in->rcvbuf, status); if (!(skb = dev_alloc_skb(status))) { WARN("receive out of memory\n"); break; } memcpy(skb_put(skb, status), in->rcvbuf, status); in->hisax_if->l1l2(in->hisax_if, PH_DATA | INDICATION, skb); } else if (status == -HDLC_CRC_ERROR) { INFO("CRC error"); } else if (status == -HDLC_FRAMING_ERROR) { INFO("framing error"); } else if (status == -HDLC_LENGTH_ERROR) { INFO("length error"); } } // Prepare URB for next transfer urb->dev = in->adapter->usb_dev; urb->actual_length = 0; SUBMIT_URB(urb, GFP_ATOMIC);}int st5481_setup_in(struct st5481_in *in){ struct usb_device *dev = in->adapter->usb_dev; int retval; DBG(4,""); in->rcvbuf = kmalloc(in->bufsize, GFP_KERNEL); retval = -ENOMEM; if (!in->rcvbuf) goto err; retval = st5481_setup_isocpipes(in->urb, dev, usb_rcvisocpipe(dev, in->ep), in->num_packets, in->packet_size, in->num_packets * in->packet_size, usb_in_complete, in); if (retval) goto err_free; return 0; err_free: kfree(in->rcvbuf); err: return retval;}void st5481_release_in(struct st5481_in *in){ DBG(2,""); st5481_release_isocpipes(in->urb);}/* * Make the transfer_buffer contiguous by * copying from the iso descriptors if necessary. */static int st5481_isoc_flatten(struct urb *urb){ struct usb_iso_packet_descriptor *pipd,*pend; unsigned char *src,*dst; unsigned int len; if (urb->status < 0) { return urb->status; } for (pipd = &urb->iso_frame_desc[0], pend = &urb->iso_frame_desc[urb->number_of_packets], dst = urb->transfer_buffer; pipd < pend; pipd++) { if (pipd->status < 0) { return (pipd->status); } len = pipd->actual_length; pipd->actual_length = 0; src = urb->transfer_buffer+pipd->offset; if (src != dst) { // Need to copy since isoc buffers not full while (len--) { *dst++ = *src++; } } else { // No need to copy, just update destination buffer dst += len; } } // Return size of flattened buffer return (dst - (unsigned char *)urb->transfer_buffer);}static void st5481_start_rcv(void *context){ struct st5481_in *in = context; struct st5481_adapter *adapter = in->adapter; DBG(4,""); in->urb[0]->dev = adapter->usb_dev; SUBMIT_URB(in->urb[0], GFP_KERNEL); in->urb[1]->dev = adapter->usb_dev; SUBMIT_URB(in->urb[1], GFP_KERNEL);}void st5481_in_mode(struct st5481_in *in, int mode){ if (in->mode == mode) return; in->mode = mode; usb_unlink_urb(in->urb[0]); usb_unlink_urb(in->urb[1]); if (in->mode != L1_MODE_NULL) { if (in->mode != L1_MODE_TRANS) isdnhdlc_rcv_init(&in->hdlc_state, in->mode == L1_MODE_HDLC_56K); st5481_usb_pipe_reset(in->adapter, in->ep, NULL, NULL); st5481_usb_device_ctrl_msg(in->adapter, in->counter, in->packet_size, NULL, NULL); st5481_start_rcv(in); } else { st5481_usb_device_ctrl_msg(in->adapter, in->counter, 0, NULL, NULL); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -