📄 usbdrv.c
字号:
/*************************************************************************** usbdrv.cpp - description ------------------- begin : 五 9月 9 2005 copyright : (C) 2005 by root email : root@localhost.localdomain ***************************************************************************//*************************************************************************** * * * 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. * * * ***************************************************************************/#define __KERNEL__#define MODULE#include <linux/module.h>#include <linux/kernel.h>#include <linux/errno.h>#include <asm/uaccess.h>#include <linux/init.h>#include <linux/slab.h>#include <linux/delay.h>#include <linux/ioctl.h>#include <linux/fs.h>#include <linux/sched.h>#include <linux/smp_lock.h>#include <linux/devfs_fs_kernel.h>#include <linux/config.h>#include <linux/mm.h>#include <linux/slab.h>//#include <linux/devfs_fs_kernel.h>#include <linux/version.h>#include <linux/usb.h>//#define DEBUG//#ifdef DEBUG #define db printk //#define warn printk // #define err printk//#else //#define db dbg//#endif#define USB_SN_VENDOR_ID 0x7890#define USB_SN_PRODUCT_ID 0x0002/* Get a minor range for your devices from the usb maintainer */#define SCN_BASE_MNR 128/* we can have up to this number of device plugged in at once */#define MAX_DEVICES 16#define IBUF_SIZE 16384*2//32768#define OBUF_SIZE 4096#define CMD_READ_STATE 6#define CMD_READ_DATA 8#define IS_EP_BULK(ep) ((ep).bmAttributes == USB_ENDPOINT_XFER_BULK ? 1 : 0)#define IS_EP_BULK_IN(ep) (IS_EP_BULK(ep) && ((ep).bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)#define IS_EP_BULK_OUT(ep) (IS_EP_BULK(ep) && ((ep).bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT)#define IS_EP_INTR(ep) ((ep).bmAttributes == USB_ENDPOINT_XFER_INT ? 1 : 0)#define USB_SN_MINOR(X) MINOR((X)->i_rdev) - SCN_BASE_MNR#define SNUSB_IOCTL_READ_STATUS _IOWR('U', 0x26, void*)#define SNUSB_IOCTL_USER_CODE _IOWR('U', 0x27, void*)#define ENDPOINT_IN 0x2#define ENDPOINT_OUT 0x0#define ENDPOINT_INIR 0x1//#define COMPANY "SinoData"//#define DESCRIPTION "SinoData Usb Linux Driver by HP"MODULE_AUTHOR("SinoData");MODULE_DESCRIPTION("SinoData Usb Linux Driver by HP");MODULE_LICENSE("GPL");int ibuf_size=IBUF_SIZE;struct scn_usb_data { struct usb_device *scn_dev; devfs_handle_t devfs; /* devfs device */ struct usb_interface* interface; struct urb* write_urb; unsigned int ifnum; /* Interface number of the USB device */ kdev_t scn_minor; /* sn minor - used in disconnect() */ unsigned char button; /* Front panel buffer */ char isopen; /* Not zero if the device is open */ char present; /* Not zero if device is present */ char *bulk_out_buffer; char *bulk_in_buffer; /* transfer buffers */ char bulk_in_ep; char bulk_out_ep; char intr_ep; /* Endpoint assignments */ int bulk_in_size; int bulk_out_size; int open_count; wait_queue_head_t rd_wait_q; /* read timeouts */ struct semaphore sem; /* lock to prevent concurrent reads or writes */ unsigned int rd_nak_timeout; /* Seconds to wait before read() timeout. */};/* the global usb devfs handle */extern devfs_handle_t usb_devfs_handle;static struct scn_usb_data *minor_table[MAX_DEVICES];/* lock to protect the minor_table structure */static DECLARE_MUTEX (minor_table_mutex);static struct usb_device_id sn_table [] ={ //{USB_DEVICE(0x7890,0x0002)}, {USB_DEVICE(USB_SN_VENDOR_ID, USB_SN_PRODUCT_ID)}, {}};MODULE_DEVICE_TABLE (usb, sn_table);////////////////////////-----------------------------------------------------------------static void usb_show_endpoint(struct usb_endpoint_descriptor *endpoint)/* [<][>][^][v][top][bottom][index][help] */{ usb_show_endpoint_descriptor(endpoint);}static void usb_show_interface(struct usb_interface_descriptor *altsetting)/* [<][>][^][v][top][bottom][index][help] */{ int i; usb_show_interface_descriptor(altsetting); for (i = 0; i < altsetting->bNumEndpoints; i++) usb_show_endpoint(altsetting->endpoint + i);}static void usb_show_config(struct usb_config_descriptor *config)/* [<][>][^][v][top][bottom][index][help] */{ int i, j; struct usb_interface *ifp; usb_show_config_descriptor(config); for (i = 0; i < config->bNumInterfaces; i++) { ifp = config->interface + i; if (!ifp) break; printk("\n Interface: %d\n", i); for (j = 0; j < ifp->num_altsetting; j++) usb_show_interface(ifp->altsetting + j); }}void usb_show_device(struct usb_device *dev)/* [<][>][^][v][top][bottom][index][help] */{ int i; usb_show_device_descriptor(&dev->descriptor); for (i = 0; i < dev->descriptor.bNumConfigurations; i++) usb_show_config(dev->config + i);}/* * Parse and show the different USB descriptors. */void usb_show_device_descriptor(struct usb_device_descriptor *desc)/* [<][>][^][v][top][bottom][index][help] */{ if (!desc) { db("Invalid USB device descriptor (NULL POINTER)\n"); return; } db(" Length = %2d%s\n", desc->bLength, desc->bLength == USB_DT_DEVICE_SIZE ? "" : " (!!!)"); db(" DescriptorType = %02x\n", desc->bDescriptorType); db(" USB version = %x.%02x\n", desc->bcdUSB >> 8, desc->bcdUSB & 0xff); db(" Vendor:Product = %04x:%04x\n", desc->idVendor, desc->idProduct); db(" MaxPacketSize0 = %d\n", desc->bMaxPacketSize0); db(" NumConfigurations = %d\n", desc->bNumConfigurations); db(" Device version = %x.%02x\n", desc->bcdDevice >> 8, desc->bcdDevice & 0xff); db(" Device Class:SubClass:Protocol = %02x:%02x:%02x\n", desc->bDeviceClass, desc->bDeviceSubClass, desc->bDeviceProtocol); switch (desc->bDeviceClass) { case 0: db(" Per-interface classes\n"); break; case USB_CLASS_AUDIO: db(" Audio device class\n"); break; case USB_CLASS_COMM: db(" Communications class\n"); break; case USB_CLASS_HID: db(" Human Interface Devices class\n"); break; case USB_CLASS_PRINTER: db(" Printer device class\n"); break; case USB_CLASS_MASS_STORAGE: db(" Mass Storage device class\n"); break; case USB_CLASS_HUB: db(" Hub device class\n"); break; case USB_CLASS_VENDOR_SPEC: db(" Vendor class\n"); break; default: db(" Unknown class\n"); }}void usb_show_config_descriptor(struct usb_config_descriptor *desc)/* [<][>][^][v][top][bottom][index][help] */{ db("Configuration:\n"); db(" bLength = %4d%s\n", desc->bLength, desc->bLength == USB_DT_CONFIG_SIZE ? "" : " (!!!)"); db(" bDescriptorType = %02x\n", desc->bDescriptorType); db(" wTotalLength = %04x\n", desc->wTotalLength); db(" bNumInterfaces = %02x\n", desc->bNumInterfaces); db(" bConfigurationValue = %02x\n", desc->bConfigurationValue); db(" iConfiguration = %02x\n", desc->iConfiguration); db(" bmAttributes = %02x\n", desc->bmAttributes); db(" MaxPower = %4dmA\n", desc->MaxPower * 2);}void usb_show_interface_descriptor(struct usb_interface_descriptor *desc)/* [<][>][^][v][top][bottom][index][help] */{ db(" Alternate Setting: %2d\n", desc->bAlternateSetting); db(" bLength = %4d%s\n", desc->bLength, desc->bLength == USB_DT_INTERFACE_SIZE ? "" : " (!!!)"); db(" bDescriptorType = %02x\n", desc->bDescriptorType); db(" bInterfaceNumber = %02x\n", desc->bInterfaceNumber); db(" bAlternateSetting = %02x\n", desc->bAlternateSetting); db(" bNumEndpoints = %02x\n", desc->bNumEndpoints); db(" bInterface Class:SubClass:Protocol = %02x:%02x:%02x\n", desc->bInterfaceClass, desc->bInterfaceSubClass, desc->bInterfaceProtocol); db(" iInterface = %02x\n", desc->iInterface);}void usb_show_endpoint_descriptor(struct usb_endpoint_descriptor *desc)/* [<][>][^][v][top][bottom][index][help] */{ char *LengthCommentString = (desc->bLength == USB_DT_ENDPOINT_AUDIO_SIZE) ? " (Audio)" : (desc->bLength == USB_DT_ENDPOINT_SIZE) ? "" : " (!!!)"; char *EndpointType[4] = { "Control", "Isochronous", "Bulk", "Interrupt" }; db(" Endpoint:\n"); db(" bLength = %4d%s\n", desc->bLength, LengthCommentString); db(" bDescriptorType = %02x\n", desc->bDescriptorType); db(" bEndpointAddress = %02x (%s)\n", desc->bEndpointAddress, (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_CONTROL ? "i/o" : (desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK) ? "in" : "out"); db(" bmAttributes = %02x (%s)\n", desc->bmAttributes, EndpointType[USB_ENDPOINT_XFERTYPE_MASK & desc->bmAttributes]); db(" wMaxPacketSize = %04x\n", desc->wMaxPacketSize); db(" bInterval = %02x\n", desc->bInterval); /* Audio extensions to the endpoint descriptor */ if (desc->bLength == USB_DT_ENDPOINT_AUDIO_SIZE) { db(" bRefresh = %02x\n", desc->bRefresh); db(" bSynchAddress = %02x\n", desc->bSynchAddress); }}void usb_show_string(struct usb_device *dev, char *id, int index)/* [<][>][^][v][top][bottom][index][help] */{ char *buf; if (!index) return; if (!(buf = kmalloc(256, GFP_KERNEL))) return; if (usb_string(dev, index, buf, 256) > 0) printk(KERN_INFO "%s: %s\n", id, buf); kfree(buf);}/*void usb_dump_urb (purb_t purb){ printk ("urb :%p\n", purb); printk ("next :%p\n", purb->next); printk ("dev :%p\n", purb->dev); printk ("pipe :%08X\n", purb->pipe); printk ("status :%d\n", purb->status); printk ("transfer_flags :%08X\n", purb->transfer_flags); printk ("transfer_buffer :%p\n", purb->transfer_buffer); printk ("transfer_buffer_length:%d\n", purb->transfer_buffer_length); printk ("actual_length :%d\n", purb->actual_length); printk ("setup_packet :%p\n", purb->setup_packet); printk ("start_frame :%d\n", purb->start_frame); printk ("number_of_packets :%d\n", purb->number_of_packets); printk ("interval :%d\n", purb->interval); printk ("error_count :%d\n", purb->error_count); printk ("context :%p\n", purb->context); printk ("complete :%p\n", purb->complete);} *///////--------------------------------------------------------static void sn_write_bulk_callback (struct urb *urb){ struct usb_skel *dev = (struct usb_skel *)urb->context; dbg(__FUNCTION__ " - minor %d", dev->minor); if ((urb->status != -ENOENT) && (urb->status != -ECONNRESET)) { dbg(__FUNCTION__ " - nonzero write bulk status received: %d", urb->status); return; } return;}static int sn_open (struct inode *inode, struct file *file){ struct scn_usb_data *dev = NULL; int subminor; int retval = 0; db("SINODATA_HP_OPEN :Begin Open Function"); dbg(__FUNCTION__); subminor = MINOR (inode->i_rdev) - SCN_BASE_MNR; if ((subminor < 0) || (subminor >= MAX_DEVICES)) { db("SINODATA_HP_OPEN :minor %d error", subminor); return -ENODEV; } db("SINODATA_HP_OPEN :minor %d ", subminor); /* Increment our usage count for the module. * This is redundant here, because "struct file_operations" * has an "owner" field. This line is included here soley as * a reference for drivers using lesser structures... ;-) */ MOD_INC_USE_COUNT; /* lock our minor table and get our local data for this minor */ down (&minor_table_mutex); dev = minor_table[subminor]; if (dev == NULL) { up (&minor_table_mutex); db("SINODATA_HP_OPEN :No device data"); MOD_DEC_USE_COUNT; return -ENODEV; } /* lock this device */ down (&dev->sem); /* unlock the minor table */ up (&minor_table_mutex); if (!dev->present) { db ("SINODATA_HP_OPEN :Device is not present!"); up (&dev->sem); MOD_DEC_USE_COUNT; return -ENODEV; } db ("SINODATA_HP_OPEN :Device is present!"); if (dev->isopen) { db("SINODATA_HP_OPEN :Device is opened before!"); up (&dev->sem); MOD_DEC_USE_COUNT; return -EBUSY; } /* increment our usage count for the driver */ ++dev->open_count; db ("SINODATA_HP_OPEN :Device open count is %d", dev->open_count); /* save our object in the file's private structure */ file->private_data = dev; usb_reset_device ((struct usb_device*)dev); /* unlock this device */ up (&dev->sem);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -