From a34e43f038c5a8051ea84c2ee9e1655a7478dc9a Mon Sep 17 00:00:00 2001 From: "Javier S. Pedro" Date: Sat, 5 Jul 2014 22:29:59 +0200 Subject: initial import --- Makefile | 6 +++ README | 23 +++++++++++ hidptp.c | 134 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 163 insertions(+) create mode 100644 Makefile create mode 100644 README create mode 100644 hidptp.c diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..036f476 --- /dev/null +++ b/Makefile @@ -0,0 +1,6 @@ +CFLAGS?=-Wall -Os -ggdb + +all: hidptp + +clean: + rm -f hidptp *.o diff --git a/README b/README new file mode 100644 index 0000000..781ba33 --- /dev/null +++ b/README @@ -0,0 +1,23 @@ +hidptp -- a quick and dirty utility to debug Precision Touchpad (PTP) devices + +Build hidptp by typing "make". + +Use the utility as follows: + +./hidptp + +For example, +./hidptp /dev/usb/hiddev0 0 + +will disable PTP mode in device hiddev0. It is hard to know which physical device +"hiddev0" represents, but on my Surface Pro 2 it is the Type Cover v2. You may +need to test hiddev1, hiddev2, etc. + +The utility will print the name of the device (so for a Type/Touch Cover 1/2 it +should be "MICROSOFT SAM"), and then enable or disable PTP mode as requested. + +Current Linux versions can't work when the touchpad is configured in PTP mode. +So in most scenarios you want to disable PTP mode. + +As an additional feature the tool will start listening and dumping events from +the selected device. Stop with Ctrl+C. diff --git a/hidptp.c b/hidptp.c new file mode 100644 index 0000000..9cf9918 --- /dev/null +++ b/hidptp.c @@ -0,0 +1,134 @@ +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +static int devfd; + +static char *get_device_name() +{ + static char buf[1024]; + + if (ioctl(devfd, HIDIOCGNAME(sizeof(buf)), buf) >= 0) { + return buf; + } + + return NULL; +} + +static void process_event(struct hiddev_usage_ref *ev) +{ + printf("0x%x (0x%x): %d\n", ev->usage_code, ev->report_id, ev->value); +} + +static bool send_report(unsigned int report_type, unsigned int report_id) +{ + struct hiddev_report_info rinfo; + rinfo.report_type = report_type; + rinfo.report_id = report_id; + rinfo.num_fields = 0; + + if (ioctl(devfd, HIDIOCSREPORT, &rinfo) < 0) { + perror("HIDIOCSREPORT"); + return false; + } + + printf("Report 0x%x sent\n", rinfo.report_id); + + return true; +} + +static __s32 read_usage(unsigned int report_type, unsigned int usage_code) +{ + struct hiddev_usage_ref uref; + uref.report_type = report_type; + uref.report_id = HID_REPORT_ID_UNKNOWN; + uref.usage_code = usage_code; + + if (ioctl(devfd, HIDIOCGUSAGE, &uref) < 0) { + perror("HIDIOCGUSAGE"); + return -1; + } + + printf("0x%x: %d\n", uref.usage_code, uref.value); + + return uref.value; +} + +static void write_usage(unsigned int report_type, unsigned int usage_code, __s32 value) +{ + struct hiddev_usage_ref uref; + uref.report_type = report_type; + uref.report_id = HID_REPORT_ID_UNKNOWN; + uref.usage_code = usage_code; + + if (ioctl(devfd, HIDIOCGUSAGE, &uref) < 0) { + perror("HIDIOCGUSAGE"); + return; + } + + uref.value = value; + if (ioctl(devfd, HIDIOCSUSAGE, &uref) < 0) + { + perror("HIDIOCSUSAGE"); + return; + } + + printf("0x%x := %d\n", uref.usage_code, uref.value); + + send_report(uref.report_type, uref.report_id); +} + +int main(int argc, const char *argv[]) +{ + if (argc != 3) { + fprintf(stderr, "Usage: %s <0|1>\n", argv[0]); + return EXIT_FAILURE; + } + + const char *device = argv[1]; + const bool enable_ptp = strtol(argv[2], NULL, 10); + + printf("Opening %s...\n", device); + devfd = open(device, O_RDONLY); + + if (devfd == -1) { + perror("Could not open device"); + return EXIT_FAILURE; + } + + printf("Found '%s'\n", get_device_name()); + + // Setup flags + int flags = HIDDEV_FLAG_UREF | HIDDEV_FLAG_REPORT; + if (ioctl(devfd, HIDIOCSFLAG, &flags) < 0) { + perror("HIDIOCSFLAG"); + return EXIT_FAILURE; + } + + write_usage(HID_REPORT_TYPE_FEATURE, 0x0d0052, enable_ptp ? 3 : 0); + + int rc; + do { + struct hiddev_usage_ref ev; + rc = read(devfd, &ev, sizeof(ev)); + if (rc < 0) { + perror("Could not read events from device"); + return EXIT_FAILURE; + } else if (rc == 0) { + } + + process_event(&ev); + } while (rc > 0); + + return EXIT_SUCCESS; +} -- cgit v1.2.3