Chinaunix首页 | 论坛 | 博客
  • 博客访问: 82227
  • 博文数量: 19
  • 博客积分: 325
  • 博客等级: 一等列兵
  • 技术积分: 197
  • 用 户 组: 普通用户
  • 注册时间: 2012-10-29 11:51
文章分类

全部博文(19)

文章存档

2013年(1)

2012年(18)

我的朋友

分类: LINUX

2012-11-20 23:10:28

在USB设备的逻辑组织中,包含设备、配置、接口和端点4个层次。


点击(此处)折叠或打开

  1. /* USB_DT_DEVICE: Device descriptor */
  2. struct usb_device_descriptor {
  3.     __u8 bLength;
  4.     __u8 bDescriptorType;

  5.     __le16 bcdUSB;
  6.     __u8 bDeviceClass;
  7.     __u8 bDeviceSubClass;
  8.     __u8 bDeviceProtocol;
  9.     __u8 bMaxPacketSize0;
  10.     __le16 idVendor;
  11.     __le16 idProduct;
  12.     __le16 bcdDevice;
  13.     __u8 iManufacturer;
  14.     __u8 iProduct;
  15.     __u8 iSerialNumber;
  16.     __u8 bNumConfigurations;
  17. } __attribute__ ((packed));

点击(此处)折叠或打开

  1. /* USB_DT_CONFIG: Configuration descriptor information.
  2.  *
  3.  * USB_DT_OTHER_SPEED_CONFIG is the same descriptor, except that the
  4.  * descriptor type is different. Highspeed-capable devices can look
  5.  * different depending on what speed they're currently running. Only
  6.  * devices with a USB_DT_DEVICE_QUALIFIER have any OTHER_SPEED_CONFIG
  7.  * descriptors.
  8.  */
  9. struct usb_config_descriptor {
  10.     __u8 bLength;
  11.     __u8 bDescriptorType;

  12.     __le16 wTotalLength;
  13.     __u8 bNumInterfaces;
  14.     __u8 bConfigurationValue;
  15.     __u8 iConfiguration;
  16.     __u8 bmAttributes;
  17.     __u8 bMaxPower;
  18. } __attribute__ ((packed));

点击(此处)折叠或打开

  1. /* USB_DT_INTERFACE: Interface descriptor */
  2. struct usb_interface_descriptor {
  3.     __u8 bLength;
  4.     __u8 bDescriptorType;

  5.     __u8 bInterfaceNumber;
  6.     __u8 bAlternateSetting;
  7.     __u8 bNumEndpoints;
  8.     __u8 bInterfaceClass;
  9.     __u8 bInterfaceSubClass;
  10.     __u8 bInterfaceProtocol;
  11.     __u8 iInterface;
  12. } __attribute__ ((packed));

点击(此处)折叠或打开

  1. /* USB_DT_ENDPOINT: Endpoint descriptor */
  2. struct usb_endpoint_descriptor {
  3.     __u8 bLength;
  4.     __u8 bDescriptorType;

  5.     __u8 bEndpointAddress;
  6.     __u8 bmAttributes;
  7.     __le16 wMaxPacketSize;
  8.     __u8 bInterval;

  9.     /* NOTE: these two are _only_ in audio endpoints. */
  10.     /* use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof. */
  11.     __u8 bRefresh;
  12.     __u8 bSynchAddress;
  13. } __attribute__ ((packed));

关于usb抓包可以看Document/usb/usbmon.txt

点击(此处)折叠或打开

  1. #include <linux/kernel.h>
  2. #include <linux/slab.h>
  3. #include <linux/input.h>
  4. #include <linux/module.h>
  5. #include <linux/init.h>
  6. #include <linux/usb.h>
  7. #include <linux/usb/input.h>
  8. #include <linux/hid.h>

  9. #define DRIVER_VERSION "v1.0"
  10. #define DRIVER_AUTHOR "hacker.do@163.com"
  11. #define DRIVER_DESC "USB Touchscreen Driver"

  12. #define CONFIG_TOUCHSCREEN_USB_IR_TOUCH

  13. #define LCD_X_SIZE 320
  14. #define LCD_Y_SIZE 480

  15. static int swap_xy;
  16. module_param(swap_xy, bool, 0644);
  17. MODULE_PARM_DESC(swap_xy, "If set X and Y axes are swapped.");

  18. static int hwcalib_xy;
  19. module_param(hwcalib_xy, bool, 0644);
  20. MODULE_PARM_DESC(hwcalib_xy, "If set hw-calibrated X/Y are used if available");

  21. /* device specifc data/functions */
  22. struct usbtouch_usb;
  23. struct usbtouch_device_info {
  24.         int min_xc, max_xc;
  25.         int min_yc, max_yc;
  26.         int min_press, max_press;
  27.         int rept_size;

  28.         /*
  29.          * Always service the USB devices irq not just when the input device is
  30.          * open. This is useful when devices have a watchdog which prevents us
  31.          * from periodically polling the device. Leave this unset unless your
  32.          * touchscreen device requires it, as it does consume more of the USB
  33.          * bandwidth.
  34.          */
  35.         bool irq_always;

  36.         void (*process_pkt) (struct usbtouch_usb *usbtouch, unsigned char *pkt, int len);

  37.         /*
  38.          * used to get the packet len. possible return values:
  39.          * > 0: packet len
  40.          * = 0: skip one byte
  41.          * < 0: -return value more bytes needed
  42.          */
  43.         int (*get_pkt_len) (unsigned char *pkt, int len);

  44.         int (*read_data) (struct usbtouch_usb *usbtouch, unsigned char *pkt);
  45.         int (*alloc) (struct usbtouch_usb *usbtouch);
  46.         int (*init) (struct usbtouch_usb *usbtouch);
  47.         void (*exit) (struct usbtouch_usb *usbtouch);
  48. };

  49. /* a usbtouch device */
  50. struct usbtouch_usb {
  51.         unsigned char *data;
  52.         dma_addr_t data_dma;
  53.         unsigned char *buffer;
  54.         int buf_len;
  55.         struct urb *irq;
  56.         struct usb_interface *interface;
  57.         struct input_dev *input;
  58.         struct usbtouch_device_info *type;
  59.         char name[128];
  60.         char phys[64];
  61.         void *priv;

  62.         int x, y;
  63.         int touch, press;
  64. };


  65. /* device types */
  66. enum {
  67.         DEVTYPE_IGNORE = -1,
  68.         DEVTYPE_EGALAX,
  69.         DEVTYPE_PANJIT,
  70.         DEVTYPE_3M,
  71.         DEVTYPE_ITM,
  72.         DEVTYPE_ETURBO,
  73.         DEVTYPE_GUNZE,
  74.         DEVTYPE_DMC_TSC10,
  75.         DEVTYPE_IRTOUCH,
  76.         DEVTYPE_IDEALTEK,
  77.         DEVTYPE_GENERAL_TOUCH,
  78.         DEVTYPE_GOTOP,
  79.         DEVTYPE_JASTEC,
  80.         DEVTYPE_E2I,
  81.         DEVTYPE_ZYTRONIC,
  82.         DEVTYPE_TC45USB,
  83.         DEVTYPE_NEXIO,
  84. };


  85. static const struct usb_device_id usbtouch_devices[] = {
  86. #ifdef CONFIG_TOUCHSCREEN_USB_IR_TOUCH
  87.         {USB_DEVICE(0x10c4, 0x8002), .driver_info = DEVTYPE_IRTOUCH},
  88. #endif
  89.         {}
  90. };

  91. /*****************************************************************************
  92.  * IRTOUCH Part
  93.  */
  94. #ifdef CONFIG_TOUCHSCREEN_USB_IR_TOUCH
  95. static int irtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
  96. {
  97.         //printk("finger num is %d, P1_x : %d, P1_y : %d\n", pkt[1], pkt[3], pkt[5]);
  98.         //printk("%4d %4d %4d %4d %4d %4d %4d %4d\n", pkt[15], pkt[14], pkt[13], pkt[12], pkt[11], pkt[10], pkt[9], pkt[8]);
  99.         return 1;
  100. }
  101. #endif

  102. static struct usbtouch_device_info usbtouch_dev_info[] = {
  103. #ifdef CONFIG_TOUCHSCREEN_USB_IR_TOUCH
  104.         [DEVTYPE_IRTOUCH] = {
  105.                 .min_xc = 0x0,
  106.                 .max_xc = 0x0fff,
  107.                 .min_yc = 0x0,
  108.                 .max_yc = 0x0fff,
  109.                 .rept_size = 32,
  110.                 .read_data = irtouch_read_data,
  111.         },
  112. #endif
  113. };


  114. /*****************************************************************************
  115.  * Generic Part
  116.  */
  117. static void usbtouch_process_pkt(struct usbtouch_usb *usbtouch,
  118.                                  unsigned char *pkt, int len)
  119. {
  120.         struct usbtouch_device_info *type = usbtouch->type;
  121.         volatile int x, y;

  122.         if (!type->read_data(usbtouch, pkt))
  123.                         return;

  124.         if (!swap_xy) {
  125.                 x = pkt[3] * LCD_X_SIZE / 26;
  126.                 y = pkt[5] * LCD_Y_SIZE / 15;
  127.         } else {
  128.                 y = pkt[3] * LCD_X_SIZE / 26;
  129.                 x = pkt[5] * LCD_Y_SIZE / 15;
  130.         }

  131.         if (pkt[1] == 1) {
  132.                 input_report_abs(usbtouch->input, ABS_MT_TOUCH_MAJOR, 1);
  133.                 input_report_abs(usbtouch->input, ABS_MT_POSITION_X, x);
  134.                 input_report_abs(usbtouch->input, ABS_MT_POSITION_Y, y);
  135.                 input_mt_sync(usbtouch->input);
  136.         } else {
  137.                 input_report_abs(usbtouch->input, ABS_MT_TOUCH_MAJOR, 0);
  138.                 input_mt_sync(usbtouch->input);
  139.         }

  140.         input_sync(usbtouch->input);
  141. }


  142. #ifdef MULTI_PACKET
  143. static void usbtouch_process_multi(struct usbtouch_usb *usbtouch,
  144.                                    unsigned char *pkt, int len)
  145. {
  146.         unsigned char *buffer;
  147.         int pkt_len, pos, buf_len, tmp;

  148.         /* process buffer */
  149.         if (unlikely(usbtouch->buf_len)) {
  150.                 /* try to get size */
  151.                 pkt_len = usbtouch->type->get_pkt_len(
  152.                                 usbtouch->buffer, usbtouch->buf_len);

  153.                 /* drop? */
  154.                 if (unlikely(!pkt_len))
  155.                         goto out_flush_buf;

  156.                 /* need to append -pkt_len bytes before able to get size */
  157.                 if (unlikely(pkt_len < 0)) {
  158.                         int append = -pkt_len;
  159.                         if (unlikely(append > len))
  160.                                append = len;
  161.                         if (usbtouch->buf_len + append >= usbtouch->type->rept_size)
  162.                                 goto out_flush_buf;
  163.                         memcpy(usbtouch->buffer + usbtouch->buf_len, pkt, append);
  164.                         usbtouch->buf_len += append;

  165.                         pkt_len = usbtouch->type->get_pkt_len(
  166.                                         usbtouch->buffer, usbtouch->buf_len);
  167.                         if (pkt_len < 0)
  168.                                 return;
  169.                 }

  170.                 /* append */
  171.                 tmp = pkt_len - usbtouch->buf_len;
  172.                 if (usbtouch->buf_len + tmp >= usbtouch->type->rept_size)
  173.                         goto out_flush_buf;
  174.                 memcpy(usbtouch->buffer + usbtouch->buf_len, pkt, tmp);
  175.                 usbtouch_process_pkt(usbtouch, usbtouch->buffer, pkt_len);

  176.                 buffer = pkt + tmp;
  177.                 buf_len = len - tmp;
  178.         } else {
  179.                 buffer = pkt;
  180.                 buf_len = len;
  181.         }

  182.         /* loop over the received packet, process */
  183.         pos = 0;
  184.         while (pos < buf_len) {
  185.                 /* get packet len */
  186.                 pkt_len = usbtouch->type->get_pkt_len(buffer + pos,
  187.                                                         buf_len - pos);

  188.                 /* unknown packet: skip one byte */
  189.                 if (unlikely(!pkt_len)) {
  190.                         pos++;
  191.                         continue;
  192.                 }

  193.                 /* full packet: process */
  194.                 if (likely((pkt_len > 0) && (pkt_len <= buf_len - pos))) {
  195.                         usbtouch_process_pkt(usbtouch, buffer + pos, pkt_len);
  196.                 } else {
  197.                         /* incomplete packet: save in buffer */
  198.                         memcpy(usbtouch->buffer, buffer + pos, buf_len - pos);
  199.                         usbtouch->buf_len = buf_len - pos;
  200.                         return;
  201.                 }
  202.                 pos += pkt_len;
  203.         }

  204. out_flush_buf:
  205.         usbtouch->buf_len = 0;
  206.         return;
  207. }
  208. #endif


  209. static void usbtouch_irq(struct urb *urb)
  210. {
  211.         struct usbtouch_usb *usbtouch = urb->context;
  212.         int retval;

  213.         switch (urb->status) {
  214.         case 0:
  215.                 /* success */
  216.                 break;
  217.         case -ETIME:
  218.                 /* this urb is timing out */
  219.                 dbg("%s - urb timed out - was the device unplugged?",
  220.                     __func__);
  221.                 return;
  222.         case -ECONNRESET:
  223.         case -ENOENT:
  224.         case -ESHUTDOWN:
  225.         case -EPIPE:
  226.                 /* this urb is terminated, clean up */
  227.                 dbg("%s - urb shutting down with status: %d",
  228.                     __func__, urb->status);
  229.                 return;
  230.         default:
  231.                 dbg("%s - nonzero urb status received: %d",
  232.                     __func__, urb->status);
  233.                 goto exit;
  234.         }

  235.         usbtouch->type->process_pkt(usbtouch, usbtouch->data, urb->actual_length);

  236. exit:
  237.         usb_mark_last_busy(interface_to_usbdev(usbtouch->interface));
  238.         retval = usb_submit_urb(urb, GFP_ATOMIC);
  239.         if (retval)
  240.                 err("%s - usb_submit_urb failed with result: %d",
  241.                     __func__, retval);
  242. }

  243. static int usbtouch_open(struct input_dev *input)
  244. {
  245.         struct usbtouch_usb *usbtouch = input_get_drvdata(input);
  246.         int r;

  247.         usbtouch->irq->dev = interface_to_usbdev(usbtouch->interface);

  248.         r = usb_autopm_get_interface(usbtouch->interface) ? -EIO : 0;
  249.         if (r < 0)
  250.                 goto out;

  251.         if (!usbtouch->type->irq_always) {
  252.                 if (usb_submit_urb(usbtouch->irq, GFP_KERNEL)) {
  253.                         r = -EIO;
  254.                         goto out_put;
  255.                 }
  256.         }

  257.         usbtouch->interface->needs_remote_wakeup = 1;
  258. out_put:
  259.         usb_autopm_put_interface(usbtouch->interface);
  260. out:
  261.         return r;
  262. }

  263. static void usbtouch_close(struct input_dev *input)
  264. {
  265.         struct usbtouch_usb *usbtouch = input_get_drvdata(input);
  266.         int r;

  267.         if (!usbtouch->type->irq_always)
  268.                 usb_kill_urb(usbtouch->irq);
  269.         r = usb_autopm_get_interface(usbtouch->interface);
  270.         usbtouch->interface->needs_remote_wakeup = 0;
  271.         if (!r)
  272.                 usb_autopm_put_interface(usbtouch->interface);
  273. }

  274. static int usbtouch_suspend
  275. (struct usb_interface *intf, pm_message_t message)
  276. {
  277.         struct usbtouch_usb *usbtouch = usb_get_intfdata(intf);

  278.         usb_kill_urb(usbtouch->irq);

  279.         return 0;
  280. }

  281. static int usbtouch_resume(struct usb_interface *intf)
  282. {
  283.         struct usbtouch_usb *usbtouch = usb_get_intfdata(intf);
  284.         struct input_dev *input = usbtouch->input;
  285.         int result = 0;

  286.         mutex_lock(&input->mutex);
  287.         if (input->users || usbtouch->type->irq_always)
  288.                 result = usb_submit_urb(usbtouch->irq, GFP_NOIO);
  289.         mutex_unlock(&input->mutex);

  290.         return result;
  291. }

  292. static int usbtouch_reset_resume(struct usb_interface *intf)
  293. {
  294.         struct usbtouch_usb *usbtouch = usb_get_intfdata(intf);
  295.         struct input_dev *input = usbtouch->input;
  296.         int err = 0;

  297.         /* reinit the device */
  298.         if (usbtouch->type->init) {
  299.                 err = usbtouch->type->init(usbtouch);
  300.                 if (err) {
  301.                         dbg("%s - type->init() failed, err: %d",
  302.                             __func__, err);
  303.                         return err;
  304.                 }
  305.         }

  306.         /* restart IO if needed */
  307.         mutex_lock(&input->mutex);
  308.         if (input->users)
  309.                 err = usb_submit_urb(usbtouch->irq, GFP_NOIO);
  310.         mutex_unlock(&input->mutex);

  311.         return err;
  312. }

  313. static void usbtouch_free_buffers(struct usb_device *udev,
  314.                                   struct usbtouch_usb *usbtouch)
  315. {
  316.         usb_free_coherent(udev, usbtouch->type->rept_size,
  317.                           usbtouch->data, usbtouch->data_dma);
  318.         kfree(usbtouch->buffer);
  319. }

  320. static struct usb_endpoint_descriptor *
  321. usbtouch_get_input_endpoint(struct usb_host_interface *interface)
  322. {
  323.         int i;

  324.         for (i = 0; i < interface->desc.bNumEndpoints; i++)
  325.                 if (usb_endpoint_dir_in(&interface->endpoint[i].desc))
  326.                         return &interface->endpoint[i].desc;

  327.         return NULL;
  328. }

  329. static int usbtouch_probe(struct usb_interface *intf,
  330.                           const struct usb_device_id *id)
  331. {
  332.         struct usbtouch_usb *usbtouch;
  333.         struct input_dev *input_dev;
  334.         struct usb_endpoint_descriptor *endpoint;
  335.         struct usb_device *udev = interface_to_usbdev(intf);
  336.         struct usbtouch_device_info *type;
  337.         int err = -ENOMEM;

  338.         /* some devices are ignored */
  339.         if (id->driver_info == DEVTYPE_IGNORE)
  340.                 return -ENODEV;

  341.         endpoint = usbtouch_get_input_endpoint(intf->cur_altsetting);
  342.         if (!endpoint)
  343.                 return -ENXIO;

  344.         usbtouch = kzalloc(sizeof(struct usbtouch_usb), GFP_KERNEL);
  345.         input_dev = input_allocate_device();
  346.         if (!usbtouch || !input_dev)
  347.                 goto out_free;

  348.         type = &usbtouch_dev_info[id->driver_info];
  349.         usbtouch->type = type;
  350.         if (!type->process_pkt)
  351.                 type->process_pkt = usbtouch_process_pkt;

  352.         usbtouch->data = usb_alloc_coherent(udev, type->rept_size,
  353.                                             GFP_KERNEL, &usbtouch->data_dma);
  354.         if (!usbtouch->data)
  355.                 goto out_free;

  356.         if (type->get_pkt_len) {
  357.                 usbtouch->buffer = kmalloc(type->rept_size, GFP_KERNEL);
  358.                 if (!usbtouch->buffer)
  359.                         goto out_free_buffers;
  360.         }

  361.         usbtouch->irq = usb_alloc_urb(0, GFP_KERNEL);
  362.         if (!usbtouch->irq) {
  363.                 dbg("%s - usb_alloc_urb failed: usbtouch->irq", __func__);
  364.                 goto out_free_buffers;
  365.         }

  366.         usbtouch->interface = intf;
  367.         usbtouch->input = input_dev;

  368.         if (udev->manufacturer)
  369.                 strlcpy(usbtouch->name, udev->manufacturer, sizeof(usbtouch->name));

  370.         if (udev->product) {
  371.                 if (udev->manufacturer)
  372.                         strlcat(usbtouch->name, " ", sizeof(usbtouch->name));
  373.                 strlcat(usbtouch->name, udev->product, sizeof(usbtouch->name));
  374.         }

  375.         if (!strlen(usbtouch->name))
  376.                 snprintf(usbtouch->name, sizeof(usbtouch->name),
  377.                         "USB Touchscreen %04x:%04x",
  378.                          le16_to_cpu(udev->descriptor.idVendor),
  379.                          le16_to_cpu(udev->descriptor.idProduct));

  380.         usb_make_path(udev, usbtouch->phys, sizeof(usbtouch->phys));
  381.         strlcat(usbtouch->phys, "/input0", sizeof(usbtouch->phys));

  382.         input_dev->name = usbtouch->name;
  383.         input_dev->phys = usbtouch->phys;
  384.         usb_to_input_id(udev, &input_dev->id);
  385.         input_dev->dev.parent = &intf->dev;

  386.         input_set_drvdata(input_dev, usbtouch);

  387.         input_dev->open = usbtouch_open;
  388.         input_dev->close = usbtouch_close;

  389.         input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
  390.         input_set_abs_params(input_dev, ABS_MT_POSITION_X, type->min_xc, type->max_xc, 0, 0);
  391.         input_set_abs_params(input_dev, ABS_MT_POSITION_Y, type->min_yc, type->max_yc, 0, 0);
  392.         input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 1, 0, 0);

  393.         if (usb_endpoint_type(endpoint) == USB_ENDPOINT_XFER_INT)
  394.                 usb_fill_int_urb(usbtouch->irq, udev,
  395.                          usb_rcvintpipe(udev, endpoint->bEndpointAddress),
  396.                          usbtouch->data, type->rept_size,
  397.                          usbtouch_irq, usbtouch, endpoint->bInterval);
  398.         else
  399.                 usb_fill_bulk_urb(usbtouch->irq, udev,
  400.                          usb_rcvbulkpipe(udev, endpoint->bEndpointAddress),
  401.                          usbtouch->data, type->rept_size,
  402.                          usbtouch_irq, usbtouch);

  403.         usbtouch->irq->dev = udev;
  404.         usbtouch->irq->transfer_dma = usbtouch->data_dma;
  405.         usbtouch->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;

  406.         /* device specific allocations */
  407.         if (type->alloc) {
  408.                 err = type->alloc(usbtouch);
  409.                 if (err) {
  410.                         dbg("%s - type->alloc() failed, err: %d", __func__, err);
  411.                         goto out_free_urb;
  412.                 }
  413.         }

  414.         /* device specific initialisation*/
  415.         if (type->init) {
  416.                 err = type->init(usbtouch);
  417.                 if (err) {
  418.                         dbg("%s - type->init() failed, err: %d", __func__, err);
  419.                         goto out_do_exit;
  420.                 }
  421.         }

  422.         err = input_register_device(usbtouch->input);
  423.         if (err) {
  424.                 dbg("%s - input_register_device failed, err: %d", __func__, err);
  425.                 goto out_do_exit;
  426.         }

  427.         usb_set_intfdata(intf, usbtouch);

  428.         if (usbtouch->type->irq_always) {
  429.                 /* this can't fail */
  430.                 usb_autopm_get_interface(intf);
  431.                 err = usb_submit_urb(usbtouch->irq, GFP_KERNEL);
  432.                 if (err) {
  433.                         usb_autopm_put_interface(intf);
  434.                         err("%s - usb_submit_urb failed with result: %d",
  435.                             __func__, err);
  436.                         goto out_unregister_input;
  437.                 }
  438.         }

  439.         return 0;

  440. out_unregister_input:
  441.         input_unregister_device(input_dev);
  442.         input_dev = NULL;
  443. out_do_exit:
  444.         if (type->exit)
  445.                 type->exit(usbtouch);
  446. out_free_urb:
  447.         usb_free_urb(usbtouch->irq);
  448. out_free_buffers:
  449.         usbtouch_free_buffers(udev, usbtouch);
  450. out_free:
  451.         input_free_device(input_dev);
  452.         kfree(usbtouch);
  453.         return err;
  454. }

  455. static void usbtouch_disconnect(struct usb_interface *intf)
  456. {
  457.         struct usbtouch_usb *usbtouch = usb_get_intfdata(intf);

  458.         dbg("%s - called", __func__);

  459.         if (!usbtouch)
  460.                 return;

  461.         dbg("%s - usbtouch is initialized, cleaning up", __func__);
  462.         usb_set_intfdata(intf, NULL);
  463.         /* this will stop IO via close */
  464.         input_unregister_device(usbtouch->input);
  465.         usb_free_urb(usbtouch->irq);
  466.         if (usbtouch->type->exit)
  467.                 usbtouch->type->exit(usbtouch);
  468.         usbtouch_free_buffers(interface_to_usbdev(intf), usbtouch);
  469.         kfree(usbtouch);
  470. }

  471. MODULE_DEVICE_TABLE(usb, usbtouch_devices);

  472. static struct usb_driver usbtouch_driver = {
  473.         .name = "usbtouchscreen",
  474.         .probe = usbtouch_probe,
  475.         .disconnect = usbtouch_disconnect,
  476.         .suspend = usbtouch_suspend,
  477.         .resume = usbtouch_resume,
  478.         .reset_resume = usbtouch_reset_resume,
  479.         .id_table = usbtouch_devices,
  480.         .supports_autosuspend = 1,
  481. };

  482. static int __init usbtouch_init(void)
  483. {
  484.         return usb_register(&usbtouch_driver);
  485. }

  486. static void __exit usbtouch_cleanup(void)
  487. {
  488.         usb_deregister(&usbtouch_driver);
  489. }

  490. module_init(usbtouch_init);
  491. module_exit(usbtouch_cleanup);

  492. MODULE_AUTHOR(DRIVER_AUTHOR);
  493. MODULE_DESCRIPTION(DRIVER_DESC);
  494. MODULE_LICENSE("GPL");

  495. MODULE_ALIAS("touchkitusb");
  496. MODULE_ALIAS("itmtouch");
  497. MODULE_ALIAS("mtouchusb");

阅读(1164) | 评论(0) | 转发(0) |
0

上一篇:MMU简介[转帖]

下一篇:Ubuntu 12.10设置ramdisk

给主人留下些什么吧!~~