📄 usbdrv.c
字号:
db("SINODATA_HP_OPEN :Device is open now!"); return retval;}static inline void sn_delete (struct scn_usb_data *dev){ minor_table[dev->scn_minor] = NULL; if (dev->bulk_in_buffer != NULL) kfree (dev->bulk_in_buffer); if (dev->bulk_out_buffer != NULL) kfree (dev->bulk_out_buffer); if (dev->write_urb != NULL) usb_free_urb (dev->write_urb); kfree (dev);}static int sn_release (struct inode *inode, struct file *file){ struct scn_usb_data *dev; kdev_t minor; minor = USB_SN_MINOR (inode); db("SINODATA-HP close: scn_minor:%d\n", minor); if (!minor_table[minor]) { db("SINODATA-HP close: (%d): invalid scn_minor\n", minor); return -ENODEV; } down(&minor_table_mutex); dev = minor_table[minor]; down(&(dev->sem)); dev->isopen = 0; file->private_data = NULL; up(&minor_table_mutex); up(&(dev->sem)); return 0;}static int sn_ioctl(struct inode *inode, struct file *file,unsigned int cmd, unsigned long arg){ struct scn_usb_data *scn; struct usb_device *dev; int retval = -ENOTTY; char status =0; struct { unsigned short value; unsigned short status; }args; struct { int buf_len; char buf[100]; }codes; db("SINODATA-HP :ioctrl ! Cmd is % \n, cmd"); scn = file->private_data; down(&(scn->sem)); dev = scn->scn_dev; switch (cmd) { case SNUSB_IOCTL_READ_STATUS: if (copy_from_user(&args, (void *)arg, sizeof(args))) { retval = -EFAULT; break; } printk ("<1>value=%d,status=%d\n",args.value, args.status); retval = usb_control_msg(dev, usb_rcvctrlpipe(dev,scn->bulk_out_ep), CMD_READ_STATE, USB_TYPE_VENDOR| USB_RECIP_DEVICE|USB_DIR_IN, 0,args.value, &args.status,sizeof(args.status), HZ*5); printk ("<1>value=%d,status=%d\n",args.value,args.status); if (copy_to_user((void*)arg, &args, sizeof(args))) retval = -EFAULT; printk ("<1>IOCTL_READ_STATUS ioctl cmd=%d\n",cmd); break; case SNUSB_IOCTL_USER_CODE: if (copy_from_user(&codes, (void *)arg, sizeof(codes))) { retval = -EFAULT; break; } retval = usb_control_msg(dev, usb_rcvctrlpipe(dev, scn->bulk_out_ep), CMD_READ_DATA, USB_TYPE_VENDOR|USB_RECIP_DEVICE|USB_DIR_IN, 0, 0, codes.buf,codes.buf_len, HZ*5); if (copy_to_user((void *)arg, &codes,sizeof(codes))) retval = -EFAULT; printk ("<1> IOCTL_USER_CODE ioctl cmd=%d\n",cmd); printk ("<1>Code is %s\n", codes.buf); break; default: printk ("<1>nvilidata IO ctrl\n"); break; } }static ssize_t sn_write(struct file * file, const char * buffer,size_t count, loff_t *ppos){ return 0;}static ssize_t sn_read(struct file * file, char * buffer,size_t count, loff_t *ppos){ return 0;}static struct file_operations sn_fops = { owner: THIS_MODULE, read: sn_read, write: sn_write, ioctl: sn_ioctl, open: sn_open, release: sn_release,};static void * sn_probe(struct usb_device *udev, unsigned int ifnum, const struct usb_device_id *id){ struct scn_usb_data *dev = NULL; struct usb_interface *interface; struct usb_interface_descriptor *iface_desc; struct usb_endpoint_descriptor *endpoint; int minor; int buffer_size; int i; char name[10]; char have_bulk_in, have_bulk_out, have_intr; int ep_count; printk ("<1>Device Probe"); if ((udev->descriptor.idVendor != USB_SN_VENDOR_ID) || (udev->descriptor.idProduct != USB_SN_PRODUCT_ID)) { return NULL; } //Check idVendor And idProduct if (udev->descriptor.bNumConfigurations != 1) { info("SINODATA-HP: Only one device configuration is supported.\n"); return NULL; } interface =&(udev->actconfig->interface[ifnum]); //iface_desc =&(interface->altsetting[0]); iface_desc = udev->config[0].interface[ifnum].altsetting; //endpoint =iface_desc->endpoint; endpoint = iface_desc[0].endpoint; usb_show_interface_descriptor(iface_desc); usb_show_device_descriptor(&udev->descriptor); usb_show_config_descriptor(udev->config); printk ("<1>SINODATA-HP : Device endpoint count is %d", iface_desc->bNumEndpoints); ep_count =have_bulk_in =have_bulk_out =have_intr =0; while (ep_count < iface_desc->bNumEndpoints) { if (!have_bulk_in && IS_EP_BULK_IN(endpoint[ep_count])) { ep_count++; have_bulk_in=0x2; printk ("<1>SINODATA-HP : probe_snusb: bulk_in_ep:%d\n", have_bulk_in); continue; } if (!have_bulk_out && IS_EP_BULK_OUT(endpoint[ep_count])) { ep_count++; have_bulk_out=0; printk ("<1>SINODATA-HP : probe_snusb: bulk_out_ep:%d\n", have_bulk_out); continue; } if (!have_intr && IS_EP_INTR(endpoint[ep_count])) { ep_count++; have_intr=1; printk ("<1>SINODATA-HP : probe_snusb: intr_ep:%d\n", have_intr); continue; } info("probe_snusb: Undetected endpoint -- consult Documentation/usb/snusb.txt.\n"); return NULL; } switch(iface_desc->bNumEndpoints) { case 1: if (!have_bulk_in) { info("SINODATA-HP : One bulk-in endpoint required.\n"); return NULL; } break; case 2: if (!have_bulk_in || !have_bulk_out) { info("SINODATA-HP : Two bulk endpoints required.\n"); return NULL; } break; case 3: if (!have_bulk_in || !have_bulk_out || !have_intr) { db("SINODATA-HP-Probe : Two bulk endpoint and one interrupt endpoint required.\n"); info("SINODATA-HP-Probe : Two bulk endpoints and one interrupt endpoint required.\n"); } break; default: info("SINODATA-HP-Probe : Endpoint determination failed -- consult Documentation/usb/snusb.txt\n"); return NULL; } down (&minor_table_mutex); for (minor = 0; minor < MAX_DEVICES; ++minor) { if (minor_table[minor] == NULL) break; } //get the minor if (minor >= MAX_DEVICES) { info ("Too many devices plugged in, can not handle this device."); goto exit; }// allocate memory for our device state and intialize it dev = kmalloc (sizeof (struct scn_usb_data), GFP_KERNEL); if (dev == NULL) { err ("Out of memory"); goto exit; } dev->write_urb = usb_alloc_urb(0); if (have_intr) { db("SINODATA-HP-Probe : (%d): Configuring IRQ handler for intr EP:%d\n", minor, have_intr); FILL_INT_URB(dev->write_urb, udev,usb_rcvintpipe(udev, have_intr), &dev->button, 1, \ sn_write_bulk_callback, dev, 250); if (usb_submit_urb(dev->write_urb)) { err("probe_snusb(%d): Unable to allocate INT URB.\n", minor); kfree(dev); up(&minor_table_mutex); return NULL; } } if (!(dev->bulk_out_buffer = (char *)kmalloc(OBUF_SIZE, GFP_KERNEL))) { db("probe_snusb(%d): Not enough memory for the output buffer.\n", minor); kfree(dev); up(&minor_table_mutex); return NULL; } db("SINODATA-HP-Probe : (%d): obuf address:%p\n", minor, dev->bulk_out_buffer); if (!(dev->bulk_in_buffer = (char *)kmalloc(ibuf_size, GFP_KERNEL))) { db("probe_snusb(%d): Not enough memory for the input buffer.\n", minor); kfree(dev->bulk_out_buffer); kfree(dev); up(&minor_table_mutex); return NULL; } db("SINODATA-HP-Probe : (%d): ibuf address:%p\n", minor, dev->bulk_in_buffer); //interface = &udev->actconfig->interface[ifnum]; init_MUTEX (&(dev->sem)); dev->scn_dev = udev; dev->interface = interface; dev->scn_minor = minor; dev->bulk_in_ep = have_bulk_in; dev->bulk_out_ep = have_bulk_out; dev->intr_ep = have_intr; dev->present = 1; dev->scn_minor = minor; dev->isopen = 0; //iface_desc = &interface->altsetting[0]; // initialize the devfs node for this device and register it sprintf(name, "snusb"); db("SINODATA-HP-Probe : Dev Name is %s , Minor is %d \n", name, dev->scn_minor); //if (register_chrdev (128, "snusb", &sn_fops) <0) //db("SINODATA-HP-Probe : Register Char Dev Failt\n", minor); dev->devfs = devfs_register (usb_devfs_handle, name, DEVFS_FL_DEFAULT, USB_MAJOR, SCN_BASE_MNR + dev->scn_minor, S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, &sn_fops, NULL); if (dev->devfs == NULL) db("SINODATA-HP-Probe : snusb%d: device node registration failed\n", minor); db("SINODATA-HP-Probe : name=%s,devfs=%d, Handle is % d\n",name,dev->devfs, usb_devfs_handle); minor_table[minor] = dev; // let the user know what node this device is now attached to db ("SINODATA-HP-Probe : USB SinoData device now attached to USBSn%d", dev->scn_minor); goto exit;error: //skel_delete (dev); dev = NULL;exit: up (&minor_table_mutex); return dev;}static void sn_disconnect(struct usb_device *udev, void *ptr);static struct usb_driver sn_driver = { name: "SnUsbDrv", probe: sn_probe, disconnect: sn_disconnect, fops: &sn_fops, minor: SCN_BASE_MNR, id_table: sn_table,};static void sn_disconnect(struct usb_device *udev, void *ptr){ struct scn_usb_data *dev; int minor; dev = (struct scn_usb_data *)ptr; db("SINODATA-HP-disconnect\n"); down (&minor_table_mutex); down (&dev->sem); if (dev->intr_ep) { db("SINODATA-HP-disconnect_snusb(%d): Unlinking IRQ URB\n", minor); usb_unlink_urb(dev->write_urb); } usb_driver_release_interface(&sn_driver, dev->interface); minor = dev->scn_minor; if (dev->bulk_in_buffer != NULL) kfree (dev->bulk_in_buffer); if (dev->bulk_out_buffer != NULL) kfree (dev->bulk_out_buffer); if (dev->write_urb != NULL) usb_free_urb (dev->write_urb); db("disconnect_snusb: De-allocating minor:%d\n", minor); up (&dev->sem); /* remove our devfs node */ devfs_unregister(dev->devfs); //unregister_chrdev(128, "snusb"); minor_table[minor] =NULL; /* if the device is not opened, then we clean up right now */ dev->scn_dev = NULL; kfree (dev); up (&minor_table_mutex);}int init_module(void){ printk ("<1>SnUsb Init module"); if (usb_register(&sn_driver) < 0) { printk ("error to registry"); return -1; } //info(DRIVER_VERSION ":" DRIVER_DESC "\n"); printk ("<1>Sinodata Usb Driver V2.0 \n"); return 0;}void cleanup_module(void){ printk ("<1>SnUsb Exit module"); usb_deregister(&sn_driver);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -