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...
入口函数