linux usb枚举分析4----(demo制作-基于HID的touch)

手机作为USB单点触摸板实例

        此功能是将一台android手机作为一个usb触摸板,将device的触摸数据上报到host,主要是通过linux gadget中的f_hid.c来实现。

        修改init.qcom.usb.rc,具体如下,使手机成为一个同时有ADB和HID device功能的复合设备:

on property:sys.usb.ffs.ready=1 && property:sys.usb.config=hid,adb && property:sys.usb.configfs=1

    write /config/usb_gadget/g1/configs/b.1/strings/0x409/configuration "hid_adb"

    rm /config/usb_gadget/g1/configs/b.1/f1

    rm /config/usb_gadget/g1/configs/b.1/f2

    rm /config/usb_gadget/g1/configs/b.1/f3

    rm /config/usb_gadget/g1/configs/b.1/f4

    rm /config/usb_gadget/g1/configs/b.1/f5

    rm /config/usb_gadget/g1/configs/b.1/f6

    rm /config/usb_gadget/g1/configs/b.1/f7

    rm /config/usb_gadget/g1/configs/b.1/f8

    rm /config/usb_gadget/g1/configs/b.1/f9

    symlink /config/usb_gadget/g1/configs/b.1 /config/usb_gadget/g1/os_desc/b.1

    write /config/usb_gadget/g1/configs/b.1/strings/0x409/MaxPower 120

    write /config/usb_gadget/g1/idVendor 0x2717

    write /config/usb_gadget/g1/idProduct 0x5001

    write /config/usb_gadget/g1/functions/hid.0/protocol 1

    write /config/usb_gadget/g1/functions/hid.0/subclass 1

    write /config/usb_gadget/g1/functions/hid.0/report_length 8

on property:sys.usb.ffs.ready=1 && property:sys.usb.config=hid2,adb && property:sys.usb.configfs=1

       symlink /config/usb_gadget/g1/functions/hid.0 /config/usb_gadget/g1/configs/b.1/f1

    symlink /config/usb_gadget/g1/functions/ffs.adb /config/usb_gadget/g1/configs/b.1/f2

    write /config/usb_gadget/g1/UDC ${sys.usb.controller}

        重启后,将属性切到hid,adb模式上来,并向手机发送USB touch的报告描述符,然后再切到hid2,adb上来,使手机插入usb host时能被枚举成一个usb touch设备。

setprop sys.usb.config hid,adb

echo -ne \\x05\\x0D\\x09\\x04\\xA1\\x01\\x85\\x01\\x09\\x22\\xA1\\x02\\x09\\x42\\x15\\x00\\x25\\x01\\x75\\x01\\x95\\x01\\x81\\x02\\x09\\x32\\x81\\x02\\x95\\x06\\x81\\x03\\x75\\x08\\x09\\x51\\x95\\x01\\x81\\x02\\x05\\x01\\x09\\x30\\x75\\x10\\x95\\x01\\x55\\x0E\\x65\\x33\\x35\\x00\\x46\\xFF\\x7F\\x26\\x30\\x2A\\x81\\x02\\x09\\x31\\x75\\x10\\x95\\x01\\x55\\x0E\\x65\\x33\\x35\\x00\\x46\\xFF\\x7F\\x26\\xC0\\x5D\\x81\\x02\\xC0\\xC0 > /config/usb_gadget/g1/functions/hid.0/report_desc

setprop sys.usb.config hid2,adb

        报告描述符解析如下:

0x05, 0x0D,        // Usage Page (Digitizer)

0x09, 0x04,        // Usage (Touch Screen)

0xA1, 0x01,        // Collection (Application)

0x85, 0x01,        //   Report ID (1) 用来表示不同的功能,如鼠标、键盘、touchpad、touchscreen的序号

0x09, 0x22,        //   Usage (Finger)

0xA1, 0x02,        //   Collection (Logical)

0x09, 0x42,        //     Usage (Tip Switch)

0x15, 0x00,        //     Logical Minimum (0)

0x25, 0x01,        //     Logical Maximum (1)

0x75, 0x01,        //     Report Size (1)

0x95, 0x01,        //     Report Count (1)

0x81, 0x02,        //     Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)

0x09, 0x32,        //     Usage (In Range)

0x81, 0x02,        //     Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)

0x95, 0x06,        //     Report Count (6)

0x81, 0x03,        //     Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)

0x75, 0x08,        //     Report Size (8)

0x09, 0x51,        //     Usage (0x51)

0x95, 0x01,        //     Report Count (1)

0x81, 0x02,        //     Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)

0x05, 0x01,        //     Usage Page (Generic Desktop Ctrls)

0x09, 0x30,        //     Usage (X)

0x75, 0x10,                                 //     Report Size (16)

0x95, 0x01,                           //     Report Count (1)

0x55, 0x0E,                           //     Unit Exponent (-2)

0x65, 0x33,                            //     Unit (Eng Lin: in^3)

0x35, 0x00,                           //     Physical Minimum (0)

0x46, 0xFF, 0x7F,                    //     Physical Maximum (32767)

0x26, 0x30, 0x2A,                 //     Logical Maximum (10800)

0x81, 0x02,        //     Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)

0x09, 0x31,        //     Usage (Y)

0x75, 0x10,                            //     Report Size (16)

0x95, 0x01,                           //     Report Count (1)

0x55, 0x0E,                                 //     Unit Exponent (-2)

0x65, 0x33,                            //     Unit (Eng Lin: in^3)

0x35, 0x00,                            //     Physical Minimum (0)

0x46, 0xFF, 0x7F,                    //     Physical Maximum (32767)

0x26, 0xC0, 0x5D,                        //     Logical Maximum (24000)

0x81, 0x02,        //     Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)

0xC0,              //   End Collection

0xC0,              // End Collection

        与之前的调试相比,在开始准备x与y坐标的上报时,从Usage Page开始,x和y分别作为一个usage,之前的对Logical Maximum的定义是在Usage (X)和 Usage Page之间,这样有个问题就是导致Usage Page下的每个usage都用这个属性,但我们需要对每个usage分别定义。所以把之前的逻辑删除,在Usage (X)和Usage (Y)下面分别规定Logical Maximum、Logical Maximum是触摸时与屏幕边界对应的值,如果比要求的值大,会导致触摸的边界在屏幕中央的某个地方,如果比要求值小,会导致触摸的边界在屏幕外面。

        手机通过C-TO-C线插入另一个USB host手机后,在host端可以看到一个触摸的输入设备:

        枚举成功后,device向host发送的输入报告,将device的触摸数据读到后,根据上面的报告描述符,重新组合成新的usb输入报告,并将数据写入/dev/hidg0,然后数据会通过USB总线发送到usb host。通过Bus hound抓包如下:

        此时usb host可同步响应device的触摸事件。

        参考用户应用程序如下:

#include <sys/stat.h>
#include <stdio.h>
#include <fcntl.h>
#include <signal.h>
#include <unistd.h>
#include <linux/input.h>
#include <stdlib.h>
#include <string.h>

struct input_event ev;
unsigned char* report;


int main()
{
  //int oflags;
  int fd_hid = -1;
  int fd_tp = -1;
  int ret = -1;
  unsigned char button = 0;
  unsigned char track_id = 0;
  int x = 0;
  int y = 0;
  report = malloc(7);
  memset(report,0,7);  
  fd_hid = open("/dev/hidg0", O_RDWR);
  fd_tp = open("/dev/input/event4", O_RDWR);

  if (fd_tp !=  - 1)
  {	  
    while(1){
		ret = read( fd_tp, &ev, sizeof(ev));
		if(ret < 0)
		{ 
		  printf("Failed to read from /dev/input/event13");
		}
		else if(ret > 0)
		{
			if (ev.type == EV_ABS) {
				if (ev.code == 53) {//x
					//x = 2880.0/1581.0*ev.value;
					x = ev.value;
				} else if (ev.code == 54) {//y
					//y = 1880.0/1582.0*ev.value;
					y = ev.value;
				} else if (ev.code == ABS_MT_TRACKING_ID) {
					if (ev.value == -1) {
						// 触摸结束
						//button = 0x0;
						track_id = ev.value;
					} else {
						// 触摸开始或移动
						//button = 0x01;
						track_id = ev.value;
					}
				}
			}
						

			if(ev.type == 0x01) {//EV_KEY 
				if(ev.code == BTN_TOUCH){
					if (ev.value == 0) {
						// 触摸点离开
						button = button & 0xfe;//tip switch
					} else if(ev.value == 1) {
						// 触摸开始有触摸
						button = button | 0x01;
					}

				}
			}
		
			// 发送HID报告
			if (ev.type == EV_SYN) {	
				report[0] = 0x01; // 报告ID
				report[1] = button; // 按钮状态button
				report[2] = 0x00; // range
				report[3] = x & 0xff; // X坐标的LSB
				report[4] = (x >> 8) & 0xff; // X坐标的MSB
				report[5] = y & 0xff; // Y坐标的LSB
				report[6] = (y >> 8) & 0xff; // Y坐标的MSB
			}
			else
				continue;
		
			printf("button:%d,track_id:%d,x_low:0x%x,x_high:0x%x,y_low:0x%x,y_high:0x%x\n",report[1],report[2],report[3],report[4],report[5],report[6]);
			// 向/dev/hidg0写入数据
			ret = write(fd_hid, report, 7);
			if (ret < 0) {
				printf("Failed to write to /dev/hidg0\n");
			}
		}
    }
  }
  else
  {
    printf("device open failure\n");
  }

  return 0;
}

  • 8
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值