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

📄 usbd-monitor.c

📁 linux嵌入式课程实践中的一个关于声卡驱动程序 。
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * linux/drivers/usbd/usbd-monitor.c - USB Device Cable Monitor * * Copyright (c) 2000, 2001, 2002 Lineo * Copyright (c) 2001 Hewlett Packard * * By:  *      Stuart Lynne <sl@lineo.com>,  *      Tom Rushworth <tbr@lineo.com>,  *      Bruce Balden <balden@lineo.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */#include <linux/config.h>#include <linux/module.h>#include "usbd-export.h"#include "usbd-build.h"#include "usbd-module.h"MODULE_AUTHOR("sl@lineo.com, tbr@lineo.com");MODULE_DESCRIPTION("USB Device Monitor");USBD_MODULE_INFO("usbd_monitor 0.3");EXPORT_NO_SYMBOLS;#include <linux/init.h>#include <linux/kernel.h>#include <linux/list.h>#include <asm/uaccess.h>#include <linux/netdevice.h>#include <linux/skbuff.h>#include <linux/etherdevice.h>#include <net/arp.h>#include <linux/rtnetlink.h>#include <linux/smp_lock.h>#include <linux/ctype.h>#include <linux/timer.h>#include <linux/string.h>#include <linux/pkt_sched.h>#include <asm/io.h>#include <linux/proc_fs.h>#include <linux/kmod.h>/* * Architecture specific includes */#ifdef CONFIG_ARCH_SA1100#include <asm/irq.h>#include <asm/hardware.h>#include "usbd.h"#include "usbd-func.h"#include "usbd-bus.h"#include "hotplug.h"#include "sa1100_bi/sa1100.h"#endif#if defined(CONFIG_PM)#include <linux/pm.h>#endif/* Module Parameters ************************************************************************* */typedef enum monitor_status {    MONITOR_UNKNOWN,    MONITOR_LOADING,            // loading due to cable connection interrupt    MONITOR_LOADED,             // loaded     MONITOR_UNLOADING,          // unloading due to cable disconnection interrupt    MONITOR_UNLOADED,           // unloaded#ifdef CONFIG_PM    MONITOR_SUSPENDING,         // suspending due to power management event    MONITOR_SUSPENDED,          // suspended due to power management event    MONITOR_RESTORING,          // restoring #endif} monitor_status_t;/* struct monitor_bi_data - * * private data structure for this bus interface driver */struct monitor_data {    monitor_status_t            status;    struct tq_struct            monitor_bh;    struct tq_struct            hotplug_bh;    int                         have_irq;#ifdef CONFIG_PM    struct pm_dev              *pm_info;#endif};struct monitor_data monitor;void monitor_int_hndlr(int irq, void *dev_id, struct pt_regs *regs);/** * monitor_request_irq */int monitor_request_irq(void){#if defined(CONFIG_SA1100_USBCABLE_GPIO)    int rc;    printk(KERN_DEBUG"monitor_request_irq: %d %d\n",             CONFIG_SA1100_USBCABLE_GPIO, SA1100_GPIO_TO_IRQ(CONFIG_SA1100_USBCABLE_GPIO));    if ((rc = request_irq(SA1100_GPIO_TO_IRQ(CONFIG_SA1100_USBCABLE_GPIO),                     monitor_int_hndlr, SA_SHIRQ, "USBD Monitor", &monitor)))     {        printk(KERN_DEBUG"monitor_request_irq: failed: %d\n", rc);        return -EINVAL;    }    GPDR &= ~GPIO_GPIO(CONFIG_SA1100_USBCABLE_GPIO);    set_GPIO_IRQ_edge(GPIO_GPIO(CONFIG_SA1100_USBCABLE_GPIO), GPIO_BOTH_EDGES);#endif    return 0;}/** * monitor_free_irq */void monitor_free_irq(void){#if defined(CONFIG_SA1100_USBCABLE_GPIO)    free_irq(SA1100_GPIO_TO_IRQ(CONFIG_SA1100_USBCABLE_GPIO), NULL); #endif}/** * monitor_connected - connected to cable * * Return non-zero if via USB cable to USB Hub or Host */int monitor_connected(void) {    int rc = 1;    /*     * Architecture specific - determine connect status     */    /*     * SA-1100     *     * Only pay attention to the status if we also can control the pullup.     */#if defined(CONFIG_SA1100_USBCABLE_GPIO) && defined(CONFIG_SA1100_CONNECT_GPIO)#ifdef CONFIG_SA1100_CONNECT_ACTIVE_HIGH    rc = (GPLR & GPIO_GPIO(23)) != 0;    printk(KERN_DEBUG"udc_connected: ACTIVE_HIGH: %d", rc);#else    rc = (GPLR & GPIO_GPIO(23)) == 0;    printk(KERN_DEBUG"udc_connected: ACTIVE_LOW: %d", rc);#endif#endif /* CONFIG_ARCH_SA1100 && CONFIG_SA1100_USBCABLE_GPIO */    printk(KERN_DEBUG"monitor_connected: %d\n", rc);    return rc;}static char *hotplug_actions[] = {    "load",    "suspend",    "restore-loaded",    "restore-unloaded",    "unload"};/* indices for the hotplug_actions array, these must match the array */#define MHA_LOAD               0#define MHA_SUSPEND            1#define MHA_RESTORE_LOADED     2#define MHA_RESTORE_UNLOADED   3#define MHA_UNLOAD             4#if defined(CONFIG_USBD_PROCFS) && defined(CONFIG_PM)#define HOTPLUG_SYNC_TIMEOUT  (10*HZ)static DECLARE_MUTEX_LOCKED(hotplug_done);static struct timer_list hotplug_timeout;static void hotplug_sync_over(unsigned long data){    printk(KERN_ERR "usbdmonitor: warning - hotplug script timed out\n");    up(&hotplug_done);}#endifstatic int monitor_exiting = 0;int monitor_hotplug(int action_ndx){    /* This should probably be serialized - if PM runs in a separate       context, it would seem possible for someone to "rmmmod usbdmonitor"       (e.g. via "at") at the same time time PM decides to suspend.       Unfortunately, there is no airtight way to accomplish that inside       this module - once PM has called the registered fn, the "race"       is on :(. */    int rc;    if (action_ndx < 0 || action_ndx > MHA_UNLOAD) {        return(-EINVAL);    }    if (monitor_exiting) {        if (MHA_UNLOAD != action_ndx) {            return(-EINVAL);	}	if (MONITOR_UNLOADED == monitor.status ||            MONITOR_UNLOADING == monitor.status) {            /* No need to do it again... */            return(0);        }    }    printk(KERN_DEBUG "monitor_hotplug: agent: usbd interface: monitor action: %s\n", hotplug_actions[action_ndx]);#if defined(CONFIG_USBD_PROCFS) && defined(CONFIG_PM)    /* Sync - fire up the script and wait for it to echo something to              /proc/usb-monitor (or else PM SUSPEND may not work) */    init_MUTEX_LOCKED(&hotplug_done);    /* fire up the script */    rc = hotplug("usbd", "monitor", hotplug_actions[action_ndx]);    if (0 == rc) {        /* wait for the nudge from a write to /proc/usb-monitor */        init_timer(&hotplug_timeout);        hotplug_timeout.data = 0;        hotplug_timeout.function = hotplug_sync_over;        hotplug_timeout.expires = jiffies + HOTPLUG_SYNC_TIMEOUT;        add_timer(&hotplug_timeout);        down_interruptible(&hotplug_done);        del_timer(&hotplug_timeout);    }#else    /* Async - fire up the script and return */    rc = hotplug("usbd", "monitor", hotplug_actions[action_ndx]);#endif    return(rc);}#ifdef CONFIG_PM/** * monitor_suspend * * Check status, unload if required, set monitor status. */int monitor_suspend(void){    unsigned long flags;    local_irq_save(flags);    switch(monitor.status) {    case MONITOR_UNKNOWN:    case MONITOR_UNLOADED:        local_irq_restore(flags);        return 0;    case MONITOR_LOADING:    case MONITOR_UNLOADING:    case MONITOR_SUSPENDING:    case MONITOR_RESTORING:    case MONITOR_SUSPENDED:        // XXX we should wait for this        local_irq_restore(flags);        return -EINVAL;     case MONITOR_LOADED:        monitor.status = MONITOR_SUSPENDING;        local_irq_restore(flags);        monitor_hotplug(MHA_SUSPEND);        monitor.status = MONITOR_SUSPENDED;        return 0;    default:        return -EINVAL;    }}/** * hotplug_bh -  * @ignored: * * Check connected status and load/unload as appropriate. */void hotplug_bh(void *ignored){    printk(KERN_DEBUG "hotplug_bh:\n");    if (monitor_connected()) {        printk(KERN_DEBUG"monitor_restore: RESTORE_LOADED\n");        monitor_hotplug(MHA_RESTORE_LOADED);        monitor.status = MONITOR_LOADED;    }    else {        printk(KERN_DEBUG"monitor_restore: RESTORE_UNLOADED\n");        monitor_hotplug(MHA_RESTORE_UNLOADED);        monitor.status = MONITOR_UNLOADED;    }    MOD_DEC_USE_COUNT;}/** * hotplug_schedule_bh - */void hotplug_schedule_bh(void) {    printk(KERN_DEBUG "hotplug_schedule_bh: schedule bh\n");    if (monitor.hotplug_bh.sync) {        return;    }    MOD_INC_USE_COUNT;    if (!schedule_task(&monitor.hotplug_bh)) {        printk(KERN_DEBUG "monitor_schedule_bh: failed\n");        MOD_DEC_USE_COUNT;    }}/** * monitor_restore * * Check status, load if required, set monitor status. */int monitor_restore(void){    unsigned long flags;    local_irq_save(flags);    switch(monitor.status) {    case MONITOR_SUSPENDED:        monitor.status = MONITOR_RESTORING;        local_irq_restore(flags);        hotplug_schedule_bh();        return 0;    case MONITOR_UNKNOWN:    case MONITOR_UNLOADED:    case MONITOR_LOADING:    case MONITOR_UNLOADING:    case MONITOR_SUSPENDING:    case MONITOR_RESTORING:        // XXX we should wait for this        local_irq_restore(flags);        return -EINVAL;     case MONITOR_LOADED:        local_irq_restore(flags);        return 0;    default:        return -EINVAL;    }}/** * monitor_pm_event * * Handle power management event */static int monitor_pm_event(struct pm_dev *dev, pm_request_t rqst, void *unused){    int rc;    /* See comment regarding race condition at start of monitor_hotplug() */    MOD_INC_USE_COUNT;    rc = 0;    switch (rqst) {    case PM_SUSPEND:        // Force unloading        rc = monitor_suspend();        printk(KERN_ERR "%s: suspend finished (rc=%d)\n",__FUNCTION__,rc);        break;    case PM_RESUME:        // load if required.        monitor_restore();    }    MOD_DEC_USE_COUNT;

⌨️ 快捷键说明

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