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

📄 usbd-bi.c

📁 linux嵌入式课程实践中的一个关于声卡驱动程序 。
💻 C
📖 第 1 页 / 共 2 页
字号:
                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    This function is called for each physical bus interface that is found.  Register an interrupt handler and IO region. Return non-zero for error. */int bi_udc_init(){                                      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;    }        if (udc_init()) {        udc_release_udc_irq();        udc_release_io();        dbg_init(1,"name: %s probe failed", udc_name());        return -EINVAL;    }    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();    }}/* bi_exit - decommission bus interface driver */static void bi_exit(void){}#ifdef CONFIG_PM/* 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(device);                          // enable USB pullup if we can                        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/* 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_modexit - decommission bus interface driver */void __exit bi_modexit(void){    struct usb_bus_instance *bus;    struct usb_device_instance *device;    struct bi_data *data;    dbgENTER(dbgflg_usbdbi_init,1);    if ((device = device_array[0])) {        // XXX moved to usbd_deregister_device()        //device->status = USBD_CLOSING;        udc_disconnect();        udc_disable();        // XXX XXX        if (dbgflg_usbdbi_tick > 0) {            ticker_killoff();        }        bus = device->bus;        data = bus->privdata;        // XXX        usbd_device_event(device, DEVICE_RESET, 0);        usbd_device_event(device, DEVICE_POWER_INTERRUPTION, 0);        usbd_device_event(device, DEVICE_HUB_RESET, 0);        dbg_init(1,"DEVICE_DESTROY");        usbd_device_event(device, DEVICE_DESTROY, 0);        dbg_init(1,"DISABLE ENDPOINTS");        bi_disable_endpoints(device);        dbg_init(1,"UDC_DISABLE");        //udc_disable();        dbg_init(1,"BI_UDC_EXIT");        bi_udc_exit();        device_array[0] = NULL;        bus->privdata = NULL;#ifdef CONFIG_PM        dbg_init(1,"PM_UNREGISTER(pm_dev#%p)",pm_dev);        if (pm_dev) {            pm_unregister(pm_dev);        }#endif        dbg_init(1,"DEREGISTER DEVICE");        usbd_deregister_device(device);        bus->device = NULL;        dbg_init(1,"kfree(data#%p)",data);        if (data) {            kfree(data);        }        if (bus->serial_number_str) {            kfree(bus->serial_number_str);        }        dbg_init(1,"DEREGISTER BUS");        usbd_deregister_bus(bus);    }    else {        dbg_init(0,"device is NULL");    }    dbg_init(1,"BI_EXIT");    bi_exit();    dbgLEAVE(dbgflg_usbdbi_init,1);}/* ticker *//* Clock Tick Debug support ****************************************************************** */#define RETRYTIME 10int ticker_terminating;int ticker_timer_set;unsigned int udc_interrupts;unsigned int udc_interrupts_last;static DECLARE_MUTEX_LOCKED(ticker_sem_start);static DECLARE_MUTEX_LOCKED(ticker_sem_work);void ticker_tick(unsigned long data){    ticker_timer_set = 0;    up(&ticker_sem_work);}void udc_ticker_poke(void){    up(&ticker_sem_work);}int ticker_thread(void *data) {    struct timer_list ticker;    // detach        lock_kernel();    exit_mm(current);    exit_files(current);    exit_fs(current);    // setsid equivalent, used at start of kernel thread, no error checks needed, or at least none made :).     current->leader = 1;    current->session = current->pgrp = current->pid;    current->tty = NULL;    current->tty_old_pgrp = 0;    // Name this thread     sprintf(current->comm, "usbd-bi");    // setup signal handler    current->exit_signal = SIGCHLD;    spin_lock(&current->sigmask_lock);    flush_signals(current);    spin_unlock(&current->sigmask_lock);    // XXX Run at a high priority, ahead of sync and friends    current->nice = -20;    current->policy = SCHED_OTHER;    unlock_kernel();    // setup timer    init_timer(&ticker);    ticker.data = 0;    ticker.function = ticker_tick;    // let startup continue    up(&ticker_sem_start);    // process loop    for (ticker_timer_set = ticker_terminating = 0; !ticker_terminating;) {        char buf[100];        char *cp;        if (!ticker_timer_set) {            mod_timer(&ticker, jiffies + HZ*RETRYTIME);        }        // wait for someone to tell us to do something        down(&ticker_sem_work);        if (udc_interrupts != udc_interrupts_last) {            dbg_tick(1,"--------------");        }        // do some work        memset(buf, 0, sizeof(buf));        cp = buf;        if (dbgflg_usbdbi_tick) {            unsigned long flags;            local_irq_save(flags);            dbg_tick(1,"[%d]", udc_interrupts);            udc_regs();            local_irq_restore(flags);        }#if 0        // XXX#if defined(CONFIG_SA1110_CALYPSO) && defined(CONFIG_PM) && defined(CONFIG_USBD_TRAFFIC_KEEPAWAKE)        /* Check for rx/tx activity, and reset the sleep timer if present */        if (device->usbd_rxtx_timestamp != device->usbd_last_rxtx_timestamp) {            extern void resetSleepTimer(void);            dbg_tick(7,"resetting sleep timer");            resetSleepTimer();            device->usbd_last_rxtx_timestamp = device->usbd_rxtx_timestamp;        }#endif#endif#if 0        /* Check for TX endpoint stall.  If the endpoint has           stalled, we have probably run into the DMA/TCP window           problem, and the only thing we can do is disconnect           from the bus, then reconnect (and re-enumerate...). */        if (reconnect > 0 && 0 >= --reconnect) {            dbg_init(0,"TX stall disconnect finished");            udc_connect();  /* TODO:  needs a device pointer */        }         else if (0 != USBD_STALL_TIMEOUT_SECONDS) {            // Stall watchdog unleashed            unsigned long now,            tx_waiting;            now = jiffies;            tx_waiting = (now - tx_queue_head_timestamp(now)) / HZ;            if (tx_waiting > USBD_STALL_TIMEOUT_SECONDS) {                /* The URB at the head of the queue has waited too long */                reconnect = USBD_STALL_DISCONNECT_DURATION;                dbg_init(0,"TX stalled, disconnecting for %d seconds",                        reconnect);                udc_disconnect();            }        }#endif    }    // remove timer    del_timer(&ticker);    // let the process stopping us know we are done and return    up(&ticker_sem_start);    return 0;}/** * kickoff_thread - start management thread */void ticker_kickoff(void){    ticker_terminating = 0;    kernel_thread(&ticker_thread, NULL, 0);    down(&ticker_sem_start);}/** * killoff_thread - stop management thread */void ticker_killoff(void){    if (!ticker_terminating) {        ticker_terminating = 1;        up(&ticker_sem_work);        down(&ticker_sem_start);    }}/* module *//*module_init(bi_modinit);module_exit(bi_modexit);*/

⌨️ 快捷键说明

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