/** * usbd_device_event - called to respond to various usb events * @device: pointer to struct device * @event: event to respond to * * Used by a Bus driver to indicate an event. */ void usbd_device_event_irq (struct usb_device_instance *device, usb_device_event_t event, int data) { struct urb *urb; usb_device_state_t state; if (!device || !device->bus) { dbg_usbe (1, "(%p,%d) NULL device or device->bus", device, event); return; } state = device->device_state; dbg_usbe (3, "-------------------------------------------------------------------------------------"); dbg_usbe (1,"%s", USBD_DEVICE_EVENTS(event)); switch (event) { case DEVICE_UNKNOWN: break; case DEVICE_INIT: device->device_state = STATE_INIT; break; case DEVICE_CREATE: device->device_state = STATE_ATTACHED; break; case DEVICE_HUB_CONFIGURED: device->device_state = STATE_POWERED; break; case DEVICE_RESET: device->device_state = STATE_DEFAULT; device->address = 0; break; case DEVICE_ADDRESS_ASSIGNED: device->device_state = STATE_ADDRESSED; break; case DEVICE_CONFIGURED: device->device_state = STATE_CONFIGURED; break; case DEVICE_DE_CONFIGURED: device->device_state = STATE_ADDRESSED; break; case DEVICE_BUS_INACTIVE: if (device->status != USBD_CLOSING) { device->status = USBD_SUSPENDED; } break; case DEVICE_BUS_ACTIVITY: if (device->status != USBD_CLOSING) { device->status = USBD_OK; } break; case DEVICE_SET_INTERFACE: break; case DEVICE_SET_FEATURE: break; case DEVICE_CLEAR_FEATURE: break; case DEVICE_POWER_INTERRUPTION: device->device_state = STATE_POWERED; break; case DEVICE_HUB_RESET: device->device_state = STATE_ATTACHED; break; case DEVICE_DESTROY: device->device_state = STATE_UNKNOWN; break; case DEVICE_FUNCTION_PRIVATE: break; } dbg_usbe (3, "%s event: %d oldstate: %d newstate: %d status: %d address: %d", device->name, event, state, device->device_state, device->status, device->address);; // tell the bus interface driver if (device->bus && device->bus->driver->ops->device_event) { dbg_usbe (3, "calling bus->event"); device->bus->driver->ops->device_event (device, event, data); } #if 0 if (device->function_instance_array && (device->function_instance_array + port)->function_driver->ops->event) { dbg_usbe (3, "calling function->event"); (device->function_instance_array + port)->function_driver->ops->event (device, event); } #endif if (device->ep0 && device->ep0->function_driver->ops->event) { dbg_usbe (3, "calling ep0->event"); device->ep0->function_driver->ops->event (device, event, data); } #if 0 // tell the bus interface driver if (device->bus && device->bus->driver->ops->device_event) { dbg_usbe (3, "calling bus->event"); device->bus->driver->ops->device_event (device, event); } #endif // dbg_usbe(0, "FINISHED - NO FUNCTION BH"); // return; // XXX // queue an urb to endpoint zero dbg_usbe(1,"queueing event urb"); if ((urb = usbd_alloc_urb (device, device->function_instance_array, 0, 0))) { urb->event = event; urb->data = data; urb_append_irq (&(urb->endpoint->events), urb); usbd_schedule_function_bh (device); } dbg_usbe (5, "FINISHED"); return; }
/** * 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; }