⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usbd-bus.c

📁 linux嵌入式课程实践中的一个关于声卡驱动程序 。
💻 C
📖 第 1 页 / 共 2 页
字号:
    if ((device = data) && (device->status != USBD_CLOSING)) {        int i;        // XXX this should only be done for endpoint zero...        for (i = 0; i < device->bus->driver->max_endpoints; i++) {            struct usb_endpoint_instance *endpoint = device->bus->endpoint_array + i;            // process event urbs            if (!endpoint->endpoint_address) {                struct usbd_urb *urb;                while ((urb = first_urb_detached(&endpoint->events))) {                    if (device->function_instance_array && (device->function_instance_array+0)->function_driver->ops->event) {                        (device->function_instance_array+0)->function_driver->ops->event(device, urb->event, urb->data);                    }                    usbd_dealloc_urb(urb);                }            }        }    }#if 0    // Not an error if closing in progress    else if (NULL == device) {        printk(KERN_ERR"usbd_function_bh: device NULL\n");    }#endif}/* usb-device USB BUS INTERFACE generic functions ******************************************** *//** * usbd_register_bus - called by a USB BUS INTERFACE driver to register a bus driver * @driver: pointer to bus driver structure * * Used by a USB Bus interface driver to register itself with the usb device * layer. */struct __init usb_bus_instance *usbd_register_bus(struct usb_bus_driver *driver){    struct usb_bus_instance *bus;    int i;    dbg_init(2, "-");    if ((bus = ckmalloc(sizeof(struct usb_bus_instance), GFP_ATOMIC))==NULL) {        return NULL;    }    bus->driver = driver;    if (!(bus->endpoint_array = ckmalloc(sizeof(struct usb_endpoint_instance) * bus->driver->max_endpoints, GFP_ATOMIC))) {        kfree(bus);        return NULL;    }    for (i = 0; i < bus->driver->max_endpoints; i++) {        struct usb_endpoint_instance *endpoint = bus->endpoint_array + i;        urb_link_init(&endpoint->events);        urb_link_init(&endpoint->rcv);        urb_link_init(&endpoint->rdy);        urb_link_init(&endpoint->tx);        urb_link_init(&endpoint->done);    }    return bus;}/** * usbd_deregister_bus - called by a USB BUS INTERFACE driver to deregister a bus driver * @bus: pointer to bus driver instance * * Used by a USB Bus interface driver to de-register itself with the usb device * layer. */void __exit usbd_deregister_bus(struct usb_bus_instance *bus){    dbg_init(3, "%s", bus->driver->name);    kfree(bus->endpoint_array);    kfree(bus);}/* usb-device USB Device generic functions *************************************************** *//** * usbd_register_device - called to create a virtual device * @name: name * @bus: pointer to struct usb_device_instance * @maxpacketsize: ep0 maximum packetsize * * Used by a USB Bus interface driver to create a virtual device. */struct usb_device_instance *__init usbd_register_device(char *name, struct usb_bus_instance *bus, int maxpacketsize){    struct usb_device_instance *device;    struct usb_function_instance *function_instance_array;    struct list_head *lhd;    int num = usb_devices++;    char buf[32];    int function;    dbg_init(3, "-      -       -       -       -       -       -");    // allocate a usb_device_instance structure    if (!(device = ckmalloc(sizeof(struct usb_device_instance), GFP_ATOMIC))) {        dbg_init(0, "ckmalloc device failed");        return NULL;    }    // create a name    if (!name || !strlen(name)) {        sprintf(buf, "usb%d", num);        name = buf;    }    if ((device->name = strdup(name))==NULL) {        kfree(device);        dbg_init(0, "strdup name failed");        return NULL;    }    device->device_state = STATE_CREATED;    device->status = USBD_OPENING;    // allocate a usb_function_instance for ep0 default control function driver    if ((device->ep0 = ckmalloc(sizeof(struct usb_function_instance),GFP_ATOMIC))==NULL) {        kfree(device->name);        kfree(device);        dbg_init(0, "ckmalloc device failed");        return NULL;    }    device->ep0->function_driver = &ep0_driver;    // allocate an array of usb configuration instances    if ((function_instance_array =                 ckmalloc(sizeof(struct usb_function_instance)*registered_functions, GFP_ATOMIC))==NULL)    {        kfree(device->ep0);        kfree(device->name);        kfree(device);        dbg_init(0, "ckmalloc function_instance_array failed");        return NULL;    }    device->functions = registered_functions;    device->function_instance_array = function_instance_array;    dbg_init(2, "device: %p function_instance[]: %p registered_functions: %d",             device, device->function_instance_array, registered_functions);    // connect us to bus    device->bus = bus;    // iterate across all of the function drivers to construct a complete list of configuration descriptors    // XXX there is currently only one XXX    function = 0;    dbg_init(1, "function init");    list_for_each(lhd, &function_drivers) {        struct usb_function_driver *function_driver;        function_driver = list_entry_func(lhd);        // build descriptors        dbg_init(1, "calling function_init");        usbd_function_init(bus, device, function_driver);        // save         function_instance_array[function].function_driver = function_driver;    }    // device bottom half    device->device_bh.routine = usbd_device_bh;    device->device_bh.data = device;    // XXX device->device_bh.sync = 0;    // function bottom half    device->function_bh.routine = usbd_function_bh;    device->function_bh.data = device;    // XXX device->function_bh.sync = 0;    dbg_init(3,"%p %p", device, device->device_bh.data);    // add to devices queue    list_add_tail(&device->devices, &devices);    registered_devices++;    dbg_init(3, "%s finished", bus->driver->name);    return device;}/** * usbd_deregister_device - called by a USB BUS INTERFACE driver to deregister a physical interface * @device: pointer to struct usb_device_instance * * Used by a USB Bus interface driver to destroy a virtual device. */void __exit usbd_deregister_device(struct usb_device_instance *device){    struct usb_function_instance *function_instance;    dbg_init(3, "%s start", device->bus->driver->name);    // prevent any more bottom half scheduling    device->status = USBD_CLOSING;#ifdef USBD_CONFIG_NOWAIT_DEREGISTER_DEVICE    if (device->device_bh.sync) {	// The only way deal with this other than waiting is to do the task.	run_task_queue(&tq_immediate);        if (device->device_bh.sync) {            printk(KERN_ERR "%s: run_task_queue(&tq_immediate) fails to clear device_bh!\n",__FUNCTION__);        }    }    if (device->function_bh.sync) {	// The only way deal with this other than waiting is to do the task.        flush_scheduled_tasks();        if (device->function_bh.sync) {            printk(KERN_ERR "%s: flush_scheduled_tasks() fails to clear function_bh!\n",__FUNCTION__);        }    }    /* Leave the wait in as paranoia - in case one of the task operations       above fails to clear the queued task.  It should never happen, but ... */#endif    // wait for pending device and function bottom halfs to finish    while (device->device_bh.sync || device->function_bh.sync) {        dbg_init(1, "wainting for usbd_device_bh");        schedule_timeout(10*HZ);    }    // tell the function driver to close    usbd_function_close(device);    // disconnect from bus    device->bus = NULL;        // remove from devices queue    list_del(&device->devices);    // free function_instances    if ((function_instance = device->function_instance_array)) {        device->function_instance_array = NULL;        dbg_init(3, "freeing function instances: %p", function_instance);        kfree(function_instance);    }    // de-configured ep0    if ((function_instance = device->ep0)) {        device->ep0 = NULL;        dbg_init(3, "freeing ep0 instance: %p", function_instance);        kfree(function_instance);    }    kfree(device->name);    kfree(device);    registered_devices--;    dbg_init(3, "finished");}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -