/* * * 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: len += sprintf ((char *) page + len, "Cable: %s\n", udc_connected ()? "Plugged" : "Unplugged"); break; case 2: if ((device = device_array[0])) { struct usb_function_instance * function_instance; struct usb_bus_instance * bus; len += sprintf ((char *) page + len, "Device status: %s\n", USBD_DEVICE_STATUS(device->status)); len += sprintf ((char *) page + len, "Device state: %s\n", USBD_DEVICE_STATE(device->device_state)); if ((function_instance = device->function_instance_array+0)) { len += sprintf ((char *) page + len, "Function: %s\n", function_instance->function_driver->name); } if ((bus= device->bus)) { len += sprintf ((char *) page + len, "Bus interface: %s\n", bus->driver->name); } } break; default: break; } 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; }
/** * 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); }
/* 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_device_event - handle generic bus event * @device: device pointer * @event: interrupt event * * Called by usb core layer to inform bus of an event. */ int bi_device_event(struct usb_device_instance *device, usb_device_event_t event, int data) { sie_info * sie_data; cy_priv_t * cy_priv; otg_t * otg; sie_data = (sie_info *) device->bus->privdata; cy_priv = (cy_priv_t *) sie_data->cy_priv; otg = (otg_t *) cy_priv->otg; //printk(KERN_DEBUG "bi_device_event: event: %d\n", event); if (!device) { return 0; } switch (event) { case DEVICE_UNKNOWN: break; case DEVICE_INIT: break; case DEVICE_CREATE: // XXX should this stuff be in DEVICE_INIT? bi_config(device); // enable udc, enable interrupts, enable connect udc_enable(device); udc_all_interrupts(device); udc_connect(); break; case DEVICE_HUB_CONFIGURED: break; case DEVICE_RESET: device->address = 0; udc_set_address(device->address, device); udc_reset_ep(0, device); udc_all_interrupts(device); // XXX break; case DEVICE_ADDRESS_ASSIGNED: udc_set_address(device->address, device); device->status = USBD_OK; break; case DEVICE_CONFIGURED: bi_config(device); break; case DEVICE_DE_CONFIGURED: udc_reset_ep(1, device); udc_reset_ep(2, device); udc_reset_ep(3, device); break; case DEVICE_SET_INTERFACE: bi_config(device); break; case DEVICE_SET_FEATURE: break; case DEVICE_CLEAR_FEATURE: 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_BUS_REQUEST: otg->b_bus_req = TRUE; update_otg_state(otg); break; case DEVICE_BUS_RELEASE: otg->b_bus_req = FALSE; update_otg_state(otg); break; case DEVICE_RCV_URB_RECYCLED: udc_rcv_urb_recycled(); break; case DEVICE_ACCEPT_HNP: otg->b_hnp_en = TRUE; update_otg_state(otg); break; case DEVICE_REQUEST_SRP: //otg->srp_start_flag = TRUE; otg->b_bus_req = TRUE; otg->b_se0_srp = TRUE; update_otg_state(otg); break; case DEVICE_FUNCTION_PRIVATE: break; } return 0; }
/** * bi_device_event - handle generic bus event * @device: device pointer * @event: interrupt event * * Called by usb core layer to inform bus of an event. */ int bi_device_event (struct usb_device_instance *device, usb_device_event_t event, int data) { //printk(KERN_DEBUG "bi_device_event: event: %d\n", event); if (!device) { return 0; } dbg_usbe (1,"%s", USBD_DEVICE_EVENTS(event)); switch (event) { case DEVICE_UNKNOWN: break; case DEVICE_INIT: break; case DEVICE_CREATE: // XXX should this stuff be in DEVICE_INIT? // enable upstream port //ep0_enable(device); // for net_create bi_config (device); // enable udc, enable interrupts, enable connect printk(KERN_INFO"bi_device_event: call udc_enable\n"); udc_enable (device); printk(KERN_INFO"bi_device_event: call udc_all_interrupts\n"); // XXX verify udc_suspended_interrupts (device); //udc_all_interrupts (device); dbg_usbe (1, "CREATE done"); break; case DEVICE_HUB_CONFIGURED: udc_connect (); break; case DEVICE_RESET: device->address = 0; udc_set_address (device->address); udc_reset_ep (0); // XXX verify udc_suspended_interrupts (device); dbg_usbe (1, "DEVICE RESET done: %d", device->address); break; case DEVICE_ADDRESS_ASSIGNED: udc_set_address (device->address); device->status = USBD_OK; // XXX verify udc_all_interrupts (device); // XXX break; case DEVICE_CONFIGURED: device->status = USBD_OK; bi_config (device); break; case DEVICE_DE_CONFIGURED: { int ep; for (ep = 1; ep < udc_max_endpoints (); ep++) udc_reset_ep (ep); } break; case DEVICE_SET_INTERFACE: bi_config (device); break; case DEVICE_SET_FEATURE: break; case DEVICE_CLEAR_FEATURE: 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_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; }