📄 usbd-monitor.c
字号:
// load if required. monitor_restore (); } MOD_DEC_USE_COUNT; return rc;}#endif /* CONFIG_PM *//** * monitor_load * * Check status, load if required, set monitor status. */int monitor_load (void){ unsigned long flags; printk (KERN_DEBUG "monitor_load: \n"); local_irq_save (flags); switch (monitor.status) { case MONITOR_UNKNOWN: case MONITOR_UNLOADED: monitor.status = MONITOR_LOADING; local_irq_restore (flags); monitor_hotplug (MHA_LOAD); monitor.status = MONITOR_LOADED; return 0; case MONITOR_LOADING: case MONITOR_UNLOADING:#ifdef CONFIG_PM case MONITOR_SUSPENDING: case MONITOR_SUSPENDED: case MONITOR_RESTORING:#endif // 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_unload * * Check status, unload if required, set monitor status. */int monitor_unload (void){ unsigned long flags; printk (KERN_DEBUG "monitor_unload: \n"); 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:#ifdef CONFIG_PM case MONITOR_SUSPENDING: case MONITOR_SUSPENDED: case MONITOR_RESTORING:#endif // XXX we should wait for this local_irq_restore (flags); return -EINVAL; case MONITOR_LOADED: monitor.status = MONITOR_UNLOADING; local_irq_restore (flags); monitor_hotplug (MHA_UNLOAD); monitor.status = MONITOR_UNLOADED; return 0; default: return -EINVAL; }}/*** monitor_event - called from monitor interrupt handler */void monitor_event (void){ if (monitor_connected ()) { monitor_load (); } else { monitor_unload (); /* If there is no way to know when the cable is reconnected, (ie no cable connect IRQ), we need to reload right away. */#if !defined(CONFIG_SA1100_CONNECT_GPIO) monitor_load ();#endif }}/** * monitor_bh - * @ignored: * * Check connected status and load/unload as appropriate. */void monitor_bh (void *ignored){ printk (KERN_DEBUG "monitor_bh:\n"); monitor_event (); MOD_DEC_USE_COUNT;}/** * monitor_schedule_bh - */void monitor_schedule_bh (void){ //printk(KERN_DEBUG "monitor_schedule_bh: schedule bh to %s\n", msg); if (monitor.monitor_bh.sync) { return; } MOD_INC_USE_COUNT; if (!schedule_task (&monitor.monitor_bh)) { printk (KERN_DEBUG "monitor_schedule_bh: failed\n"); MOD_DEC_USE_COUNT; }}/** * monitor_int_hndlr - * @irq: * @dev_id: * @regs */void monitor_int_hndlr (int irq, void *dev_id, struct pt_regs *regs){ printk (KERN_DEBUG "\n"); printk (KERN_DEBUG "monitor_int_hndlr:\n"); monitor_schedule_bh ();}#ifdef CONFIG_USBD_PROCFS/* Proc Filesystem *************************************************************************** *//* * * usbd_monitor_proc_read - implement proc file system read. * @file * @buf * @count * @pos * * Standard proc file system read function. */static ssize_t usbd_monitor_proc_read (struct file *file, char *buf, size_t count, loff_t * pos){ 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)++; if (index == 0) { len += sprintf ((char *) page + len, "usb-monitor status\n"); } if (index == 1) { switch (monitor.status) { case MONITOR_UNKNOWN: len += sprintf ((char *) page + len, "unknown\n"); break; case MONITOR_UNLOADED: len += sprintf ((char *) page + len, "unloaded\n"); break; case MONITOR_LOADING: len += sprintf ((char *) page + len, "loading\n"); break; case MONITOR_UNLOADING: len += sprintf ((char *) page + len, "unloading\n"); break;#ifdef CONFIG_PM case MONITOR_SUSPENDING: len += sprintf ((char *) page + len, "suspending\n"); break; case MONITOR_SUSPENDED: len += sprintf ((char *) page + len, "suspended\n"); break; case MONITOR_RESTORING: len += sprintf ((char *) page + len, "restoring\n"); break;#endif case MONITOR_LOADED: len += sprintf ((char *) page + len, "loaded\n"); break; default: len += sprintf ((char *) page + len, "?\n"); } } 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;}/* * * usbd_monitor_proc_write - implement proc file system write. * @file * @buf * @count * @pos * * Proc file system write function, used to signal monitor actions complete. * (Hotplug script (or whatever) writes to the file to signal the completion * of the script.) An ugly hack. */static ssize_t usbd_monitor_proc_write (struct file *file, const char *buf, size_t count, loff_t * pos){ size_t n = count; char c; MOD_INC_USE_COUNT; //printk(KERN_DEBUG "%s: count=%u\n",__FUNCTION__,count); while (n > 0) { // Not too efficient, but it shouldn't matter if (copy_from_user (&c, buf + (count - n), 1)) { count = -EFAULT; break; } n -= 1; //printk(KERN_DEBUG "%s: %u/%u %02x\n",__FUNCTION__,count-n,count,c); } up (&hotplug_done); MOD_DEC_USE_COUNT; return (count);}static struct file_operations usbd_monitor_proc_operations_functions = { read:usbd_monitor_proc_read, write:usbd_monitor_proc_write,};#endif/* Module Init ******************************************************************************* *//** * monitor_modinit - commission bus interface driver * */static int __init monitor_modinit (void){ printk (KERN_INFO "usbdm: %s\n", __usbd_module_info); // Initialize data structures _before_ installing interrupt handlers monitor.status = MONITOR_UNKNOWN; monitor.monitor_bh.routine = monitor_bh; monitor.monitor_bh.data = NULL; // XXX monitor.monitor_bh.sync = 0; monitor.hotplug_bh.routine = hotplug_bh; monitor.hotplug_bh.data = NULL; // XXX monitor.hotplug_bh.sync = 0; /* * Architecture specific - request IRQ */ if (!monitor_request_irq ()) { monitor.have_irq++; } else { printk (KERN_DEBUG "usbdm: request irq failed\n"); }#ifdef CONFIG_PM /* * Architecture specific - register with power management */ monitor.pm_info = NULL; if (!(monitor.pm_info = pm_register (PM_USB_DEV, PM_SYS_UNKNOWN, monitor_pm_event))) { printk (KERN_ERR "%s: couldn't register for power management\n", __FUNCTION__); if (monitor.have_irq) { monitor_free_irq (); } return 1; } monitor.pm_info->state = 0;#endif#ifdef CONFIG_USBD_PROCFS { struct proc_dir_entry *p; // create proc filesystem entries if ((p = create_proc_entry ("usb-monitor", 0, 0)) == NULL) { if (monitor.have_irq) { monitor_free_irq (); monitor.have_irq = 0; }#ifdef CONFIG_PM if (monitor.pm_info) { pm_unregister_all(monitor_pm_event); monitor.pm_info = NULL; }#endif return -ENOMEM; } p->proc_fops = &usbd_monitor_proc_operations_functions; }#endif // Find out if the cable is connected // and load USBD modules if we are. monitor_event (); printk (KERN_INFO "monitor_modinit: finished\n"); return 0;}/** * monitor_modexit - decommission bus interface driver * */static void __exit monitor_modexit (void){ printk (KERN_INFO "\n"); printk (KERN_INFO "monitor_modexit:\n"); /* Stop any hotplug actions except unload */ monitor_exiting = 1; /* * Architecture specific - free appropriate IRQ */ monitor_free_irq ();#ifdef CONFIG_PM if (monitor.pm_info) { pm_unregister_all(monitor_pm_event); monitor.pm_info = NULL; }#endif /* * Force unloading */ monitor_hotplug (MHA_UNLOAD);#ifdef CONFIG_USBD_PROCFS // remove proc filesystem entry *AFTER* the last hotplug, // in case it is being used for sync hotplug. remove_proc_entry ("usb-monitor", NULL);#endif return;}module_init (monitor_modinit);module_exit (monitor_modexit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -