usbtouchscreen.c
来自「linux 内核源代码」· C语言 代码 · 共 1,005 行 · 第 1/2 页
C
1,005 行
*/#ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCHstatic int general_touch_read_data(struct usbtouch_usb *dev, unsigned char *pkt){ dev->x = ((pkt[2] & 0x0F) << 8) | pkt[1] ; dev->y = ((pkt[4] & 0x0F) << 8) | pkt[3] ; dev->press = pkt[5] & 0xff; dev->touch = pkt[0] & 0x01; return 1;}#endif/***************************************************************************** * GoTop Part */#ifdef CONFIG_TOUCHSCREEN_USB_GOTOPstatic int gotop_read_data(struct usbtouch_usb *dev, unsigned char *pkt){ dev->x = ((pkt[1] & 0x38) << 4) | pkt[2]; dev->y = ((pkt[1] & 0x07) << 7) | pkt[3]; dev->touch = pkt[0] & 0x01; return 1;}#endif/***************************************************************************** * the different device descriptors */#ifdef MULTI_PACKETstatic void usbtouch_process_multi(struct usbtouch_usb *usbtouch, unsigned char *pkt, int len);#endifstatic struct usbtouch_device_info usbtouch_dev_info[] = {#ifdef CONFIG_TOUCHSCREEN_USB_EGALAX [DEVTYPE_EGALAX] = { .min_xc = 0x0, .max_xc = 0x07ff, .min_yc = 0x0, .max_yc = 0x07ff, .rept_size = 16, .process_pkt = usbtouch_process_multi, .get_pkt_len = egalax_get_pkt_len, .read_data = egalax_read_data, },#endif#ifdef CONFIG_TOUCHSCREEN_USB_PANJIT [DEVTYPE_PANJIT] = { .min_xc = 0x0, .max_xc = 0x0fff, .min_yc = 0x0, .max_yc = 0x0fff, .rept_size = 8, .read_data = panjit_read_data, },#endif#ifdef CONFIG_TOUCHSCREEN_USB_3M [DEVTYPE_3M] = { .min_xc = 0x0, .max_xc = 0x4000, .min_yc = 0x0, .max_yc = 0x4000, .rept_size = 11, .read_data = mtouch_read_data, .init = mtouch_init, },#endif#ifdef CONFIG_TOUCHSCREEN_USB_ITM [DEVTYPE_ITM] = { .min_xc = 0x0, .max_xc = 0x0fff, .min_yc = 0x0, .max_yc = 0x0fff, .max_press = 0xff, .rept_size = 8, .read_data = itm_read_data, },#endif#ifdef CONFIG_TOUCHSCREEN_USB_ETURBO [DEVTYPE_ETURBO] = { .min_xc = 0x0, .max_xc = 0x07ff, .min_yc = 0x0, .max_yc = 0x07ff, .rept_size = 8, .process_pkt = usbtouch_process_multi, .get_pkt_len = eturbo_get_pkt_len, .read_data = eturbo_read_data, },#endif#ifdef CONFIG_TOUCHSCREEN_USB_GUNZE [DEVTYPE_GUNZE] = { .min_xc = 0x0, .max_xc = 0x0fff, .min_yc = 0x0, .max_yc = 0x0fff, .rept_size = 4, .read_data = gunze_read_data, },#endif#ifdef CONFIG_TOUCHSCREEN_USB_DMC_TSC10 [DEVTYPE_DMC_TSC10] = { .min_xc = 0x0, .max_xc = 0x03ff, .min_yc = 0x0, .max_yc = 0x03ff, .rept_size = 5, .init = dmc_tsc10_init, .read_data = dmc_tsc10_read_data, },#endif#ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH [DEVTYPE_IRTOUCH] = { .min_xc = 0x0, .max_xc = 0x0fff, .min_yc = 0x0, .max_yc = 0x0fff, .rept_size = 8, .read_data = irtouch_read_data, },#endif#ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK [DEVTYPE_IDEALTEK] = { .min_xc = 0x0, .max_xc = 0x0fff, .min_yc = 0x0, .max_yc = 0x0fff, .rept_size = 8, .process_pkt = usbtouch_process_multi, .get_pkt_len = idealtek_get_pkt_len, .read_data = idealtek_read_data, },#endif#ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH [DEVTYPE_GENERAL_TOUCH] = { .min_xc = 0x0, .max_xc = 0x0500, .min_yc = 0x0, .max_yc = 0x0500, .rept_size = 7, .read_data = general_touch_read_data, },#endif#ifdef CONFIG_TOUCHSCREEN_USB_GOTOP [DEVTYPE_GOTOP] = { .min_xc = 0x0, .max_xc = 0x03ff, .min_yc = 0x0, .max_yc = 0x03ff, .rept_size = 4, .read_data = gotop_read_data, },#endif};/***************************************************************************** * Generic Part */static void usbtouch_process_pkt(struct usbtouch_usb *usbtouch, unsigned char *pkt, int len){ struct usbtouch_device_info *type = usbtouch->type; if (!type->read_data(usbtouch, pkt)) return; input_report_key(usbtouch->input, BTN_TOUCH, usbtouch->touch); if (swap_xy) { input_report_abs(usbtouch->input, ABS_X, usbtouch->y); input_report_abs(usbtouch->input, ABS_Y, usbtouch->x); } else { input_report_abs(usbtouch->input, ABS_X, usbtouch->x); input_report_abs(usbtouch->input, ABS_Y, usbtouch->y); } if (type->max_press) input_report_abs(usbtouch->input, ABS_PRESSURE, usbtouch->press); input_sync(usbtouch->input);}#ifdef MULTI_PACKETstatic void usbtouch_process_multi(struct usbtouch_usb *usbtouch, unsigned char *pkt, int len){ unsigned char *buffer; int pkt_len, pos, buf_len, tmp; /* process buffer */ if (unlikely(usbtouch->buf_len)) { /* try to get size */ pkt_len = usbtouch->type->get_pkt_len( usbtouch->buffer, usbtouch->buf_len); /* drop? */ if (unlikely(!pkt_len)) goto out_flush_buf; /* need to append -pkt_len bytes before able to get size */ if (unlikely(pkt_len < 0)) { int append = -pkt_len; if (unlikely(append > len)) append = len; if (usbtouch->buf_len + append >= usbtouch->type->rept_size) goto out_flush_buf; memcpy(usbtouch->buffer + usbtouch->buf_len, pkt, append); usbtouch->buf_len += append; pkt_len = usbtouch->type->get_pkt_len( usbtouch->buffer, usbtouch->buf_len); if (pkt_len < 0) return; } /* append */ tmp = pkt_len - usbtouch->buf_len; if (usbtouch->buf_len + tmp >= usbtouch->type->rept_size) goto out_flush_buf; memcpy(usbtouch->buffer + usbtouch->buf_len, pkt, tmp); usbtouch_process_pkt(usbtouch, usbtouch->buffer, pkt_len); buffer = pkt + tmp; buf_len = len - tmp; } else { buffer = pkt; buf_len = len; } /* loop over the received packet, process */ pos = 0; while (pos < buf_len) { /* get packet len */ pkt_len = usbtouch->type->get_pkt_len(buffer + pos, buf_len - pos); /* unknown packet: skip one byte */ if (unlikely(!pkt_len)) { pos++; continue; } /* full packet: process */ if (likely((pkt_len > 0) && (pkt_len <= buf_len - pos))) { usbtouch_process_pkt(usbtouch, buffer + pos, pkt_len); } else { /* incomplete packet: save in buffer */ memcpy(usbtouch->buffer, buffer + pos, buf_len - pos); usbtouch->buf_len = buf_len - pos; return; } pos += pkt_len; }out_flush_buf: usbtouch->buf_len = 0; return;}#endifstatic void usbtouch_irq(struct urb *urb){ struct usbtouch_usb *usbtouch = urb->context; int retval; switch (urb->status) { case 0: /* success */ break; case -ETIME: /* this urb is timing out */ dbg("%s - urb timed out - was the device unplugged?", __FUNCTION__); return; case -ECONNRESET: case -ENOENT: case -ESHUTDOWN: /* this urb is terminated, clean up */ dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); return; default: dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); goto exit; } usbtouch->type->process_pkt(usbtouch, usbtouch->data, urb->actual_length);exit: retval = usb_submit_urb(urb, GFP_ATOMIC); if (retval) err("%s - usb_submit_urb failed with result: %d", __FUNCTION__, retval);}static int usbtouch_open(struct input_dev *input){ struct usbtouch_usb *usbtouch = input_get_drvdata(input); usbtouch->irq->dev = usbtouch->udev; if (usb_submit_urb(usbtouch->irq, GFP_KERNEL)) return -EIO; return 0;}static void usbtouch_close(struct input_dev *input){ struct usbtouch_usb *usbtouch = input_get_drvdata(input); usb_kill_urb(usbtouch->irq);}static void usbtouch_free_buffers(struct usb_device *udev, struct usbtouch_usb *usbtouch){ usb_buffer_free(udev, usbtouch->type->rept_size, usbtouch->data, usbtouch->data_dma); kfree(usbtouch->buffer);}static int usbtouch_probe(struct usb_interface *intf, const struct usb_device_id *id){ struct usbtouch_usb *usbtouch; struct input_dev *input_dev; struct usb_host_interface *interface; struct usb_endpoint_descriptor *endpoint; struct usb_device *udev = interface_to_usbdev(intf); struct usbtouch_device_info *type; int err = -ENOMEM; interface = intf->cur_altsetting; endpoint = &interface->endpoint[0].desc; usbtouch = kzalloc(sizeof(struct usbtouch_usb), GFP_KERNEL); input_dev = input_allocate_device(); if (!usbtouch || !input_dev) goto out_free; type = &usbtouch_dev_info[id->driver_info]; usbtouch->type = type; if (!type->process_pkt) type->process_pkt = usbtouch_process_pkt; usbtouch->data = usb_buffer_alloc(udev, type->rept_size, GFP_KERNEL, &usbtouch->data_dma); if (!usbtouch->data) goto out_free; if (type->get_pkt_len) { usbtouch->buffer = kmalloc(type->rept_size, GFP_KERNEL); if (!usbtouch->buffer) goto out_free_buffers; } usbtouch->irq = usb_alloc_urb(0, GFP_KERNEL); if (!usbtouch->irq) { dbg("%s - usb_alloc_urb failed: usbtouch->irq", __FUNCTION__); goto out_free_buffers; } usbtouch->udev = udev; usbtouch->input = input_dev; if (udev->manufacturer) strlcpy(usbtouch->name, udev->manufacturer, sizeof(usbtouch->name)); if (udev->product) { if (udev->manufacturer) strlcat(usbtouch->name, " ", sizeof(usbtouch->name)); strlcat(usbtouch->name, udev->product, sizeof(usbtouch->name)); } if (!strlen(usbtouch->name)) snprintf(usbtouch->name, sizeof(usbtouch->name), "USB Touchscreen %04x:%04x", le16_to_cpu(udev->descriptor.idVendor), le16_to_cpu(udev->descriptor.idProduct)); usb_make_path(udev, usbtouch->phys, sizeof(usbtouch->phys)); strlcat(usbtouch->phys, "/input0", sizeof(usbtouch->phys)); input_dev->name = usbtouch->name; input_dev->phys = usbtouch->phys; usb_to_input_id(udev, &input_dev->id); input_dev->dev.parent = &intf->dev; input_set_drvdata(input_dev, usbtouch); input_dev->open = usbtouch_open; input_dev->close = usbtouch_close; input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); input_set_abs_params(input_dev, ABS_X, type->min_xc, type->max_xc, 0, 0); input_set_abs_params(input_dev, ABS_Y, type->min_yc, type->max_yc, 0, 0); if (type->max_press) input_set_abs_params(input_dev, ABS_PRESSURE, type->min_press, type->max_press, 0, 0); usb_fill_int_urb(usbtouch->irq, usbtouch->udev, usb_rcvintpipe(usbtouch->udev, endpoint->bEndpointAddress), usbtouch->data, type->rept_size, usbtouch_irq, usbtouch, endpoint->bInterval); usbtouch->irq->dev = usbtouch->udev; usbtouch->irq->transfer_dma = usbtouch->data_dma; usbtouch->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; /* device specific init */ if (type->init) { err = type->init(usbtouch); if (err) { dbg("%s - type->init() failed, err: %d", __FUNCTION__, err); goto out_free_buffers; } } err = input_register_device(usbtouch->input); if (err) { dbg("%s - input_register_device failed, err: %d", __FUNCTION__, err); goto out_free_buffers; } usb_set_intfdata(intf, usbtouch); return 0;out_free_buffers: usbtouch_free_buffers(udev, usbtouch);out_free: input_free_device(input_dev); kfree(usbtouch); return err;}static void usbtouch_disconnect(struct usb_interface *intf){ struct usbtouch_usb *usbtouch = usb_get_intfdata(intf); dbg("%s - called", __FUNCTION__); if (!usbtouch) return; dbg("%s - usbtouch is initialized, cleaning up", __FUNCTION__); usb_set_intfdata(intf, NULL); usb_kill_urb(usbtouch->irq); input_unregister_device(usbtouch->input); usb_free_urb(usbtouch->irq); usbtouch_free_buffers(interface_to_usbdev(intf), usbtouch); kfree(usbtouch);}MODULE_DEVICE_TABLE(usb, usbtouch_devices);static struct usb_driver usbtouch_driver = { .name = "usbtouchscreen", .probe = usbtouch_probe, .disconnect = usbtouch_disconnect, .id_table = usbtouch_devices,};static int __init usbtouch_init(void){ return usb_register(&usbtouch_driver);}static void __exit usbtouch_cleanup(void){ usb_deregister(&usbtouch_driver);}module_init(usbtouch_init);module_exit(usbtouch_cleanup);MODULE_AUTHOR(DRIVER_AUTHOR);MODULE_DESCRIPTION(DRIVER_DESC);MODULE_LICENSE("GPL");MODULE_ALIAS("touchkitusb");MODULE_ALIAS("itmtouch");MODULE_ALIAS("mtouchusb");
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?