static int bi_udc_resume(struct device *dev, u32 level) { int ret = 0; struct usb_device_instance *device = device_array[0]; 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; }
static int bi_udc_suspend(struct device *dev, u32 state, u32 level) { struct usb_device_instance *device = device_array[0]; 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; }
/* * 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; }
/* bi_modinit - commission bus interface driver */ int __init bi_modinit(void) { struct usb_bus_instance * bus; struct usb_device_instance * device; //extern const char __usbd_module_info[]; //printk(KERN_INFO "%s (dbg=\"%s\")\n", __usbd_module_info, dbg?dbg:""); if (0 != scan_debug_options("usb-bus",dbg_table,dbg)) { printk("Failed to scan dbg in bi_modinit\n"); } if (bi_udc_init()) { return(-EINVAL); } // register this bus interface driver and create the device driver instance if ((bus = usbd_register_bus(&bi_driver))==NULL) { bi_udc_exit(); return -EINVAL; } // see if we can scrounge up something to set a sort of unique device // address if (!udc_serial_init(bus)) { dbg_init(1,"serial: %s %04x", bus->serial_number_str, bus->serial_number); } if ((device = usbd_register_device(NULL, bus, 8))==NULL) { usbd_deregister_bus(bus); bi_udc_exit(); return -EINVAL; } #ifdef CONFIG_PM // register with power management pm_dev = pm_register(PM_USB_DEV, PM_SYS_UNKNOWN, bi_pm_event); pm_dev->data = device; #endif bus->device = device; device_array[0] = device; // initialize the device { struct usb_endpoint_instance *endpoint = device->bus->endpoint_array + 0; // setup endpoint zero endpoint->endpoint_address = 0; endpoint->tx_attributes = 0; endpoint->tx_transferSize = 255; endpoint->tx_packetSize = udc_ep0_packetsize(); endpoint->rcv_attributes = 0; endpoint->rcv_transferSize = 0x8; endpoint->rcv_packetSize = udc_ep0_packetsize(); udc_setup_ep(device, 0, endpoint); } // hopefully device enumeration will finish this process udc_startup_events(device); #ifdef CONFIG_PM dbg_pm(0,"pm_dev->callback#%p",pm_dev->callback); if (!udc_connected()) { /* Fake a call from the PM system to suspend the UDC until it is needed (cable connect, etc) */ (void) bi_pm_event(pm_dev,PM_SUSPEND,NULL); /* There appears to be no constant for this, but inspection of arch/arm/mach-l7200/apm.c:send_event() shows that the suspended state is 3 (i.e. pm_send_all(PM_SUSPEND, (void *)3)) corresponding to ACPI_D3. */ pm_dev->state = 3; } #endif if (dbgflg_usbdbi_tick > 0) { // start ticker ticker_kickoff(); } dbgLEAVE(dbgflg_usbdbi_init,1); return 0; }
/* bi_modinit - commission bus interface driver */ static int __init bi_modinit (void) { extern const char __usbd_module_info[]; struct usb_bus_instance *bus; struct usb_device_instance *device; struct bi_data *data; printk (KERN_INFO "%s (dbg=\"%s\")\n", __usbd_module_info, dbg ? dbg : ""); // process debug options if (0 != scan_debug_options ("usbd-bi", dbg_table, dbg)) { return -EINVAL; } // check if we can see the UDC if (bi_udc_init ()) { return -EINVAL; } // allocate a bi private data structure if ((data = kmalloc (sizeof (struct bi_data), GFP_KERNEL)) == NULL) { bi_udc_exit (); return -EINVAL; } memset (data, 0, sizeof (struct bi_data)); // register this bus interface driver and create the device driver instance if ((bus = usbd_register_bus (&bi_driver)) == NULL) { kfree (data); bi_udc_exit (); return -EINVAL; } bus->privdata = data; // see if we can scrounge up something to set a sort of unique device address if (!udc_serial_init (bus)) { dbg_init (1, "serial: %s %04x\n", bus->serial_number_str, bus->serial_number); } if ((device = usbd_register_device (NULL, bus, 8)) == NULL) { usbd_deregister_bus (bus); kfree (data); bi_udc_exit (); return -EINVAL; } #if defined(CONFIG_PM) && !defined(CONFIG_USBD_MONITOR) && !defined(CONFIG_USBD_MONITOR_MODULE) // register with power management pm_dev = pm_register (PM_USB_DEV, PM_SYS_UNKNOWN, bi_pm_event); pm_dev->data = device; #endif #ifdef CONFIG_DPM /* MVL-CEE */ bi_udc_ldm_driver_register(); bi_udc_ldm_device_register(); #endif bus->device = device; device_array[0] = device; // initialize the device { struct usb_endpoint_instance *endpoint = device->bus->endpoint_array + 0; // setup endpoint zero endpoint->endpoint_address = 0; endpoint->tx_attributes = 0; endpoint->tx_transferSize = 255; endpoint->tx_packetSize = udc_ep0_packetsize (); endpoint->rcv_attributes = 0; endpoint->rcv_transferSize = 0x8; endpoint->rcv_packetSize = udc_ep0_packetsize (); udc_setup_ep (device, 0, endpoint); } // hopefully device enumeration will finish this process printk(KERN_INFO"bi_modinit: call udc_startup_events\n"); udc_startup_events (device); #if defined(CONFIG_PM) && !defined(CONFIG_USBD_MONITOR) && !defined(CONFIG_USBD_MONITOR_MODULE) dbg_pm (0, "pm_dev->callback#%p", pm_dev->callback); if (!udc_connected ()) { /* Fake a call from the PM system to suspend the UDC until it is needed (cable connect, etc) */ (void) bi_pm_event (pm_dev, PM_SUSPEND, NULL); /* There appears to be no constant for this, but inspection of arch/arm/mach-l7200/apm.c:send_event() shows that the suspended state is 3 (i.e. pm_send_all(PM_SUSPEND, (void *)3)) corresponding to ACPI_D3. */ pm_dev->state = 3; } #endif if (dbgflg_usbdbi_tick > 0) { // start ticker ticker_kickoff (); } #ifdef CONFIG_USBD_PROCFS { struct proc_dir_entry *p; // create proc filesystem entries if ((p = create_proc_entry ("usbd", 0, 0)) == NULL) { return -ENOMEM; } p->proc_fops = &usbd_proc_operations_functions; } #endif dbgLEAVE (dbgflg_usbdbi_init, 1); return 0; }