📄 vtplayer.c
字号:
dbg("%s: minor %d", __FUNCTION__, dev->minor); /* lock our device */ down (&dev->sem); if (dev->open <= 0) { dbg ("%s: device not opened", __FUNCTION__); retval = -ENODEV; goto exit_not_opened; } --dev->open; if (!dev->present) { /* the device was unplugged before the file was released */ up (&dev->sem); vtp_delete (dev); return 0; }exit_not_opened: up (&dev->sem); return retval;}/** * vtp_ioctl * * The only supported command is VTP_CMD_SET_PADS, which sets the * configuration of the tactile pads. */static int vtp_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){ struct vtplayer *dev; int retval = 0; unsigned char *buffer; dev = (struct vtplayer *)file->private_data; dbg("%s(%X, %lX)", __FUNCTION__, cmd, arg); switch(cmd) { case VTP_CMD_SET_PADS: /* Set pad configuration */ /* lock this object */ down (&dev->sem); /* verify that the device wasn't unplugged */ if (!dev->present) { retval = -ENODEV; goto exit; } /* allocate buffer */ buffer = kmalloc (VTP_DATA_LENGTH, GFP_KERNEL); /* copy the data from userspace into our transfer buffer; * this is the only copy required. */ if (copy_from_user(buffer, (unsigned char *)arg, VTP_DATA_LENGTH)) { retval = -EFAULT; goto exit; } retval = usb_control_msg( dev->udev, usb_sndctrlpipe(dev->udev, 0), /* Default control pipe */ 0x09, /* bRequest */ 0x21, /* bmRequestType */ 0x0200, /* wValue */ 0x0000, /* wIndex */ buffer, /* data */ VTP_DATA_LENGTH, /* wLength */ HZ*10); /* timeout */ /* we can deallocate "buffer" now because the call is synchronous */ kfree(buffer); if (retval != VTP_DATA_LENGTH) { err("%s - failed submitting write urb, error %d", __FUNCTION__, retval); retval = -1; } else { retval = 0; } exit: /* unlock the device */ up (&dev->sem); break; default: retval = -ENOTTY; } return retval;}/** * vtp_probe * * Called by the usb core when a new device is connected that it thinks * this driver might be interested in. */static int vtp_probe(struct usb_interface *interface, const struct usb_device_id *id){ struct usb_device *udev = interface_to_usbdev(interface); struct vtplayer *dev = NULL; struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; int i; int retval = -ENOMEM; char path[64]; char *buf; int maxp = 0; int irq_pipe = 0; int pollInterval = 0; dbg("probing: %04X:%04X", le16_to_cpu(udev->descriptor.idVendor), le16_to_cpu(udev->descriptor.idProduct)); /* See if the device offered us matches what we can accept */ if ((le16_to_cpu(udev->descriptor.idVendor) != VTP_VENDOR_ID) || (le16_to_cpu(udev->descriptor.idProduct) != VTP_PRODUCT_ID)) { return -ENODEV; } /* allocate memory for our device state and initialize it */ dev = kmalloc (sizeof(struct vtplayer), GFP_KERNEL); if (dev == NULL) { err ("Out of memory"); goto error; } memset (dev, 0x00, sizeof (*dev)); init_MUTEX (&dev->sem); dev->udev = udev; dev->interface = interface; /* set up the endpoint information */ /* check out the endpoints */ /* use the first Interrupt endpoint */ /* (normally, the VTP-1 has only one endpoint (interrupt one), */ /* at 0x81) */ iface_desc = &interface->altsetting[0]; for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { endpoint = &iface_desc->endpoint[i].desc; if ((endpoint->bEndpointAddress & USB_DIR_IN) && ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) { /* we found an interrupt in endpoint */ dev->int_in_endpointAddr = endpoint->bEndpointAddress; pollInterval = endpoint->bInterval; dbg("%s: found interrupt-in endpoint at 0x%02X (mouse function)\n", __FUNCTION__, dev->int_in_endpointAddr); irq_pipe = usb_rcvintpipe(udev, dev->int_in_endpointAddr); maxp = usb_maxpacket(udev, irq_pipe, usb_pipeout(irq_pipe)); break; } } if (!(dev->int_in_endpointAddr)) { err("Couldn't find interrupt-in endpoint.\n"); goto error; } /* allow device read, write and ioctl */ dev->present = 1; /********************** MOUSE INITIALIZATION *************************/ dev->mouse_data = usb_buffer_alloc(udev, 8, SLAB_GFP_ATOMIC, &dev->mouse_data_dma); if (!dev->mouse_data) { kfree(dev); return -ENOMEM; } dev->mouse_irq = usb_alloc_urb(0, GFP_KERNEL); if (!dev->mouse_irq) { usb_buffer_free(udev, 8, dev->mouse_data, dev->mouse_data_dma); kfree(dev); return -ENODEV; } dev->udev = udev; dev->mouse_dev = input_allocate_device(); dev->mouse_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL); dev->mouse_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); dev->mouse_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y); dev->mouse_dev->keybit[LONG(BTN_MOUSE)] |= BIT(BTN_SIDE) | BIT(BTN_EXTRA); dev->mouse_dev->private = dev; dev->mouse_dev->open = vtp_mouse_open; dev->mouse_dev->close = vtp_mouse_close; usb_make_path(udev, path, 64); sprintf(dev->mouse_phys, "%s/input0", path); dev->mouse_dev->name = dev->mouse_name; dev->mouse_dev->phys = dev->mouse_phys; dev->mouse_dev->id.bustype = BUS_USB; dev->mouse_dev->id.vendor = udev->descriptor.idVendor; dev->mouse_dev->id.product = udev->descriptor.idProduct; dev->mouse_dev->id.version = udev->descriptor.bcdDevice; if (!(buf = kmalloc(63, GFP_KERNEL))) { usb_buffer_free(udev, 8, dev->mouse_data, dev->mouse_data_dma); kfree(dev); return -ENOMEM; } if (udev->descriptor.iManufacturer && usb_string(udev, udev->descriptor.iManufacturer, buf, 63) > 0) strcat(dev->mouse_name, buf); if (udev->descriptor.iProduct && usb_string(udev, udev->descriptor.iProduct, buf, 63) > 0) sprintf(dev->mouse_name, "%s %s", dev->mouse_name, buf); if (!strlen(dev->mouse_name)) sprintf(dev->mouse_name, "USB VTPlayer Mouse %04x:%04x", dev->mouse_dev->id.vendor, dev->mouse_dev->id.product); kfree(buf); dbg("%s: maxp = %i\n", __FUNCTION__, maxp); usb_fill_int_urb(dev->mouse_irq, udev, irq_pipe, dev->mouse_data, (maxp > 8 ? 8 : maxp), vtp_mouse_irq, dev, pollInterval); dev->mouse_irq->transfer_dma = dev->mouse_data_dma; dev->mouse_irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; input_register_device(dev->mouse_dev); printk(KERN_INFO "input: %s on %s\n", dev->mouse_name, path); usb_set_intfdata(interface, dev); /*********************************************************************/ /* we can register the device now, as it is ready */ retval = usb_register_dev (interface, &vtp_class); if (retval) { /* something prevented us from registering this driver */ err ("Not able to get a minor for this device."); usb_set_intfdata (interface, NULL); goto error; } dev->minor = interface->minor; /* let the user know what node this device is now attached to */ info ("VTPlayer now attached to /dev/vtplayer%d (180,%d)", dev->minor - VTP_MINOR_BASE, dev->minor); return 0;error: vtp_delete (dev); return retval;}/** * vtp_disconnect * * Called by the usb core when the device is removed from the system. * * This routine guarantees that the driver will not submit any more urbs * by clearing dev->udev. It is also supposed to terminate any currently * active urbs. Unfortunately, usb_bulk_msg(), used in skel_read(), does * not provide any way to do this. But at least we can cancel an active * write. */static void vtp_disconnect(struct usb_interface *interface){ struct vtplayer *dev; int minor; /* prevent races with open() */ down (&disconnect_sem); dev = usb_get_intfdata (interface); usb_set_intfdata (interface, NULL); down (&dev->sem); minor = dev->minor; /* give back our minor */ usb_deregister_dev (interface, &vtp_class); /* Disconnecting the mouse part of the driver */ usb_unlink_urb(dev->mouse_irq); input_unregister_device(dev->mouse_dev); usb_free_urb(dev->mouse_irq); usb_buffer_free(interface_to_usbdev(interface), 8, dev->mouse_data, dev->mouse_data_dma); /* prevent device read, write and ioctl */ dev->present = 0; up (&dev->sem); /* if the device is opened, vtp_release will clean this up */ if (!dev->open) vtp_delete (dev); up (&disconnect_sem); info("VTPlayer vtplayer%d now disconnected", minor - VTP_MINOR_BASE);}/** * vtp_init */static int __init vtp_init(void){ int result; /* register this driver with the USB subsystem */ result = usb_register(&vtp_driver); if (result) { err("usb_register failed. Error number %d", result); return result; } info(DRIVER_DESC " " DRIVER_VERSION); return 0;}/** * vtp_exit */static void __exit vtp_exit(void){ /* deregister this driver with the USB subsystem */ usb_deregister(&vtp_driver);}module_init (vtp_init);module_exit (vtp_exit);MODULE_AUTHOR(DRIVER_AUTHOR);MODULE_DESCRIPTION(DRIVER_DESC);MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -