📄 usb_ctl.c
字号:
{ int next_device_state = sm_state_to_device_state[ next_state ]; if( usb_debug) printk( "%s%s --> [%s] --> %s. Device in %s state.\n", pszMe, state_names[ sm_state ], event_names[ event ], state_names[ next_state ], device_state_names[ next_device_state ] ); sm_state = next_state; if ( usbd_info.state != next_device_state ) { if ( configured_callback != NULL && next_device_state == USB_STATE_CONFIGURED && usbd_info.state != USB_STATE_SUSPENDED ) { configured_callback(); } usbd_info.state = next_device_state; ep_bulk_out1_state_change_notify( next_device_state ); ep_bulk_in1_state_change_notify( next_device_state ); } }#if 1 else printk( "%s%s --> [%s] --> ??? is an error.\n", pszMe, state_names[ sm_state ], event_names[ event ] );#endif return next_state;}//////////////////////////////////////////////////////////////////////////////// Private Helpers///////////////////////////////////////////////////////////////////////////////* setup default descriptors */static voidinitialize_descriptors(void){ desc.dev.bLength = sizeof( device_desc_t ); desc.dev.bDescriptorType = USB_DESC_DEVICE; desc.dev.bcdUSB = 0x100; /* 1.0 */ desc.dev.bDeviceClass = 0xFF; /* vendor specific */ desc.dev.bDeviceSubClass = 0; desc.dev.bDeviceProtocol = 0; desc.dev.bMaxPacketSize0 = EP0_FIFO_SIZE; /* ep0 max fifo size */ desc.dev.idVendor = 0; /* vendor ID undefined */ desc.dev.idProduct = 0; /* product */ desc.dev.bcdDevice = 0; /* vendor assigned device release num */ desc.dev.iManufacturer = 0; /* index of manufacturer string */ desc.dev.iProduct = 0; /* index of product description string */ desc.dev.iSerialNumber = 0; /* index of string holding product s/n */ desc.dev.bNumConfigurations = 1; desc.b.cfg.bLength = sizeof( config_desc_t ); desc.b.cfg.bDescriptorType = USB_DESC_CONFIG; desc.b.cfg.wTotalLength = make_word_c( sizeof(struct cdb) ); desc.b.cfg.bNumInterfaces = 1; desc.b.cfg.bConfigurationValue = 1; desc.b.cfg.iConfiguration = 0;#ifdef CONFIG_S3C2440_SMDK desc.b.cfg.bmAttributes = USB_CONFIG_BUSPOWERED | USB_CONFIG_SELFPOWERED; desc.b.cfg.MaxPower = USB_POWER( 0 );#else desc.b.cfg.bmAttributes = USB_CONFIG_BUSPOWERED; desc.b.cfg.MaxPower = USB_POWER( 500 );#endif desc.b.intf.bLength = sizeof( intf_desc_t ); desc.b.intf.bDescriptorType = USB_DESC_INTERFACE; desc.b.intf.bInterfaceNumber = 0; /* unique intf index*/ desc.b.intf.bAlternateSetting = 0; desc.b.intf.bNumEndpoints = 2; desc.b.intf.bInterfaceClass = 0xFF; /* vendor specific */ desc.b.intf.bInterfaceSubClass = 0; desc.b.intf.bInterfaceProtocol = 0; desc.b.intf.iInterface = 0; desc.b.ep1.bLength = sizeof( ep_desc_t ); desc.b.ep1.bDescriptorType = USB_DESC_ENDPOINT; desc.b.ep1.bEndpointAddress = USB_EP_ADDRESS( 1, USB_OUT ); desc.b.ep1.bmAttributes = USB_EP_BULK; desc.b.ep1.wMaxPacketSize = make_word_c( EP1_FIFO_SIZE ); desc.b.ep1.bInterval = 0; desc.b.ep2.bLength = sizeof( ep_desc_t ); desc.b.ep2.bDescriptorType = USB_DESC_ENDPOINT; desc.b.ep2.bEndpointAddress = USB_EP_ADDRESS( 2, USB_IN ); desc.b.ep2.bmAttributes = USB_EP_BULK; desc.b.ep2.wMaxPacketSize = make_word_c( EP2_FIFO_SIZE ); desc.b.ep2.bInterval = 0;#if defined(CONFIG_S3C2440_USB_CDC_ENCM) || defined(CONFIG_S3C2440_USB_CDC_ENCM_MODULE) desc.cdc_b.cfg.bLength = sizeof( config_desc_t ); desc.cdc_b.cfg.bDescriptorType = USB_DESC_CONFIG; desc.cdc_b.cfg.wTotalLength = make_word_c( sizeof(struct cdc_cdb) ); desc.cdc_b.cfg.bNumInterfaces = 2; desc.cdc_b.cfg.bConfigurationValue = 1; desc.cdc_b.cfg.iConfiguration = 0;#ifdef CONFIG_S3C2440_SMDK desc.cdc_b.cfg.bmAttributes = USB_CONFIG_BUSPOWERED | USB_CONFIG_SELFPOWERED; desc.cdc_b.cfg.MaxPower = USB_POWER( 0 );#else desc.cdc_b.cfg.bmAttributes = USB_CONFIG_BUSPOWERED; desc.cdc_b.cfg.MaxPower = USB_POWER( 500 );#endif desc.cdc_b.comm_intf.bLength = sizeof( intf_desc_t ); desc.cdc_b.comm_intf.bDescriptorType = USB_DESC_INTERFACE; desc.cdc_b.comm_intf.bInterfaceNumber = 0; desc.cdc_b.comm_intf.bAlternateSetting = 0; desc.cdc_b.comm_intf.bNumEndpoints = 0; desc.cdc_b.comm_intf.bInterfaceClass = CDC_COMM_INTERFACE_CLASS; desc.cdc_b.comm_intf.bInterfaceSubClass = CDC_COMM_INTERFACE_SUBCLASS_ENCM; desc.cdc_b.comm_intf.bInterfaceProtocol = 0; desc.cdc_b.comm_intf.iInterface = 0; desc.cdc_b.func.hdr.bLength = sizeof( hdr_func_desc_t ); desc.cdc_b.func.hdr.bDescriptorType = CDC_CS_INTERFACE; desc.cdc_b.func.hdr.bDescriptorSubtype = CDC_DESC_SUBTYPE_HEADER; desc.cdc_b.func.hdr.bcdCDC = CDC_CLASS_BCD_VERSION; desc.cdc_b.func.eth.bLength = sizeof( eth_func_desc_t ); desc.cdc_b.func.eth.bDescriptorType = CDC_CS_INTERFACE; desc.cdc_b.func.eth.bDescriptorSubtype = CDC_DESC_SUBTYPE_ETHER; desc.cdc_b.func.eth.iMACAddress = 0; desc.cdc_b.func.eth.bmEthernetStatistics = 0; desc.cdc_b.func.eth.wMaxSegmentSize = 1514; desc.cdc_b.func.eth.wNumberMCFilters = 0; desc.cdc_b.func.eth.bNumberPowerFilters = 0; desc.cdc_b.func.uni.bLength = sizeof( union_func_desc_t ); desc.cdc_b.func.uni.bDescriptorType = CDC_CS_INTERFACE; desc.cdc_b.func.uni.bDescriptorSubtype = CDC_DESC_SUBTYPE_UNION; desc.cdc_b.func.uni.bMasterInterface = 0; desc.cdc_b.func.uni.bSlaveInterface = 1;#ifdef CDC_ALTERNATE_INTERFACE desc.cdc_b.data_intf0.bLength = sizeof( intf_desc_t ); desc.cdc_b.data_intf0.bDescriptorType = USB_DESC_INTERFACE; desc.cdc_b.data_intf0.bInterfaceNumber = 1; desc.cdc_b.data_intf0.bAlternateSetting = 0; desc.cdc_b.data_intf0.bNumEndpoints = 0; desc.cdc_b.data_intf0.bInterfaceClass = CDC_DATA_INTERFACE_CLASS; desc.cdc_b.data_intf0.bInterfaceSubClass = 0; desc.cdc_b.data_intf0.bInterfaceProtocol = 0; desc.cdc_b.data_intf0.iInterface = 0;#endif /* CDC_ALTERNATE_INTERFACE */ desc.cdc_b.data_intf1.bLength = sizeof( intf_desc_t ); desc.cdc_b.data_intf1.bDescriptorType = USB_DESC_INTERFACE; desc.cdc_b.data_intf1.bInterfaceNumber = 1;#ifdef CDC_ALTERNATE_INTERFACE desc.cdc_b.data_intf1.bAlternateSetting = 2;#else desc.cdc_b.data_intf1.bAlternateSetting = 0;#endif /* CDC_ALTERNATE_INTERFACE */ desc.cdc_b.data_intf1.bNumEndpoints = 2; desc.cdc_b.data_intf1.bInterfaceClass = CDC_DATA_INTERFACE_CLASS; desc.cdc_b.data_intf1.bInterfaceSubClass = 0; desc.cdc_b.data_intf1.bInterfaceProtocol = 0; desc.cdc_b.data_intf1.iInterface = 0; desc.cdc_b.ep2.bLength = sizeof( ep_desc_t ); desc.cdc_b.ep2.bDescriptorType = USB_DESC_ENDPOINT; desc.cdc_b.ep2.bEndpointAddress = USB_EP_ADDRESS( 2, USB_OUT ); desc.cdc_b.ep2.bmAttributes = USB_EP_BULK; desc.cdc_b.ep2.wMaxPacketSize = make_word_c( EP2_FIFO_SIZE ); desc.cdc_b.ep2.bInterval = 0; desc.cdc_b.ep1.bLength = sizeof( ep_desc_t ); desc.cdc_b.ep1.bDescriptorType = USB_DESC_ENDPOINT; desc.cdc_b.ep1.bEndpointAddress = USB_EP_ADDRESS( 1, USB_IN ); desc.cdc_b.ep1.bmAttributes = USB_EP_BULK; desc.cdc_b.ep1.wMaxPacketSize = make_word_c( EP1_FIFO_SIZE ); desc.cdc_b.ep1.bInterval = 0;#endif /* CONFIG_S3C2440_USB_CDC_ENCM || CONFIG_S3C2440_USB_CDC_ENCM_MODULE */// FIXME: Add support for all endpoint... /* set language */ /* See: http://www.usb.org/developers/data/USB_LANGIDs.pdf */ sd_zero.bDescriptorType = USB_DESC_STRING; sd_zero.bLength = sizeof( string_desc_t ); sd_zero.bString[0] = make_word_c( 0x409 ); /* American English */ elfin_usb_set_string_descriptor( 0, &sd_zero );}/* soft_connect_hook() * Some devices have platform-specific circuitry to make USB * not seem to be plugged in, even when it is. This allows * software to control when a device 'appears' on the USB bus * (after Linux has booted and this driver has loaded, for * example). If you have such a circuit, control it here. */static voidsoft_connect_hook( int enable ){}/* disable the UDC at the source */static voidudc_disable(void){ soft_connect_hook( 0 ); CLKCON &= ~CLKCON_USBD;}/* enable the udc at the source */static voidudc_enable(void){ int tmp; CLKCON &= ~CLKCON_USBD; UD_INDEX = UD_INDEX_EP2; // EP2 input tmp = UD_ICSR1; tmp &= ~(UD_ICSR1_SENTSTL | UD_ICSR1_FFLUSH | UD_ICSR1_UNDRUN); tmp &= ~(UD_ICSR1_PKTRDY | UD_ICSR1_SENDSTL); UD_ICSR1 = tmp; UD_INDEX = UD_INDEX_EP1; // EP1 output tmp = UD_OCSR1; tmp &= ~(UD_OCSR1_SENTSTL | UD_OCSR1_FFLUSH | UD_OCSR1_OVRRUN); tmp &= ~(UD_OCSR1_PKTRDY | UD_OCSR1_SENDSTL); UD_OCSR1 = tmp; CLKCON |= CLKCON_USBD;}static void reconfig_usbd(void){ UD_PWR = UD_PWR_DEFAULT; /* EP0 */ UD_INDEX = UD_INDEX_EP0; UD_MAXP = (EP0_FIFO_SIZE >> 3); UD_INDEX = UD_INDEX_EP0; UD_ICSR1 = EP0_CSR_SOPKTRDY | EP0_CSR_SSE; /* EP2 */ UD_INDEX = UD_INDEX_EP2; UD_MAXP = (EP2_FIFO_SIZE >> 3); UD_INDEX = UD_INDEX_EP2; UD_ICSR1 = UD_ICSR1_FFLUSH | UD_ICSR1_CLRDT; // fifo flush, data toggle UD_INDEX = UD_INDEX_EP2; UD_ICSR2 = UD_ICSR2_MODEIN | UD_ICSR2_DMAIEN; // input mode, IN_PKT_RDY dis #ifdef USE_USBD_DMA UD_ICSR2 &= ~UD_ICSR2_DMAIEN;#endif /* EP1 */ UD_INDEX = UD_INDEX_EP1; UD_MAXP = (EP1_FIFO_SIZE >> 3); UD_INDEX = UD_INDEX_EP1; UD_ICSR1 = UD_ICSR1_FFLUSH | UD_ICSR1_CLRDT; // fifo flush, data toggle UD_INDEX = UD_INDEX_EP1; UD_ICSR2 = 0x0; // output mode UD_INDEX = UD_INDEX_EP1; UD_OCSR1 = UD_OCSR1_FFLUSH | UD_OCSR1_CLRDT; // fifo flush UD_INDEX = UD_INDEX_EP1; UD_OCSR2 = UD_OCSR2_DMAIEN; // OUT_PKT_RDY interrupt disable#ifdef USE_USBD_DMA UD_OCSR2 &= ~UD_OCSR2_DMAIEN; // OUT_PKT_RDY interrupt disable#endif UD_INTE = UD_INTE_EP0 | UD_INTE_EP2 | UD_INTE_EP1; UD_USBINTE = UD_USBINTE_RESET | UD_USBINTE_SUSPND;}//////////////////////////////////////////////////////////////////////////////// Proc Filesystem Support//////////////////////////////////////////////////////////////////////////////#if CONFIG_PROC_FS#define SAY( fmt, args... ) p += sprintf(p, fmt, ## args )#define SAYV( num ) p += sprintf(p, num_fmt, "Value", num )#define SAYC( label, yn ) p += sprintf(p, yn_fmt, label, yn )#define SAYS( label, v ) p += sprintf(p, cnt_fmt, label, v )static int usbctl_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data){ const char * cnt_fmt = "%25.25s: %lu\n"; // const char * num_fmt = "%25.25s: %8.8lX\n"; // const char * yn_fmt = "%25.25s: %s\n"; char * p = page; int len; SAY( "S3C2440 USB Controller Core\n" ); SAY( "Active Client: %s\n", usbd_info.client_name ? usbd_info.client_name : "none"); SAY( "USB state: %s (%s) %d\n", device_state_names[ sm_state_to_device_state[ sm_state ] ], state_names[ sm_state ], sm_state ); SAYS( "ep0 bytes read", usbd_info.stats.ep0_bytes_read ); SAYS( "ep0 bytes written", usbd_info.stats.ep0_bytes_written ); SAYS( "ep0 FIFO read failures", usbd_info.stats.ep0_fifo_write_failures ); SAYS( "ep0 FIFO write failures", usbd_info.stats.ep0_fifo_write_failures ); SAY( "\n" ); len = ( p - page ) - off; if ( len < 0 ) len = 0; *eof = ( len <=count ) ? 1 : 0; *start = page + off; return len;}#endif /* CONFIG_PROC_FS *///////////////////////////////////////////////////////////////////////////////// Module Initialization and Shutdown///////////////////////////////////////////////////////////////////////////////* * usbctl_init() * Module load time. Allocate interrupt resources. Setup /proc fs * entry. Leave UDC disabled. */int __init usbctl_init( void ){ int retval = 0; memset( &usbd_info, 0, sizeof( usbd_info ) );#if CONFIG_PROC_FS create_proc_read_entry ( PROC_NODE_NAME, 0, NULL, usbctl_read_proc, NULL);#endif MISCCR &= ~(1<<13 | 1<<3); CLKCON |= CLKCON_USBD; /* 96MHz */ //UPLLCON = FInsrt(0x3c, fPLL_MDIV) | FInsrt(4, fPLL_PDIV)| FInsrt(1, fPLL_SDIV); //CLKDIVN |= DIVN_UPLL; /* UCLK is 48Mhz */ printk(KERN_DEBUG "CLKCON : [0x%08x], LOCKTIME: [0x%08x]\n", CLKCON, LOCKTIME ); printk(KERN_DEBUG "UPLLCON : [0x%08x], CLKDIVN : [0x%08x]\n", UPLLCON, CLKDIVN); printk(KERN_DEBUG "MISCCR : [0x%08x], CLKSLOW : [0x%08x]\n", MISCCR, CLKSLOW); /* now allocate the IRQ. */ retval = request_irq(IRQ_USBD, udc_int_hndlr, SA_INTERRUPT, "USBD", NULL); if (retval) { printk("%sCouldn't request USB irq rc=%d\n",pszMe, retval); goto err_irq; } printk( "S3C2440 USBD Controller Core Initialized\n"); return 0;err_irq: return retval;}/* * usbctl_exit() * Release interrupt resources */void __exit usbctl_exit( void ){ printk("Unloading S3C2440 USBD Controller\n"); udc_disable();#if CONFIG_PROC_FS remove_proc_entry ( PROC_NODE_NAME, NULL);#endif free_irq(IRQ_USBD, NULL);}module_init( usbctl_init );module_exit( usbctl_exit );EXPORT_SYMBOL( elfin_usb_open );EXPORT_SYMBOL( elfin_usb_start );EXPORT_SYMBOL( elfin_usb_stop );EXPORT_SYMBOL( elfin_usb_close );EXPORT_SYMBOL( elfin_usb_get_descriptor_ptr );EXPORT_SYMBOL( elfin_usb_set_string_descriptor );EXPORT_SYMBOL( elfin_usb_get_string_descriptor );EXPORT_SYMBOL( elfin_usb_kmalloc_string_descriptor );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -