From 069733643558304d92ec38eab229338dd424f265 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Fri, 18 Mar 2011 14:27:52 +0100 Subject: [PATCH] --- yaml --- r: 248510 b: refs/heads/master c: 9498f954a4ec389806333041a1018909c6fe0518 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/Documentation/hid/hidraw.txt | 119 ------------- trunk/Documentation/{hid => usb}/hiddev.txt | 0 trunk/drivers/hid/hid-multitouch.c | 52 ++++-- trunk/samples/Kconfig | 6 - trunk/samples/Makefile | 2 +- trunk/samples/hidraw/Makefile | 10 -- trunk/samples/hidraw/hid-example.c | 178 -------------------- 8 files changed, 39 insertions(+), 330 deletions(-) delete mode 100644 trunk/Documentation/hid/hidraw.txt rename trunk/Documentation/{hid => usb}/hiddev.txt (100%) delete mode 100644 trunk/samples/hidraw/Makefile delete mode 100644 trunk/samples/hidraw/hid-example.c diff --git a/[refs] b/[refs] index 8e379b34f86d..4c5dd5aec432 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: d431b2e33cd54e4334019a95979ae93aea4735e8 +refs/heads/master: 9498f954a4ec389806333041a1018909c6fe0518 diff --git a/trunk/Documentation/hid/hidraw.txt b/trunk/Documentation/hid/hidraw.txt deleted file mode 100644 index 029e6cb9a7e8..000000000000 --- a/trunk/Documentation/hid/hidraw.txt +++ /dev/null @@ -1,119 +0,0 @@ - HIDRAW - Raw Access to USB and Bluetooth Human Interface Devices - ================================================================== - -The hidraw driver provides a raw interface to USB and Bluetooth Human -Interface Devices (HIDs). It differs from hiddev in that reports sent and -received are not parsed by the HID parser, but are sent to and received from -the device unmodified. - -Hidraw should be used if the userspace application knows exactly how to -communicate with the hardware device, and is able to construct the HID -reports manually. This is often the case when making userspace drivers for -custom HID devices. - -Hidraw is also useful for communicating with non-conformant HID devices -which send and receive data in a way that is inconsistent with their report -descriptors. Because hiddev parses reports which are sent and received -through it, checking them against the device's report descriptor, such -communication with these non-conformant devices is impossible using hiddev. -Hidraw is the only alternative, short of writing a custom kernel driver, for -these non-conformant devices. - -A benefit of hidraw is that its use by userspace applications is independent -of the underlying hardware type. Currently, Hidraw is implemented for USB -and Bluetooth. In the future, as new hardware bus types are developed which -use the HID specification, hidraw will be expanded to add support for these -new bus types. - -Hidraw uses a dynamic major number, meaning that udev should be relied on to -create hidraw device nodes. Udev will typically create the device nodes -directly under /dev (eg: /dev/hidraw0). As this location is distribution- -and udev rule-dependent, applications should use libudev to locate hidraw -devices attached to the system. There is a tutorial on libudev with a -working example at: - http://www.signal11.us/oss/udev/ - -The HIDRAW API ---------------- - -read() -------- -read() will read a queued report received from the HID device. On USB -devices, the reports read using read() are the reports sent from the device -on the INTERRUPT IN endpoint. By default, read() will block until there is -a report available to be read. read() can be made non-blocking, by passing -the O_NONBLOCK flag to open(), or by setting the O_NONBLOCK flag using -fcntl(). - -On a device which uses numbered reports, the first byte of the returned data -will be the report number; the report data follows, beginning in the second -byte. For devices which do not use numbered reports, the report data -will begin at the first byte. - -write() --------- -The write() function will write a report to the device. For USB devices, if -the device has an INTERRUPT OUT endpoint, the report will be sent on that -endpoint. If it does not, the report will be sent over the control endpoint, -using a SET_REPORT transfer. - -The first byte of the buffer passed to write() should be set to the report -number. If the device does not use numbered reports, the first byte should -be set to 0. The report data itself should begin at the second byte. - -ioctl() --------- -Hidraw supports the following ioctls: - -HIDIOCGRDESCSIZE: Get Report Descriptor Size -This ioctl will get the size of the device's report descriptor. - -HIDIOCGRDESC: Get Report Descriptor -This ioctl returns the device's report descriptor using a -hidraw_report_descriptor struct. Make sure to set the size field of the -hidraw_report_descriptor struct to the size returned from HIDIOCGRDESCSIZE. - -HIDIOCGRAWINFO: Get Raw Info -This ioctl will return a hidraw_devinfo struct containing the bus type, the -vendor ID (VID), and product ID (PID) of the device. The bus type can be one -of: - BUS_USB - BUS_HIL - BUS_BLUETOOTH - BUS_VIRTUAL -which are defined in linux/input.h. - -HIDIOCGRAWNAME(len): Get Raw Name -This ioctl returns a string containing the vendor and product strings of -the device. The returned string is Unicode, UTF-8 encoded. - -HIDIOCGRAWPHYS(len): Get Physical Address -This ioctl returns a string representing the physical address of the device. -For USB devices, the string contains the physical path to the device (the -USB controller, hubs, ports, etc). For Bluetooth devices, the string -contains the hardware (MAC) address of the device. - -HIDIOCSFEATURE(len): Send a Feature Report -This ioctl will send a feature report to the device. Per the HID -specification, feature reports are always sent using the control endpoint. -Set the first byte of the supplied buffer to the report number. For devices -which do not use numbered reports, set the first byte to 0. The report data -begins in the second byte. Make sure to set len accordingly, to one more -than the length of the report (to account for the report number). - -HIDIOCGFEATURE(len): Get a Feature Report -This ioctl will request a feature report from the device using the control -endpoint. The first byte of the supplied buffer should be set to the report -number of the requested report. For devices which do not use numbered -reports, set the first byte to 0. The report will be returned starting at -the first byte of the buffer (ie: the report number is not returned). - -Example ---------- -In samples/, find hid-example.c, which shows examples of read(), write(), -and all the ioctls for hidraw. The code may be used by anyone for any -purpose, and can serve as a starting point for developing applications using -hidraw. - -Document by: - Alan Ott , Signal 11 Software diff --git a/trunk/Documentation/hid/hiddev.txt b/trunk/Documentation/usb/hiddev.txt similarity index 100% rename from trunk/Documentation/hid/hiddev.txt rename to trunk/Documentation/usb/hiddev.txt diff --git a/trunk/drivers/hid/hid-multitouch.c b/trunk/drivers/hid/hid-multitouch.c index ee01e65e22d6..b9f9eeceaa98 100644 --- a/trunk/drivers/hid/hid-multitouch.c +++ b/trunk/drivers/hid/hid-multitouch.c @@ -60,8 +60,9 @@ struct mt_device { __s8 inputmode; /* InputMode HID feature, -1 if non-existent */ __u8 num_received; /* how many contacts we received */ __u8 num_expected; /* expected last contact index */ + __u8 maxcontacts; bool curvalid; /* is the current contact valid? */ - struct mt_slot slots[0]; /* first slot */ + struct mt_slot *slots; }; struct mt_class { @@ -79,6 +80,8 @@ struct mt_class { #define MT_CLS_CYPRESS 4 #define MT_CLS_EGALAX 5 +#define MT_DEFAULT_MAXCONTACT 10 + /* * these device-dependent functions determine what slot corresponds * to a valid contact that was just read. @@ -95,12 +98,12 @@ static int cypress_compute_slot(struct mt_device *td) static int find_slot_from_contactid(struct mt_device *td) { int i; - for (i = 0; i < td->mtclass->maxcontacts; ++i) { + for (i = 0; i < td->maxcontacts; ++i) { if (td->slots[i].contactid == td->curdata.contactid && td->slots[i].touch_state) return i; } - for (i = 0; i < td->mtclass->maxcontacts; ++i) { + for (i = 0; i < td->maxcontacts; ++i) { if (!td->slots[i].seen_in_this_frame && !td->slots[i].touch_state) return i; @@ -113,8 +116,7 @@ static int find_slot_from_contactid(struct mt_device *td) struct mt_class mt_classes[] = { { .name = MT_CLS_DEFAULT, - .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP, - .maxcontacts = 10 }, + .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP }, { .name = MT_CLS_DUAL_INRANGE_CONTACTID, .quirks = MT_QUIRK_VALID_IS_INRANGE | MT_QUIRK_SLOT_IS_CONTACTID, @@ -142,9 +144,19 @@ struct mt_class mt_classes[] = { static void mt_feature_mapping(struct hid_device *hdev, struct hid_field *field, struct hid_usage *usage) { - if (usage->hid == HID_DG_INPUTMODE) { - struct mt_device *td = hid_get_drvdata(hdev); + struct mt_device *td = hid_get_drvdata(hdev); + + switch (usage->hid) { + case HID_DG_INPUTMODE: td->inputmode = field->report->id; + break; + case HID_DG_CONTACTMAX: + td->maxcontacts = field->value[0]; + if (td->mtclass->maxcontacts) + /* check if the maxcontacts is given by the class */ + td->maxcontacts = td->mtclass->maxcontacts; + + break; } } @@ -208,8 +220,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, td->last_slot_field = usage->hid; return 1; case HID_DG_CONTACTID: - input_mt_init_slots(hi->input, - td->mtclass->maxcontacts); + input_mt_init_slots(hi->input, td->maxcontacts); td->last_slot_field = usage->hid; return 1; case HID_DG_WIDTH: @@ -292,7 +303,7 @@ static void mt_complete_slot(struct mt_device *td) if (td->curvalid) { int slotnum = mt_compute_slot(td); - if (slotnum >= 0 && slotnum < td->mtclass->maxcontacts) + if (slotnum >= 0 && slotnum < td->maxcontacts) td->slots[slotnum] = td->curdata; } td->num_received++; @@ -307,7 +318,7 @@ static void mt_emit_event(struct mt_device *td, struct input_dev *input) { int i; - for (i = 0; i < td->mtclass->maxcontacts; ++i) { + for (i = 0; i < td->maxcontacts; ++i) { struct mt_slot *s = &(td->slots[i]); if ((td->mtclass->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP) && !s->seen_in_this_frame) { @@ -341,7 +352,7 @@ static int mt_event(struct hid_device *hid, struct hid_field *field, struct mt_device *td = hid_get_drvdata(hid); __s32 quirks = td->mtclass->quirks; - if (hid->claimed & HID_CLAIMED_INPUT) { + if (hid->claimed & HID_CLAIMED_INPUT && td->slots) { switch (usage->hid) { case HID_DG_INRANGE: if (quirks & MT_QUIRK_VALID_IS_INRANGE) @@ -442,9 +453,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) */ hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC; - td = kzalloc(sizeof(struct mt_device) + - mtclass->maxcontacts * sizeof(struct mt_slot), - GFP_KERNEL); + td = kzalloc(sizeof(struct mt_device), GFP_KERNEL); if (!td) { dev_err(&hdev->dev, "cannot allocate multitouch data\n"); return -ENOMEM; @@ -461,6 +470,18 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) if (ret) goto fail; + if (!td->maxcontacts) + td->maxcontacts = MT_DEFAULT_MAXCONTACT; + + td->slots = kzalloc(td->maxcontacts * sizeof(struct mt_slot), + GFP_KERNEL); + if (!td->slots) { + dev_err(&hdev->dev, "cannot allocate multitouch slots\n"); + hid_hw_stop(hdev); + ret = -ENOMEM; + goto fail; + } + mt_set_input_mode(hdev); return 0; @@ -482,6 +503,7 @@ static void mt_remove(struct hid_device *hdev) { struct mt_device *td = hid_get_drvdata(hdev); hid_hw_stop(hdev); + kfree(td->slots); kfree(td); hid_set_drvdata(hdev, NULL); } diff --git a/trunk/samples/Kconfig b/trunk/samples/Kconfig index 977980317a7d..e03cf0e374d7 100644 --- a/trunk/samples/Kconfig +++ b/trunk/samples/Kconfig @@ -61,10 +61,4 @@ config SAMPLE_KDB Build an example of how to dynamically add the hello command to the kdb shell. -config SAMPLE_HIDRAW - bool "Build simple hidraw example" - depends on HIDRAW && HEADERS_CHECK - help - Build an example of how to use hidraw from userspace. - endif # SAMPLES diff --git a/trunk/samples/Makefile b/trunk/samples/Makefile index 6280817c2b7e..f26c0959fd86 100644 --- a/trunk/samples/Makefile +++ b/trunk/samples/Makefile @@ -1,4 +1,4 @@ # Makefile for Linux samples code obj-$(CONFIG_SAMPLES) += kobject/ kprobes/ tracepoints/ trace_events/ \ - hw_breakpoint/ kfifo/ kdb/ hidraw/ + hw_breakpoint/ kfifo/ kdb/ diff --git a/trunk/samples/hidraw/Makefile b/trunk/samples/hidraw/Makefile deleted file mode 100644 index 382eeae77bd6..000000000000 --- a/trunk/samples/hidraw/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# kbuild trick to avoid linker error. Can be omitted if a module is built. -obj- := dummy.o - -# List of programs to build -hostprogs-y := hid-example - -# Tell kbuild to always build the programs -always := $(hostprogs-y) - -HOSTCFLAGS_hid-example.o += -I$(objtree)/usr/include diff --git a/trunk/samples/hidraw/hid-example.c b/trunk/samples/hidraw/hid-example.c deleted file mode 100644 index 816e2dcda7ca..000000000000 --- a/trunk/samples/hidraw/hid-example.c +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Hidraw Userspace Example - * - * Copyright (c) 2010 Alan Ott - * Copyright (c) 2010 Signal 11 Software - * - * The code may be used by anyone for any purpose, - * and can serve as a starting point for developing - * applications using hidraw. - */ - -/* Linux */ -#include -#include -#include - -/* - * Ugly hack to work around failing compilation on systems that don't - * yet populate new version of hidraw.h to userspace. - * - * If you need this, please have your distro update the kernel headers. - */ -#ifndef HIDIOCSFEATURE -#define HIDIOCSFEATURE(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x06, len) -#define HIDIOCGFEATURE(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x07, len) -#endif - -/* Unix */ -#include -#include -#include -#include -#include - -/* C */ -#include -#include -#include -#include - -const char *bus_str(int bus); - -int main(int argc, char **argv) -{ - int fd; - int i, res, desc_size = 0; - char buf[256]; - struct hidraw_report_descriptor rpt_desc; - struct hidraw_devinfo info; - - /* Open the Device with non-blocking reads. In real life, - don't use a hard coded path; use libudev instead. */ - fd = open("/dev/hidraw0", O_RDWR|O_NONBLOCK); - - if (fd < 0) { - perror("Unable to open device"); - return 1; - } - - memset(&rpt_desc, 0x0, sizeof(rpt_desc)); - memset(&info, 0x0, sizeof(info)); - memset(buf, 0x0, sizeof(buf)); - - /* Get Report Descriptor Size */ - res = ioctl(fd, HIDIOCGRDESCSIZE, &desc_size); - if (res < 0) - perror("HIDIOCGRDESCSIZE"); - else - printf("Report Descriptor Size: %d\n", desc_size); - - /* Get Report Descriptor */ - rpt_desc.size = desc_size; - res = ioctl(fd, HIDIOCGRDESC, &rpt_desc); - if (res < 0) { - perror("HIDIOCGRDESC"); - } else { - printf("Report Descriptor:\n"); - for (i = 0; i < rpt_desc.size; i++) - printf("%hhx ", rpt_desc.value[i]); - puts("\n"); - } - - /* Get Raw Name */ - res = ioctl(fd, HIDIOCGRAWNAME(256), buf); - if (res < 0) - perror("HIDIOCGRAWNAME"); - else - printf("Raw Name: %s\n", buf); - - /* Get Physical Location */ - res = ioctl(fd, HIDIOCGRAWPHYS(256), buf); - if (res < 0) - perror("HIDIOCGRAWPHYS"); - else - printf("Raw Phys: %s\n", buf); - - /* Get Raw Info */ - res = ioctl(fd, HIDIOCGRAWINFO, &info); - if (res < 0) { - perror("HIDIOCGRAWINFO"); - } else { - printf("Raw Info:\n"); - printf("\tbustype: %d (%s)\n", - info.bustype, bus_str(info.bustype)); - printf("\tvendor: 0x%04hx\n", info.vendor); - printf("\tproduct: 0x%04hx\n", info.product); - } - - /* Set Feature */ - buf[0] = 0x9; /* Report Number */ - buf[1] = 0xff; - buf[2] = 0xff; - buf[3] = 0xff; - res = ioctl(fd, HIDIOCSFEATURE(4), buf); - if (res < 0) - perror("HIDIOCSFEATURE"); - else - printf("ioctl HIDIOCGFEATURE returned: %d\n", res); - - /* Get Feature */ - buf[0] = 0x9; /* Report Number */ - res = ioctl(fd, HIDIOCGFEATURE(256), buf); - if (res < 0) { - perror("HIDIOCGFEATURE"); - } else { - printf("ioctl HIDIOCGFEATURE returned: %d\n", res); - printf("Report data (not containing the report number):\n\t"); - for (i = 0; i < res; i++) - printf("%hhx ", buf[i]); - puts("\n"); - } - - /* Send a Report to the Device */ - buf[0] = 0x1; /* Report Number */ - buf[1] = 0x77; - res = write(fd, buf, 2); - if (res < 0) { - printf("Error: %d\n", errno); - perror("write"); - } else { - printf("write() wrote %d bytes\n", res); - } - - /* Get a report from the device */ - res = read(fd, buf, 16); - if (res < 0) { - perror("read"); - } else { - printf("read() read %d bytes:\n\t", res); - for (i = 0; i < res; i++) - printf("%hhx ", buf[i]); - puts("\n"); - } - close(fd); - return 0; -} - -const char * -bus_str(int bus) -{ - switch (bus) { - case BUS_USB: - return "USB"; - break; - case BUS_HIL: - return "HIL"; - break; - case BUS_BLUETOOTH: - return "Bluetooth"; - break; - case BUS_VIRTUAL: - return "Virtual"; - break; - default: - return "Other"; - break; - } -}