usbd-bi.c
来自「Linux2.4.20针对三星公司的s3c2440内核基础上的一些设备驱动代码」· C语言 代码 · 共 1,414 行 · 第 1/3 页
C
1,414 行
break; case DEVICE_BUS_INACTIVE: // disable suspend interrupt udc_suspended_interrupts (device); // XXX check on linkup and sl11 // if we are no longer connected then force a reset if (!udc_connected ()) { usbd_device_event_irq (device, DEVICE_RESET, 0); } break; case DEVICE_BUS_ACTIVITY: // enable suspend interrupt udc_all_interrupts (device); break; case DEVICE_POWER_INTERRUPTION: break; case DEVICE_HUB_RESET: break; case DEVICE_DESTROY: udc_disconnect (); bi_disable_endpoints (device); udc_disable_interrupts (device); udc_disable (); break; case DEVICE_FUNCTION_PRIVATE: break; } return 0;}/** * bi_send_urb - start transmit * @urb: */int bi_send_urb (struct urb *urb){ unsigned long flags; dbg_tx (4, "urb: %p", urb); local_irq_save (flags); if (urb && urb->endpoint && !urb->endpoint->tx_urb) { dbg_tx (2, "urb: %p endpoint: %x", urb, urb->endpoint->endpoint_address); usbd_tx_complete_irq (urb->endpoint, 0); udc_start_in_irq (urb->endpoint); } local_irq_restore (flags); // Shouldn't need to make this atomic, all we need is a change indicator urb->device->usbd_rxtx_timestamp = jiffies; return 0;}#if defined(CONFIG_PM) && !defined(CONFIG_USBD_MONITOR) && !defined(CONFIG_USBD_MONITOR_MODULE)static int bi_pm_event (struct pm_dev *pm_dev, pm_request_t request, void *unused);#endifstruct usb_bus_operations bi_ops = { send_urb:bi_send_urb, cancel_urb:bi_cancel_urb, endpoint_halted:bi_endpoint_halted, device_feature:bi_device_feature, device_event:bi_device_event,};struct usb_bus_driver bi_driver = { name:"", max_endpoints:0, ops:&bi_ops, this_module:THIS_MODULE,};/* Bus Interface Received Data *************************************************************** */struct usb_device_instance *device_array[MAX_DEVICES];/* Bus Interface Support Functions *********************************************************** *//** * udc_cable_event - called from cradle interrupt handler */void udc_cable_event (void){ struct usb_bus_instance *bus; struct usb_device_instance *device; struct bi_data *data; dbgENTER (dbgflg_usbdbi_init, 1); // sanity check if (!(device = device_array[0]) || !(bus = device->bus) || !(data = bus->privdata)) { return; } { unsigned long flags; local_irq_save (flags); if (udc_connected ()) { dbg_init (1, "state: %d connected: %d", device->device_state, 1);; if (device->device_state == STATE_ATTACHED) { dbg_init (1, "LOADING"); usbd_device_event_irq (device, DEVICE_HUB_CONFIGURED, 0); usbd_device_event_irq (device, DEVICE_RESET, 0); } } else { dbg_init (1, "state: %d connected: %d", device->device_state, 0);; if (device->device_state != STATE_ATTACHED) { dbg_init (1, "UNLOADING"); usbd_device_event_irq (device, DEVICE_RESET, 0); usbd_device_event_irq (device, DEVICE_POWER_INTERRUPTION, 0); usbd_device_event_irq (device, DEVICE_HUB_RESET, 0); } } local_irq_restore (flags); } dbgLEAVE (dbgflg_usbdbi_init, 1);}/* Module Init - the device init and exit routines ******************************************* *//** * bi_udc_init - initialize USB Device Controller * * Get ready to use the USB Device Controller. * * Register an interrupt handler and IO region. Return non-zero for error. */int bi_udc_init (void){ dbg_init (1, "Loading %s", udc_name ()); bi_driver.name = udc_name (); bi_driver.max_endpoints = udc_max_endpoints (); bi_driver.maxpacketsize = udc_ep0_packetsize (); dbg_init (1, "name: %s endpoints: %d ep0: %d", bi_driver.name, bi_driver.max_endpoints, bi_driver.maxpacketsize); // request device IRQ if (udc_request_udc_irq ()) { dbg_init (0, "name: %s request udc irq failed", udc_name ()); return -EINVAL; } // request device IO if (udc_request_io ()) { udc_release_udc_irq (); dbg_init (0, "name: %s request udc io failed", udc_name ()); return -EINVAL; } // probe for device if (udc_init ()) { udc_release_udc_irq (); udc_release_io (); dbg_init (1, "name: %s probe failed", udc_name ()); return -EINVAL; } // optional cable IRQ have_cable_irq = !udc_request_cable_irq (); dbg_init (1, "name: %s request cable irq %d", udc_name (), have_cable_irq); return 0;}/** * bi_udc_exit - Stop using the USB Device Controller * * Stop using the USB Device Controller. * * Shutdown and free dma channels, de-register the interrupt handler. */void bi_udc_exit (void){ int i; dbg_init (1, "Unloading %s", udc_name ()); for (i = 0; i < udc_max_endpoints (); i++) { udc_disable_ep (i); } // free io and irq udc_disconnect (); udc_disable (); udc_release_io (); udc_release_udc_irq (); if (have_cable_irq) { udc_release_cable_irq (); }}/* Module Init - the module init and exit routines ************************************* */#if 0/* bi_init - commission bus interface driver */static int bi_init (void){ return 0;}#endif/* bi_exit - decommission bus interface driver */static void bi_exit (void){}#if defined(CONFIG_PM) && !defined(CONFIG_USBD_MONITOR) && !defined(CONFIG_USBD_MONITOR_MODULE)/* Module Init - Power management ************************************************************ *//* The power management scheme is simple. Simply do the following: * * Event Call Equivalent * ------------------------------------------ * PM_SUSPEND bi_exit(); rmmod * PM_RESUME bi_init(); insmod * */static int pm_suspended;/* * usbd_pm_callback * @dev: * @rqst: * @unused: * * Used to signal power management events. */static int bi_pm_event (struct pm_dev *pm_dev, pm_request_t request, void *unused){ struct usb_device_instance *device; dbg_pm (0, "request: %d pm_dev: %p data: %p", request, pm_dev, pm_dev->data); if (!(device = pm_dev->data)) { dbg_pm (0, "DATA NULL, NO DEVICE"); return 0; } switch (request) {#if defined(CONFIG_IRIS) case PM_STANDBY: case PM_BLANK:#endif case PM_SUSPEND: dbg_pm (0, "PM_SUSPEND"); if (!pm_suspended) { pm_suspended = 1; dbg_init (1, "MOD_INC_USE_COUNT %d", GET_USE_COUNT (THIS_MODULE)); udc_disconnect (); // disable USB pullup if we can udc_disable_interrupts (device); // disable interupts udc_disable (); // disable UDC dbg_pm (0, "PM_SUSPEND: finished"); } break;#if defined(CONFIG_IRIS) case PM_UNBLANK:#endif case PM_RESUME: dbg_pm (0, "PM_RESUME"); if (pm_suspended) { // probe for device if (udc_init ()) { dbg_init (0, "udc_init failed"); //return -EINVAL; } udc_enable (device); // enable UDC udc_all_interrupts (device); // enable interrupts udc_connect (); // enable USB pullup if we can //udc_set_address(device->address); //udc_reset_ep(0); pm_suspended = 0; dbg_init (1, "MOD_INC_USE_COUNT %d", GET_USE_COUNT (THIS_MODULE)); dbg_pm (0, "PM_RESUME: finished"); } break; } return 0;}#endif#ifdef CONFIG_DPM /* MVL-CEE */static int bi_udc_suspend(struct device *dev, u32 state, u32 level);static int bi_udc_resume(struct device *dev, u32 level);static int bi_udc_scale(struct bus_op_point *op, u32 level);static struct device_driver bi_udc_driver_ldm = { .name = "usb-device", .devclass = NULL, .probe = NULL, .suspend = bi_udc_suspend, .resume = bi_udc_resume, .scale = bi_udc_scale, .remove = NULL, .constraints = NULL,};static struct device bi_udc_device_ldm = { .name = "USB Device", .bus_id = "usbd", .driver = NULL, .power_state = DPM_POWER_ON,};static voidbi_udc_ldm_driver_register(void){#ifdef CONFIG_OMAP_INNOVATOR extern void mpu_public_driver_register(struct device_driver *driver); mpu_public_driver_register(&bi_udc_driver_ldm);#endif#ifdef CONFIG_ARCH_MAINSTONE extern void pxaopb_driver_register(struct device_driver *driver); pxaopb_driver_register(&bi_udc_driver_ldm);#endif}static voidbi_udc_ldm_device_register(void){#ifdef CONFIG_OMAP_INNOVATOR extern void mpu_public_device_register(struct device *device); mpu_public_device_register(&bi_udc_device_ldm);#endif#ifdef CONFIG_ARCH_MAINSTONE extern void pxaopb_device_register(struct device *device); pxaopb_device_register(&bi_udc_device_ldm);#endif}static voidbi_udc_ldm_driver_unregister(void){#ifdef CONFIG_OMAP_INNOVATOR extern void mpu_public_driver_unregister(struct device_driver *driver); mpu_public_driver_unregister(&bi_udc_driver_ldm);#endif#ifdef CONFIG_ARCH_MAINSTONE extern void pxaopb_driver_unregister(struct device_driver *driver); pxaopb_driver_unregister(&bi_udc_driver_ldm);#endif}static voidbi_udc_ldm_device_unregister(void){#ifdef CONFIG_OMAP_INNOVATOR extern void mpu_public_device_unregister(struct device *device); mpu_public_device_unregister(&bi_udc_device_ldm);#endif#ifdef CONFIG_ARCH_MAINSTONE extern void pxaopb_device_unregister(struct device *device); pxaopb_device_unregister(&bi_udc_device_ldm);#endif}static intbi_udc_scale(struct bus_op_point *op, u32 level){ printk("+++: bi_udc_scale\n"); /* REVISIT */ return 0;}static intbi_udc_suspend(struct device *dev, u32 state, u32 level){ struct usb_device_instance *device = device_array[0]; if (usbd_bi_dbg) printk("+++: bi_udc_suspend\n"); switch (level) { case SUSPEND_POWER_DOWN: dbg_pm (0, "SUSPEND_POWER_DOWN"); dbg_init (1, "MOD_INC_USE_COUNT %d", GET_USE_COUNT (THIS_MODULE)); udc_disconnect (); /* disable USB pullup */ if (device) udc_disable_interrupts (device); /* disable interrupts */ udc_disable (); /* disable UDC */ dbg_pm (0, "SUSPEND_POWER_DOWN: finished"); break; } return 0;}static intbi_udc_resume(struct device *dev, u32 level){ int ret = 0; struct usb_device_instance *device = device_array[0]; if (usbd_bi_dbg) printk("+++: bi_udc_resume\n"); switch (level) { case RESUME_POWER_ON: dbg_pm (0, "RESUME_POWER_ON"); if (udc_init ()) { dbg_init (0, "udc_init failed"); } if (device) { udc_enable (device); /* enable UDC */ udc_all_interrupts (device); /* enable interrupts */ } udc_connect (); /* enable USB pullup */ dbg_init (1, "MOD_INC_USE_COUNT %d", GET_USE_COUNT (THIS_MODULE)); dbg_pm (0, "RESUME_POWER_ON: finished"); break; } return ret;}#endif /* ifdef CONFIG_DPM */#ifdef CONFIG_USBD_PROCFS/* Proc Filesystem *************************************************************************** *//* * * usbd_proc_read - implement proc file system read. * @file * @buf * @count * @pos * * Standard proc file system read function. */static ssize_t usbd_proc_read (struct file *file, char *buf, size_t count, loff_t * pos){ struct usb_device_instance *device; 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)++; switch (index) { case 0: len += sprintf ((char *) page + len, "USBD Status\n"); break; case 1:
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?