📄 hfc_usb.c
字号:
start_int_fifo(hfc->fifos + HFCUSB_D_RX); if (hfc->fifos[HFCUSB_PCM_RX].pipe) start_int_fifo(hfc->fifos + HFCUSB_PCM_RX); start_int_fifo(hfc->fifos + HFCUSB_B1_RX); start_int_fifo(hfc->fifos + HFCUSB_B2_RX); } /* 3 (+1) ISO IN + 3 ISO OUT */ if (hfc->cfg_used == CNF_3ISO3ISO || hfc->cfg_used == CNF_4ISO3ISO) { start_isoc_chain(hfc->fifos + HFCUSB_D_RX, ISOC_PACKETS_D, rx_iso_complete, 16); if (hfc->fifos[HFCUSB_PCM_RX].pipe) start_isoc_chain(hfc->fifos + HFCUSB_PCM_RX, ISOC_PACKETS_D, rx_iso_complete, 16); start_isoc_chain(hfc->fifos + HFCUSB_B1_RX, ISOC_PACKETS_B, rx_iso_complete, 16); 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); handle_led(hfc, LED_POWER_ON); return (0);} /* usb_init *//*************************************************//* function called to probe a new plugged device *//*************************************************/static inthfc_usb_probe(struct usb_interface *intf, const struct usb_device_id *id){ struct usb_device *dev = interface_to_usbdev(intf); hfcusb_data *context; struct usb_host_interface *iface = intf->cur_altsetting; struct usb_host_interface *iface_used = NULL; struct usb_host_endpoint *ep; int ifnum = iface->desc.bInterfaceNumber; 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; hfcsusb_vdata *driver_info; vend_idx = 0xffff; for (i = 0; hfcusb_idtab[i].idVendor; i++) { if (dev->descriptor.idVendor == hfcusb_idtab[i].idVendor && dev->descriptor.idProduct == hfcusb_idtab[i].idProduct) { vend_idx = i; continue; } }#ifdef CONFIG_HISAX_DEBUG DBG(USB_DBG, "HFC-USB: probing interface(%d) actalt(%d) minor(%d)\n", ifnum, iface->desc.bAlternateSetting, intf->minor);#endif printk(KERN_INFO "HFC-S USB: probing interface(%d) actalt(%d) minor(%d)\n", ifnum, iface->desc.bAlternateSetting, intf->minor); if (vend_idx != 0xffff) { /* if vendor and product ID is OK, start probing alternate settings */ alt_idx = 0; small_match = 0xffff; /* default settings */ iso_packet_size = 16; packet_size = 64; while (alt_idx < intf->num_altsetting) { iface = intf->altsetting + alt_idx; probe_alt_setting = iface->desc.bAlternateSetting; cfg_used = 0; /* check for config EOL element */ while (validconf[cfg_used][0]) { cfg_found = TRUE; vcf = validconf[cfg_used]; /* first endpoint descriptor */ ep = iface->endpoint;#ifdef CONFIG_HISAX_DEBUG DBG(USB_DBG, "HFC-S USB: (if=%d alt=%d cfg_used=%d)\n", ifnum, probe_alt_setting, cfg_used);#endif memcpy(cmptbl, vcf, 16 * sizeof(int)); /* check for all endpoints in this alternate setting */ for (i = 0; i < iface->desc.bNumEndpoints; i++) { ep_addr = ep->desc.bEndpointAddress; /* get endpoint base */ idx = ((ep_addr & 0x7f) - 1) * 2; if (ep_addr & 0x80) idx++; attr = ep->desc.bmAttributes; if (cmptbl[idx] == EP_NUL) { 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; /* check if all INT endpoints match minimum interval */ 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; } ep++; } 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 (cfg_found) { if (cfg_used < small_match) { small_match = cfg_used; alt_used = probe_alt_setting; iface_used = iface; }#ifdef CONFIG_HISAX_DEBUG DBG(USB_DBG, "HFC-USB: small_match=%x %x\n", small_match, alt_used);#endif } cfg_used++; } alt_idx++; } /* (alt_idx < intf->num_altsetting) */ /* found a valid USB Ta Endpint config */ if (small_match != 0xffff) { iface = iface_used; if (! (context = kmalloc(sizeof(hfcusb_data), GFP_KERNEL))) return (-ENOMEM); /* got no mem */ memset(context, 0, sizeof(hfcusb_data)); ep = iface->endpoint; vcf = validconf[small_match]; for (i = 0; i < iface->desc.bNumEndpoints; i++) { ep_addr = ep->desc.bEndpointAddress; /* get endpoint base */ idx = ((ep_addr & 0x7f) - 1) * 2; if (ep_addr & 0x80) idx++; cidx = idx & 7; attr = ep->desc.bmAttributes; /* init Endpoints */ 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 = ep->desc. wMaxPacketSize; 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); context-> fifos[cidx]. usb_transfer_mode = USB_BULK; packet_size = ep->desc. wMaxPacketSize; 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); context-> fifos[cidx]. usb_transfer_mode = USB_ISOC; iso_packet_size = ep->desc. wMaxPacketSize; break; default: context-> fifos[cidx]. pipe = 0; } /* switch attribute */ if (context->fifos[cidx].pipe) { context->fifos[cidx]. fifonum = cidx; context->fifos[cidx].hfc = context; context->fifos[cidx]. usb_packet_maxlen = ep->desc. wMaxPacketSize; context->fifos[cidx]. intervall = ep->desc.bInterval; context->fifos[cidx]. skbuff = NULL; } } ep++; } 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->packet_size = packet_size; context->iso_packet_size = iso_packet_size; /* create the control pipes needed for register access */ context->ctrl_in_pipe = usb_rcvctrlpipe(context->dev, 0); context->ctrl_out_pipe = usb_sndctrlpipe(context->dev, 0); context->ctrl_urb = usb_alloc_urb(0, GFP_KERNEL); driver_info = (hfcsusb_vdata *) hfcusb_idtab[vend_idx]. driver_info; printk(KERN_INFO "HFC-S USB: detected \"%s\"\n", driver_info->vend_name);#ifdef CONFIG_HISAX_DEBUG DBG(USB_DBG, "HFC-S USB: Endpoint-Config: %s (if=%d alt=%d)\n", conf_str[small_match], context->if_used, context->alt_used); printk(KERN_INFO "HFC-S USB: E-channel (\"ECHO:\") logging "); if (validconf[small_match][18]) printk(" possible\n"); else printk("NOT possible\n");#endif /* init the chip and register the driver */ if (usb_init(context)) { if (context->ctrl_urb) { usb_unlink_urb(context->ctrl_urb); usb_free_urb(context->ctrl_urb); context->ctrl_urb = NULL; } 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);}/****************************************************//* function called when an active device is removed *//****************************************************/static voidhfc_usb_disconnect(struct usb_interface *intf){ hfcusb_data *context = usb_get_intfdata(intf); int i; printk(KERN_INFO "HFC-S USB: device disconnect\n"); context->disc_flag = TRUE; 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); /* 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 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 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) { usb_unlink_urb(context->fifos[i].urb); 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 *//************************************//* our driver information structure *//************************************/static struct usb_driver hfc_drv = { .owner = THIS_MODULE, .name = "hfc_usb", .id_table = hfcusb_idtab, .probe = hfc_usb_probe, .disconnect = hfc_usb_disconnect,};static void __exithfc_usb_exit(void){#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-S USB: module removed\n");}static int __inithfc_usb_init(void){#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-S USB: Unable to register HFC-S USB module at usb stack\n"); return (-1); /* unable to register */ } return (0);}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, hfcusb_idtab);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -