📄 l7205.c
字号:
udc_interrupts, status, rawstatus); } } } } // end of loopcount loop}/* ********************************************************************************************* *//* * Start of public functions. *//** * udc_request_udc_irq - request UDC interrupt * * Return non-zero if not successful. */int udc_request_udc_irq (){ // request IRQ if (request_irq (IRQ_USBF, udc_int_hndlr, SA_INTERRUPT | SA_SAMPLE_RANDOM, "L7205 USBD Bus Interface", NULL) != 0) { dbg_init (0, "Couldn't request USB irq"); return -EINVAL; } return 0;}/** * udc_start_in_irq - start transmit * @eendpoint: endpoint instance * * Called by bus interface driver to see if we need to start a data transmission. */void udc_start_in_irq (struct usb_endpoint_instance *endpoint){ if (!(IO_USBF_STATUS & USBF_STATUS_F2BSY)) { ep2_start (); }}/** * udc_stall_ep - stall endpoint * @ep: physical endpoint * * Stall the endpoint. */void udc_stall_ep (unsigned int ep){}/** * udc_reset_ep - reset endpoint * @ep: physical endpoint * reset the endpoint. * * returns : 0 if ok, -1 otherwise */void udc_reset_ep (unsigned int ep){ if (ep < UDC_MAX_ENDPOINTS) { // reset switch (ep) { case 0: case 1: case 0x82: /* do nothing */ break; } }}/** * udc_endpoint_halted - is endpoint halted * @ep: * * Return non-zero if endpoint is halted */int udc_endpoint_halted (unsigned int ep){ return 0;}/** * udc_set_address - set the USB address for this device * @address: * * Called from control endpoint function after it decodes a set address setup packet. */void udc_set_address (unsigned char address){}static int crc32 (char *s, int length){ /* indices */ int pByte; int pBit; const unsigned long poly = 0xedb88320; unsigned long crc_value = 0xffffffff; for (pByte = 0; pByte < length; pByte++) { unsigned char c = *(s++); for (pBit = 0; pBit < 8; pBit++) { crc_value = (crc_value >> 1) ^ (((crc_value ^ c) & 0x01) ? poly : 0); c >>= 1; } } return crc_value;}/** * udc_serial_init - set a serial number if available */int __init udc_serial_init (struct usb_bus_instance *bus){#ifdef CONFIG_IRIS iris_serial_number_struct serial; if (!iris_get_serial_number (&serial) && (bus->serial_number_str = kmalloc (36, GFP_KERNEL))) { sprintf (bus->serial_number_str, "%08x-%08x-%08x-%08x", serial.b3, serial.b2, serial.b1, serial.b0); bus->serial_number = crc32 (bus->serial_number_str, 32); return 0; }#endif return -EINVAL;}/** * udc_max_endpoints - max physical endpoints * * Return number of physical endpoints. */int udc_max_endpoints (void){ return UDC_MAX_ENDPOINTS;}/** * udc_check_ep - check logical endpoint * @lep: * * Return physical endpoint number to use for this logical endpoint or zero if not valid. */int udc_check_ep (int logical_endpoint, int packetsize){ if (packetsize > 32) { return 0; } switch (logical_endpoint) { case 1: return 1; case 0x82: return 2; case 0x83: return 3; default: return 0; }}/** * udc_set_ep - setup endpoint * @ep: * @endpoint: * * Associate a physical endpoint with endpoint_instance */void udc_setup_ep (struct usb_device_instance *device, unsigned int ep, struct usb_endpoint_instance *endpoint){ dbg_init (1, "ep: %d", ep); if (ep < UDC_MAX_ENDPOINTS) { ep_endpoints[ep] = endpoint; switch (ep) { case 0: // Control break; case 1: // OUT usbd_fill_rcv (device, endpoint, 10); // XXX endpoint->rcv_urb = first_urb_detached (&endpoint->rdy); ep1_device = device; ep1_endpoint = endpoint; break; case 2: // IN ep2_device = device; ep2_endpoint = endpoint; break; } }}/** * udc_disable_ep - disable endpoint * @ep: * * Disable specified endpoint */void udc_disable_ep (unsigned int ep){ if (ep < UDC_MAX_ENDPOINTS) { struct usb_endpoint_instance *endpoint; switch (ep) { case 0: // Control break; case 1: // OUT ep1_endpoint = NULL; break; case 2: // IN ep2_device = NULL; ep2_endpoint = NULL; break; } if ((endpoint = ep_endpoints[ep])) { ep_endpoints[ep] = NULL; usbd_flush_ep (endpoint); } }}/** * udc_connected - is the USB cable connected * * Return non-zeron if cable is connected. */int udc_connected (){#ifdef CONFIG_IRIS // Return TRUE if USB cable shows Vbus _and_ AC power present dbg_pur (0, "Vbus: %x AC: %x", iris_read_usb_sync (), iris_read_ac_sync ()); return (iris_read_usb_sync () && iris_read_ac_sync ());#else return 1;#endif}/** * udc_connect - enable pullup resistor * * Turn on the USB connection by enabling the pullup resistor. */void udc_connect (void){#ifdef CONFIG_IRIS // Enable the pullup resistor. dbg_pur (0, "Enabling IRIS USB pullup resistor"); SET_PB_OUT (USB_PULLUP_GPIO); SET_PBDR_HI (USB_PULLUP_GPIO); SET_PBSBSR_LO (USB_PULLUP_GPIO);#endif}/** * udc_disconnect - disable pullup resistor * * Turn off the USB connection by disabling the pullup resistor. */void udc_disconnect (void){#ifdef CONFIG_IRIS // Disable the pullup resistor. dbg_pur (0, "Disabling IRIS USB pullup resistor"); SET_PB_OUT (USB_PULLUP_GPIO); SET_PBDR_LO (USB_PULLUP_GPIO); SET_PBSBSR_LO (USB_PULLUP_GPIO);#endif}/** * udc_all_interrupts - enable interrupts * * Switch on UDC interrupts. * */void udc_all_interrupts (struct usb_device_instance *device){ dbg_init (1, " "); // set interrupt mask}/** * udc_suspended_interrupts - enable suspended interrupts * * Switch on only UDC resume interrupt. * */void udc_suspended_interrupts (struct usb_device_instance *device){ dbg_init (1, " "); // set interrupt mask}/** * udc_disable_interrupts - disable interrupts. * * switch off interrupts */void udc_disable_interrupts (struct usb_device_instance *device){ dbg_init (1, " "); // reset interrupt mask}/** * udc_ep0_packetsize - return ep0 packetsize */int udc_ep0_packetsize (void){ return EP0_PACKETSIZE;}/** * udc_startup_events - allow udc code to do any additional startup */void udc_startup_events (struct usb_device_instance *device){ usbd_device_event (device, DEVICE_INIT, 0); usbd_device_event (device, DEVICE_CREATE, 0); usbd_device_event (device, DEVICE_HUB_CONFIGURED, 0); // XXX moved to first SOF after HRST //usbd_device_event(device, DEVICE_RESET, 0); // XXX should be done from device event // XXX usbd_device_event(device, DEVICE_ADDRESS_ASSIGNED, 0); //device->configuration = 0; // XXX usbd_device_event(device, DEVICE_CONFIGURED, 0); //device->interface = 1; //device->alternate = 0; // XXX usbd_device_event(device, DEVICE_SET_INTERFACE, 0);}/** * udc_name - return name of USB Device Controller */char *udc_name (void){ return UDC_NAME;}/** * udc_request_cable_irq - request Cable interrupt * * Return non-zero if not successful. */int udc_request_cable_irq (){ return 0;}#ifdef CONFIG_USBD_PROCFS/* Proc Filesystem *************************************************************************** *//* * * l7205_proc_read - implement proc file system read. * @file * @buf * @count * @pos * * Standard proc file system read function. */static ssize_t l7205_proc_read (struct file *file, char *buf, size_t count, loff_t * pos){ unsigned long page; int len = 0; int index; MOD_INC_USE_COUNT; // get a page, max 4095 bytes of data... if (!(page = get_free_page (GFP_KERNEL))) { MOD_DEC_USE_COUNT; return -ENOMEM; } len = 0; index = (*pos)++; if (index == 0) { len += sprintf ((char *) page + len, "l7205 UDC status\n"); } if (index == 1) { len += sprintf ((char *) page + len, "%s\n", udc_connected ()? "Connected" : "Not connected"); } if (len > count) { len = -EINVAL; } else if (len > 0 && copy_to_user (buf, (char *) page, len)) { len = -EFAULT; } free_page (page); MOD_DEC_USE_COUNT; return len;}/* * * l7205_proc_write - implement proc file system write. * @file * @buf * @count * @pos * * Proc file system write function, used to signal monitor actions complete. * (Hotplug script (or whatever) writes to the file to signal the completion * of the script.) An ugly hack. */static ssize_t l7205_proc_write (struct file *file, const char *buf, size_t count, loff_t * pos){ size_t n = count; char command[64]; char *cp = command; int i = 0; MOD_INC_USE_COUNT; //printk(KERN_DEBUG "%s: count=%u\n",__FUNCTION__,count); while ((n > 0) && (i < 64)) { // Not too efficient, but it shouldn't matter if (copy_from_user (cp++, buf + (count - n), 1)) { count = -EFAULT; break; } *cp = '\0'; i++; n -= 1; //printk(KERN_DEBUG "%s: %u/%u %02x\n",__FUNCTION__,count-n,count,c); } if (!strncmp (command, "plug", 4)) { udc_connect (); } else if (!strncmp (command, "unplug", 6)) { udc_disconnect (); } MOD_DEC_USE_COUNT; return (count);}static struct file_operations l7205_proc_operations_functions = { read:l7205_proc_read, write:l7205_proc_write,};#endif/** * udc_request_udc_io - request UDC io region * * Return non-zero if not successful. */int udc_request_io (){#ifdef CONFIG_USBD_PROCFS { struct proc_dir_entry *p; // create proc filesystem entries if ((p = create_proc_entry ("l7205", 0, 0)) == NULL) { return -ENOMEM; } p->proc_fops = &l7205_proc_operations_functions; }#endif return 0;}/** * udc_release_udc_irq - release UDC irq */void udc_release_udc_irq (){ free_irq (IRQ_USBF, NULL);}/** * udc_release_cable_irq - release Cable irq */void udc_release_cable_irq (){}/** * udc_release_release_io - release UDC io region */void udc_release_io (){#ifdef CONFIG_USBD_PROCFS remove_proc_entry ("l7205", NULL);#endif}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -