?? usb-mininurse.c
字號(hào):
/* * USB Mini-Nurse Driver - 0.1 * * Copyright (C) 2004 Marco (Chopin_1998@Sina.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 driver is just to drive Mini-Nurse, Just for Fun. * * Thanks to Linus, USBCORE guys, and all Open-Source World * * BUG: * - Yes,I canNOT run on a SMP machine or even Sigle-CPU with preemptive kernel. * * TODO: * - let it running on a SMP and Linux2.6 preemptive kernel * - enhence it to use more feature of PDIUSBD12 (and of course it should be supported by MN's FIRMWARE) * - add it with more kernel feature (like procfs and so on) * * History: * * 2004_05_26 - 0.1.0 - the first version * 2004_05_31 - 0.1.1 - the second version * - serval bugs fixed * - full DevFS supported */#include "usb-mininurse.h"#include "usb-mn-ioctls.h"static inline void mn_delete (struct usb_mn *dev) /* when the driver is useless, free its resource */{ info("Driver of MN will be deleted!"); minor_table[dev->minor] = NULL; kfree (dev);}static int mn_open (struct inode *inode, struct file *file){ struct usb_mn *dev = NULL; /* another way to get the Major/Minor, as tranditional method U can read it from inode */ int dmajor,dminor; devfs_get_maj_min (usb_devfs_handle, &dmajor, &dminor); dev = minor_table[dminor-1]; //U SHOULD MINUS ONE HERE !!! if (dev == NULL) { info("from mn_open(): device NULL?"); return -ENODEV; } ++(dev->open_count); file->private_data = dev; info("open Mini-Nurse device now"); return 0;}static int mn_release (struct inode *inode, struct file *file){ struct usb_mn *dev; int retval = 0; dev = (struct usb_mn *)file->private_data; if (dev == NULL) return -ENODEV; /* usb_control_msg(dev->udev,usb_sndctrlpipe(dev->udev,0), LEDoff, USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_ENDPOINT, 0,LEDA, NULL,0,.1*HZ); */ if (dev->open_count <= 0) { retval = -ENODEV; goto exit_not_opened; } if (dev->udev == NULL) { mn_delete (dev); return 0; } --dev->open_count; if (dev->open_count <= 0) dev->open_count = 0; exit_not_opened: return retval;}static int mn_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){ struct usb_mn *dev; dev = (struct usb_mn *)file->private_data; if (dev->udev == NULL) return -ENODEV; u16 LEDnum=(u16)arg; info("from mn_ioctl: cmd=%d arg=%d",cmd,LEDnum); switch (cmd) { case MN_LEDon: usb_control_msg(dev->udev,usb_sndctrlpipe(dev->udev,0), LEDon, USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_ENDPOINT, 0,LEDnum, NULL,0,.1*HZ); break; case MN_LEDoff: usb_control_msg(dev->udev,usb_sndctrlpipe(dev->udev,0), LEDoff, USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_ENDPOINT, 0,LEDnum, NULL,0,.1*HZ); break; default: /* new return number to mis-understand ioctl call */ return -ENOTTY; } return 0;}static void * mn_probe(struct usb_device *udev, unsigned int ifnum, const struct usb_device_id *id){ struct usb_mn *dev = NULL; int minor; char name[10]="MiniNurse";/* file name pleaced in /dev */ struct usb_interface *interface; if ((udev->descriptor.idVendor != USB_MN_VENDOR_ID) || (udev->descriptor.idProduct != USB_MN_PRODUCT_ID)) { return NULL; } for (minor = 0; minor < MAX_DEVICES; ++minor) { if (minor_table[minor] == NULL) break; } if (minor >= MAX_DEVICES) { info ("from mn_probe: Too many devices plugged in, can not handle this device."); mn_delete (dev); dev=NULL; } dev = kmalloc (sizeof(struct usb_mn), GFP_KERNEL); if (dev == NULL) { err ("from mn_probe: Out of memory"); mn_delete (dev); dev=NULL; } memset (dev, 0x00, sizeof (*dev)); minor_table[minor] = dev; interface = &udev->actconfig->interface[ifnum]; dev->udev = udev; dev->interface = interface; dev->devfs = devfs_register (NULL, name, DEVFS_FL_AUTO_DEVNUM, USB_MAJOR,USB_MN_MINOR_BASE + dev->minor, S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, &mn_fops, NULL); usb_devfs_handle = dev->devfs; info("%d from mn_probe-->usb_control_msg", usb_control_msg(udev,usb_sndctrlpipe(udev,0), LEDon, USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_ENDPOINT, 0,LEDA, NULL,0,.1*HZ) ); unsigned long j = jiffies + 1.25*HZ; while (jiffies < j) schedule(); info("%d from mn_probe-->usb_control_msg", usb_control_msg(udev,usb_sndctrlpipe(udev,0), LEDoff, USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_ENDPOINT, 0,LEDA, NULL,0,.1*HZ) ); return dev;}static void mn_disconnect(struct usb_device *udev, void *ptr){ struct usb_mn *dev; dev = (struct usb_mn *)ptr; devfs_unregister(dev->devfs); if (!dev->open_count) mn_delete (dev); else dev->udev = NULL; info("MN now disconnected");}static int usb_mn_init(void){ if (usb_register(&mn_driver)<0) { err("from usb_mn_init: a error on usb_register"); return -1; } info(DRIVER_DESC " " DRIVER_VERSION); return 0;}static void usb_mn_exit(void){ info("ByeBye. MN out of control now."); usb_deregister(&mn_driver);}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -