usb_touch_screen Linux 驱动


static int __init general_touch_single_init(void)
{
	int ret = usb_register(&generaltouchsingle_usb_driver);
	if (ret == 0)
		printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" DRIVER_DESC);
	return ret;
}

static struct usb_driver generaltouchsingle_usb_driver = {
	.name        = "general_touch_single",
	.probe        = general_touch_single_probe,
	.disconnect    = general_touch_single_disconnect,
	.id_table    = general_touch_single_id_table,
};
当有设备匹配的时候会调用probe方法,也就是general_touch_single_probe

在static const struct usb_device_id general_touch_single_id_table []中定义了的usb设备插入就会匹配并触发probe

可以用宏USB_DEVICE简化设置usb设备id信息,如下:

static struct usb_device_id general_touch_single_id_table [] = {
	{ USB_DEVICE(0x0dfc, 0x0001) },
	{ }   
};
{USB_DEVICE(0x3823, 0x0001), .driver_info = DEVTYPE_EGALAX},  

driver_info是驱动类型,有一下选择
enum {
	DEVTYPE_IGNORE = -1,
	DEVTYPE_EGALAX,
	DEVTYPE_PANJIT,
	DEVTYPE_3M,
	DEVTYPE_ITM,
	DEVTYPE_ETURBO,
	DEVTYPE_GUNZE,
	DEVTYPE_DMC_TSC10,
	DEVTYPE_IRTOUCH,
	DEVTYPE_IDEALTEK,
	DEVTYPE_GENERAL_TOUCH,
	DEVTYPE_GOTOP,
	DEVTYPE_JASTEC,
	DEVTYPE_E2I,
	DEVTYPE_ZYTRONIC,
	DEVTYPE_TC45USB,
	DEVTYPE_NEXIO,
};
没有选择也可以自己添加一个在枚举体后面
(0x0dfc, 0x0001)这两个分别是usb设备的厂商id和产品id
下面代码是我插拔usb触摸屏的打印信息

[ 3643.430000] usb 1-2.3.3: USB disconnect, device number 10
[ 3648.245000] usb 1-2.3.3: new full-speed USB device number 12 using s5p-ehci
[ 3648.350000] usb 1-2.3.3: New USB device found, idVendor=0dfc, idProduct=0001
[ 3648.350000] usb 1-2.3.3: New USB device strings: Mfr=0, Product=0, SerialNumb
er=0

作为我的设备,我就把idVendor=0dfc, idProduct=0001添加进USB_DEVICE宏就行
static struct usb_device_id general_touch_single_id_table [] = {
	{ USB_DEVICE(0x0dfc, 0x0001) },
	{ }   
};
只有这个匹配了,才会成功调用probe了。

static int general_touch_single_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
		struct usb_device *dev = interface_to_usbdev(intf);
		struct usb_host_interface *interface;
		struct usb_endpoint_descriptor *endpoint;
		struct generaltouch_device *general_touch_single;
		struct input_dev *input_dev;
		int pipe;
		int error = -ENOMEM;
		
		interface = intf->cur_altsetting;
		
		if (interface->desc.bNumEndpoints != 1)
			return -ENODEV;
	//	/*根据HID规则,期望鼠标只有一个端点即中断端点bNumEndpoints 就是接口描述符中的成员,表示这个接口有多少个端点,不过这其中不包括0 号端点,0号端点是任何一个usb 设备都必须是提供的,这个端点专门用于进行控制传输,即它是一个控制端点.正因为如此,所以即使一个设备没有进行任何设置,usb 主机也可以开始跟它进行一些通信,因为即使不知道其它的端点,但至少知道它一定有一个0号端点,或者说一个控制端点。
	        
		endpoint = &interface->endpoint[0].desc;
		if (!(endpoint->bEndpointAddress & USB_DIR_IN))
			return -ENODEV;
	//*先看bEndpointAddress,这个struct usb_endpoint_descriptor 中的一个成员,是8个bit,或者说1 个byte,其中bit7 表示的是这个端点的方向,0 表示OUT,1 表示IN,OUT 与IN 是对主机而言。OUT 就是从主机到设备,IN 就是从设备到主机。而宏*USB_DIR_IN 来自
	//         *include/linux/usb_ch9.h
	//         * USB directions
	//         * This bit flag is used in endpoint descriptors' bEndpointAddress field.
	//         * It's also one of three fields in control requests bRequestType.
	//         *#define USB_DIR_OUT 0 /* to device */
	//         *#define USB_DIR_IN 0x80 /* to host */ 
	//		
		if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT)
			return -ENODEV;
	//判断是否是中断类型
	// bmAttributes 表示属性,总共8位,其中bit1和bit0 共同称为Transfer Type,即传输类型,即00 表示控制,01 表示等时,10 表示批量,11 表示中断*/ 
		pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
		//构造中断端点的输入pipe
		
		general_touch_single= kzalloc(sizeof(struct generaltouch_device), GFP_KERNEL);
		//分配一个generaltouch_device结构体
		input_dev = input_allocate_device();
	  //分配一个input_dev结构体;
		if (!general_touch_single || !input_dev)
			goto fail_dev;
		
		general_touch_single->data = usb_alloc_coherent(dev, USB_TRANSFER_LENGTH, GFP_ATOMIC, &general_touch_single->data_dma);
		if (!general_touch_single->data)
			goto fail_dev;
		//分配缓冲区
		general_touch_single->irq = usb_alloc_urb(0, GFP_KERNEL); 
		if (!general_touch_single->irq)
			goto fail_data;
		//分配urb   
		general_touch_single->usbdev = dev;
	 	//捆绑general_touch_single和usb_device
		general_touch_single->dev = input_dev;
		//捆绑general_touch_single和输入设备  
		if (dev->manufacturer)
			strlcpy(general_touch_single->name, dev->manufacturer, sizeof(general_touch_single->name));
		//存在工厂名则设置工厂名
		if (dev->product) {
			if (dev->manufacturer)
				strlcat(general_touch_single->name, " ", sizeof(general_touch_single->name));
			strlcat(general_touch_single->name, dev->product, sizeof(general_touch_single->name));
		}
		//存在产品名则设置产品名
		if (!strlen(general_touch_single->name))
			snprintf(general_touch_single->name, sizeof(general_touch_single->name),
					"lamson:--generaltouch single-touch  %04x:%04x",
					le16_to_cpu(dev->descriptor.idVendor),
					le16_to_cpu(dev->descriptor.idProduct));
					//若不存在工厂名和产品名   
		usb_make_path(dev, general_touch_single->phys, sizeof(general_touch_single->phys));
		
		strlcat(general_touch_single->phys, "/input0", sizeof(general_touch_single->phys));
		
		input_dev->name = general_touch_single->name;
		//设置输入设备名
		input_dev->phys = general_touch_single->phys;
		设置输入设备路径
		usb_to_input_id(dev, &input_dev->id);
		//将usb_driver的支持项拷贝给input
		input_dev->dev.parent = &intf->dev;
		//设置usb设备为输入设备的父设备
		
		input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) | BIT_MASK(EV_SYN);
		按键和绝对位移事件
		input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
		//触摸按键
		input_set_abs_params(input_dev, ABS_X, 0, 32767, 0, 0);
		input_set_abs_params(input_dev, ABS_Y, 0, 32767, 0, 0);
		//绝对x坐标位移
		//input_set_abs_params(input_dev, ABS_PRESSURE, 0, 1, 0, 0);       	
		input_set_drvdata(input_dev, general_touch_single);
		//这里将自定义结构体对象 赋给它
		input_dev->open = general_touch_single_open_device;
		//设置输入设备的open方法   
	
		input_dev->close = general_touch_single_close_device;
		//设置输入设备的close方法   
	
		usb_fill_int_urb(general_touch_single->irq, dev, pipe, general_touch_single->data, USB_TRANSFER_LENGTH,
				general_touch_single_irq, general_touch_single, endpoint->bInterval);
		//中断传输方式   
		general_touch_single->irq->transfer_dma = general_touch_single->data_dma;
		//传输数据dma地址缓冲区
		general_touch_single->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
		//传输标志物dma映射传输 
		error = input_register_device(general_touch_single->dev);
		 //注册输入设备 
		usb_set_intfdata(intf, general_touch_single);
		
		error = usb_register_dev(intf, &general_touch_single_class_driver);
		//注销usb设备
		if(error)
		{
			printk("lamson dbg general_touch_single:  %s failed to get a minor for generaltouch device.",__func__);
			usb_set_intfdata(intf,NULL);
			goto fail_reg;
		}
		
		msleep(1000);	
		general_touch_single_mkdev();
		printk("lamson :general_touch_single probe success!!!\n");
		
		return 0;
		
		fail_reg:
		usb_free_urb(general_touch_single->irq);
		fail_data:
		usb_free_coherent(dev, USB_TRANSFER_LENGTH, general_touch_single->data, general_touch_single->data_dma);
		
		fail_dev:
		input_free_device(input_dev);
		kfree(general_touch_single);
		return -ENOMEM;
	}
	/
	static void general_touch_single_disconnect(struct usb_interface *intf)
	{
	struct generaltouch_device *general_touch_single = usb_get_intfdata (intf);
	
	dev_t dev_nb = MKDEV(GENERALTOUCH_DEVICE_MAJOR,GENERALTOUCH_DEVICE_MINOR);
	
	cdev_del(&general_touch_single_cdev);
	unregister_chrdev_region(dev_nb,1);
	
	device_destroy(generaltouchsingle_class,dev_nb);
	class_destroy(generaltouchsingle_class);
	
	usb_deregister_dev(intf, &general_touch_single_class_driver);
	
	usb_set_intfdata(intf, NULL);
	if(general_touch_single) 
	{
		usb_kill_urb(general_touch_single->irq);
		input_unregister_device(general_touch_single->dev);
		usb_free_urb(general_touch_single->irq);
		usb_free_coherent(interface_to_usbdev(intf), USB_TRANSFER_LENGTH, general_touch_single->data, general_touch_single->data_dma);
		kfree(general_touch_single);
	}

}
/
struct generaltouch_device {
	char name[128];
	char phys[64];
	struct usb_device *usbdev;#
	struct input_dev *dev;
	struct urb *irq;
	unsigned char *data;
	dma_addr_t data_dma;
};
struct usbtouch_usb {
	unsigned char *data;
	dma_addr_t data_dma;
	unsigned char *buffer;
	int buf_len;
	struct urb *irq;
	struct usb_interface *interface;
	struct input_dev *input;
	struct usbtouch_device_info *type;
	char name[128];
	char phys[64];
	void *priv;

	int x, y;
	int touch, press;
};

static void general_touch_single_irq(struct urb *urb)
{
	struct generaltouch_device *general_touch_single = urb->context;
	int status;

	switch (urb->status) {
		case 0:            /* success */
			break;
		case -ECONNRESET:  /* unlink */
		case -ENOENT:
		case -ESHUTDOWN:
			return;    /* -EPIPE:  should clear the halt */
		default:	   /* error */
			printk("lamson dbg general_touch_single: %s - nonzero urb status received: %d",
		    __func__, urb->status);
			goto resubmit;
	}
	
	general_touch_processdata(general_touch_single, general_touch_single->data, USB_TRANSFER_LENGTH);

	resubmit:
	status = usb_submit_urb (urb, GFP_ATOMIC);
	if (status)
		printk ("lamson dbg general_touch_single: can't resubmit intr, %s-%s/input0, status %d",
				general_touch_single->usbdev->bus->bus_name,
				general_touch_single->usbdev->devpath, status);
}

//static void general_touch_processdata(struct generaltouch_device *general_touch_single,
//                                 unsigned char *pkt, int len)
//{
//	int x = 0, y = 0, touch = 0;
//
//	x = (pkt[2] << 8) | pkt[1];
//	y = (pkt[4] << 8) | pkt[3];
//        touch = pkt[0] & 0x01;
//	//if(touch == 1){
//       	    input_report_abs(general_touch_single->dev, ABS_X, x);
//            input_report_abs(general_touch_single->dev, ABS_Y, y);
//	//}
//	input_report_key(general_touch_single->dev, BTN_TOUCH, touch);
//	//input_report_abs(general_touch_single->dev,ABS_PRESSURE,touch);
//	input_sync(general_touch_single->dev);
//}
//static void usbtouch_process_pkt(struct usbtouch_usb *usbtouch,unsigned char *pkt, int len)	//默认的usb触摸数据包处理函数
//{
//	struct usbtouch_device_info *type = usbtouch->type;	//获取usbtouch_device_info对象
//
//	if (!type->read_data(usbtouch, pkt))	//调用usbtouch_device_info对象的read_data方法
//			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);	//上报绝对坐标X事件
//		input_report_abs(usbtouch->input, ABS_Y, usbtouch->y);	//上报绝对坐标Y事件
//	}
//	if (type->max_press)
//		input_report_abs(usbtouch->input, ABS_PRESSURE, usbtouch->press);
//	input_sync(usbtouch->input);	//同步输入事件
//}
这些处理的细节跟具体硬件厂商或者协议有关,调试可以将dev->x和dev->y打印出来
可能你加了打印之后触摸屏幕压根就没有打印信息

那是因为要打开设备,所以应用层也要有测试软件,有界面的测试软件最好

没有也可以用下面这段代码去简单测试一下(来着网络)

#include <stdio.h>
#include <linux/input.h>

static int event0_fd = -1;
struct input_event ev0[64];

static int handle_event0()
{
	int button = 0, realx=0, realy=0, i, rd;
	rd = read(event0_fd, ev0, sizeof(struct input_event)* 64);
	if(rd < sizeof(struct input_event)) return 0;
	for(i=0;i<rd/sizeof(struct input_event); i++)
	{
		if(EV_ABS == ev0[i].type)
		{
			if(ev0[i].code == 0) {
				realx = ev0[i].value;
			} else if(ev0[i].code == 1) {
				realy = ev0[i].value;
			}
		}
		printf("realx:%3d; realy:%3d\n",realx,realy);
		//printf("event(%d):type:%d; code:%3d; value:%3d; realx:%3d; realy:%3d\n",i,ev0[i].type,ev0[i].code,ev0[i].value,realx,realy);
		
	}
	return 1;
}


int main(void)
{
	int done = 1;
	event0_fd = open("/dev/input/event1",02);	//打开设备
	if(event0_fd <0) {
		printf("open input device error\n");
		return -1;
	}
	while (done)
	{
		//printf("begin handle_event0...\n");
		done = handle_event0();
		//printf("end handle_event0...\n");
	}
	if(event0_fd > 0)
	{
		close(event0_fd);
		event0_fd = -1;
	}
	return 0;
}
这段代码打开的设备修改成你的设备路径,插拔触摸屏判断哪个是你触摸屏的设备
或者ls -l  /sys/class/input看信息结合插入设备的打印信息也可以判断你的设备是哪个
lrwxrwxrwx root     root              2014-12-19 11:38 event0 -> ../../devices/v
irtual/input/input0/event0
lrwxrwxrwx root     root              2014-12-19 11:38 event1 -> ../../devices/v
irtual/rc/rc0/input1/event1
lrwxrwxrwx root     root              2014-12-19 11:38 event2 -> ../../devices/p
latform/s3c2440-i2c.3/i2c-3/3-004c/input/input2/event2
lrwxrwxrwx root     root              2014-12-19 11:38 event3 -> ../../devices/p
latform/s5p-ehci/usb1/1-2/1-2.3/1-2.3.3/1-2.3.3:1.0/input/input3/event3
lrwxrwxrwx root     root              2014-12-19 11:38 input0 -> ../../devices/v
irtual/input/input0
lrwxrwxrwx root     root              2014-12-19 11:38 input1 -> ../../devices/v
irtual/rc/rc0/input1
lrwxrwxrwx root     root              2014-12-19 11:38 input2 -> ../../devices/p
latform/s3c2440-i2c.3/i2c-3/3-004c/input/input2
lrwxrwxrwx root     root              2014-12-19 11:38 input3 -> ../../devices/p
latform/s5p-ehci/usb1/1-2/1-2.3/1-2.3.3/1-2.3.3:1.0/input/input3
lrwxrwxrwx root     root              2014-12-19 11:38 mice -> ../../devices/vir
tual/input/mice
lrwxrwxrwx root     root              2014-12-19 11:38 mouse0 -> ../../devices/p
latform/s5p-ehci/usb1/1-2/1-2.3/1-2.3.3/1-2.3.3:1.0/input/input3/mouse0
	-------------------------------------------------------------------------------
	拔出设备
	lrwxrwxrwx root     root              2014-12-19 11:38 event0 -> ../../devices/v
irtual/input/input0/event0
lrwxrwxrwx root     root              2014-12-19 11:38 event1 -> ../../devices/v
irtual/rc/rc0/input1/event1
lrwxrwxrwx root     root              2014-12-19 11:38 event2 -> ../../devices/p
latform/s3c2440-i2c.3/i2c-3/3-004c/input/input2/event2
lrwxrwxrwx root     root              2014-12-19 11:38 event3 -> ../../devices/p
latform/s5p-ehci/usb1/1-2/1-2.3/1-2.3.3/1-2.3.3:1.0/input/input3/event3
lrwxrwxrwx root     root              2014-12-19 11:38 input0 -> ../../devices/v
irtual/input/input0
lrwxrwxrwx root     root              2014-12-19 11:38 input1 -> ../../devices/v
irtual/rc/rc0/input1
lrwxrwxrwx root     root              2014-12-19 11:38 input2 -> ../../devices/p
latform/s3c2440-i2c.3/i2c-3/3-004c/input/input2
lrwxrwxrwx root     root              2014-12-19 11:38 input3 -> ../../devices/p
latform/s5p-ehci/usb1/1-2/1-2.3/1-2.3.3/1-2.3.3:1.0/input/input3
lrwxrwxrwx root     root              2014-12-19 11:38 mice -> ../../devices/vir
tual/input/mice
lrwxrwxrwx root     root              2014-12-19 11:38 mouse0 -> ../../devices/p
latform/s5p-ehci/usb1/1-2/1-2.3/1-2.3.3/1-2.3.3:1.0/input/input3/mouse0
shell@android:/mnt/yangjia/samba/driver/toochscreen # ls -l  /sys/class/input
lrwxrwxrwx root     root              2014-12-19 11:38 event0 -> ../../devices/v
irtual/input/input0/event0
lrwxrwxrwx root     root              2014-12-19 11:38 event1 -> ../../devices/v
irtual/rc/rc0/input1/event1
lrwxrwxrwx root     root              2014-12-19 11:38 event2 -> ../../devices/p
latform/s3c2440-i2c.3/i2c-3/3-004c/input/input2/event2
lrwxrwxrwx root     root              2014-12-19 11:38 input0 -> ../../devices/v
irtual/input/input0
lrwxrwxrwx root     root              2014-12-19 11:38 input1 -> ../../devices/v
irtual/rc/rc0/input1
lrwxrwxrwx root     root              2014-12-19 11:38 input2 -> ../../devices/p
latform/s3c2440-i2c.3/i2c-3/3-004c/input/input2
lrwxrwxrwx root     root              2014-12-19 11:38 mice -> ../../devices/vir
tual/input/mice

再或者cat /proc/bus/input/devices也可以

I: Bus=0003 Vendor=0dfc Product=0001 Version=0305
N: Name="lamson:--generaltouch single-touch  0dfc:0001"
P: Phys=usb-s5p-ehci-2.3.3/input0
S: Sysfs=/devices/platform/s5p-ehci/usb1/1-2/1-2.3/1-2.3.3/1-2.3.3:1.0/input/inp
ut4
U: Uniq=
H: Handlers=mouse0 event3
B: PROP=0
B: EV=b
B: KEY=400 0 0 0 0 0 0 0 0 0 0
B: ABS=3
cat /proc/bus/input/devices",找到Name="... ETWO USB TOUCHSCREEN",再找到其中Handlers=event* 就是结果了。
在命令行执行命令 cat /dev/input/event3, 然后触摸USB触摸屏,如果终端上有数据出现,则说明USB触摸屏被关联到此event了(按Ctrl+c结束); 如果没有,则用同样方法再试其他event, 如0,1, 2, 4... 
入口函数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值