精华内容
下载资源
问答
  • usb 接口触摸屏驱动

    千次阅读 2013-11-19 19:10:38
    以前写的 USB 接口触摸屏驱动,那段时间简单的看了下 USB 协议的一些东西,主要是 HID 相关的,代码留着作为记录: /* Created by_fire 2012.2.13 */ #include #include #include #include #include #...

    以前写的 USB 接口的触摸屏驱动,那段时间简单的看了下 USB 协议的一些东西,主要是 HID 相关的,代码记录:

    /*
    	Created by_fire	2012.2.13
    */
    #include <linux/kernel.h>
    #include <linux/errno.h>
    #include <linux/init.h>
    #include <linux/slab.h>
    #include <linux/module.h>
    #include <linux/kref.h>
    #include <linux/uaccess.h>
    #include <linux/usb.h>
    #include <linux/mutex.h>
    #include <linux/input.h>
    #include <linux/usb/input.h>
    
    #define DEBUG 0
    
    #if DEBUG
    #define usb_ts_dbg(fmt, arg...) printk(fmt, ##arg)
    #else
    #define usb_ts_dbg(arg...) 
    #endif
    
    /* Define these values to match your devices */
    #define USB_SKEL_VENDOR_ID	0x0eef
    #define USB_SKEL_PRODUCT_ID	0x0001
    
    /* table of devices that work with this driver */
    static const struct usb_device_id usb_ts_table[] = {
    	{ USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) },
    	{ }					/* Terminating entry */
    };
    MODULE_DEVICE_TABLE(usb, usb_ts_table);
    
    static int swap_xy;
    module_param(swap_xy, bool, 0644);
    MODULE_PARM_DESC(swap_xy, "If set X and Y axes are swapped.");
    
    struct usb_ts;
    struct usb_ts_device_info {
    	int min_xc, max_xc;
    	int min_yc, max_yc;
    	int min_press, max_press;
    	int rept_size;
    
    	/*
    	 * Always service the USB devices irq not just when the input device is
    	 * open. This is useful when devices have a watchdog which prevents us
    	 * from periodically polling the device. Leave this unset unless your
    	 * touchscreen device requires it, as it does consume more of the USB
    	 * bandwidth.
    	 */
    	bool irq_always;
    
    	void (*process_pkt) (struct usb_ts *usbtouch, unsigned char *pkt, int len);
    
    	/*
    	 * used to get the packet len. possible return values:
    	 * > 0: packet len
    	 * = 0: skip one byte
    	 * < 0: -return value more bytes needed
    	 */
    	int  (*get_pkt_len) (unsigned char *pkt, int len);
    
    	int  (*read_data)   (struct usb_ts *usbtouch, unsigned char *pkt);
    	int  (*init)        (struct usb_ts *usbtouch);
    	void (*exit)	    (struct usb_ts *usbtouch);
    };
    
    /* a usbtouch device */
    struct usb_ts {
    	unsigned char *data;
    	dma_addr_t data_dma;
    	unsigned char *buffer;
    	int buf_len;
    	struct urb *int_urb;
    	struct usb_interface *interface;
    	struct input_dev *input;
    	struct usb_ts_device_info *dev_info;
    	char name[128];
    	char phys[64];
    	void *priv;
    
    	int x, y;
    	int touch, press;
    };
    
    static int usb_ts_read_data(struct usb_ts *dev, unsigned char *pkt)
    {
    	usb_ts_dbg("%s\n", __func__);
    
    	dev->x = ((pkt[3] & 0x0F) << 7) | (pkt[4] & 0x7F);
    	dev->y = ((pkt[1] & 0x0F) << 7) | (pkt[2] & 0x7F);
    	dev->touch = pkt[0] & 0x01;
    	dev->press = 0x01;
    
    	return 1;
    }
    
    static void usb_ts_process_pkt(struct usb_ts *usbtouch, unsigned char *pkt, int len)
    {
    	usb_ts_dbg("%s\n", __func__);
    	struct usb_ts_device_info *dev_info = usbtouch->dev_info;
    
    	int i;
    	
    	if(!(pkt[0] & 0x80)) return;
    	
    #if 0
    	for(i = 0; i < len; i++)
    		printk("pkt[%d] = %02x ", i, pkt[i]);
    
    	printk("\n");
    #endif
    
    	if (!dev_info->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);
    	}
    
    	usb_ts_dbg("x = %d, y = %d, p = %d\n", usbtouch->x, usbtouch->y, usbtouch->touch);
    	
    	if (dev_info->max_press)
    		input_report_abs(usbtouch->input, ABS_PRESSURE, usbtouch->press);
    	
    	input_sync(usbtouch->input);
    }
    
    static struct usb_ts_device_info usb_ts_dev_info[] = {
    	[0] = {
    		.min_xc		= 50,
    		.max_xc		= 1960,
    		.min_yc		= 140,
    		.max_yc		= 1900,
    		.min_press  = 0x0,
    		.max_press  = 0x1,
    		.rept_size	= 16,
    		.process_pkt	= usb_ts_process_pkt,
    		.read_data	= usb_ts_read_data,
    	},
    };
    
    static void usb_ts_irq(struct urb *urb)
    {
    	usb_ts_dbg("%s\n", __func__);
    	struct usb_ts *usbtouch = urb->context;
    	int retval;
    
    	switch (urb->status) {
    	case 0:
    		/* success */
    		break;
    	case -ETIME:
    		/* this urb is timing out */
    		usb_ts_dbg("%s - urb timed out - was the device unplugged?", __func__);
    		return;
    	case -ECONNRESET:
    	case -ENOENT:
    	case -ESHUTDOWN:
    	case -EPIPE:
    		/* this urb is terminated, clean up */
    		usb_ts_dbg("%s - urb shutting down with status: %d", __func__, urb->status);
    		return;
    	default:
    		usb_ts_dbg("%s - nonzero urb status received: %d", __func__, urb->status);
    		goto exit;
    	}
    
    	usbtouch->dev_info->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", __func__, retval);
    }
    
    static int usb_ts_open(struct input_dev *input)
    {
    	usb_ts_dbg("%s\n", __func__);
    	struct usb_ts *usbtouch = input_get_drvdata(input);
    
    	usbtouch->int_urb->dev = interface_to_usbdev(usbtouch->interface);
    
    	if (!usbtouch->dev_info->irq_always) {
    		if (usb_submit_urb(usbtouch->int_urb, GFP_KERNEL))
    		  return -EIO;
    	}
    
    	return 0;
    }
    
    static void usb_ts_close(struct input_dev *input)
    {
    	usb_ts_dbg("%s\n", __func__);
    	struct usb_ts *usbtouch = input_get_drvdata(input);
    
    	if (!usbtouch->dev_info->irq_always)
    		usb_kill_urb(usbtouch->int_urb);
    }
    
    static void usb_ts_free_buffers(struct usb_device *udev, struct usb_ts *usbtouch)
    {
    	usb_ts_dbg("%s\n", __func__);
    	usb_free_coherent(udev, usbtouch->dev_info->rept_size, usbtouch->data, usbtouch->data_dma);
    	kfree(usbtouch->buffer);
    }
    
    static struct usb_endpoint_descriptor *usb_ts_get_input_endpoint(struct usb_host_interface *interface)
    {
    	usb_ts_dbg("%s\n", __func__);
    	int i;
    
    	for (i = 0; i < interface->desc.bNumEndpoints; i++)
    		if (usb_endpoint_dir_in(&interface->endpoint[i].desc))
    			return &interface->endpoint[i].desc;
    
    	return NULL;
    }
    
    static int usb_ts_probe(struct usb_interface *intf, const struct usb_device_id *id)
    {
    	struct usb_ts *usbtouch;
    	struct input_dev *input_dev;
    	struct usb_endpoint_descriptor *endpoint;
    	struct usb_device *udev = interface_to_usbdev(intf);
    	struct usb_ts_device_info *dev_info;
    	int err = -ENOMEM;
    	
    	usb_ts_dbg("%s 1\n", __func__);
    
    	endpoint = usb_ts_get_input_endpoint(intf->cur_altsetting);
    	if (!endpoint)
    		return -ENXIO;
    
    	usbtouch = kzalloc(sizeof(struct usb_ts), GFP_KERNEL);
    	input_dev = input_allocate_device();
    	if (!usbtouch || !input_dev)
    		goto out_free;
    
    	dev_info = &usb_ts_dev_info[0];
    	usbtouch->dev_info = dev_info;
    	if (!dev_info->process_pkt)
    		dev_info->process_pkt = usb_ts_process_pkt;
    
    	usbtouch->data = usb_alloc_coherent(udev, dev_info->rept_size, GFP_KERNEL, &usbtouch->data_dma);
    	if (!usbtouch->data)
    		goto out_free;
    
    	if (dev_info->get_pkt_len) {
    		usbtouch->buffer = kmalloc(dev_info->rept_size, GFP_KERNEL);
    		if (!usbtouch->buffer)
    			goto out_free_buffers;
    	}
    
    	usbtouch->int_urb = usb_alloc_urb(0, GFP_KERNEL);
    	if (!usbtouch->int_urb) {
    		usb_ts_dbg("%s - usb_alloc_urb failed: usbtouch->irq", __func__);
    		goto out_free_buffers;
    	}
    	
    	usb_ts_dbg("%s 2\n", __func__);
    
    	usbtouch->interface = intf;
    	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 = usb_ts_open;
    	input_dev->close = usb_ts_close;
    	
    	usb_ts_dbg("%s 3\n", __func__);
    
    	input_dev->evbit[0] = BIT_MASK(EV_SYN) | 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, dev_info->min_xc, dev_info->max_xc, 0, 0);
    	input_set_abs_params(input_dev, ABS_Y, dev_info->min_yc, dev_info->max_yc, 0, 0);
    	if (dev_info->max_press)
    		input_set_abs_params(input_dev, ABS_PRESSURE, dev_info->min_press, dev_info->max_press, 0, 0);
    
    	if (usb_endpoint_type(endpoint) == USB_ENDPOINT_XFER_INT)
    		usb_fill_int_urb(usbtouch->int_urb, udev,
    			 usb_rcvintpipe(udev, endpoint->bEndpointAddress),
    			 usbtouch->data, dev_info->rept_size,
    			 usb_ts_irq, usbtouch, endpoint->bInterval);
    	else
    		usb_fill_bulk_urb(usbtouch->int_urb, udev,
    			 usb_rcvbulkpipe(udev, endpoint->bEndpointAddress),
    			 usbtouch->data, dev_info->rept_size,
    			 usb_ts_irq, usbtouch);
    
    	usbtouch->int_urb->dev = udev;
    	usbtouch->int_urb->transfer_dma = usbtouch->data_dma;
    	usbtouch->int_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
    
    	/* device specific init */
    	if (dev_info->init) {
    		err = dev_info->init(usbtouch);
    		if (err) {
    			usb_ts_dbg("%s - type->init() failed, err: %d", __func__, err);
    			goto out_free_urb;
    		}
    	}
    
    	err = input_register_device(usbtouch->input);
    	if (err) {
    		usb_ts_dbg("%s - input_register_device failed, err: %d", __func__, err);
    		goto out_do_exit;
    	}
    
    	usb_set_intfdata(intf, usbtouch);
    
    	if (usbtouch->dev_info->irq_always) {
    		err = usb_submit_urb(usbtouch->int_urb, GFP_KERNEL);
    		if (err) {
    			err("%s - usb_submit_urb failed with result: %d",
    			    __func__, err);
    			goto out_unregister_input;
    		}
    	}
    	
    	usb_ts_dbg("%s 4\n", __func__);
    
    	return 0;
    
    out_unregister_input:
    	input_unregister_device(input_dev);
    	input_dev = NULL;
    out_do_exit:
    	if (dev_info->exit)
    		dev_info->exit(usbtouch);
    out_free_urb:
    	usb_free_urb(usbtouch->int_urb);
    out_free_buffers:
    	usb_ts_free_buffers(udev, usbtouch);
    out_free:
    	input_free_device(input_dev);
    	kfree(usbtouch);
    	return err;
    }
    
    static void usb_ts_disconnect(struct usb_interface *intf)
    {
    	struct usb_ts *usbtouch = usb_get_intfdata(intf);
    
    	usb_ts_dbg("%s - called", __func__);
    
    	if (!usbtouch)
    		return;
    
    	usb_ts_dbg("%s - usbtouch is initialized, cleaning up", __func__);
    	usb_set_intfdata(intf, NULL);
    	/* this will stop IO via close */
    	input_unregister_device(usbtouch->input);
    	usb_free_urb(usbtouch->int_urb);
    	if (usbtouch->dev_info->exit)
    		usbtouch->dev_info->exit(usbtouch);
    	usb_ts_free_buffers(interface_to_usbdev(intf), usbtouch);
    	kfree(usbtouch);
    }
    
    static struct usb_driver usb_ts_driver = {
    	.name		= "usb_ts",
    	.probe		= usb_ts_probe,
    	.disconnect	= usb_ts_disconnect,
    	.id_table	= usb_ts_table,
    };
    
    static int __init usb_ts_init(void)
    {
    	int result;
    
    	/* register this driver with the USB subsystem */
    	result = usb_register(&usb_ts_driver);
    	if (result)
    		err("usb_register failed. Error number %d", result);
    
    	return result;
    }
    
    static void __exit usb_ts_exit(void)
    {
    	/* deregister this driver with the USB subsystem */
    	usb_deregister(&usb_ts_driver);
    }
    
    module_init(usb_ts_init);
    module_exit(usb_ts_exit);
    
    MODULE_AUTHOR("fire <fire@gochen.com.cn>");
    MODULE_DESCRIPTION("Gochen USB Touchscreen driver");
    MODULE_LICENSE("GPL");
    展开全文
  • ...最近需要往TV上装一个触摸屏设备,现在比较常见的就是使用usb接口触摸框,适用于各种平台,这里大体记录一下在 Android 上kernel中的usbtouchscreen驱动.  撰写不易,转载需注明出处: ...
     
    

    最近需要往TV上装一个触摸屏设备,现在比较常见的就是使用usb接口的触摸框,适用于各种平台,这里大体记录一下在Android上kernel中的usbtouchscreen驱动.

                                                  撰写不易,转载需注明出处:http://blog.csdn.net/jscese/article/details/41827495

    驱动编译:

        目前的kernel中都是自带了usbtouchscreen驱动的,我的版本3.1.10

    源码位于:/kernel/drivers/input/touchscreen/usbtouchscreen.c

    从这个路径可以看出所属驱动分支,我这边平台本身是没放开的,并没有编译进kernel,谁会想到触摸电视呢~

    可以在make menuconfig之后,通过Device Drivers——>Input device support——>Touchscreens——>USB Touchscreen Driver 然后选取需要的touchscreen类型

    通过查看相关目录下的的Kconfig Makefile,可参考:Kernel 编译配置机制



    注册usb驱动:

      熟悉Linux驱动的都知道模块入口:module_init(usbtouch_init) ,这里看下这个init:

    1. static int __init usbtouch_init(void)  
    2. {  
    3.     return usb_register(&usbtouch_driver);  //调用了usb 核心的注册函数,传入的是一个usb_driver结构体指针  
    4. }  

    usb_register实现在/kernel/include/linux/usb.h中:

    1. static inline int usb_register(struct usb_driver *driver)  
    2. {  
    3.     return usb_register_driver(driver, THIS_MODULE, KBUILD_MODNAME);//这里再往后就是usb核心驱动的事,注册这个module驱动到usb总线上  
    4. }  

    这里必须是要先注册的总线,当一个USB设备被插入的时候,USB设备驱动,也就是usb_generic_driver会跟USB设备交互,得到其所有的各种描述符,并为每个接口都定义成为一个device,之后再加载到usb_bus上,让其去匹配其对应的接口驱动程序,有兴趣可以去看下/kernel/drivers/base/bus.c中的 bus_for_each_drv函数。


    这里注册到总线的接口驱动就是 usbtouch_driver


    usbtouch_driver

     这个usb_driver类型的变量usbtouch_driver 就是整个usbtouchscreen的灵魂核心,可以在上面说到的usb.h中查看usb_driver结构原型,

    这里usbtouch_driver使用了部分接口:

    1. static struct usb_driver usbtouch_driver = {  
    2.     .name        = "usbtouchscreen"//driver name  
    3.     .probe        = usbtouch_probe,  //probe接口,用于总线上匹配检测到这个驱动对应的设备之后,/kernel/drivers/usb/core/driver.c中的usb_probe_interface调用到我们这个驱动的接口  
    4.     .disconnect    = usbtouch_disconnect,  //与probe相反,断开的时候调用  
    5.     .suspend    = usbtouch_suspend, //usb 设备挂起  
    6.     .resume        = usbtouch_resume,  // 和上面挂起相反,唤醒  
    7.     .reset_resume    = usbtouch_reset_resume,  // 重置唤醒  
    8.     .id_table    = usbtouch_devices, //支持的设备ID表  
    9.     .supports_autosuspend = 1,  
    10. };  

    id_table:

    首先可以关注一下 id_table 这个变量,代表支持的设备id列表,数据类型为:

    1. struct usb_device_id {  
    2.     /* which fields to match against? */  
    3.     __u16       match_flags;  
    4.   
    5.     /* Used for product specific matches; range is inclusive */  
    6.     __u16       idVendor;  
    7.     __u16       idProduct;  
    8.     __u16       bcdDevice_lo;  
    9.     __u16       bcdDevice_hi;  
    10.   
    11.     /* Used for device class matches */  
    12.     __u8        bDeviceClass;  
    13.     __u8        bDeviceSubClass;  
    14.     __u8        bDeviceProtocol;  
    15.   
    16.     /* Used for interface class matches */  
    17.     __u8        bInterfaceClass;  
    18.     __u8        bInterfaceSubClass;  
    19.     __u8        bInterfaceProtocol;  
    20.   
    21.     /* not matched against */  
    22.     kernel_ulong_t  driver_info;  
    23. };  

    这些设备信息会被上面说到的usb bus 来匹配对应的驱动,只有这里的信息跟usb设备驱动那边收集到的设备信息匹配上,才会调用进这个驱动.

    目前已有的id_table:

    1. static const struct usb_device_id usbtouch_devices[] = {  
    2. #ifdef CONFIG_TOUCHSCREEN_USB_EGALAX  
    3.     /* ignore the HID capable devices, handled by usbhid */  
    4.     {USB_DEVICE_HID_CLASS(0x0eef, 0x0001), .driver_info = DEVTYPE_IGNORE},  
    5.     {USB_DEVICE_HID_CLASS(0x0eef, 0x0002), .driver_info = DEVTYPE_IGNORE},  
    6.   
    7. ...  
    8.   
    9. #endif  
    10.   
    11. ...  
    12.   
    13. };  

    其中可以看到 两个字节的十六进制数字,第一个代表idVendor 厂商ID,idProduct 产品ID ,这两个一般作为设备的标识.


    driver_info:

    像上面的usbtouch_devices的数组中driver_info 设置为枚举值:

    1. /* device types */  
    2. enum {  
    3.     DEVTYPE_IGNORE = -1,  
    4.     DEVTYPE_EGALAX,  
    5.     DEVTYPE_PANJIT,  
    6.     DEVTYPE_3M,  
    7.     DEVTYPE_ITM,  
    8.     DEVTYPE_ETURBO,  
    9.     DEVTYPE_GUNZE,  
    10.     DEVTYPE_DMC_TSC10,  
    11.     DEVTYPE_IRTOUCH,  
    12.     DEVTYPE_IDEALTEK,  
    13.     DEVTYPE_GENERAL_TOUCH,  
    14.     DEVTYPE_GOTOP,  
    15.     DEVTYPE_JASTEC,  
    16.     DEVTYPE_E2I,  
    17.     DEVTYPE_ZYTRONIC,  
    18.     DEVTYPE_TC45USB,  
    19.     DEVTYPE_NEXIO,  
    20. };  

    那么这些driver 的真正的info保存在哪里呢? 在注册的时候,现在只是注册上去一个枚举数字而已,

    真正有设备识别到的时候这些个枚举值就起到作用了! 在下面的 usbtouch_probe 会介绍!


    usbtouch_probe

     在前面有稍微提到,usbtouchscreen驱动是怎么被映射到的,这个过程暂时不做深入,作为这个驱动中的第一个接入点就是usbtouch_probe.

    1. static int usbtouch_probe(struct usb_interface *intf,  
    2.               const struct usb_device_id *id)  
    3. {  
    4.     struct usbtouch_usb *usbtouch;  //usbtouch 设备  
    5.     struct input_dev *input_dev;  //输入设备  
    6.     struct usb_endpoint_descriptor *endpoint;  //usb 的端点  
    7.     struct usb_device *udev = interface_to_usbdev(intf);  //从usb接口获取对应的设备  
    8.     struct usbtouch_device_info *type;   //这个就是上面说的真正的 driver info了  
    9.   
    10.   
    11.     endpoint = usbtouch_get_input_endpoint(intf->cur_altsetting);  //获取端点  
    12.     if (!endpoint)  
    13.         return -ENXIO;  
    14.     usbtouch = kzalloc(sizeof(struct usbtouch_usb), GFP_KERNEL);  
    15.     input_dev = input_allocate_device();  //分配内存,申请input 设备结构  
    16.   
    17. ...  
    18.   
    19.     type = &usbtouch_dev_info[id->driver_info];   // 这里就用到了 上面说到的枚举值了, 真正的info 是放在这个数组里面的!  
    20.   
    21. ...  
    22.   
    23.     usbtouch->irq = usb_alloc_urb(0, GFP_KERNEL);  //分配了一个urb 用于 获得触摸屏设备返回的触摸事件的数据,urb的概念可参考usb driver  
    24.     if (!usbtouch->irq) {  
    25.         dbg("%s - usb_alloc_urb failed: usbtouch->irq", __func__);  
    26.         goto out_free_buffers;  
    27.     }  
    28.   
    29. ...  
    30.   
    31. //往下都是一些分配内存,input注册,初始化操作了  
    32.   
    33.     input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); //这里是就是input设备触摸坐标的初始化赋值了,为ABS 绝对坐标  
    34.     input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);  
    35.     input_set_abs_params(input_dev, ABS_X, type->min_xc, type->max_xc, 00);  
    36.     input_set_abs_params(input_dev, ABS_Y, type->min_yc, type->max_yc, 00);  
    37.   
    38. ...  
    39.   
    40.     if (usb_endpoint_type(endpoint) == USB_ENDPOINT_XFER_INT)  
    41.         usb_fill_int_urb(usbtouch->irq, udev,  
    42.              usb_rcvintpipe(udev, endpoint->bEndpointAddress),  
    43.              usbtouch->data, type->rept_size,  
    44.              usbtouch_irq, usbtouch, endpoint->bInterval);  
    45.     else  
    46.         usb_fill_bulk_urb(usbtouch->irq, udev,  
    47.              usb_rcvbulkpipe(udev, endpoint->bEndpointAddress),  
    48.              usbtouch->data, type->rept_size,  
    49.              usbtouch_irq, usbtouch);  //初始化urb的回调函数为 usbtouch_irq  
    50.   
    51.     usbtouch->irq->dev = udev;  
    52.     usbtouch->irq->transfer_dma = usbtouch->data_dma;  
    53.     usbtouch->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;  
    54.   
    55. ...  
    56.   
    57. }  


    usbtouch_device_info:

     这个就是上面driver_info 以及usbtouch_probe 中抽取的驱动模块的info数组,不同的usbtouchscreen 注册的时候就是注册了一个枚举值,这个值就是usbtouch_dev_info 数组的第几元素.

    1. struct usbtouch_device_info {  
    2.     int min_xc, max_xc;  
    3.     int min_yc, max_yc;  
    4.     int min_press, max_press;  
    5.     int rept_size;  
    6.   
    7.     /* 
    8.      * Always service the USB devices irq not just when the input device is 
    9.      * open. This is useful when devices have a watchdog which prevents us 
    10.      * from periodically polling the device. Leave this unset unless your 
    11.      * touchscreen device requires it, as it does consume more of the USB 
    12.      * bandwidth. 
    13.      */  
    14.     bool irq_always;  
    15.   
    16.     void (*process_pkt) (struct usbtouch_usb *usbtouch, unsigned charchar *pkt, int len);  //这个函数指针是用来接收处理中断的。  
    17.   
    18.     /* 
    19.      * used to get the packet len. possible return values: 
    20.      * > 0: packet len 
    21.      * = 0: skip one byte 
    22.      * < 0: -return value more bytes needed 
    23.      */  
    24.     int  (*get_pkt_len) (unsigned charchar *pkt, int len);  
    25.   
    26.     int  (*read_data)   (struct usbtouch_usb *usbtouch, unsigned charchar *pkt);  
    27.     int  (*alloc)       (struct usbtouch_usb *usbtouch);  
    28.     int  (*init)        (struct usbtouch_usb *usbtouch);  
    29.     void (*exit)        (struct usbtouch_usb *usbtouch);  
    30. };  

    usbtouch_dev_info 数组:
    1. static struct usbtouch_device_info usbtouch_dev_info[] = {  
    2. #ifdef CONFIG_TOUCHSCREEN_USB_EGALAX  
    3.     [DEVTYPE_EGALAX] = {  
    4.         .min_xc        = 0x0,  
    5.         .max_xc        = 0x07ff,  
    6.         .min_yc        = 0x0,  
    7.         .max_yc        = 0x07ff,  
    8.         .rept_size    = 16,  
    9.         .process_pkt    = usbtouch_process_multi,//用于中断回调函数,用于处理中断,得到input的event,上传数据  
    10.         .get_pkt_len    = egalax_get_pkt_len,  
    11.         .read_data    = egalax_read_data, //用于中断回调函数,用于读取数据  
    12.     },  
    13. #endif  
    14.   
    15. ...  
    16.   
    17. #ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH  
    18.     [DEVTYPE_IRTOUCH] = {  
    19.         .min_xc        = 0x0,  
    20.         .max_xc        = 0x0fff,  
    21.         .min_yc        = 0x0,  
    22.         .max_yc        = 0x0fff,  
    23.         .rept_size    = 8,  
    24.         .read_data    = irtouch_read_data,  
    25.     },  
    26. #endif   
    27.   
    28. ...  
    29.   
    30. };  

    可以看到这个数组的成员都是以前面说到的注册枚举值来区分的!这些x,y 参数以及回调函数,都在上面说到的 usbtouch_probe 中被抽离出来使用.


    usbtouch_irq:

     这个函数作为中断响应函数,在上面的 usbtouch_probe中初始化,看下函数主要实现:

    1. static void usbtouch_irq(struct urb *urb)  
    2. {  
    3.   
    4. ...  
    5.   
    6.     usbtouch->type->process_pkt(usbtouch, usbtouch->data, urb->actual_length);    
    7.   
    8. //这个type的类型就是 usbtouch_device_info,此时的process_pkt指针自然指向的是上面对应的函数,如果此时是触发的设备type为 DEVTYPE_EGALAX,那么这里调用的 usbtouch_process_multi  
    9.   
    10. //如果此时是DEVTYPE_IRTOUCH 那么就是执行 usbtouch_process_pkt函数,因为usbtouch_probe中:  
    11.   
    12. //    if (!type->process_pkt)  
    13. //        type->process_pkt = usbtouch_process_pkt;  
    14.   
    15. ...  
    16.   
    17. }  


    接下来的都会调用到usbtouch_process_pkt中,通过type->read_data,和上面一样的指针读取,然后调用input_report_key发送,input_sync用于同步.关于usbtouchscreen的驱动部分就分析到这里。
    展开全文
  • 目前,USB接口的使用越来越广泛,许多设备上都提供了USB接口。传统的USB控制器需要使用包括数据线和控制线在内的十多根线,占用了大量的CPU资源。而现代设备正在向体积小、功能强的方向发展,CPU更是要求表贴封装,...
  • USB接口可编程触摸键盘设计USB接口可编程触摸键盘设计USB接口可编程触摸键盘设计USB接口可编程触摸键盘设计
  • ThinkPad X1 Tablet键盘改USB接口

    万次阅读 2019-06-15 13:37:53
    ThinkPad X1 Tablet键盘改USB接口记 起因 用USB独立键盘,打字的同时又要去用鼠标的感觉实在糟糕,就算是有一个好的机械键盘也是如此。能不能有一个像笔记本那样既有按键又有触摸板在下方的键盘呢?最好再加个小红点...

    ThinkPad X1 Tablet键盘改USB接口记

    起因

    用USB独立键盘,打字的同时又要去用鼠标的感觉实在糟糕,就算是有一个好的机械键盘也是如此。能不能有一个像笔记本那样既有按键又有触摸板在下方的键盘呢?最好再加个小红点。怀着这样的目标,逛了淘宝一圈,发现万能的淘宝居然没有针对这样需求的键盘(可能我的需求比较奇葩),怀揣着这样的目标,突发奇想:不如改装ThinkPad的笔记本键盘吧?
    查阅了广大资料之后,发现居然能够直接改装笔记本键盘为USB接口,开始行动。

    参考

    这里感谢下列贴吧主和博主的资料:
    ThinkPad键盘改无线套件:https://forum.51nb.com/forum.php?mod=viewthread&tid=1619134
    外接式指点杆键盘大收集: https://forum.51nb.com/forum.php?mod=viewthread&tid=1854098
    ThinkPad键盘底座改装列表
    Hack X1 Tablet keyboard with USB: https://www.reddit.com/r/thinkpad/comments/a4wm07/hack_x1_tablet_keyboard_with_usb/
    ThinkPad X1 Tablet键盘底座引脚定义
    ThinkPad X1 Tablet 2016&2017 Keyboard to USB Hack Tool: https://www.thingiverse.com/thing:3041109

    通过查阅资料然后对资料进行总结,发现了一般存在的两种改造笔记本键盘的方法:

    第一种方法

    做法:拿到笔记本的原生键盘,直接将笔记本键盘的阵列排线与单片机引脚相连。然后对单片机编程,通过监听笔记本的键盘阵列信号,将键盘阵列信号转换为符合USB规范的信号,然后将USB信号输出。
    准备材料: 单片机芯片(最好是STM32、推测不用8位或者16位的原因是引脚过少和频率较低),PCB板(需要自己规划线路、然后做出来),键盘排线接口(将键盘排线与电路板连接),若干电子元器件。
    分析:这种方法对技术要求比较高,需要PCB打板,单片机编程,电路接线等知识,但是灵活性比较高,适用于目前市场上的任何键盘改造。

    第二种方法

    做法:拿到具有USB线定义的磁吸键盘(一般磁吸键盘为了减少接线柱,都会使用USB协议传输信号),然后自己做一个磁吸底座,通过和USB线连接,就能使用。如果不考虑以后还用磁吸底座的话,也可以直接和pogo pin连线。
    准备材料:磁吸键盘底座,USB连接线,磁铁,能打洞的胶板(也可以用3D打印出来资料里面的那个3D模型)。
    分析:这种方法对技术要求比较低,灵活度也比较低,只能适用于使用USB协议传输的磁吸键盘底座。而磁吸键盘底座就目前来说,都有键盘键程偏短的缺点。这两种方法自己可以好好抉择。
    当然,还有更高级一点的玩法,通过将STM32单片机与蓝牙模块或者无线模块结合,制作一个无线蓝牙的键盘。

    行动

    通过自己对自己技术能力各方面的抉择(其实就是菜呗),最终选定直接将ThinkPad Tablet的磁吸键盘底座改为USB接口的方案。注意ThinkPad Tablet目前比较好改装的是16 17款的第一二代的键盘底座。
    然后在国外一个网站上找到了这个键盘底座的六个pogo pin的定义了,其中四个对上USB的定义线。从上到下,从左往右依次是
    上排:白,红,nc,
    下排:黑,绿,nc(gnd)。
    注意:只用那四个带颜色的pogo pin对上USB的颜色定义线就行。
    自己经过了准备磁铁和胶板,规划,裁剪,打洞,接线等阶段之后,我的键盘终于诞生了。Tablet键盘底座的唯一缺点就是键程偏短,其他的完美符合我的要求。不错,她就是一个带着触摸板,小红点和按键还带背光的能插任何电脑的USB独立键盘了(关键是只花了150块大洋)。改造后对Windows10和deepin系统进行了测试,发现完美兼容,指点杆和触摸板都能用。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    我要用我的键盘打字了,哈哈哈哈。

    展开全文
  • 电信设备-一种基于单片机的触摸USB2.0接口通信装置.zip
  • 电信设备-一种基于单片机的触摸USB1.1接口通信装置.zip
  • 使用tslib来校准usb接口触摸

    千次阅读 2015-05-22 14:11:51
    现在使用eGalax的usb触摸屏设备。然后使用LinuxInput的Qt库,之前使用的是Qt里面的校准程序。但是发现,程序里面能够分辨的,设备的右下角坐标,总是等于内核的分辨率,也就是800*600。在开发板的环境变量里面有个,...

    现在使用eGalax的usb触摸屏设备。然后使用LinuxInput的Qt库,之前使用的是Qt里面的校准程序。但是发现,程序里面能够分辨的,设备的右下角坐标,总是等于内核的分辨率,也就是800*600。在开发板的环境变量里面有个,QWS_SIZE这个东西,我设置了也没见什么效果,删除了也没什么问题。所以校准出来的结果是,触摸屏左上四分之一,就已经能够表达显示器的全屏了,即800*600。
    但是,这没法用。所以最后又把目光投向tslib,之前就想过自己修改tslib,这回也许是瞎猫和耗子的关系,竟然真的实现了。
    在之前使用tslib时,打开usb设备,会经过fd_check()这个函数。它会对当前设备进行判断,看看是不是触屏设备(当然是了)。但是不知道是什么原因,usb的触屏就是不认,EV_VERSION这个东西我也修改了,发现不行,因为还有其他的很多判断条件。索性我直接在input-raw.c里面的,mod_init()这个函数里面把i->sane_fd = 0;这个修改成1。即
    TSAPI struct tslib_module_info *mod_init(struct tsdev *dev, const char *params)
    {
    struct tslib_input *i;

    i = malloc(sizeof(struct tslib_input));
    if (i == NULL)
        return NULL;
    
    i->module.ops = &__ts_input_ops;
    i->current_x = 0;
    i->current_y = 0;
    i->current_p = 0;
    i->sane_fd = 1;
    i->using_syn = 0;
    return &(i->module);
    

    }这样就直接屏蔽了fd_check()这个过程。继续测试,发现还是不行,打开debug发现其实x、y坐标已经有了,但是就因为没有pressure的值,所以在tests\Testutils.c文件中有个while循环过不去。见getxy()函数中,
    do {
    if (ts_read_raw(ts, &samp[0], 1) < 0) {
    perror(“ts_read”);
    close_framebuffer ();
    exit(1);
    }

    } while (samp[0].pressure == 0);
    所以我在ts_input_read()函数中
    #ifdef DEBUG
                fprintf(stderr, "RAW---------------------------> %d %d %d\n",
                    samp->x, samp->y, samp->pressure);
    #endif   /*DEBUG*/
    

    这个地方加了一句,samp->pressure = 1;
    编译测试。成功了!!!当然方法比较傻,暂时能够实现。因为不太会linux下面的编程,特别是关于驱动的。如果会的话,我觉得应该可以参考tslib,自己写一个校准软件出来。

    展开全文
  • 驱动编译:  ... 目前的kernel中都是自带了usbtouchscreen驱动的,我的版本3.1.10 源码位于:/kernel/drivers/input/touchscreen/usbtouchscreen.c 从这个路径可以看出所属驱动分支,我...
  • linux usb触摸屏设备实现指导

    千次阅读 2019-09-25 16:33:20
    USB Touchscreen 属于一种HID设备,linux 2.6.31 目前已经支持多种USB touchscreen设备,source code位于/kernel/driver/input/ 的usbtouchscreen.c 增加新的设备需要更改usbtouchscreen.c /*********************...
  • CypressTrueTouchTM电容触摸屏方案可以在多个领域获得广泛应用:单点触摸,...TrueTouchTM芯片与主机通过TX/I2C/SPI/USB接口通讯,PSoCDesigner5.0提供了相应的各种通讯用户模块,这将大大简化用户的编程和调试工作。
  • 介绍了关于永宏C3系列触摸屏通讯接口定义以及与常用PLC通讯连线的详细说明,提供永宏PLC的技术资料的下载。
  • 信捷触摸屏的驱动程序,内附usb驱动程序,以及安装指导文件。本驱动可以自动安装,也可以手动安装。下载之后先解压缩,内含XP WIN7 WIN8版本。 在安装驱动之前,请不要将触摸屏幕的USB电缆连接到电脑的USB端口上。 ...
  • USB触摸屏的驱动

    千次阅读 2017-06-19 13:26:11
    我们都知道410c没有配套的触摸屏,如果有屏的话,在调试或者其他方面就方便多了,所以我们自己买了一个usb触摸屏,现在让我们看看usb触摸屏的驱动。  驱动路经:drivers/input/touchscreen/usbtouchscreen.c  ...
  • usb触摸屏驱动 - usbtouchscreen

    千次阅读 2016-08-22 17:12:11
    驱动编译: 目前的kernel中都是自带了usbtouchscreen...从这个路径可以看出所属驱动分支,我这边平台本身是没放开的,并没有编译进kernel,谁会想到触摸电视呢~ 可以在make menuconfig之后,通过Device Drivers...
  • USB接口定义

    千次阅读 2019-01-23 12:42:45
    USB接口标准 USB是电脑的常见接口,有4根线,两根电源线和两个信号线,电源线正负极供电,接烦可能导致USB设备或电脑的南桥芯片烧坏。 type A 即我们常见的标准USB大口,主流的可以分为USB2.0速度(几十M/S)和...
  • 本文介绍了基于嵌入式 Linux 系统平台上 Qt/Embedded 的触摸屏驱动的...该方案已成功运用于工程机械安全仪和电能质量监测仪项目,实现了 GUI(图形用户操作接口)界面对触摸屏的支持,并能根据触摸屏的不同进行定制。
  • Zynq移植USB触摸

    2020-08-07 12:15:59
    Zynq平台移植USB触摸屏的实现(Qt5.7) 使用的环境: 1. CPU type:ARM CortexA9(Xilinx zynq7000)(使用的是黑金AX7021开发板) 2. Kernel version:4.9 3. no X-window, GUI system:QT5.7 4. Controller...
  • 公司自主研发的,安卓主板外接 红外触摸框,触摸接口是通过usb hid串口方式连接与 发送数据的,请教下应用程序如何在触摸时能够获取触摸框的原始数据,而不是经过底层 处理后的MotionEvent中的触摸数据。之前尝试...
  • 2007年iPhone面世并取得了巨大成功,它采用的电容式触摸屏提供了更高的透光性和新颖的多点触摸功能,开始成为便携式产品的新热点,并显现出成为主流输入接口方式的趋势。
  • android usb触摸屏idc实现触摸唤醒

    千次阅读 2019-03-30 11:21:30
    如果是i2c接口触摸屏需要修改驱动。 有的可能在目录下面没有发现对应Vid pid设备,可手动添加 附加一句,有的时候调试完触摸屏之后会出现边缘触摸点有偏差问题,这个一般也是idc导致了,添加一个idc之后问题...
  • 常见USB接口类型

    千次阅读 2020-12-01 16:00:42
    常见USB接口 Type-A:标准版 USB 接口 Type-B:打印机设备常用 TYPE Micro-B:移动设备的 USB 标准 (如安卓手机充电口) Type-C:正在成为主流趋势接口类型 (如安卓手机充电口) USB3.1百科 USB 3.1 Gen2是最新...
  • 该设计结合了USB和无线设备的优点,将手持端的鼠标触摸板控制信息通过无线发送到接收端并通过USB接口与主机PC实现交互通信。整个系统主要由PIC16FB77A单片机,PDIUSBDl2芯片,CC2420无线模块,PS/2鼠标触摸板实现。
  • 永宏PLC FBs-PLC 主机USB接口驱动程序rar,永宏PLC FBs-PLC 主机USB接口驱动程序
  • 针对越来越多的商显项目,由于有触摸的交互需求,那么触控方案选择也就比较重要。目前市面流行的主要 有红外框的,电容屏的。单系统(安卓 or OPS)的又分为串口,usb口。双系统(安卓 + OPS) 则有“串口+USB”,“双...
  • STM32 电容触摸屏I2C转USB实现

    千次阅读 2020-06-23 12:03:53
    最近有个需求要把一个电容式触摸屏转为标准USB HID TP设备,同时需要把TP数据通过串口输出到MCU。市面方案大多采用CH554E做I2C USB转换,没有多余的UART口。问了几家供应商都说做不了,只好自己搞了。 能偷懒就偷懒...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 9,487
精华内容 3,794
关键字:

usb触摸接口