From 423dfbc362b76b8a51745187a0c7e00d056d5b59 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 9 May 2019 13:47:04 +0200 Subject: HID: logitech-dj: Add usb-id for the 27MHz MX3000 receiver Testing has shown that, as expected, the MX3000 receiver is fully compatible with the existing 27MHz receiver support in hid-logitech-dj.c. After this the only, presumably also compatible, receiver id left in hid-lg.c is the USB_DEVICE_ID_S510_RECEIVER / 0xc50c id. If we can get someone to confirm that this receiver works with the dj 27Mhz support too, then the handling of the LG_RDESC and LG_WIRELESS quirks can be removed from hid-lg.c. Signed-off-by: Hans de Goede Signed-off-by: Jiri Kosina --- drivers/hid/hid-lg.c | 2 -- drivers/hid/hid-logitech-dj.c | 3 +++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c index 36d725fdb199..3f6be4aebfaf 100644 --- a/drivers/hid/hid-lg.c +++ b/drivers/hid/hid-lg.c @@ -872,8 +872,6 @@ static void lg_remove(struct hid_device *hdev) } static const struct hid_device_id lg_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER), - .driver_data = LG_RDESC | LG_WIRELESS }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER), .driver_data = LG_RDESC | LG_WIRELESS }, diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index b1e894618eed..e09c8e02351c 100644 --- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c @@ -1835,6 +1835,9 @@ static const struct hid_device_id logi_dj_receivers[] = { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_GAMING), .driver_data = recvr_type_gaming_hidpp}, + { /* Logitech 27 MHz HID++ 1.0 receiver (0xc513) */ + HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER), + .driver_data = recvr_type_27mhz}, { /* Logitech 27 MHz HID++ 1.0 receiver (0xc517) */ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2), -- cgit v1.2.3 From d8e9806005f28bbb49899dab2068e3359e22ba35 Mon Sep 17 00:00:00 2001 From: Aaron Armstrong Skomra Date: Fri, 10 May 2019 15:31:16 -0700 Subject: HID: wacom: generic: only switch the mode on devices with LEDs Currently, the driver will attempt to set the mode on all devices with a center button, but some devices with a center button lack LEDs, and attempting to set the LEDs on devices without LEDs results in the kernel error message of the form: "leds input8::wacom-0.1: Setting an LED's brightness failed (-32)" This is because the generic codepath erroneously assumes that the BUTTON_CENTER usage indicates that the device has LEDs, the previously ignored TOUCH_RING_SETTING usage is a more accurate indication of the existence of LEDs on the device. Fixes: 10c55cacb8b2 ("HID: wacom: generic: support LEDs") Cc: # v4.11+ Signed-off-by: Aaron Armstrong Skomra Reviewed-by: Jason Gerecke Signed-off-by: Jiri Kosina --- drivers/hid/wacom_sys.c | 3 +++ drivers/hid/wacom_wac.c | 2 -- drivers/hid/wacom_wac.h | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index a8633b1437b2..2e3e03df83da 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -307,6 +307,9 @@ static void wacom_feature_mapping(struct hid_device *hdev, wacom_hid_usage_quirk(hdev, field, usage); switch (equivalent_usage) { + case WACOM_HID_WD_TOUCH_RING_SETTING: + wacom->generic_has_leds = true; + break; case HID_DG_CONTACTMAX: /* leave touch_max as is if predefined */ if (!features->touch_max) { diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 747730d32ab6..62bf8ec6023e 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -1906,8 +1906,6 @@ static void wacom_wac_pad_usage_mapping(struct hid_device *hdev, features->device_type |= WACOM_DEVICETYPE_PAD; break; case WACOM_HID_WD_BUTTONCENTER: - wacom->generic_has_leds = true; - /* fall through */ case WACOM_HID_WD_BUTTONHOME: case WACOM_HID_WD_BUTTONUP: case WACOM_HID_WD_BUTTONDOWN: diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h index 295fd3718caa..f67d871841c0 100644 --- a/drivers/hid/wacom_wac.h +++ b/drivers/hid/wacom_wac.h @@ -145,6 +145,7 @@ #define WACOM_HID_WD_OFFSETBOTTOM (WACOM_HID_UP_WACOMDIGITIZER | 0x0d33) #define WACOM_HID_WD_DATAMODE (WACOM_HID_UP_WACOMDIGITIZER | 0x1002) #define WACOM_HID_WD_DIGITIZERINFO (WACOM_HID_UP_WACOMDIGITIZER | 0x1013) +#define WACOM_HID_WD_TOUCH_RING_SETTING (WACOM_HID_UP_WACOMDIGITIZER | 0x1032) #define WACOM_HID_UP_G9 0xff090000 #define WACOM_HID_G9_PEN (WACOM_HID_UP_G9 | 0x02) #define WACOM_HID_G9_TOUCHSCREEN (WACOM_HID_UP_G9 | 0x11) -- cgit v1.2.3 From d4b8efeb46d99a5d02e7f88ac4eaccbe49370770 Mon Sep 17 00:00:00 2001 From: Aaron Armstrong Skomra Date: Fri, 10 May 2019 15:34:17 -0700 Subject: HID: wacom: generic: Correct pad syncing Only sync the pad once per report, not once per collection. Also avoid syncing the pad on battery reports. Fixes: f8b6a74719b5 ("HID: wacom: generic: Support multiple tools per report") Cc: # v4.17+ Signed-off-by: Aaron Armstrong Skomra Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 62bf8ec6023e..ed6726eeeae5 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -2097,14 +2097,12 @@ static void wacom_wac_pad_report(struct hid_device *hdev, bool active = wacom_wac->hid_data.inrange_state != 0; /* report prox for expresskey events */ - if ((wacom_equivalent_usage(field->physical) == HID_DG_TABLETFUNCTIONKEY) && - wacom_wac->hid_data.pad_input_event_flag) { + if (wacom_wac->hid_data.pad_input_event_flag) { input_event(input, EV_ABS, ABS_MISC, active ? PAD_DEVICE_ID : 0); input_sync(input); if (!active) wacom_wac->hid_data.pad_input_event_flag = false; } - } static void wacom_wac_pen_usage_mapping(struct hid_device *hdev, @@ -2680,9 +2678,7 @@ static int wacom_wac_collection(struct hid_device *hdev, struct hid_report *repo if (report->type != HID_INPUT_REPORT) return -1; - if (WACOM_PAD_FIELD(field) && wacom->wacom_wac.pad_input) - wacom_wac_pad_report(hdev, report, field); - else if (WACOM_PEN_FIELD(field) && wacom->wacom_wac.pen_input) + if (WACOM_PEN_FIELD(field) && wacom->wacom_wac.pen_input) wacom_wac_pen_report(hdev, report); else if (WACOM_FINGER_FIELD(field) && wacom->wacom_wac.touch_input) wacom_wac_finger_report(hdev, report); @@ -2696,7 +2692,7 @@ void wacom_wac_report(struct hid_device *hdev, struct hid_report *report) struct wacom_wac *wacom_wac = &wacom->wacom_wac; struct hid_field *field; bool pad_in_hid_field = false, pen_in_hid_field = false, - finger_in_hid_field = false; + finger_in_hid_field = false, true_pad = false; int r; int prev_collection = -1; @@ -2712,6 +2708,8 @@ void wacom_wac_report(struct hid_device *hdev, struct hid_report *report) pen_in_hid_field = true; if (WACOM_FINGER_FIELD(field)) finger_in_hid_field = true; + if (wacom_equivalent_usage(field->physical) == HID_DG_TABLETFUNCTIONKEY) + true_pad = true; } wacom_wac_battery_pre_report(hdev, report); @@ -2735,6 +2733,9 @@ void wacom_wac_report(struct hid_device *hdev, struct hid_report *report) } wacom_wac_battery_report(hdev, report); + + if (true_pad && wacom->wacom_wac.pad_input) + wacom_wac_pad_report(hdev, report, field); } static int wacom_bpt_touch(struct wacom_wac *wacom) -- cgit v1.2.3 From 68c20cc2164cc5c7c73f8012ae6491afdb1f7f72 Mon Sep 17 00:00:00 2001 From: Aaron Armstrong Skomra Date: Fri, 10 May 2019 15:34:18 -0700 Subject: HID: wacom: correct touch resolution x/y typo This affects the 2nd-gen Intuos Pro Medium and Large when using their Bluetooth connection. Fixes: 4922cd26f03c ("HID: wacom: Support 2nd-gen Intuos Pro's Bluetooth classic interface") Cc: # v4.11+ Signed-off-by: Aaron Armstrong Skomra Reviewed-by: Jason Gerecke Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index ed6726eeeae5..a98ad4fdcf9e 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -3692,7 +3692,7 @@ int wacom_setup_touch_input_capabilities(struct input_dev *input_dev, 0, 5920, 4, 0); } input_abs_set_res(input_dev, ABS_MT_POSITION_X, 40); - input_abs_set_res(input_dev, ABS_MT_POSITION_X, 40); + input_abs_set_res(input_dev, ABS_MT_POSITION_Y, 40); /* fall through */ -- cgit v1.2.3 From 39d21e7e004340417395884979882e5d749a6157 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 10 May 2019 14:10:39 +0100 Subject: HID: logitech-dj: make const array template static Don't populate the array template on the stack but instead make it static. Makes the object code smaller by 10 bytes. Also reformat the declaration. Before: text data bss dec hex filename 29376 9360 128 38864 97d0 drivers/hid/hid-logitech-dj.o After: text data bss dec hex filename 29270 9456 128 38854 97c6 drivers/hid/hid-logitech-dj.o (gcc version 8.3.0, amd64) Signed-off-by: Colin Ian King Signed-off-by: Jiri Kosina --- drivers/hid/hid-logitech-dj.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index e09c8e02351c..1cbd898bbdc3 100644 --- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c @@ -1111,12 +1111,14 @@ static int logi_dj_recv_send_report(struct dj_receiver_dev *djrcv_dev, static int logi_dj_recv_query_hidpp_devices(struct dj_receiver_dev *djrcv_dev) { - const u8 template[] = {REPORT_ID_HIDPP_SHORT, - HIDPP_RECEIVER_INDEX, - HIDPP_SET_REGISTER, - HIDPP_REG_CONNECTION_STATE, - HIDPP_FAKE_DEVICE_ARRIVAL, - 0x00, 0x00}; + static const u8 template[] = { + REPORT_ID_HIDPP_SHORT, + HIDPP_RECEIVER_INDEX, + HIDPP_SET_REGISTER, + HIDPP_REG_CONNECTION_STATE, + HIDPP_FAKE_DEVICE_ARRIVAL, + 0x00, 0x00 + }; u8 *hidpp_report; int retval; -- cgit v1.2.3 From a96a8a576bf5cc45534d0079d7006fc3fe25282b Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 10 May 2019 14:17:22 +0100 Subject: HID: logitech-hidpp: HID: make const array consumer_rdesc_start static Don't populate the array consumer_rdesc_start on the stack but instead make it static. Makes the object code smaller by 88 bytes. Before: text data bss dec hex filename 59155 9840 448 69443 10f43 drivers/hid/hid-logitech-hidpp.o After: text data bss dec hex filename 59003 9904 448 69355 10eeb drivers/hid/hid-logitech-hidpp.o (gcc version 8.3.0, amd64) Signed-off-by: Colin Ian King Signed-off-by: Jiri Kosina --- drivers/hid/hid-logitech-hidpp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c index 72fc9c0566db..df960491e473 100644 --- a/drivers/hid/hid-logitech-hidpp.c +++ b/drivers/hid/hid-logitech-hidpp.c @@ -2862,7 +2862,7 @@ static u8 *hidpp10_consumer_keys_report_fixup(struct hidpp_device *hidpp, u8 *_rdesc, unsigned int *rsize) { /* Note 0 terminated so we can use strnstr to search for this. */ - const char consumer_rdesc_start[] = { + static const char consumer_rdesc_start[] = { 0x05, 0x0C, /* USAGE_PAGE (Consumer Devices) */ 0x09, 0x01, /* USAGE (Consumer Control) */ 0xA1, 0x01, /* COLLECTION (Application) */ -- cgit v1.2.3 From dbcbabf7da921f98beefb4a6f4b91eb62d072076 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 25 May 2019 22:09:08 +0800 Subject: HID: logitech-dj: fix return value of logi_dj_recv_query_hidpp_devices We should return 'retval' as the correct return value instead of always zero. Fixes: 74808f9115ce ("HID: logitech-dj: add support for non unifying receivers") Signed-off-by: YueHaibing Reviewed-by: Hans de Goede Signed-off-by: Benjamin Tissoires --- drivers/hid/hid-logitech-dj.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index 1cbd898bbdc3..d644d5a815f0 100644 --- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c @@ -1133,7 +1133,7 @@ static int logi_dj_recv_query_hidpp_devices(struct dj_receiver_dev *djrcv_dev) HID_REQ_SET_REPORT); kfree(hidpp_report); - return 0; + return retval; } static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev) -- cgit v1.2.3 From 88bb346dd63b65e5cb4922466cffbbb27d24f08d Mon Sep 17 00:00:00 2001 From: Wang Xuerui Date: Sat, 8 Jun 2019 17:23:24 +0800 Subject: HID: uclogic: Add support for Ugee Rainbow CV720 Add support for Ugee Rainbow CV720 to hid-uclogic. Signed-off-by: Wang Xuerui Reviewed-by: Nikolai Kondrashov Signed-off-by: Benjamin Tissoires --- drivers/hid/hid-ids.h | 1 + drivers/hid/hid-uclogic-core.c | 2 ++ drivers/hid/hid-uclogic-params.c | 2 ++ 3 files changed, 5 insertions(+) diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 1c8c72093b5a..3ab3f5d221a8 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -1156,6 +1156,7 @@ #define USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01 0x0042 #define USB_DEVICE_ID_UGEE_TABLET_G5 0x0074 #define USB_DEVICE_ID_UGEE_TABLET_EX07S 0x0071 +#define USB_DEVICE_ID_UGEE_TABLET_RAINBOW_CV720 0x0055 #define USB_VENDOR_ID_UNITEC 0x227d #define USB_DEVICE_ID_UNITEC_USB_TOUCH_0709 0x0709 diff --git a/drivers/hid/hid-uclogic-core.c b/drivers/hid/hid-uclogic-core.c index 8fe02d81265d..490c1ddb350c 100644 --- a/drivers/hid/hid-uclogic-core.c +++ b/drivers/hid/hid-uclogic-core.c @@ -387,6 +387,8 @@ static const struct hid_device_id uclogic_devices[] = { USB_DEVICE_ID_UGEE_TABLET_G5) }, { HID_USB_DEVICE(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_TABLET_EX07S) }, + { HID_USB_DEVICE(USB_VENDOR_ID_UGEE, + USB_DEVICE_ID_UGEE_TABLET_RAINBOW_CV720) }, { HID_USB_DEVICE(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_XPPEN_TABLET_G540) }, { HID_USB_DEVICE(USB_VENDOR_ID_UGEE, diff --git a/drivers/hid/hid-uclogic-params.c b/drivers/hid/hid-uclogic-params.c index 0187c9f8fc22..8e120dde31fa 100644 --- a/drivers/hid/hid-uclogic-params.c +++ b/drivers/hid/hid-uclogic-params.c @@ -999,6 +999,8 @@ int uclogic_params_init(struct uclogic_params *params, USB_DEVICE_ID_UGEE_XPPEN_TABLET_G540): case VID_PID(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_XPPEN_TABLET_G640): + case VID_PID(USB_VENDOR_ID_UGEE, + USB_DEVICE_ID_UGEE_TABLET_RAINBOW_CV720): /* If this is the pen interface */ if (bInterfaceNumber == 1) { /* Probe v1 pen parameters */ -- cgit v1.2.3 From 912c6aa67ad4252dc92e6569cfcb32ee44575183 Mon Sep 17 00:00:00 2001 From: Aaron Armstrong Skomra Date: Wed, 12 Jun 2019 14:19:28 -0700 Subject: HID: wacom: Add 2nd gen Intuos Pro Small support The existing INTUOSP2_BT device class supports LEDs and this device does not. A new device class enum entry, "INTUOSP2S_BT", is created to avoid the INTUOSP2_BT LED code. Signed-off-by: Aaron Armstrong Skomra Reviewed-by: Jason Gerecke Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.c | 30 +++++++++++++++++++++++++----- drivers/hid/wacom_wac.h | 1 + 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index a98ad4fdcf9e..b764e9d72b5b 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -1220,7 +1220,8 @@ static void wacom_intuos_pro2_bt_pen(struct wacom_wac *wacom) unsigned char *data = wacom->data; int i; - if (wacom->features.type == INTUOSP2_BT) { + if (wacom->features.type == INTUOSP2_BT || + wacom->features.type == INTUOSP2S_BT) { wacom->serial[0] = get_unaligned_le64(&data[99]); wacom->id[0] = get_unaligned_le16(&data[107]); pen_frame_len = 14; @@ -1257,7 +1258,8 @@ static void wacom_intuos_pro2_bt_pen(struct wacom_wac *wacom) input_report_abs(pen_input, ABS_X, get_unaligned_le16(&frame[1])); input_report_abs(pen_input, ABS_Y, get_unaligned_le16(&frame[3])); - if (wacom->features.type == INTUOSP2_BT) { + if (wacom->features.type == INTUOSP2_BT || + wacom->features.type == INTUOSP2S_BT) { /* Fix rotation alignment: userspace expects zero at left */ int16_t rotation = (int16_t)get_unaligned_le16(&frame[9]); @@ -1276,7 +1278,8 @@ static void wacom_intuos_pro2_bt_pen(struct wacom_wac *wacom) } } input_report_abs(pen_input, ABS_PRESSURE, get_unaligned_le16(&frame[5])); - if (wacom->features.type == INTUOSP2_BT) { + if (wacom->features.type == INTUOSP2_BT || + wacom->features.type == INTUOSP2S_BT) { input_report_abs(pen_input, ABS_DISTANCE, range ? frame[13] : wacom->features.distance_max); } else { @@ -1436,7 +1439,8 @@ static int wacom_intuos_pro2_bt_irq(struct wacom_wac *wacom, size_t len) } wacom_intuos_pro2_bt_pen(wacom); - if (wacom->features.type == INTUOSP2_BT) { + if (wacom->features.type == INTUOSP2_BT || + wacom->features.type == INTUOSP2S_BT) { wacom_intuos_pro2_bt_touch(wacom); wacom_intuos_pro2_bt_pad(wacom); wacom_intuos_pro2_bt_battery(wacom); @@ -3204,6 +3208,7 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) break; case INTUOSP2_BT: + case INTUOSP2S_BT: case INTUOSHT3_BT: sync = wacom_intuos_pro2_bt_irq(wacom_wac, len); break; @@ -3384,7 +3389,8 @@ void wacom_setup_device_quirks(struct wacom *wacom) if (features->type == REMOTE) features->device_type = WACOM_DEVICETYPE_PAD; - if (features->type == INTUOSP2_BT) { + if (features->type == INTUOSP2_BT || + features->type == INTUOSP2S_BT) { features->device_type |= WACOM_DEVICETYPE_PEN | WACOM_DEVICETYPE_PAD | WACOM_DEVICETYPE_TOUCH; @@ -3565,6 +3571,7 @@ int wacom_setup_pen_input_capabilities(struct input_dev *input_dev, case INTUOS5S: case INTUOSPS: case INTUOSP2_BT: + case INTUOSP2S_BT: input_set_abs_params(input_dev, ABS_DISTANCE, 0, features->distance_max, features->distance_fuzz, 0); @@ -3676,6 +3683,7 @@ int wacom_setup_touch_input_capabilities(struct input_dev *input_dev, switch (features->type) { case INTUOSP2_BT: + case INTUOSP2S_BT: input_dev->evbit[0] |= BIT_MASK(EV_SW); __set_bit(SW_MUTE_DEVICE, input_dev->swbit); @@ -3691,6 +3699,12 @@ int wacom_setup_touch_input_capabilities(struct input_dev *input_dev, input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, 5920, 4, 0); } + else if (wacom_wac->shared->touch->product == 0x393) { + input_set_abs_params(input_dev, ABS_MT_POSITION_X, + 0, 6400, 4, 0); + input_set_abs_params(input_dev, ABS_MT_POSITION_Y, + 0, 4000, 4, 0); + } input_abs_set_res(input_dev, ABS_MT_POSITION_X, 40); input_abs_set_res(input_dev, ABS_MT_POSITION_Y, 40); @@ -3997,6 +4011,7 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev, case INTUOS5S: case INTUOSPS: case INTUOSP2_BT: + case INTUOSP2S_BT: input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0); break; @@ -4574,6 +4589,10 @@ static const struct wacom_features wacom_features_0x37A = static const struct wacom_features wacom_features_0x37B = { "Wacom One by Wacom M", 21600, 13500, 2047, 63, BAMBOO_PEN, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; +static const struct wacom_features wacom_features_0x393 = + { "Wacom Intuos Pro S", 31920, 19950, 8191, 63, + INTUOSP2S_BT, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 7, + .touch_max = 10 }; static const struct wacom_features wacom_features_HID_ANY_ID = { "Wacom HID", .type = HID_GENERIC, .oVid = HID_ANY_ID, .oPid = HID_ANY_ID }; @@ -4746,6 +4765,7 @@ const struct hid_device_id wacom_ids[] = { { BT_DEVICE_WACOM(0x379) }, { USB_DEVICE_WACOM(0x37A) }, { USB_DEVICE_WACOM(0x37B) }, + { BT_DEVICE_WACOM(0x393) }, { USB_DEVICE_WACOM(0x4001) }, { USB_DEVICE_WACOM(0x4004) }, { USB_DEVICE_WACOM(0x5000) }, diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h index f67d871841c0..48f08f8a556d 100644 --- a/drivers/hid/wacom_wac.h +++ b/drivers/hid/wacom_wac.h @@ -215,6 +215,7 @@ enum { INTUOSPM, INTUOSPL, INTUOSP2_BT, + INTUOSP2S_BT, INTUOSHT3_BT, WACOM_21UX2, WACOM_22HD, -- cgit v1.2.3 From 184eccd40389df29abefab88092c4ff33191fd0c Mon Sep 17 00:00:00 2001 From: Aaron Armstrong Skomra Date: Wed, 12 Jun 2019 14:19:29 -0700 Subject: HID: wacom: generic: read HID_DG_CONTACTMAX from any feature report In the generic code path, HID_DG_CONTACTMAX was previously only read from the second byte of report 0x23. Another report (0x82) has the HID_DG_CONTACTMAX in the higher nibble of the third byte. We should support reading the value of HID_DG_CONTACTMAX no matter what report we are reading or which position that value is in. To do this we submit the feature report as a event report using hid_report_raw_event(). Our modified finger event path records the value of HID_DG_CONTACTMAX when it sees that usage. Fixes: 8ffffd5212846 ("HID: wacom: fix timeout on probe for some wacoms") Signed-off-by: Aaron Armstrong Skomra Signed-off-by: Jiri Kosina --- drivers/hid/wacom_sys.c | 10 ++++++---- drivers/hid/wacom_wac.c | 4 ++++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index 2e3e03df83da..9ec895e5fd00 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -314,14 +314,16 @@ static void wacom_feature_mapping(struct hid_device *hdev, /* leave touch_max as is if predefined */ if (!features->touch_max) { /* read manually */ - data = kzalloc(2, GFP_KERNEL); + n = hid_report_len(field->report); + data = hid_alloc_report_buf(field->report, GFP_KERNEL); if (!data) break; data[0] = field->report->id; ret = wacom_get_report(hdev, HID_FEATURE_REPORT, - data, 2, WAC_CMD_RETRIES); - if (ret == 2) { - features->touch_max = data[1]; + data, n, WAC_CMD_RETRIES); + if (ret == n) { + ret = hid_report_raw_event(hdev, + HID_FEATURE_REPORT, data, n, 0); } else { features->touch_max = 16; hid_warn(hdev, "wacom_feature_mapping: " diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index b764e9d72b5b..678f504239a0 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -2492,6 +2492,7 @@ static void wacom_wac_finger_event(struct hid_device *hdev, struct wacom *wacom = hid_get_drvdata(hdev); struct wacom_wac *wacom_wac = &wacom->wacom_wac; unsigned equivalent_usage = wacom_equivalent_usage(usage->hid); + struct wacom_features *features = &wacom->wacom_wac.features; switch (equivalent_usage) { case HID_GD_X: @@ -2512,6 +2513,9 @@ static void wacom_wac_finger_event(struct hid_device *hdev, case HID_DG_TIPSWITCH: wacom_wac->hid_data.tipswitch = value; break; + case HID_DG_CONTACTMAX: + features->touch_max = value; + return; } -- cgit v1.2.3 From f4e11d599610a61e978f722f6ade660872a43816 Mon Sep 17 00:00:00 2001 From: Aaron Armstrong Skomra Date: Wed, 12 Jun 2019 14:19:30 -0700 Subject: HID: wacom: generic: support the 'report valid' usage for touch Finger data is separated into chunks in our Bluetooth report, where each report contains the same number of chunks. Those chunks are not aligned in any particular way to a set of finger touches. That is, the first half of a group of simultaneous touches may be in one chunk at the end of a report and the second half could be at the beginning of the next report. Also some chunks contain no data and potentially some chunks could contain leftover (bad) data. Introduce and process the WACOM_HID_WT_REPORT_VALID usage that the device uses to let us know if we should process a chunk of data. Signed-off-by: Aaron Armstrong Skomra Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.c | 12 +++++++++++- drivers/hid/wacom_wac.h | 1 + 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 678f504239a0..67ecd149ad21 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -1752,6 +1752,9 @@ int wacom_equivalent_usage(int usage) int subpage = (usage & 0xFF00) << 8; int subusage = (usage & 0xFF); + if (usage == WACOM_HID_WT_REPORT_VALID) + return usage; + if (subpage == HID_UP_UNDEFINED) subpage = WACOM_HID_SP_DIGITIZER; @@ -2494,6 +2497,9 @@ static void wacom_wac_finger_event(struct hid_device *hdev, unsigned equivalent_usage = wacom_equivalent_usage(usage->hid); struct wacom_features *features = &wacom->wacom_wac.features; + if (wacom_wac->is_invalid_bt_frame) + return; + switch (equivalent_usage) { case HID_GD_X: wacom_wac->hid_data.x = value; @@ -2513,12 +2519,14 @@ static void wacom_wac_finger_event(struct hid_device *hdev, case HID_DG_TIPSWITCH: wacom_wac->hid_data.tipswitch = value; break; + case WACOM_HID_WT_REPORT_VALID: + wacom_wac->is_invalid_bt_frame = !value; + return; case HID_DG_CONTACTMAX: features->touch_max = value; return; } - if (usage->usage_index + 1 == field->report_count) { if (equivalent_usage == wacom_wac->hid_data.last_slot_field) wacom_wac_finger_slot(wacom_wac, wacom_wac->touch_input); @@ -2533,6 +2541,8 @@ static void wacom_wac_finger_pre_report(struct hid_device *hdev, struct hid_data* hid_data = &wacom_wac->hid_data; int i; + wacom_wac->is_invalid_bt_frame = false; + for (i = 0; i < report->maxfield; i++) { struct hid_field *field = report->field[i]; int j; diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h index 48f08f8a556d..1cb63a4a0a41 100644 --- a/drivers/hid/wacom_wac.h +++ b/drivers/hid/wacom_wac.h @@ -159,6 +159,7 @@ #define WACOM_HID_WT_SERIALNUMBER (WACOM_HID_UP_WACOMTOUCH | 0x5b) #define WACOM_HID_WT_X (WACOM_HID_UP_WACOMTOUCH | 0x130) #define WACOM_HID_WT_Y (WACOM_HID_UP_WACOMTOUCH | 0x131) +#define WACOM_HID_WT_REPORT_VALID (WACOM_HID_UP_WACOMTOUCH | 0x1d0) #define WACOM_BATTERY_USAGE(f) (((f)->hid == HID_DG_BATTERYSTRENGTH) || \ ((f)->hid == WACOM_HID_WD_BATTERY_CHARGING) || \ -- cgit v1.2.3 From 15893fa40109f5e7c67eeb8da62267d0fdf0be9d Mon Sep 17 00:00:00 2001 From: Aaron Armstrong Skomra Date: Wed, 12 Jun 2019 14:19:31 -0700 Subject: HID: wacom: generic: read the number of expected touches on a per collection basis Bluetooth connections may contain more than one set of touches, or a partial set of touches, in one report. Set the number of expected touches when reading a collection instead of once per report (in the pre-report function). Accordingly, reset the number of touches expected after each sync. Signed-off-by: Aaron Armstrong Skomra Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.c | 79 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 63 insertions(+), 16 deletions(-) diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 67ecd149ad21..104e6d1f4c80 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -2563,25 +2563,9 @@ static void wacom_wac_finger_pre_report(struct hid_device *hdev, case HID_DG_TIPSWITCH: hid_data->last_slot_field = equivalent_usage; break; - case HID_DG_CONTACTCOUNT: - hid_data->cc_report = report->id; - hid_data->cc_index = i; - hid_data->cc_value_index = j; - break; } } } - - if (hid_data->cc_report != 0 && - hid_data->cc_index >= 0) { - struct hid_field *field = report->field[hid_data->cc_index]; - int value = field->value[hid_data->cc_value_index]; - if (value) - hid_data->num_expected = value; - } - else { - hid_data->num_expected = wacom_wac->features.touch_max; - } } static void wacom_wac_finger_report(struct hid_device *hdev, @@ -2591,6 +2575,7 @@ static void wacom_wac_finger_report(struct hid_device *hdev, struct wacom_wac *wacom_wac = &wacom->wacom_wac; struct input_dev *input = wacom_wac->touch_input; unsigned touch_max = wacom_wac->features.touch_max; + struct hid_data *hid_data = &wacom_wac->hid_data; /* If more packets of data are expected, give us a chance to * process them rather than immediately syncing a partial @@ -2604,6 +2589,7 @@ static void wacom_wac_finger_report(struct hid_device *hdev, input_sync(input); wacom_wac->hid_data.num_received = 0; + hid_data->num_expected = 0; /* keep touch state for pen event */ wacom_wac->shared->touch_down = wacom_wac_finger_count_touches(wacom_wac); @@ -2678,12 +2664,73 @@ static void wacom_report_events(struct hid_device *hdev, } } +static void wacom_set_num_expected(struct hid_device *hdev, + struct hid_report *report, + int collection_index, + struct hid_field *field, + int field_index) +{ + struct wacom *wacom = hid_get_drvdata(hdev); + struct wacom_wac *wacom_wac = &wacom->wacom_wac; + struct hid_data *hid_data = &wacom_wac->hid_data; + unsigned int original_collection_level = + hdev->collection[collection_index].level; + bool end_collection = false; + int i; + + if (hid_data->num_expected) + return; + + // find the contact count value for this segment + for (i = field_index; i < report->maxfield && !end_collection; i++) { + struct hid_field *field = report->field[i]; + unsigned int field_level = + hdev->collection[field->usage[0].collection_index].level; + unsigned int j; + + if (field_level != original_collection_level) + continue; + + for (j = 0; j < field->maxusage; j++) { + struct hid_usage *usage = &field->usage[j]; + + if (usage->collection_index != collection_index) { + end_collection = true; + break; + } + if (wacom_equivalent_usage(usage->hid) == HID_DG_CONTACTCOUNT) { + hid_data->cc_report = report->id; + hid_data->cc_index = i; + hid_data->cc_value_index = j; + + if (hid_data->cc_report != 0 && + hid_data->cc_index >= 0) { + + struct hid_field *field = + report->field[hid_data->cc_index]; + int value = + field->value[hid_data->cc_value_index]; + + if (value) + hid_data->num_expected = value; + } + } + } + } + + if (hid_data->cc_report == 0 || hid_data->cc_index < 0) + hid_data->num_expected = wacom_wac->features.touch_max; +} + static int wacom_wac_collection(struct hid_device *hdev, struct hid_report *report, int collection_index, struct hid_field *field, int field_index) { struct wacom *wacom = hid_get_drvdata(hdev); + if (WACOM_FINGER_FIELD(field)) + wacom_set_num_expected(hdev, report, collection_index, field, + field_index); wacom_report_events(hdev, report, collection_index, field_index); /* -- cgit v1.2.3 From 384225c2a7243d073495aa3a6ec07ad25d01bbfe Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Sun, 23 Jun 2019 16:52:43 -0700 Subject: HID: wacom: add new MobileStudio Pro support Add product ID for new MobileStudio Pro. Signed-off-by: Ping Cheng Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 104e6d1f4c80..e35d04451595 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -2028,12 +2028,14 @@ static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field */ if (hdev->vendor == 0x56a && (hdev->product == 0x34d || hdev->product == 0x34e || /* MobileStudio Pro */ - hdev->product == 0x357 || hdev->product == 0x358)) { /* Intuos Pro 2 */ + hdev->product == 0x357 || hdev->product == 0x358 || /* Intuos Pro 2 */ + hdev->product == 0x399)) { /* MobileStudio Pro */ value = (field->logical_maximum - value); if (hdev->product == 0x357 || hdev->product == 0x358) value = wacom_offset_rotation(input, usage, value, 3, 16); - else if (hdev->product == 0x34d || hdev->product == 0x34e) + else if (hdev->product == 0x34d || hdev->product == 0x34e || + hdev->product == 0x399) value = wacom_offset_rotation(input, usage, value, 1, 2); } else { -- cgit v1.2.3 From eca0f0a6c3fb2f88f123b4a8b57d53de77cdde77 Mon Sep 17 00:00:00 2001 From: Song Hongyan Date: Sun, 2 Jun 2019 08:17:21 +0800 Subject: HID: remove NO_D3 flag when remove driver Remove the NO_D3 flag when remove the driver and let device enter into D3, it will save more power. Signed-off-by: Song Hongyan Acked-by: Srinivas Pandruvada Signed-off-by: Jiri Kosina --- drivers/hid/intel-ish-hid/ipc/pci-ish.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/hid/intel-ish-hid/ipc/pci-ish.c b/drivers/hid/intel-ish-hid/ipc/pci-ish.c index 17ae49fba920..aa80b4d3b740 100644 --- a/drivers/hid/intel-ish-hid/ipc/pci-ish.c +++ b/drivers/hid/intel-ish-hid/ipc/pci-ish.c @@ -184,6 +184,7 @@ static void ish_remove(struct pci_dev *pdev) struct ishtp_device *ishtp_dev = pci_get_drvdata(pdev); ishtp_bus_remove_all_clients(ishtp_dev, false); + pdev->dev_flags &= ~PCI_DEV_FLAGS_NO_D3; ish_device_disable(ishtp_dev); } -- cgit v1.2.3 From cca4786174656673f89684347e0028c88df57031 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 28 Jun 2019 09:19:59 -0300 Subject: docs: hid: convert to ReST Rename the HID documentation files to ReST, add an index for them and adjust in order to produce a nice html output via the Sphinx build system. While here, fix the sysfs example from hid-sensor.txt, that has a lot of "?" instead of the proper UTF-8 characters that are produced by the tree command. At its new index.rst, let's add a :orphan: while this is not linked to the main index.rst file, in order to avoid build warnings. Signed-off-by: Mauro Carvalho Chehab Acked-by: Benjamin Tissoires Signed-off-by: Benjamin Tissoires --- Documentation/hid/hid-alps.rst | 180 +++++++++++++ Documentation/hid/hid-alps.txt | 139 ----------- Documentation/hid/hid-sensor.rst | 242 ++++++++++++++++++ Documentation/hid/hid-sensor.txt | 224 ----------------- Documentation/hid/hid-transport.rst | 359 ++++++++++++++++++++++++++ Documentation/hid/hid-transport.txt | 317 ----------------------- Documentation/hid/hiddev.rst | 251 +++++++++++++++++++ Documentation/hid/hiddev.txt | 205 --------------- Documentation/hid/hidraw.rst | 138 ++++++++++ Documentation/hid/hidraw.txt | 119 --------- Documentation/hid/index.rst | 18 ++ Documentation/hid/intel-ish-hid.rst | 485 ++++++++++++++++++++++++++++++++++++ Documentation/hid/intel-ish-hid.txt | 454 --------------------------------- Documentation/hid/uhid.rst | 193 ++++++++++++++ Documentation/hid/uhid.txt | 187 -------------- Documentation/input/input.rst | 2 +- MAINTAINERS | 2 +- 17 files changed, 1868 insertions(+), 1647 deletions(-) create mode 100644 Documentation/hid/hid-alps.rst delete mode 100644 Documentation/hid/hid-alps.txt create mode 100644 Documentation/hid/hid-sensor.rst delete mode 100644 Documentation/hid/hid-sensor.txt create mode 100644 Documentation/hid/hid-transport.rst delete mode 100644 Documentation/hid/hid-transport.txt create mode 100644 Documentation/hid/hiddev.rst delete mode 100644 Documentation/hid/hiddev.txt create mode 100644 Documentation/hid/hidraw.rst delete mode 100644 Documentation/hid/hidraw.txt create mode 100644 Documentation/hid/index.rst create mode 100644 Documentation/hid/intel-ish-hid.rst delete mode 100644 Documentation/hid/intel-ish-hid.txt create mode 100644 Documentation/hid/uhid.rst delete mode 100644 Documentation/hid/uhid.txt diff --git a/Documentation/hid/hid-alps.rst b/Documentation/hid/hid-alps.rst new file mode 100644 index 000000000000..e2f4c4c11e3f --- /dev/null +++ b/Documentation/hid/hid-alps.rst @@ -0,0 +1,180 @@ +========================== +ALPS HID Touchpad Protocol +========================== + +Introduction +------------ +Currently ALPS HID driver supports U1 Touchpad device. + +U1 device basic information. + +========== ====== +Vender ID 0x044E +Product ID 0x120B +Version ID 0x0121 +========== ====== + + +HID Descriptor +-------------- + +======= ==================== ===== ======================================= +Byte Field Value Notes +======= ==================== ===== ======================================= +0 wHIDDescLength 001E Length of HID Descriptor : 30 bytes +2 bcdVersion 0100 Compliant with Version 1.00 +4 wReportDescLength 00B2 Report Descriptor is 178 Bytes (0x00B2) +6 wReportDescRegister 0002 Identifier to read Report Descriptor +8 wInputRegister 0003 Identifier to read Input Report +10 wMaxInputLength 0053 Input Report is 80 Bytes + 2 +12 wOutputRegister 0000 Identifier to read Output Report +14 wMaxOutputLength 0000 No Output Reports +16 wCommandRegister 0005 Identifier for Command Register +18 wDataRegister 0006 Identifier for Data Register +20 wVendorID 044E Vendor ID 0x044E +22 wProductID 120B Product ID 0x120B +24 wVersionID 0121 Version 01.21 +26 RESERVED 0000 RESERVED +======= ==================== ===== ======================================= + + +Report ID +--------- + +========== ================= ========================================= +ReportID-1 (Input Reports) (HIDUsage-Mouse) for TP&SP +ReportID-2 (Input Reports) (HIDUsage-keyboard) for TP +ReportID-3 (Input Reports) (Vendor Usage: Max 10 finger data) for TP +ReportID-4 (Input Reports) (Vendor Usage: ON bit data) for GP +ReportID-5 (Feature Reports) Feature Reports +ReportID-6 (Input Reports) (Vendor Usage: StickPointer data) for SP +ReportID-7 (Feature Reports) Flash update (Bootloader) +========== ================= ========================================= + + +Data pattern +------------ + +===== ========== ===== ================= +Case1 ReportID_1 TP/SP Relative/Relative +Case2 ReportID_3 TP Absolute + ReportID_6 SP Absolute +===== ========== ===== ================= + + +Command Read/Write +------------------ +To read/write to RAM, need to send a commands to the device. + +The command format is as below. + +DataByte(SET_REPORT) + +===== ====================== +Byte1 Command Byte +Byte2 Address - Byte 0 (LSB) +Byte3 Address - Byte 1 +Byte4 Address - Byte 2 +Byte5 Address - Byte 3 (MSB) +Byte6 Value Byte +Byte7 Checksum +===== ====================== + +Command Byte is read=0xD1/write=0xD2 . + +Address is read/write RAM address. + +Value Byte is writing data when you send the write commands. + +When you read RAM, there is no meaning. + +DataByte(GET_REPORT) + +===== ====================== +Byte1 Response Byte +Byte2 Address - Byte 0 (LSB) +Byte3 Address - Byte 1 +Byte4 Address - Byte 2 +Byte5 Address - Byte 3 (MSB) +Byte6 Value Byte +Byte7 Checksum +===== ====================== + +Read value is stored in Value Byte. + + +Packet Format +Touchpad data byte +------------------ + + +======= ======= ======= ======= ======= ======= ======= ======= ===== +- b7 b6 b5 b4 b3 b2 b1 b0 +======= ======= ======= ======= ======= ======= ======= ======= ===== +1 0 0 SW6 SW5 SW4 SW3 SW2 SW1 +2 0 0 0 Fcv Fn3 Fn2 Fn1 Fn0 +3 Xa0_7 Xa0_6 Xa0_5 Xa0_4 Xa0_3 Xa0_2 Xa0_1 Xa0_0 +4 Xa0_15 Xa0_14 Xa0_13 Xa0_12 Xa0_11 Xa0_10 Xa0_9 Xa0_8 +5 Ya0_7 Ya0_6 Ya0_5 Ya0_4 Ya0_3 Ya0_2 Ya0_1 Ya0_0 +6 Ya0_15 Ya0_14 Ya0_13 Ya0_12 Ya0_11 Ya0_10 Ya0_9 Ya0_8 +7 LFB0 Zs0_6 Zs0_5 Zs0_4 Zs0_3 Zs0_2 Zs0_1 Zs0_0 + +8 Xa1_7 Xa1_6 Xa1_5 Xa1_4 Xa1_3 Xa1_2 Xa1_1 Xa1_0 +9 Xa1_15 Xa1_14 Xa1_13 Xa1_12 Xa1_11 Xa1_10 Xa1_9 Xa1_8 +10 Ya1_7 Ya1_6 Ya1_5 Ya1_4 Ya1_3 Ya1_2 Ya1_1 Ya1_0 +11 Ya1_15 Ya1_14 Ya1_13 Ya1_12 Ya1_11 Ya1_10 Ya1_9 Ya1_8 +12 LFB1 Zs1_6 Zs1_5 Zs1_4 Zs1_3 Zs1_2 Zs1_1 Zs1_0 + +13 Xa2_7 Xa2_6 Xa2_5 Xa2_4 Xa2_3 Xa2_2 Xa2_1 Xa2_0 +14 Xa2_15 Xa2_14 Xa2_13 Xa2_12 Xa2_11 Xa2_10 Xa2_9 Xa2_8 +15 Ya2_7 Ya2_6 Ya2_5 Ya2_4 Ya2_3 Ya2_2 Ya2_1 Ya2_0 +16 Ya2_15 Ya2_14 Ya2_13 Ya2_12 Ya2_11 Ya2_10 Ya2_9 Ya2_8 +17 LFB2 Zs2_6 Zs2_5 Zs2_4 Zs2_3 Zs2_2 Zs2_1 Zs2_0 + +18 Xa3_7 Xa3_6 Xa3_5 Xa3_4 Xa3_3 Xa3_2 Xa3_1 Xa3_0 +19 Xa3_15 Xa3_14 Xa3_13 Xa3_12 Xa3_11 Xa3_10 Xa3_9 Xa3_8 +20 Ya3_7 Ya3_6 Ya3_5 Ya3_4 Ya3_3 Ya3_2 Ya3_1 Ya3_0 +21 Ya3_15 Ya3_14 Ya3_13 Ya3_12 Ya3_11 Ya3_10 Ya3_9 Ya3_8 +22 LFB3 Zs3_6 Zs3_5 Zs3_4 Zs3_3 Zs3_2 Zs3_1 Zs3_0 + +23 Xa4_7 Xa4_6 Xa4_5 Xa4_4 Xa4_3 Xa4_2 Xa4_1 Xa4_0 +24 Xa4_15 Xa4_14 Xa4_13 Xa4_12 Xa4_11 Xa4_10 Xa4_9 Xa4_8 +25 Ya4_7 Ya4_6 Ya4_5 Ya4_4 Ya4_3 Ya4_2 Ya4_1 Ya4_0 +26 Ya4_15 Ya4_14 Ya4_13 Ya4_12 Ya4_11 Ya4_10 Ya4_9 Ya4_8 +27 LFB4 Zs4_6 Zs4_5 Zs4_4 Zs4_3 Zs4_2 Zs4_1 Zs4_0 +======= ======= ======= ======= ======= ======= ======= ======= ===== + + +SW1-SW6: + SW ON/OFF status +Xan_15-0(16bit): + X Absolute data of the "n"th finger +Yan_15-0(16bit): + Y Absolute data of the "n"th finger +Zsn_6-0(7bit): + Operation area of the "n"th finger + + +StickPointer data byte +---------------------- + +======= ======= ======= ======= ======= ======= ======= ======= ===== +- b7 b6 b5 b4 b3 b2 b1 b0 +======= ======= ======= ======= ======= ======= ======= ======= ===== +Byte1 1 1 1 0 1 SW3 SW2 SW1 +Byte2 X7 X6 X5 X4 X3 X2 X1 X0 +Byte3 X15 X14 X13 X12 X11 X10 X9 X8 +Byte4 Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 +Byte5 Y15 Y14 Y13 Y12 Y11 Y10 Y9 Y8 +Byte6 Z7 Z6 Z5 Z4 Z3 Z2 Z1 Z0 +Byte7 T&P Z14 Z13 Z12 Z11 Z10 Z9 Z8 +======= ======= ======= ======= ======= ======= ======= ======= ===== + +SW1-SW3: + SW ON/OFF status +Xn_15-0(16bit): + X Absolute data +Yn_15-0(16bit): + Y Absolute data +Zn_14-0(15bit): + Z diff --git a/Documentation/hid/hid-alps.txt b/Documentation/hid/hid-alps.txt deleted file mode 100644 index 6b02a2447c77..000000000000 --- a/Documentation/hid/hid-alps.txt +++ /dev/null @@ -1,139 +0,0 @@ -ALPS HID Touchpad Protocol ----------------------- - -Introduction ------------- -Currently ALPS HID driver supports U1 Touchpad device. - -U1 devuce basic information. -Vender ID 0x044E -Product ID 0x120B -Version ID 0x0121 - - -HID Descriptor ------------- -Byte Field Value Notes -0 wHIDDescLength 001E Length of HID Descriptor : 30 bytes -2 bcdVersion 0100 Compliant with Version 1.00 -4 wReportDescLength 00B2 Report Descriptor is 178 Bytes (0x00B2) -6 wReportDescRegister 0002 Identifier to read Report Descriptor -8 wInputRegister 0003 Identifier to read Input Report -10 wMaxInputLength 0053 Input Report is 80 Bytes + 2 -12 wOutputRegister 0000 Identifier to read Output Report -14 wMaxOutputLength 0000 No Output Reports -16 wCommandRegister 0005 Identifier for Command Register -18 wDataRegister 0006 Identifier for Data Register -20 wVendorID 044E Vendor ID 0x044E -22 wProductID 120B Product ID 0x120B -24 wVersionID 0121 Version 01.21 -26 RESERVED 0000 RESERVED - - -Report ID ------------- -ReportID-1 (Input Reports) (HIDUsage-Mouse) for TP&SP -ReportID-2 (Input Reports) (HIDUsage-keyboard) for TP -ReportID-3 (Input Reports) (Vendor Usage: Max 10 finger data) for TP -ReportID-4 (Input Reports) (Vendor Usage: ON bit data) for GP -ReportID-5 (Feature Reports) Feature Reports -ReportID-6 (Input Reports) (Vendor Usage: StickPointer data) for SP -ReportID-7 (Feature Reports) Flash update (Bootloader) - - -Data pattern ------------- -Case1 ReportID_1 TP/SP Relative/Relative -Case2 ReportID_3 TP Absolute - ReportID_6 SP Absolute - - -Command Read/Write ------------------- -To read/write to RAM, need to send a commands to the device. -The command format is as below. - -DataByte(SET_REPORT) -Byte1 Command Byte -Byte2 Address - Byte 0 (LSB) -Byte3 Address - Byte 1 -Byte4 Address - Byte 2 -Byte5 Address - Byte 3 (MSB) -Byte6 Value Byte -Byte7 Checksum - -Command Byte is read=0xD1/write=0xD2 . -Address is read/write RAM address. -Value Byte is writing data when you send the write commands. -When you read RAM, there is no meaning. - -DataByte(GET_REPORT) -Byte1 Response Byte -Byte2 Address - Byte 0 (LSB) -Byte3 Address - Byte 1 -Byte4 Address - Byte 2 -Byte5 Address - Byte 3 (MSB) -Byte6 Value Byte -Byte7 Checksum - -Read value is stored in Value Byte. - - -Packet Format -Touchpad data byte ------------------- - b7 b6 b5 b4 b3 b2 b1 b0 -1 0 0 SW6 SW5 SW4 SW3 SW2 SW1 -2 0 0 0 Fcv Fn3 Fn2 Fn1 Fn0 -3 Xa0_7 Xa0_6 Xa0_5 Xa0_4 Xa0_3 Xa0_2 Xa0_1 Xa0_0 -4 Xa0_15 Xa0_14 Xa0_13 Xa0_12 Xa0_11 Xa0_10 Xa0_9 Xa0_8 -5 Ya0_7 Ya0_6 Ya0_5 Ya0_4 Ya0_3 Ya0_2 Ya0_1 Ya0_0 -6 Ya0_15 Ya0_14 Ya0_13 Ya0_12 Ya0_11 Ya0_10 Ya0_9 Ya0_8 -7 LFB0 Zs0_6 Zs0_5 Zs0_4 Zs0_3 Zs0_2 Zs0_1 Zs0_0 - -8 Xa1_7 Xa1_6 Xa1_5 Xa1_4 Xa1_3 Xa1_2 Xa1_1 Xa1_0 -9 Xa1_15 Xa1_14 Xa1_13 Xa1_12 Xa1_11 Xa1_10 Xa1_9 Xa1_8 -10 Ya1_7 Ya1_6 Ya1_5 Ya1_4 Ya1_3 Ya1_2 Ya1_1 Ya1_0 -11 Ya1_15 Ya1_14 Ya1_13 Ya1_12 Ya1_11 Ya1_10 Ya1_9 Ya1_8 -12 LFB1 Zs1_6 Zs1_5 Zs1_4 Zs1_3 Zs1_2 Zs1_1 Zs1_0 - -13 Xa2_7 Xa2_6 Xa2_5 Xa2_4 Xa2_3 Xa2_2 Xa2_1 Xa2_0 -14 Xa2_15 Xa2_14 Xa2_13 Xa2_12 Xa2_11 Xa2_10 Xa2_9 Xa2_8 -15 Ya2_7 Ya2_6 Ya2_5 Ya2_4 Ya2_3 Ya2_2 Ya2_1 Ya2_0 -16 Ya2_15 Ya2_14 Ya2_13 Ya2_12 Ya2_11 Ya2_10 Ya2_9 Ya2_8 -17 LFB2 Zs2_6 Zs2_5 Zs2_4 Zs2_3 Zs2_2 Zs2_1 Zs2_0 - -18 Xa3_7 Xa3_6 Xa3_5 Xa3_4 Xa3_3 Xa3_2 Xa3_1 Xa3_0 -19 Xa3_15 Xa3_14 Xa3_13 Xa3_12 Xa3_11 Xa3_10 Xa3_9 Xa3_8 -20 Ya3_7 Ya3_6 Ya3_5 Ya3_4 Ya3_3 Ya3_2 Ya3_1 Ya3_0 -21 Ya3_15 Ya3_14 Ya3_13 Ya3_12 Ya3_11 Ya3_10 Ya3_9 Ya3_8 -22 LFB3 Zs3_6 Zs3_5 Zs3_4 Zs3_3 Zs3_2 Zs3_1 Zs3_0 - -23 Xa4_7 Xa4_6 Xa4_5 Xa4_4 Xa4_3 Xa4_2 Xa4_1 Xa4_0 -24 Xa4_15 Xa4_14 Xa4_13 Xa4_12 Xa4_11 Xa4_10 Xa4_9 Xa4_8 -25 Ya4_7 Ya4_6 Ya4_5 Ya4_4 Ya4_3 Ya4_2 Ya4_1 Ya4_0 -26 Ya4_15 Ya4_14 Ya4_13 Ya4_12 Ya4_11 Ya4_10 Ya4_9 Ya4_8 -27 LFB4 Zs4_6 Zs4_5 Zs4_4 Zs4_3 Zs4_2 Zs4_1 Zs4_0 - - -SW1-SW6: SW ON/OFF status -Xan_15-0(16bit):X Absolute data of the "n"th finger -Yan_15-0(16bit):Y Absolute data of the "n"th finger -Zsn_6-0(7bit): Operation area of the "n"th finger - - -StickPointer data byte ------------------- - b7 b6 b5 b4 b3 b2 b1 b0 -Byte1 1 1 1 0 1 SW3 SW2 SW1 -Byte2 X7 X6 X5 X4 X3 X2 X1 X0 -Byte3 X15 X14 X13 X12 X11 X10 X9 X8 -Byte4 Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 -Byte5 Y15 Y14 Y13 Y12 Y11 Y10 Y9 Y8 -Byte6 Z7 Z6 Z5 Z4 Z3 Z2 Z1 Z0 -Byte7 T&P Z14 Z13 Z12 Z11 Z10 Z9 Z8 - -SW1-SW3: SW ON/OFF status -Xn_15-0(16bit):X Absolute data -Yn_15-0(16bit):Y Absolute data -Zn_14-0(15bit):Z diff --git a/Documentation/hid/hid-sensor.rst b/Documentation/hid/hid-sensor.rst new file mode 100644 index 000000000000..758972e34971 --- /dev/null +++ b/Documentation/hid/hid-sensor.rst @@ -0,0 +1,242 @@ +===================== +HID Sensors Framework +===================== +HID sensor framework provides necessary interfaces to implement sensor drivers, +which are connected to a sensor hub. The sensor hub is a HID device and it provides +a report descriptor conforming to HID 1.12 sensor usage tables. + +Description from the HID 1.12 "HID Sensor Usages" specification: +"Standardization of HID usages for sensors would allow (but not require) sensor +hardware vendors to provide a consistent Plug And Play interface at the USB boundary, +thereby enabling some operating systems to incorporate common device drivers that +could be reused between vendors, alleviating any need for the vendors to provide +the drivers themselves." + +This specification describes many usage IDs, which describe the type of sensor +and also the individual data fields. Each sensor can have variable number of +data fields. The length and order is specified in the report descriptor. For +example a part of report descriptor can look like:: + + INPUT(1)[INPUT] + .. + Field(2) + Physical(0020.0073) + Usage(1) + 0020.045f + Logical Minimum(-32767) + Logical Maximum(32767) + Report Size(8) + Report Count(1) + Report Offset(16) + Flags(Variable Absolute) + .. + .. + +The report is indicating "sensor page (0x20)" contains an accelerometer-3D (0x73). +This accelerometer-3D has some fields. Here for example field 2 is motion intensity +(0x045f) with a logical minimum value of -32767 and logical maximum of 32767. The +order of fields and length of each field is important as the input event raw +data will use this format. + + +Implementation +============== + +This specification defines many different types of sensors with different sets of +data fields. It is difficult to have a common input event to user space applications, +for different sensors. For example an accelerometer can send X,Y and Z data, whereas +an ambient light sensor can send illumination data. +So the implementation has two parts: + +- Core hid driver +- Individual sensor processing part (sensor drivers) + +Core driver +----------- +The core driver registers (hid-sensor-hub) registers as a HID driver. It parses +report descriptors and identifies all the sensors present. It adds an MFD device +with name HID-SENSOR-xxxx (where xxxx is usage id from the specification). + +For example: + +HID-SENSOR-200073 is registered for an Accelerometer 3D driver. + +So if any driver with this name is inserted, then the probe routine for that +function will be called. So an accelerometer processing driver can register +with this name and will be probed if there is an accelerometer-3D detected. + +The core driver provides a set of APIs which can be used by the processing +drivers to register and get events for that usage id. Also it provides parsing +functions, which get and set each input/feature/output report. + +Individual sensor processing part (sensor drivers) +-------------------------------------------------- + +The processing driver will use an interface provided by the core driver to parse +the report and get the indexes of the fields and also can get events. This driver +can use IIO interface to use the standard ABI defined for a type of sensor. + + +Core driver Interface +===================== + +Callback structure:: + + Each processing driver can use this structure to set some callbacks. + int (*suspend)(..): Callback when HID suspend is received + int (*resume)(..): Callback when HID resume is received + int (*capture_sample)(..): Capture a sample for one of its data fields + int (*send_event)(..): One complete event is received which can have + multiple data fields. + +Registration functions:: + + int sensor_hub_register_callback(struct hid_sensor_hub_device *hsdev, + u32 usage_id, + struct hid_sensor_hub_callbacks *usage_callback): + +Registers callbacks for an usage id. The callback functions are not allowed +to sleep:: + + + int sensor_hub_remove_callback(struct hid_sensor_hub_device *hsdev, + u32 usage_id): + +Removes callbacks for an usage id. + + +Parsing function:: + + int sensor_hub_input_get_attribute_info(struct hid_sensor_hub_device *hsdev, + u8 type, + u32 usage_id, u32 attr_usage_id, + struct hid_sensor_hub_attribute_info *info); + +A processing driver can look for some field of interest and check if it exists +in a report descriptor. If it exists it will store necessary information +so that fields can be set or get individually. +These indexes avoid searching every time and getting field index to get or set. + + +Set Feature report:: + + int sensor_hub_set_feature(struct hid_sensor_hub_device *hsdev, u32 report_id, + u32 field_index, s32 value); + +This interface is used to set a value for a field in feature report. For example +if there is a field report_interval, which is parsed by a call to +sensor_hub_input_get_attribute_info before, then it can directly set that +individual field:: + + + int sensor_hub_get_feature(struct hid_sensor_hub_device *hsdev, u32 report_id, + u32 field_index, s32 *value); + +This interface is used to get a value for a field in input report. For example +if there is a field report_interval, which is parsed by a call to +sensor_hub_input_get_attribute_info before, then it can directly get that +individual field value:: + + + int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev, + u32 usage_id, + u32 attr_usage_id, u32 report_id); + +This is used to get a particular field value through input reports. For example +accelerometer wants to poll X axis value, then it can call this function with +the usage id of X axis. HID sensors can provide events, so this is not necessary +to poll for any field. If there is some new sample, the core driver will call +registered callback function to process the sample. + + +---------- + +HID Custom and generic Sensors +------------------------------ + + +HID Sensor specification defines two special sensor usage types. Since they +don't represent a standard sensor, it is not possible to define using Linux IIO +type interfaces. +The purpose of these sensors is to extend the functionality or provide a +way to obfuscate the data being communicated by a sensor. Without knowing the +mapping between the data and its encapsulated form, it is difficult for +an application/driver to determine what data is being communicated by the sensor. +This allows some differentiating use cases, where vendor can provide applications. +Some common use cases are debug other sensors or to provide some events like +keyboard attached/detached or lid open/close. + +To allow application to utilize these sensors, here they are exported uses sysfs +attribute groups, attributes and misc device interface. + +An example of this representation on sysfs:: + + /sys/devices/pci0000:00/INT33C2:00/i2c-0/i2c-INT33D1:00/0018:8086:09FA.0001/HID-SENSOR-2000e1.6.auto$ tree -R + . + │   ├── enable_sensor + │   │   ├── feature-0-200316 + │   │   │   ├── feature-0-200316-maximum + │   │   │   ├── feature-0-200316-minimum + │   │   │   ├── feature-0-200316-name + │   │   │   ├── feature-0-200316-size + │   │   │   ├── feature-0-200316-unit-expo + │   │   │   ├── feature-0-200316-units + │   │   │   ├── feature-0-200316-value + │   │   ├── feature-1-200201 + │   │   │   ├── feature-1-200201-maximum + │   │   │   ├── feature-1-200201-minimum + │   │   │   ├── feature-1-200201-name + │   │   │   ├── feature-1-200201-size + │   │   │   ├── feature-1-200201-unit-expo + │   │   │   ├── feature-1-200201-units + │   │   │   ├── feature-1-200201-value + │   │   ├── input-0-200201 + │   │   │   ├── input-0-200201-maximum + │   │   │   ├── input-0-200201-minimum + │   │   │   ├── input-0-200201-name + │   │   │   ├── input-0-200201-size + │   │   │   ├── input-0-200201-unit-expo + │   │   │   ├── input-0-200201-units + │   │   │   ├── input-0-200201-value + │   │   ├── input-1-200202 + │   │   │   ├── input-1-200202-maximum + │   │   │   ├── input-1-200202-minimum + │   │   │   ├── input-1-200202-name + │   │   │   ├── input-1-200202-size + │   │   │   ├── input-1-200202-unit-expo + │   │   │   ├── input-1-200202-units + │   │   │   ├── input-1-200202-value + +Here there is a custom sensors with four fields, two feature and two inputs. +Each field is represented by a set of attributes. All fields except the "value" +are read only. The value field is a RW field. + +Example:: + + /sys/bus/platform/devices/HID-SENSOR-2000e1.6.auto/feature-0-200316$ grep -r . * + feature-0-200316-maximum:6 + feature-0-200316-minimum:0 + feature-0-200316-name:property-reporting-state + feature-0-200316-size:1 + feature-0-200316-unit-expo:0 + feature-0-200316-units:25 + feature-0-200316-value:1 + +How to enable such sensor? +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +By default sensor can be power gated. To enable sysfs attribute "enable" can be +used:: + + $ echo 1 > enable_sensor + +Once enabled and powered on, sensor can report value using HID reports. +These reports are pushed using misc device interface in a FIFO order:: + + /dev$ tree | grep HID-SENSOR-2000e1.6.auto + │   │   │   ├── 10:53 -> ../HID-SENSOR-2000e1.6.auto + │   ├── HID-SENSOR-2000e1.6.auto + +Each reports can be of variable length preceded by a header. This header +consist of a 32 bit usage id, 64 bit time stamp and 32 bit length field of raw +data. diff --git a/Documentation/hid/hid-sensor.txt b/Documentation/hid/hid-sensor.txt deleted file mode 100644 index b287752a31cd..000000000000 --- a/Documentation/hid/hid-sensor.txt +++ /dev/null @@ -1,224 +0,0 @@ - -HID Sensors Framework -====================== -HID sensor framework provides necessary interfaces to implement sensor drivers, -which are connected to a sensor hub. The sensor hub is a HID device and it provides -a report descriptor conforming to HID 1.12 sensor usage tables. - -Description from the HID 1.12 "HID Sensor Usages" specification: -"Standardization of HID usages for sensors would allow (but not require) sensor -hardware vendors to provide a consistent Plug And Play interface at the USB boundary, -thereby enabling some operating systems to incorporate common device drivers that -could be reused between vendors, alleviating any need for the vendors to provide -the drivers themselves." - -This specification describes many usage IDs, which describe the type of sensor -and also the individual data fields. Each sensor can have variable number of -data fields. The length and order is specified in the report descriptor. For -example a part of report descriptor can look like: - - INPUT(1)[INPUT] - .. - Field(2) - Physical(0020.0073) - Usage(1) - 0020.045f - Logical Minimum(-32767) - Logical Maximum(32767) - Report Size(8) - Report Count(1) - Report Offset(16) - Flags(Variable Absolute) -.. -.. - -The report is indicating "sensor page (0x20)" contains an accelerometer-3D (0x73). -This accelerometer-3D has some fields. Here for example field 2 is motion intensity -(0x045f) with a logical minimum value of -32767 and logical maximum of 32767. The -order of fields and length of each field is important as the input event raw -data will use this format. - - -Implementation -================= - -This specification defines many different types of sensors with different sets of -data fields. It is difficult to have a common input event to user space applications, -for different sensors. For example an accelerometer can send X,Y and Z data, whereas -an ambient light sensor can send illumination data. -So the implementation has two parts: -- Core hid driver -- Individual sensor processing part (sensor drivers) - -Core driver ------------ -The core driver registers (hid-sensor-hub) registers as a HID driver. It parses -report descriptors and identifies all the sensors present. It adds an MFD device -with name HID-SENSOR-xxxx (where xxxx is usage id from the specification). -For example -HID-SENSOR-200073 is registered for an Accelerometer 3D driver. -So if any driver with this name is inserted, then the probe routine for that -function will be called. So an accelerometer processing driver can register -with this name and will be probed if there is an accelerometer-3D detected. - -The core driver provides a set of APIs which can be used by the processing -drivers to register and get events for that usage id. Also it provides parsing -functions, which get and set each input/feature/output report. - -Individual sensor processing part (sensor drivers) ------------ -The processing driver will use an interface provided by the core driver to parse -the report and get the indexes of the fields and also can get events. This driver -can use IIO interface to use the standard ABI defined for a type of sensor. - - -Core driver Interface -===================== - -Callback structure: -Each processing driver can use this structure to set some callbacks. - int (*suspend)(..): Callback when HID suspend is received - int (*resume)(..): Callback when HID resume is received - int (*capture_sample)(..): Capture a sample for one of its data fields - int (*send_event)(..): One complete event is received which can have - multiple data fields. - -Registration functions: -int sensor_hub_register_callback(struct hid_sensor_hub_device *hsdev, - u32 usage_id, - struct hid_sensor_hub_callbacks *usage_callback): - -Registers callbacks for an usage id. The callback functions are not allowed -to sleep. - - -int sensor_hub_remove_callback(struct hid_sensor_hub_device *hsdev, - u32 usage_id): - -Removes callbacks for an usage id. - - -Parsing function: -int sensor_hub_input_get_attribute_info(struct hid_sensor_hub_device *hsdev, - u8 type, - u32 usage_id, u32 attr_usage_id, - struct hid_sensor_hub_attribute_info *info); - -A processing driver can look for some field of interest and check if it exists -in a report descriptor. If it exists it will store necessary information -so that fields can be set or get individually. -These indexes avoid searching every time and getting field index to get or set. - - -Set Feature report -int sensor_hub_set_feature(struct hid_sensor_hub_device *hsdev, u32 report_id, - u32 field_index, s32 value); - -This interface is used to set a value for a field in feature report. For example -if there is a field report_interval, which is parsed by a call to -sensor_hub_input_get_attribute_info before, then it can directly set that individual -field. - - -int sensor_hub_get_feature(struct hid_sensor_hub_device *hsdev, u32 report_id, - u32 field_index, s32 *value); - -This interface is used to get a value for a field in input report. For example -if there is a field report_interval, which is parsed by a call to -sensor_hub_input_get_attribute_info before, then it can directly get that individual -field value. - - -int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev, - u32 usage_id, - u32 attr_usage_id, u32 report_id); - -This is used to get a particular field value through input reports. For example -accelerometer wants to poll X axis value, then it can call this function with -the usage id of X axis. HID sensors can provide events, so this is not necessary -to poll for any field. If there is some new sample, the core driver will call -registered callback function to process the sample. - - ----------- - -HID Custom and generic Sensors - -HID Sensor specification defines two special sensor usage types. Since they -don't represent a standard sensor, it is not possible to define using Linux IIO -type interfaces. -The purpose of these sensors is to extend the functionality or provide a -way to obfuscate the data being communicated by a sensor. Without knowing the -mapping between the data and its encapsulated form, it is difficult for -an application/driver to determine what data is being communicated by the sensor. -This allows some differentiating use cases, where vendor can provide applications. -Some common use cases are debug other sensors or to provide some events like -keyboard attached/detached or lid open/close. - -To allow application to utilize these sensors, here they are exported uses sysfs -attribute groups, attributes and misc device interface. - -An example of this representation on sysfs: -/sys/devices/pci0000:00/INT33C2:00/i2c-0/i2c-INT33D1:00/0018:8086:09FA.0001/HID-SENSOR-2000e1.6.auto$ tree -R -. -????????? enable_sensor -????????? feature-0-200316 -??????? ????????? feature-0-200316-maximum -??????? ????????? feature-0-200316-minimum -??????? ????????? feature-0-200316-name -??????? ????????? feature-0-200316-size -??????? ????????? feature-0-200316-unit-expo -??????? ????????? feature-0-200316-units -??????? ????????? feature-0-200316-value -????????? feature-1-200201 -??????? ????????? feature-1-200201-maximum -??????? ????????? feature-1-200201-minimum -??????? ????????? feature-1-200201-name -??????? ????????? feature-1-200201-size -??????? ????????? feature-1-200201-unit-expo -??????? ????????? feature-1-200201-units -??????? ????????? feature-1-200201-value -????????? input-0-200201 -??????? ????????? input-0-200201-maximum -??????? ????????? input-0-200201-minimum -??????? ????????? input-0-200201-name -??????? ????????? input-0-200201-size -??????? ????????? input-0-200201-unit-expo -??????? ????????? input-0-200201-units -??????? ????????? input-0-200201-value -????????? input-1-200202 -??????? ????????? input-1-200202-maximum -??????? ????????? input-1-200202-minimum -??????? ????????? input-1-200202-name -??????? ????????? input-1-200202-size -??????? ????????? input-1-200202-unit-expo -??????? ????????? input-1-200202-units -??????? ????????? input-1-200202-value - -Here there is a custom sensors with four fields, two feature and two inputs. -Each field is represented by a set of attributes. All fields except the "value" -are read only. The value field is a RW field. -Example -/sys/bus/platform/devices/HID-SENSOR-2000e1.6.auto/feature-0-200316$ grep -r . * -feature-0-200316-maximum:6 -feature-0-200316-minimum:0 -feature-0-200316-name:property-reporting-state -feature-0-200316-size:1 -feature-0-200316-unit-expo:0 -feature-0-200316-units:25 -feature-0-200316-value:1 - -How to enable such sensor? -By default sensor can be power gated. To enable sysfs attribute "enable" can be -used. -$ echo 1 > enable_sensor - -Once enabled and powered on, sensor can report value using HID reports. -These reports are pushed using misc device interface in a FIFO order. -/dev$ tree | grep HID-SENSOR-2000e1.6.auto -??????? ????????? 10:53 -> ../HID-SENSOR-2000e1.6.auto -????????? HID-SENSOR-2000e1.6.auto - -Each reports can be of variable length preceded by a header. This header -consist of a 32 bit usage id, 64 bit time stamp and 32 bit length field of raw -data. diff --git a/Documentation/hid/hid-transport.rst b/Documentation/hid/hid-transport.rst new file mode 100644 index 000000000000..6f3aaa86ce7b --- /dev/null +++ b/Documentation/hid/hid-transport.rst @@ -0,0 +1,359 @@ +========================= +HID I/O Transport Drivers +========================= + +The HID subsystem is independent of the underlying transport driver. Initially, +only USB was supported, but other specifications adopted the HID design and +provided new transport drivers. The kernel includes at least support for USB, +Bluetooth, I2C and user-space I/O drivers. + +1) HID Bus +========== + +The HID subsystem is designed as a bus. Any I/O subsystem may provide HID +devices and register them with the HID bus. HID core then loads generic device +drivers on top of it. The transport drivers are responsible of raw data +transport and device setup/management. HID core is responsible of +report-parsing, report interpretation and the user-space API. Device specifics +and quirks are handled by all layers depending on the quirk. + +:: + + +-----------+ +-----------+ +-----------+ +-----------+ + | Device #1 | | Device #i | | Device #j | | Device #k | + +-----------+ +-----------+ +-----------+ +-----------+ + \\ // \\ // + +------------+ +------------+ + | I/O Driver | | I/O Driver | + +------------+ +------------+ + || || + +------------------+ +------------------+ + | Transport Driver | | Transport Driver | + +------------------+ +------------------+ + \___ ___/ + \ / + +----------------+ + | HID Core | + +----------------+ + / | | \ + / | | \ + ____________/ | | \_________________ + / | | \ + / | | \ + +----------------+ +-----------+ +------------------+ +------------------+ + | Generic Driver | | MT Driver | | Custom Driver #1 | | Custom Driver #2 | + +----------------+ +-----------+ +------------------+ +------------------+ + +Example Drivers: + + - I/O: USB, I2C, Bluetooth-l2cap + - Transport: USB-HID, I2C-HID, BT-HIDP + +Everything below "HID Core" is simplified in this graph as it is only of +interest to HID device drivers. Transport drivers do not need to know the +specifics. + +1.1) Device Setup +----------------- + +I/O drivers normally provide hotplug detection or device enumeration APIs to the +transport drivers. Transport drivers use this to find any suitable HID device. +They allocate HID device objects and register them with HID core. Transport +drivers are not required to register themselves with HID core. HID core is never +aware of which transport drivers are available and is not interested in it. It +is only interested in devices. + +Transport drivers attach a constant "struct hid_ll_driver" object with each +device. Once a device is registered with HID core, the callbacks provided via +this struct are used by HID core to communicate with the device. + +Transport drivers are responsible of detecting device failures and unplugging. +HID core will operate a device as long as it is registered regardless of any +device failures. Once transport drivers detect unplug or failure events, they +must unregister the device from HID core and HID core will stop using the +provided callbacks. + +1.2) Transport Driver Requirements +---------------------------------- + +The terms "asynchronous" and "synchronous" in this document describe the +transmission behavior regarding acknowledgements. An asynchronous channel must +not perform any synchronous operations like waiting for acknowledgements or +verifications. Generally, HID calls operating on asynchronous channels must be +running in atomic-context just fine. +On the other hand, synchronous channels can be implemented by the transport +driver in whatever way they like. They might just be the same as asynchronous +channels, but they can also provide acknowledgement reports, automatic +retransmission on failure, etc. in a blocking manner. If such functionality is +required on asynchronous channels, a transport-driver must implement that via +its own worker threads. + +HID core requires transport drivers to follow a given design. A Transport +driver must provide two bi-directional I/O channels to each HID device. These +channels must not necessarily be bi-directional in the hardware itself. A +transport driver might just provide 4 uni-directional channels. Or it might +multiplex all four on a single physical channel. However, in this document we +will describe them as two bi-directional channels as they have several +properties in common. + + - Interrupt Channel (intr): The intr channel is used for asynchronous data + reports. No management commands or data acknowledgements are sent on this + channel. Any unrequested incoming or outgoing data report must be sent on + this channel and is never acknowledged by the remote side. Devices usually + send their input events on this channel. Outgoing events are normally + not send via intr, except if high throughput is required. + - Control Channel (ctrl): The ctrl channel is used for synchronous requests and + device management. Unrequested data input events must not be sent on this + channel and are normally ignored. Instead, devices only send management + events or answers to host requests on this channel. + The control-channel is used for direct blocking queries to the device + independent of any events on the intr-channel. + Outgoing reports are usually sent on the ctrl channel via synchronous + SET_REPORT requests. + +Communication between devices and HID core is mostly done via HID reports. A +report can be of one of three types: + + - INPUT Report: Input reports provide data from device to host. This + data may include button events, axis events, battery status or more. This + data is generated by the device and sent to the host with or without + requiring explicit requests. Devices can choose to send data continuously or + only on change. + - OUTPUT Report: Output reports change device states. They are sent from host + to device and may include LED requests, rumble requests or more. Output + reports are never sent from device to host, but a host can retrieve their + current state. + Hosts may choose to send output reports either continuously or only on + change. + - FEATURE Report: Feature reports are used for specific static device features + and never reported spontaneously. A host can read and/or write them to access + data like battery-state or device-settings. + Feature reports are never sent without requests. A host must explicitly set + or retrieve a feature report. This also means, feature reports are never sent + on the intr channel as this channel is asynchronous. + +INPUT and OUTPUT reports can be sent as pure data reports on the intr channel. +For INPUT reports this is the usual operational mode. But for OUTPUT reports, +this is rarely done as OUTPUT reports are normally quite scarce. But devices are +free to make excessive use of asynchronous OUTPUT reports (for instance, custom +HID audio speakers make great use of it). + +Plain reports must not be sent on the ctrl channel, though. Instead, the ctrl +channel provides synchronous GET/SET_REPORT requests. Plain reports are only +allowed on the intr channel and are the only means of data there. + + - GET_REPORT: A GET_REPORT request has a report ID as payload and is sent + from host to device. The device must answer with a data report for the + requested report ID on the ctrl channel as a synchronous acknowledgement. + Only one GET_REPORT request can be pending for each device. This restriction + is enforced by HID core as several transport drivers don't allow multiple + simultaneous GET_REPORT requests. + Note that data reports which are sent as answer to a GET_REPORT request are + not handled as generic device events. That is, if a device does not operate + in continuous data reporting mode, an answer to GET_REPORT does not replace + the raw data report on the intr channel on state change. + GET_REPORT is only used by custom HID device drivers to query device state. + Normally, HID core caches any device state so this request is not necessary + on devices that follow the HID specs except during device initialization to + retrieve the current state. + GET_REPORT requests can be sent for any of the 3 report types and shall + return the current report state of the device. However, OUTPUT reports as + payload may be blocked by the underlying transport driver if the + specification does not allow them. + - SET_REPORT: A SET_REPORT request has a report ID plus data as payload. It is + sent from host to device and a device must update it's current report state + according to the given data. Any of the 3 report types can be used. However, + INPUT reports as payload might be blocked by the underlying transport driver + if the specification does not allow them. + A device must answer with a synchronous acknowledgement. However, HID core + does not require transport drivers to forward this acknowledgement to HID + core. + Same as for GET_REPORT, only one SET_REPORT can be pending at a time. This + restriction is enforced by HID core as some transport drivers do not support + multiple synchronous SET_REPORT requests. + +Other ctrl-channel requests are supported by USB-HID but are not available +(or deprecated) in most other transport level specifications: + + - GET/SET_IDLE: Only used by USB-HID and I2C-HID. + - GET/SET_PROTOCOL: Not used by HID core. + - RESET: Used by I2C-HID, not hooked up in HID core. + - SET_POWER: Used by I2C-HID, not hooked up in HID core. + +2) HID API +========== + +2.1) Initialization +------------------- + +Transport drivers normally use the following procedure to register a new device +with HID core:: + + struct hid_device *hid; + int ret; + + hid = hid_allocate_device(); + if (IS_ERR(hid)) { + ret = PTR_ERR(hid); + goto err_<...>; + } + + strlcpy(hid->name, , 127); + strlcpy(hid->phys, , 63); + strlcpy(hid->uniq, , 63); + + hid->ll_driver = &custom_ll_driver; + hid->bus = ; + hid->vendor = ; + hid->product = ; + hid->version = ; + hid->country = ; + hid->dev.parent = ; + hid->driver_data = ; + + ret = hid_add_device(hid); + if (ret) + goto err_<...>; + +Once hid_add_device() is entered, HID core might use the callbacks provided in +"custom_ll_driver". Note that fields like "country" can be ignored by underlying +transport-drivers if not supported. + +To unregister a device, use:: + + hid_destroy_device(hid); + +Once hid_destroy_device() returns, HID core will no longer make use of any +driver callbacks. + +2.2) hid_ll_driver operations +----------------------------- + +The available HID callbacks are: + + :: + + int (*start) (struct hid_device *hdev) + + Called from HID device drivers once they want to use the device. Transport + drivers can choose to setup their device in this callback. However, normally + devices are already set up before transport drivers register them to HID core + so this is mostly only used by USB-HID. + + :: + + void (*stop) (struct hid_device *hdev) + + Called from HID device drivers once they are done with a device. Transport + drivers can free any buffers and deinitialize the device. But note that + ->start() might be called again if another HID device driver is loaded on the + device. + + Transport drivers are free to ignore it and deinitialize devices after they + destroyed them via hid_destroy_device(). + + :: + + int (*open) (struct hid_device *hdev) + + Called from HID device drivers once they are interested in data reports. + Usually, while user-space didn't open any input API/etc., device drivers are + not interested in device data and transport drivers can put devices asleep. + However, once ->open() is called, transport drivers must be ready for I/O. + ->open() calls are nested for each client that opens the HID device. + + :: + + void (*close) (struct hid_device *hdev) + + Called from HID device drivers after ->open() was called but they are no + longer interested in device reports. (Usually if user-space closed any input + devices of the driver). + + Transport drivers can put devices asleep and terminate any I/O of all + ->open() calls have been followed by a ->close() call. However, ->start() may + be called again if the device driver is interested in input reports again. + + :: + + int (*parse) (struct hid_device *hdev) + + Called once during device setup after ->start() has been called. Transport + drivers must read the HID report-descriptor from the device and tell HID core + about it via hid_parse_report(). + + :: + + int (*power) (struct hid_device *hdev, int level) + + Called by HID core to give PM hints to transport drivers. Usually this is + analogical to the ->open() and ->close() hints and redundant. + + :: + + void (*request) (struct hid_device *hdev, struct hid_report *report, + int reqtype) + + Send an HID request on the ctrl channel. "report" contains the report that + should be sent and "reqtype" the request type. Request-type can be + HID_REQ_SET_REPORT or HID_REQ_GET_REPORT. + + This callback is optional. If not provided, HID core will assemble a raw + report following the HID specs and send it via the ->raw_request() callback. + The transport driver is free to implement this asynchronously. + + :: + + int (*wait) (struct hid_device *hdev) + + Used by HID core before calling ->request() again. A transport driver can use + it to wait for any pending requests to complete if only one request is + allowed at a time. + + :: + + int (*raw_request) (struct hid_device *hdev, unsigned char reportnum, + __u8 *buf, size_t count, unsigned char rtype, + int reqtype) + + Same as ->request() but provides the report as raw buffer. This request shall + be synchronous. A transport driver must not use ->wait() to complete such + requests. This request is mandatory and hid core will reject the device if + it is missing. + + :: + + int (*output_report) (struct hid_device *hdev, __u8 *buf, size_t len) + + Send raw output report via intr channel. Used by some HID device drivers + which require high throughput for outgoing requests on the intr channel. This + must not cause SET_REPORT calls! This must be implemented as asynchronous + output report on the intr channel! + + :: + + int (*idle) (struct hid_device *hdev, int report, int idle, int reqtype) + + Perform SET/GET_IDLE request. Only used by USB-HID, do not implement! + +2.3) Data Path +-------------- + +Transport drivers are responsible of reading data from I/O devices. They must +handle any I/O-related state-tracking themselves. HID core does not implement +protocol handshakes or other management commands which can be required by the +given HID transport specification. + +Every raw data packet read from a device must be fed into HID core via +hid_input_report(). You must specify the channel-type (intr or ctrl) and report +type (input/output/feature). Under normal conditions, only input reports are +provided via this API. + +Responses to GET_REPORT requests via ->request() must also be provided via this +API. Responses to ->raw_request() are synchronous and must be intercepted by the +transport driver and not passed to hid_input_report(). +Acknowledgements to SET_REPORT requests are not of interest to HID core. + +---------------------------------------------------- + +Written 2013, David Herrmann diff --git a/Documentation/hid/hid-transport.txt b/Documentation/hid/hid-transport.txt deleted file mode 100644 index 3dcba9fd4a3a..000000000000 --- a/Documentation/hid/hid-transport.txt +++ /dev/null @@ -1,317 +0,0 @@ - HID I/O Transport Drivers - =========================== - -The HID subsystem is independent of the underlying transport driver. Initially, -only USB was supported, but other specifications adopted the HID design and -provided new transport drivers. The kernel includes at least support for USB, -Bluetooth, I2C and user-space I/O drivers. - -1) HID Bus -========== - -The HID subsystem is designed as a bus. Any I/O subsystem may provide HID -devices and register them with the HID bus. HID core then loads generic device -drivers on top of it. The transport drivers are responsible of raw data -transport and device setup/management. HID core is responsible of -report-parsing, report interpretation and the user-space API. Device specifics -and quirks are handled by all layers depending on the quirk. - - +-----------+ +-----------+ +-----------+ +-----------+ - | Device #1 | | Device #i | | Device #j | | Device #k | - +-----------+ +-----------+ +-----------+ +-----------+ - \\ // \\ // - +------------+ +------------+ - | I/O Driver | | I/O Driver | - +------------+ +------------+ - || || - +------------------+ +------------------+ - | Transport Driver | | Transport Driver | - +------------------+ +------------------+ - \___ ___/ - \ / - +----------------+ - | HID Core | - +----------------+ - / | | \ - / | | \ - ____________/ | | \_________________ - / | | \ - / | | \ - +----------------+ +-----------+ +------------------+ +------------------+ - | Generic Driver | | MT Driver | | Custom Driver #1 | | Custom Driver #2 | - +----------------+ +-----------+ +------------------+ +------------------+ - -Example Drivers: - I/O: USB, I2C, Bluetooth-l2cap - Transport: USB-HID, I2C-HID, BT-HIDP - -Everything below "HID Core" is simplified in this graph as it is only of -interest to HID device drivers. Transport drivers do not need to know the -specifics. - -1.1) Device Setup ------------------ - -I/O drivers normally provide hotplug detection or device enumeration APIs to the -transport drivers. Transport drivers use this to find any suitable HID device. -They allocate HID device objects and register them with HID core. Transport -drivers are not required to register themselves with HID core. HID core is never -aware of which transport drivers are available and is not interested in it. It -is only interested in devices. - -Transport drivers attach a constant "struct hid_ll_driver" object with each -device. Once a device is registered with HID core, the callbacks provided via -this struct are used by HID core to communicate with the device. - -Transport drivers are responsible of detecting device failures and unplugging. -HID core will operate a device as long as it is registered regardless of any -device failures. Once transport drivers detect unplug or failure events, they -must unregister the device from HID core and HID core will stop using the -provided callbacks. - -1.2) Transport Driver Requirements ----------------------------------- - -The terms "asynchronous" and "synchronous" in this document describe the -transmission behavior regarding acknowledgements. An asynchronous channel must -not perform any synchronous operations like waiting for acknowledgements or -verifications. Generally, HID calls operating on asynchronous channels must be -running in atomic-context just fine. -On the other hand, synchronous channels can be implemented by the transport -driver in whatever way they like. They might just be the same as asynchronous -channels, but they can also provide acknowledgement reports, automatic -retransmission on failure, etc. in a blocking manner. If such functionality is -required on asynchronous channels, a transport-driver must implement that via -its own worker threads. - -HID core requires transport drivers to follow a given design. A Transport -driver must provide two bi-directional I/O channels to each HID device. These -channels must not necessarily be bi-directional in the hardware itself. A -transport driver might just provide 4 uni-directional channels. Or it might -multiplex all four on a single physical channel. However, in this document we -will describe them as two bi-directional channels as they have several -properties in common. - - - Interrupt Channel (intr): The intr channel is used for asynchronous data - reports. No management commands or data acknowledgements are sent on this - channel. Any unrequested incoming or outgoing data report must be sent on - this channel and is never acknowledged by the remote side. Devices usually - send their input events on this channel. Outgoing events are normally - not send via intr, except if high throughput is required. - - Control Channel (ctrl): The ctrl channel is used for synchronous requests and - device management. Unrequested data input events must not be sent on this - channel and are normally ignored. Instead, devices only send management - events or answers to host requests on this channel. - The control-channel is used for direct blocking queries to the device - independent of any events on the intr-channel. - Outgoing reports are usually sent on the ctrl channel via synchronous - SET_REPORT requests. - -Communication between devices and HID core is mostly done via HID reports. A -report can be of one of three types: - - - INPUT Report: Input reports provide data from device to host. This - data may include button events, axis events, battery status or more. This - data is generated by the device and sent to the host with or without - requiring explicit requests. Devices can choose to send data continuously or - only on change. - - OUTPUT Report: Output reports change device states. They are sent from host - to device and may include LED requests, rumble requests or more. Output - reports are never sent from device to host, but a host can retrieve their - current state. - Hosts may choose to send output reports either continuously or only on - change. - - FEATURE Report: Feature reports are used for specific static device features - and never reported spontaneously. A host can read and/or write them to access - data like battery-state or device-settings. - Feature reports are never sent without requests. A host must explicitly set - or retrieve a feature report. This also means, feature reports are never sent - on the intr channel as this channel is asynchronous. - -INPUT and OUTPUT reports can be sent as pure data reports on the intr channel. -For INPUT reports this is the usual operational mode. But for OUTPUT reports, -this is rarely done as OUTPUT reports are normally quite scarce. But devices are -free to make excessive use of asynchronous OUTPUT reports (for instance, custom -HID audio speakers make great use of it). - -Plain reports must not be sent on the ctrl channel, though. Instead, the ctrl -channel provides synchronous GET/SET_REPORT requests. Plain reports are only -allowed on the intr channel and are the only means of data there. - - - GET_REPORT: A GET_REPORT request has a report ID as payload and is sent - from host to device. The device must answer with a data report for the - requested report ID on the ctrl channel as a synchronous acknowledgement. - Only one GET_REPORT request can be pending for each device. This restriction - is enforced by HID core as several transport drivers don't allow multiple - simultaneous GET_REPORT requests. - Note that data reports which are sent as answer to a GET_REPORT request are - not handled as generic device events. That is, if a device does not operate - in continuous data reporting mode, an answer to GET_REPORT does not replace - the raw data report on the intr channel on state change. - GET_REPORT is only used by custom HID device drivers to query device state. - Normally, HID core caches any device state so this request is not necessary - on devices that follow the HID specs except during device initialization to - retrieve the current state. - GET_REPORT requests can be sent for any of the 3 report types and shall - return the current report state of the device. However, OUTPUT reports as - payload may be blocked by the underlying transport driver if the - specification does not allow them. - - SET_REPORT: A SET_REPORT request has a report ID plus data as payload. It is - sent from host to device and a device must update it's current report state - according to the given data. Any of the 3 report types can be used. However, - INPUT reports as payload might be blocked by the underlying transport driver - if the specification does not allow them. - A device must answer with a synchronous acknowledgement. However, HID core - does not require transport drivers to forward this acknowledgement to HID - core. - Same as for GET_REPORT, only one SET_REPORT can be pending at a time. This - restriction is enforced by HID core as some transport drivers do not support - multiple synchronous SET_REPORT requests. - -Other ctrl-channel requests are supported by USB-HID but are not available -(or deprecated) in most other transport level specifications: - - - GET/SET_IDLE: Only used by USB-HID and I2C-HID. - - GET/SET_PROTOCOL: Not used by HID core. - - RESET: Used by I2C-HID, not hooked up in HID core. - - SET_POWER: Used by I2C-HID, not hooked up in HID core. - -2) HID API -========== - -2.1) Initialization -------------------- - -Transport drivers normally use the following procedure to register a new device -with HID core: - - struct hid_device *hid; - int ret; - - hid = hid_allocate_device(); - if (IS_ERR(hid)) { - ret = PTR_ERR(hid); - goto err_<...>; - } - - strlcpy(hid->name, , 127); - strlcpy(hid->phys, , 63); - strlcpy(hid->uniq, , 63); - - hid->ll_driver = &custom_ll_driver; - hid->bus = ; - hid->vendor = ; - hid->product = ; - hid->version = ; - hid->country = ; - hid->dev.parent = ; - hid->driver_data = ; - - ret = hid_add_device(hid); - if (ret) - goto err_<...>; - -Once hid_add_device() is entered, HID core might use the callbacks provided in -"custom_ll_driver". Note that fields like "country" can be ignored by underlying -transport-drivers if not supported. - -To unregister a device, use: - - hid_destroy_device(hid); - -Once hid_destroy_device() returns, HID core will no longer make use of any -driver callbacks. - -2.2) hid_ll_driver operations ------------------------------ - -The available HID callbacks are: - - int (*start) (struct hid_device *hdev) - Called from HID device drivers once they want to use the device. Transport - drivers can choose to setup their device in this callback. However, normally - devices are already set up before transport drivers register them to HID core - so this is mostly only used by USB-HID. - - - void (*stop) (struct hid_device *hdev) - Called from HID device drivers once they are done with a device. Transport - drivers can free any buffers and deinitialize the device. But note that - ->start() might be called again if another HID device driver is loaded on the - device. - Transport drivers are free to ignore it and deinitialize devices after they - destroyed them via hid_destroy_device(). - - - int (*open) (struct hid_device *hdev) - Called from HID device drivers once they are interested in data reports. - Usually, while user-space didn't open any input API/etc., device drivers are - not interested in device data and transport drivers can put devices asleep. - However, once ->open() is called, transport drivers must be ready for I/O. - ->open() calls are nested for each client that opens the HID device. - - - void (*close) (struct hid_device *hdev) - Called from HID device drivers after ->open() was called but they are no - longer interested in device reports. (Usually if user-space closed any input - devices of the driver). - Transport drivers can put devices asleep and terminate any I/O of all - ->open() calls have been followed by a ->close() call. However, ->start() may - be called again if the device driver is interested in input reports again. - - - int (*parse) (struct hid_device *hdev) - Called once during device setup after ->start() has been called. Transport - drivers must read the HID report-descriptor from the device and tell HID core - about it via hid_parse_report(). - - - int (*power) (struct hid_device *hdev, int level) - Called by HID core to give PM hints to transport drivers. Usually this is - analogical to the ->open() and ->close() hints and redundant. - - - void (*request) (struct hid_device *hdev, struct hid_report *report, - int reqtype) - Send an HID request on the ctrl channel. "report" contains the report that - should be sent and "reqtype" the request type. Request-type can be - HID_REQ_SET_REPORT or HID_REQ_GET_REPORT. - This callback is optional. If not provided, HID core will assemble a raw - report following the HID specs and send it via the ->raw_request() callback. - The transport driver is free to implement this asynchronously. - - - int (*wait) (struct hid_device *hdev) - Used by HID core before calling ->request() again. A transport driver can use - it to wait for any pending requests to complete if only one request is - allowed at a time. - - - int (*raw_request) (struct hid_device *hdev, unsigned char reportnum, - __u8 *buf, size_t count, unsigned char rtype, - int reqtype) - Same as ->request() but provides the report as raw buffer. This request shall - be synchronous. A transport driver must not use ->wait() to complete such - requests. This request is mandatory and hid core will reject the device if - it is missing. - - - int (*output_report) (struct hid_device *hdev, __u8 *buf, size_t len) - Send raw output report via intr channel. Used by some HID device drivers - which require high throughput for outgoing requests on the intr channel. This - must not cause SET_REPORT calls! This must be implemented as asynchronous - output report on the intr channel! - - - int (*idle) (struct hid_device *hdev, int report, int idle, int reqtype) - Perform SET/GET_IDLE request. Only used by USB-HID, do not implement! - -2.3) Data Path --------------- - -Transport drivers are responsible of reading data from I/O devices. They must -handle any I/O-related state-tracking themselves. HID core does not implement -protocol handshakes or other management commands which can be required by the -given HID transport specification. - -Every raw data packet read from a device must be fed into HID core via -hid_input_report(). You must specify the channel-type (intr or ctrl) and report -type (input/output/feature). Under normal conditions, only input reports are -provided via this API. - -Responses to GET_REPORT requests via ->request() must also be provided via this -API. Responses to ->raw_request() are synchronous and must be intercepted by the -transport driver and not passed to hid_input_report(). -Acknowledgements to SET_REPORT requests are not of interest to HID core. - ----------------------------------------------------- -Written 2013, David Herrmann diff --git a/Documentation/hid/hiddev.rst b/Documentation/hid/hiddev.rst new file mode 100644 index 000000000000..209e6ba4e019 --- /dev/null +++ b/Documentation/hid/hiddev.rst @@ -0,0 +1,251 @@ +================================================ +Care and feeding of your Human Interface Devices +================================================ + +Introduction +============ + +In addition to the normal input type HID devices, USB also uses the +human interface device protocols for things that are not really human +interfaces, but have similar sorts of communication needs. The two big +examples for this are power devices (especially uninterruptable power +supplies) and monitor control on higher end monitors. + +To support these disparate requirements, the Linux USB system provides +HID events to two separate interfaces: +* the input subsystem, which converts HID events into normal input +device interfaces (such as keyboard, mouse and joystick) and a +normalised event interface - see Documentation/input/input.rst +* the hiddev interface, which provides fairly raw HID events + +The data flow for a HID event produced by a device is something like +the following:: + + usb.c ---> hid-core.c ----> hid-input.c ----> [keyboard/mouse/joystick/event] + | + | + --> hiddev.c ----> POWER / MONITOR CONTROL + +In addition, other subsystems (apart from USB) can potentially feed +events into the input subsystem, but these have no effect on the hid +device interface. + +Using the HID Device Interface +============================== + +The hiddev interface is a char interface using the normal USB major, +with the minor numbers starting at 96 and finishing at 111. Therefore, +you need the following commands:: + + mknod /dev/usb/hiddev0 c 180 96 + mknod /dev/usb/hiddev1 c 180 97 + mknod /dev/usb/hiddev2 c 180 98 + mknod /dev/usb/hiddev3 c 180 99 + mknod /dev/usb/hiddev4 c 180 100 + mknod /dev/usb/hiddev5 c 180 101 + mknod /dev/usb/hiddev6 c 180 102 + mknod /dev/usb/hiddev7 c 180 103 + mknod /dev/usb/hiddev8 c 180 104 + mknod /dev/usb/hiddev9 c 180 105 + mknod /dev/usb/hiddev10 c 180 106 + mknod /dev/usb/hiddev11 c 180 107 + mknod /dev/usb/hiddev12 c 180 108 + mknod /dev/usb/hiddev13 c 180 109 + mknod /dev/usb/hiddev14 c 180 110 + mknod /dev/usb/hiddev15 c 180 111 + +So you point your hiddev compliant user-space program at the correct +interface for your device, and it all just works. + +Assuming that you have a hiddev compliant user-space program, of +course. If you need to write one, read on. + + +The HIDDEV API +============== + +This description should be read in conjunction with the HID +specification, freely available from http://www.usb.org, and +conveniently linked of http://www.linux-usb.org. + +The hiddev API uses a read() interface, and a set of ioctl() calls. + +HID devices exchange data with the host computer using data +bundles called "reports". Each report is divided into "fields", +each of which can have one or more "usages". In the hid-core, +each one of these usages has a single signed 32 bit value. + +read(): +------- + +This is the event interface. When the HID device's state changes, +it performs an interrupt transfer containing a report which contains +the changed value. The hid-core.c module parses the report, and +returns to hiddev.c the individual usages that have changed within +the report. In its basic mode, the hiddev will make these individual +usage changes available to the reader using a struct hiddev_event:: + + struct hiddev_event { + unsigned hid; + signed int value; + }; + +containing the HID usage identifier for the status that changed, and +the value that it was changed to. Note that the structure is defined +within , along with some other useful #defines and +structures. The HID usage identifier is a composite of the HID usage +page shifted to the 16 high order bits ORed with the usage code. The +behavior of the read() function can be modified using the HIDIOCSFLAG +ioctl() described below. + + +ioctl(): +-------- + +This is the control interface. There are a number of controls: + +HIDIOCGVERSION + - int (read) + + Gets the version code out of the hiddev driver. + +HIDIOCAPPLICATION + - (none) + +This ioctl call returns the HID application usage associated with the +hid device. The third argument to ioctl() specifies which application +index to get. This is useful when the device has more than one +application collection. If the index is invalid (greater or equal to +the number of application collections this device has) the ioctl +returns -1. You can find out beforehand how many application +collections the device has from the num_applications field from the +hiddev_devinfo structure. + +HIDIOCGCOLLECTIONINFO + - struct hiddev_collection_info (read/write) + +This returns a superset of the information above, providing not only +application collections, but all the collections the device has. It +also returns the level the collection lives in the hierarchy. +The user passes in a hiddev_collection_info struct with the index +field set to the index that should be returned. The ioctl fills in +the other fields. If the index is larger than the last collection +index, the ioctl returns -1 and sets errno to -EINVAL. + +HIDIOCGDEVINFO + - struct hiddev_devinfo (read) + +Gets a hiddev_devinfo structure which describes the device. + +HIDIOCGSTRING + - struct hiddev_string_descriptor (read/write) + +Gets a string descriptor from the device. The caller must fill in the +"index" field to indicate which descriptor should be returned. + +HIDIOCINITREPORT + - (none) + +Instructs the kernel to retrieve all input and feature report values +from the device. At this point, all the usage structures will contain +current values for the device, and will maintain it as the device +changes. Note that the use of this ioctl is unnecessary in general, +since later kernels automatically initialize the reports from the +device at attach time. + +HIDIOCGNAME + - string (variable length) + +Gets the device name + +HIDIOCGREPORT + - struct hiddev_report_info (write) + +Instructs the kernel to get a feature or input report from the device, +in order to selectively update the usage structures (in contrast to +INITREPORT). + +HIDIOCSREPORT + - struct hiddev_report_info (write) + +Instructs the kernel to send a report to the device. This report can +be filled in by the user through HIDIOCSUSAGE calls (below) to fill in +individual usage values in the report before sending the report in full +to the device. + +HIDIOCGREPORTINFO + - struct hiddev_report_info (read/write) + +Fills in a hiddev_report_info structure for the user. The report is +looked up by type (input, output or feature) and id, so these fields +must be filled in by the user. The ID can be absolute -- the actual +report id as reported by the device -- or relative -- +HID_REPORT_ID_FIRST for the first report, and (HID_REPORT_ID_NEXT | +report_id) for the next report after report_id. Without a-priori +information about report ids, the right way to use this ioctl is to +use the relative IDs above to enumerate the valid IDs. The ioctl +returns non-zero when there is no more next ID. The real report ID is +filled into the returned hiddev_report_info structure. + +HIDIOCGFIELDINFO + - struct hiddev_field_info (read/write) + +Returns the field information associated with a report in a +hiddev_field_info structure. The user must fill in report_id and +report_type in this structure, as above. The field_index should also +be filled in, which should be a number from 0 and maxfield-1, as +returned from a previous HIDIOCGREPORTINFO call. + +HIDIOCGUCODE + - struct hiddev_usage_ref (read/write) + +Returns the usage_code in a hiddev_usage_ref structure, given that +given its report type, report id, field index, and index within the +field have already been filled into the structure. + +HIDIOCGUSAGE + - struct hiddev_usage_ref (read/write) + +Returns the value of a usage in a hiddev_usage_ref structure. The +usage to be retrieved can be specified as above, or the user can +choose to fill in the report_type field and specify the report_id as +HID_REPORT_ID_UNKNOWN. In this case, the hiddev_usage_ref will be +filled in with the report and field information associated with this +usage if it is found. + +HIDIOCSUSAGE + - struct hiddev_usage_ref (write) + +Sets the value of a usage in an output report. The user fills in +the hiddev_usage_ref structure as above, but additionally fills in +the value field. + +HIDIOGCOLLECTIONINDEX + - struct hiddev_usage_ref (write) + +Returns the collection index associated with this usage. This +indicates where in the collection hierarchy this usage sits. + +HIDIOCGFLAG + - int (read) +HIDIOCSFLAG + - int (write) + +These operations respectively inspect and replace the mode flags +that influence the read() call above. The flags are as follows: + + HIDDEV_FLAG_UREF + - read() calls will now return + struct hiddev_usage_ref instead of struct hiddev_event. + This is a larger structure, but in situations where the + device has more than one usage in its reports with the + same usage code, this mode serves to resolve such + ambiguity. + + HIDDEV_FLAG_REPORT + - This flag can only be used in conjunction + with HIDDEV_FLAG_UREF. With this flag set, when the device + sends a report, a struct hiddev_usage_ref will be returned + to read() filled in with the report_type and report_id, but + with field_index set to FIELD_INDEX_NONE. This serves as + additional notification when the device has sent a report. diff --git a/Documentation/hid/hiddev.txt b/Documentation/hid/hiddev.txt deleted file mode 100644 index 638448707aa2..000000000000 --- a/Documentation/hid/hiddev.txt +++ /dev/null @@ -1,205 +0,0 @@ -Care and feeding of your Human Interface Devices - -INTRODUCTION - -In addition to the normal input type HID devices, USB also uses the -human interface device protocols for things that are not really human -interfaces, but have similar sorts of communication needs. The two big -examples for this are power devices (especially uninterruptable power -supplies) and monitor control on higher end monitors. - -To support these disparate requirements, the Linux USB system provides -HID events to two separate interfaces: -* the input subsystem, which converts HID events into normal input -device interfaces (such as keyboard, mouse and joystick) and a -normalised event interface - see Documentation/input/input.rst -* the hiddev interface, which provides fairly raw HID events - -The data flow for a HID event produced by a device is something like -the following : - - usb.c ---> hid-core.c ----> hid-input.c ----> [keyboard/mouse/joystick/event] - | - | - --> hiddev.c ----> POWER / MONITOR CONTROL - -In addition, other subsystems (apart from USB) can potentially feed -events into the input subsystem, but these have no effect on the hid -device interface. - -USING THE HID DEVICE INTERFACE - -The hiddev interface is a char interface using the normal USB major, -with the minor numbers starting at 96 and finishing at 111. Therefore, -you need the following commands: -mknod /dev/usb/hiddev0 c 180 96 -mknod /dev/usb/hiddev1 c 180 97 -mknod /dev/usb/hiddev2 c 180 98 -mknod /dev/usb/hiddev3 c 180 99 -mknod /dev/usb/hiddev4 c 180 100 -mknod /dev/usb/hiddev5 c 180 101 -mknod /dev/usb/hiddev6 c 180 102 -mknod /dev/usb/hiddev7 c 180 103 -mknod /dev/usb/hiddev8 c 180 104 -mknod /dev/usb/hiddev9 c 180 105 -mknod /dev/usb/hiddev10 c 180 106 -mknod /dev/usb/hiddev11 c 180 107 -mknod /dev/usb/hiddev12 c 180 108 -mknod /dev/usb/hiddev13 c 180 109 -mknod /dev/usb/hiddev14 c 180 110 -mknod /dev/usb/hiddev15 c 180 111 - -So you point your hiddev compliant user-space program at the correct -interface for your device, and it all just works. - -Assuming that you have a hiddev compliant user-space program, of -course. If you need to write one, read on. - - -THE HIDDEV API -This description should be read in conjunction with the HID -specification, freely available from http://www.usb.org, and -conveniently linked of http://www.linux-usb.org. - -The hiddev API uses a read() interface, and a set of ioctl() calls. - -HID devices exchange data with the host computer using data -bundles called "reports". Each report is divided into "fields", -each of which can have one or more "usages". In the hid-core, -each one of these usages has a single signed 32 bit value. - -read(): -This is the event interface. When the HID device's state changes, -it performs an interrupt transfer containing a report which contains -the changed value. The hid-core.c module parses the report, and -returns to hiddev.c the individual usages that have changed within -the report. In its basic mode, the hiddev will make these individual -usage changes available to the reader using a struct hiddev_event: - - struct hiddev_event { - unsigned hid; - signed int value; - }; - -containing the HID usage identifier for the status that changed, and -the value that it was changed to. Note that the structure is defined -within , along with some other useful #defines and -structures. The HID usage identifier is a composite of the HID usage -page shifted to the 16 high order bits ORed with the usage code. The -behavior of the read() function can be modified using the HIDIOCSFLAG -ioctl() described below. - - -ioctl(): -This is the control interface. There are a number of controls: - -HIDIOCGVERSION - int (read) -Gets the version code out of the hiddev driver. - -HIDIOCAPPLICATION - (none) -This ioctl call returns the HID application usage associated with the -hid device. The third argument to ioctl() specifies which application -index to get. This is useful when the device has more than one -application collection. If the index is invalid (greater or equal to -the number of application collections this device has) the ioctl -returns -1. You can find out beforehand how many application -collections the device has from the num_applications field from the -hiddev_devinfo structure. - -HIDIOCGCOLLECTIONINFO - struct hiddev_collection_info (read/write) -This returns a superset of the information above, providing not only -application collections, but all the collections the device has. It -also returns the level the collection lives in the hierarchy. -The user passes in a hiddev_collection_info struct with the index -field set to the index that should be returned. The ioctl fills in -the other fields. If the index is larger than the last collection -index, the ioctl returns -1 and sets errno to -EINVAL. - -HIDIOCGDEVINFO - struct hiddev_devinfo (read) -Gets a hiddev_devinfo structure which describes the device. - -HIDIOCGSTRING - struct hiddev_string_descriptor (read/write) -Gets a string descriptor from the device. The caller must fill in the -"index" field to indicate which descriptor should be returned. - -HIDIOCINITREPORT - (none) -Instructs the kernel to retrieve all input and feature report values -from the device. At this point, all the usage structures will contain -current values for the device, and will maintain it as the device -changes. Note that the use of this ioctl is unnecessary in general, -since later kernels automatically initialize the reports from the -device at attach time. - -HIDIOCGNAME - string (variable length) -Gets the device name - -HIDIOCGREPORT - struct hiddev_report_info (write) -Instructs the kernel to get a feature or input report from the device, -in order to selectively update the usage structures (in contrast to -INITREPORT). - -HIDIOCSREPORT - struct hiddev_report_info (write) -Instructs the kernel to send a report to the device. This report can -be filled in by the user through HIDIOCSUSAGE calls (below) to fill in -individual usage values in the report before sending the report in full -to the device. - -HIDIOCGREPORTINFO - struct hiddev_report_info (read/write) -Fills in a hiddev_report_info structure for the user. The report is -looked up by type (input, output or feature) and id, so these fields -must be filled in by the user. The ID can be absolute -- the actual -report id as reported by the device -- or relative -- -HID_REPORT_ID_FIRST for the first report, and (HID_REPORT_ID_NEXT | -report_id) for the next report after report_id. Without a-priori -information about report ids, the right way to use this ioctl is to -use the relative IDs above to enumerate the valid IDs. The ioctl -returns non-zero when there is no more next ID. The real report ID is -filled into the returned hiddev_report_info structure. - -HIDIOCGFIELDINFO - struct hiddev_field_info (read/write) -Returns the field information associated with a report in a -hiddev_field_info structure. The user must fill in report_id and -report_type in this structure, as above. The field_index should also -be filled in, which should be a number from 0 and maxfield-1, as -returned from a previous HIDIOCGREPORTINFO call. - -HIDIOCGUCODE - struct hiddev_usage_ref (read/write) -Returns the usage_code in a hiddev_usage_ref structure, given that -given its report type, report id, field index, and index within the -field have already been filled into the structure. - -HIDIOCGUSAGE - struct hiddev_usage_ref (read/write) -Returns the value of a usage in a hiddev_usage_ref structure. The -usage to be retrieved can be specified as above, or the user can -choose to fill in the report_type field and specify the report_id as -HID_REPORT_ID_UNKNOWN. In this case, the hiddev_usage_ref will be -filled in with the report and field information associated with this -usage if it is found. - -HIDIOCSUSAGE - struct hiddev_usage_ref (write) -Sets the value of a usage in an output report. The user fills in -the hiddev_usage_ref structure as above, but additionally fills in -the value field. - -HIDIOGCOLLECTIONINDEX - struct hiddev_usage_ref (write) -Returns the collection index associated with this usage. This -indicates where in the collection hierarchy this usage sits. - -HIDIOCGFLAG - int (read) -HIDIOCSFLAG - int (write) -These operations respectively inspect and replace the mode flags -that influence the read() call above. The flags are as follows: - - HIDDEV_FLAG_UREF - read() calls will now return - struct hiddev_usage_ref instead of struct hiddev_event. - This is a larger structure, but in situations where the - device has more than one usage in its reports with the - same usage code, this mode serves to resolve such - ambiguity. - - HIDDEV_FLAG_REPORT - This flag can only be used in conjunction - with HIDDEV_FLAG_UREF. With this flag set, when the device - sends a report, a struct hiddev_usage_ref will be returned - to read() filled in with the report_type and report_id, but - with field_index set to FIELD_INDEX_NONE. This serves as - additional notification when the device has sent a report. diff --git a/Documentation/hid/hidraw.rst b/Documentation/hid/hidraw.rst new file mode 100644 index 000000000000..4a4a0ba1f362 --- /dev/null +++ b/Documentation/hid/hidraw.rst @@ -0,0 +1,138 @@ +================================================================ +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 uapi/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/Documentation/hid/hidraw.txt b/Documentation/hid/hidraw.txt deleted file mode 100644 index c8436e354f44..000000000000 --- a/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 uapi/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/Documentation/hid/index.rst b/Documentation/hid/index.rst new file mode 100644 index 000000000000..af4324902622 --- /dev/null +++ b/Documentation/hid/index.rst @@ -0,0 +1,18 @@ +:orphan: + +============================= +Human Interface Devices (HID) +============================= + +.. toctree:: + :maxdepth: 1 + + hiddev + hidraw + hid-sensor + hid-transport + + uhid + + hid-alps + intel-ish-hid diff --git a/Documentation/hid/intel-ish-hid.rst b/Documentation/hid/intel-ish-hid.rst new file mode 100644 index 000000000000..cccbf4be17d7 --- /dev/null +++ b/Documentation/hid/intel-ish-hid.rst @@ -0,0 +1,485 @@ +================================= +Intel Integrated Sensor Hub (ISH) +================================= + +A sensor hub enables the ability to offload sensor polling and algorithm +processing to a dedicated low power co-processor. This allows the core +processor to go into low power modes more often, resulting in the increased +battery life. + +There are many vendors providing external sensor hubs confirming to HID +Sensor usage tables, and used in several tablets, 2 in 1 convertible laptops +and embedded products. Linux had this support since Linux 3.9. + +Intel® introduced integrated sensor hubs as a part of the SoC starting from +Cherry Trail and now supported on multiple generations of CPU packages. There +are many commercial devices already shipped with Integrated Sensor Hubs (ISH). +These ISH also comply to HID sensor specification, but the difference is the +transport protocol used for communication. The current external sensor hubs +mainly use HID over i2C or USB. But ISH doesn't use either i2c or USB. + +1. Overview +=========== + +Using a analogy with a usbhid implementation, the ISH follows a similar model +for a very high speed communication:: + + ----------------- ---------------------- + | USB HID | --> | ISH HID | + ----------------- ---------------------- + ----------------- ---------------------- + | USB protocol | --> | ISH Transport | + ----------------- ---------------------- + ----------------- ---------------------- + | EHCI/XHCI | --> | ISH IPC | + ----------------- ---------------------- + PCI PCI + ----------------- ---------------------- + |Host controller| --> | ISH processor | + ----------------- ---------------------- + USB Link + ----------------- ---------------------- + | USB End points| --> | ISH Clients | + ----------------- ---------------------- + +Like USB protocol provides a method for device enumeration, link management +and user data encapsulation, the ISH also provides similar services. But it is +very light weight tailored to manage and communicate with ISH client +applications implemented in the firmware. + +The ISH allows multiple sensor management applications executing in the +firmware. Like USB endpoints the messaging can be to/from a client. As part of +enumeration process, these clients are identified. These clients can be simple +HID sensor applications, sensor calibration application or senor firmware +update application. + +The implementation model is similar, like USB bus, ISH transport is also +implemented as a bus. Each client application executing in the ISH processor +is registered as a device on this bus. The driver, which binds each device +(ISH HID driver) identifies the device type and registers with the hid core. + +2. ISH Implementation: Block Diagram +==================================== + +:: + + --------------------------- + | User Space Applications | + --------------------------- + + ----------------IIO ABI---------------- + -------------------------- + | IIO Sensor Drivers | + -------------------------- + -------------------------- + | IIO core | + -------------------------- + -------------------------- + | HID Sensor Hub MFD | + -------------------------- + -------------------------- + | HID Core | + -------------------------- + -------------------------- + | HID over ISH Client | + -------------------------- + -------------------------- + | ISH Transport (ISHTP) | + -------------------------- + -------------------------- + | IPC Drivers | + -------------------------- + OS + ---------------- PCI ----------------- + Hardware + Firmware + ---------------------------- + | ISH Hardware/Firmware(FW) | + ---------------------------- + +3. High level processing in above blocks +======================================== + +3.1 Hardware Interface +---------------------- + +The ISH is exposed as "Non-VGA unclassified PCI device" to the host. The PCI +product and vendor IDs are changed from different generations of processors. So +the source code which enumerate drivers needs to update from generation to +generation. + +3.2 Inter Processor Communication (IPC) driver +---------------------------------------------- + +Location: drivers/hid/intel-ish-hid/ipc + +The IPC message used memory mapped I/O. The registers are defined in +hw-ish-regs.h. + +3.2.1 IPC/FW message types +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +There are two types of messages, one for management of link and other messages +are to and from transport layers. + +TX and RX of Transport messages +............................... + +A set of memory mapped register offers support of multi byte messages TX and +RX (E.g.IPC_REG_ISH2HOST_MSG, IPC_REG_HOST2ISH_MSG). The IPC layer maintains +internal queues to sequence messages and send them in order to the FW. +Optionally the caller can register handler to get notification of completion. +A door bell mechanism is used in messaging to trigger processing in host and +client firmware side. When ISH interrupt handler is called, the ISH2HOST +doorbell register is used by host drivers to determine that the interrupt +is for ISH. + +Each side has 32 32-bit message registers and a 32-bit doorbell. Doorbell +register has the following format: +Bits 0..6: fragment length (7 bits are used) +Bits 10..13: encapsulated protocol +Bits 16..19: management command (for IPC management protocol) +Bit 31: doorbell trigger (signal H/W interrupt to the other side) +Other bits are reserved, should be 0. + +3.2.2 Transport layer interface +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To abstract HW level IPC communication, a set of callbacks are registered. +The transport layer uses them to send and receive messages. +Refer to struct ishtp_hw_ops for callbacks. + +3.3 ISH Transport layer +----------------------- + +Location: drivers/hid/intel-ish-hid/ishtp/ + +3.3.1 A Generic Transport Layer +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The transport layer is a bi-directional protocol, which defines: +- Set of commands to start, stop, connect, disconnect and flow control +(ishtp/hbm.h) for details +- A flow control mechanism to avoid buffer overflows + +This protocol resembles bus messages described in the following document: +http://www.intel.com/content/dam/www/public/us/en/documents/technical-\ +specifications/dcmi-hi-1-0-spec.pdf "Chapter 7: Bus Message Layer" + +3.3.2 Connection and Flow Control Mechanism +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Each FW client and a protocol is identified by an UUID. In order to communicate +to a FW client, a connection must be established using connect request and +response bus messages. If successful, a pair (host_client_id and fw_client_id) +will identify the connection. + +Once connection is established, peers send each other flow control bus messages +independently. Every peer may send a message only if it has received a +flow-control credit before. Once it sent a message, it may not send another one +before receiving the next flow control credit. +Either side can send disconnect request bus message to end communication. Also +the link will be dropped if major FW reset occurs. + +3.3.3 Peer to Peer data transfer +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Peer to Peer data transfer can happen with or without using DMA. Depending on +the sensor bandwidth requirement DMA can be enabled by using module parameter +ishtp_use_dma under intel_ishtp. + +Each side (host and FW) manages its DMA transfer memory independently. When an +ISHTP client from either host or FW side wants to send something, it decides +whether to send over IPC or over DMA; for each transfer the decision is +independent. The sending side sends DMA_XFER message when the message is in +the respective host buffer (TX when host client sends, RX when FW client +sends). The recipient of DMA message responds with DMA_XFER_ACK, indicating +the sender that the memory region for that message may be reused. + +DMA initialization is started with host sending DMA_ALLOC_NOTIFY bus message +(that includes RX buffer) and FW responds with DMA_ALLOC_NOTIFY_ACK. +Additionally to DMA address communication, this sequence checks capabilities: +if thw host doesn't support DMA, then it won't send DMA allocation, so FW can't +send DMA; if FW doesn't support DMA then it won't respond with +DMA_ALLOC_NOTIFY_ACK, in which case host will not use DMA transfers. +Here ISH acts as busmaster DMA controller. Hence when host sends DMA_XFER, +it's request to do host->ISH DMA transfer; when FW sends DMA_XFER, it means +that it already did DMA and the message resides at host. Thus, DMA_XFER +and DMA_XFER_ACK act as ownership indicators. + +At initial state all outgoing memory belongs to the sender (TX to host, RX to +FW), DMA_XFER transfers ownership on the region that contains ISHTP message to +the receiving side, DMA_XFER_ACK returns ownership to the sender. A sender +needs not wait for previous DMA_XFER to be ack'ed, and may send another message +as long as remaining continuous memory in its ownership is enough. +In principle, multiple DMA_XFER and DMA_XFER_ACK messages may be sent at once +(up to IPC MTU), thus allowing for interrupt throttling. +Currently, ISH FW decides to send over DMA if ISHTP message is more than 3 IPC +fragments and via IPC otherwise. + +3.3.4 Ring Buffers +^^^^^^^^^^^^^^^^^^ + +When a client initiate a connection, a ring or RX and TX buffers are allocated. +The size of ring can be specified by the client. HID client set 16 and 32 for +TX and RX buffers respectively. On send request from client, the data to be +sent is copied to one of the send ring buffer and scheduled to be sent using +bus message protocol. These buffers are required because the FW may have not +have processed the last message and may not have enough flow control credits +to send. Same thing holds true on receive side and flow control is required. + +3.3.5 Host Enumeration +^^^^^^^^^^^^^^^^^^^^^^ + +The host enumeration bus command allow discovery of clients present in the FW. +There can be multiple sensor clients and clients for calibration function. + +To ease in implantation and allow independent driver handle each client +this transport layer takes advantage of Linux Bus driver model. Each +client is registered as device on the the transport bus (ishtp bus). + +Enumeration sequence of messages: + +- Host sends HOST_START_REQ_CMD, indicating that host ISHTP layer is up. +- FW responds with HOST_START_RES_CMD +- Host sends HOST_ENUM_REQ_CMD (enumerate FW clients) +- FW responds with HOST_ENUM_RES_CMD that includes bitmap of available FW + client IDs +- For each FW ID found in that bitmap host sends + HOST_CLIENT_PROPERTIES_REQ_CMD +- FW responds with HOST_CLIENT_PROPERTIES_RES_CMD. Properties include UUID, + max ISHTP message size, etc. +- Once host received properties for that last discovered client, it considers + ISHTP device fully functional (and allocates DMA buffers) + +3.4 HID over ISH Client +----------------------- + +Location: drivers/hid/intel-ish-hid + +The ISHTP client driver is responsible for: + +- enumerate HID devices under FW ISH client +- Get Report descriptor +- Register with HID core as a LL driver +- Process Get/Set feature request +- Get input reports + +3.5 HID Sensor Hub MFD and IIO sensor drivers +--------------------------------------------- + +The functionality in these drivers is the same as an external sensor hub. +Refer to +Documentation/hid/hid-sensor.rst for HID sensor +Documentation/ABI/testing/sysfs-bus-iio for IIO ABIs to user space + +3.6 End to End HID transport Sequence Diagram +--------------------------------------------- + +:: + + HID-ISH-CLN ISHTP IPC HW + | | | | + | | |-----WAKE UP------------------>| + | | | | + | | |-----HOST READY--------------->| + | | | | + | | |<----MNG_RESET_NOTIFY_ACK----- | + | | | | + | |<----ISHTP_START------ | | + | | | | + | |<-----------------HOST_START_RES_CMD-------------------| + | | | | + | |------------------QUERY_SUBSCRIBER-------------------->| + | | | | + | |------------------HOST_ENUM_REQ_CMD------------------->| + | | | | + | |<-----------------HOST_ENUM_RES_CMD--------------------| + | | | | + | |------------------HOST_CLIENT_PROPERTIES_REQ_CMD------>| + | | | | + | |<-----------------HOST_CLIENT_PROPERTIES_RES_CMD-------| + | Create new device on in ishtp bus | | + | | | | + | |------------------HOST_CLIENT_PROPERTIES_REQ_CMD------>| + | | | | + | |<-----------------HOST_CLIENT_PROPERTIES_RES_CMD-------| + | Create new device on in ishtp bus | | + | | | | + | |--Repeat HOST_CLIENT_PROPERTIES_REQ_CMD-till last one--| + | | | | + probed() + |----ishtp_cl_connect--->|----------------- CLIENT_CONNECT_REQ_CMD-------------->| + | | | | + | |<----------------CLIENT_CONNECT_RES_CMD----------------| + | | | | + |register event callback | | | + | | | | + |ishtp_cl_send( + HOSTIF_DM_ENUM_DEVICES) |----------fill ishtp_msg_hdr struct write to HW----- >| + | | | | + | | |<-----IRQ(IPC_PROTOCOL_ISHTP---| + | | | | + |<--ENUM_DEVICE RSP------| | | + | | | | + for each enumerated device + |ishtp_cl_send( + HOSTIF_GET_HID_DESCRIPTOR|----------fill ishtp_msg_hdr struct write to HW----- >| + | | | | + ...Response + | | | | + for each enumerated device + |ishtp_cl_send( + HOSTIF_GET_REPORT_DESCRIPTOR|--------------fill ishtp_msg_hdr struct write to HW-- >| + | | | | + | | | | + hid_allocate_device + | | | | + hid_add_device | | | + | | | | + + +3.7 ISH Debugging +----------------- + +To debug ISH, event tracing mechanism is used. To enable debug logs +echo 1 > /sys/kernel/debug/tracing/events/intel_ish/enable +cat sys/kernel/debug/tracing/trace + +3.8 ISH IIO sysfs Example on Lenovo thinkpad Yoga 260 +----------------------------------------------------- + +:: + + root@otcpl-ThinkPad-Yoga-260:~# tree -l /sys/bus/iio/devices/ + /sys/bus/iio/devices/ + ├── iio:device0 -> ../../../devices/0044:8086:22D8.0001/HID-SENSOR-200073.9.auto/iio:device0 + │   ├── buffer + │   │   ├── enable + │   │   ├── length + │   │   └── watermark + ... + │   ├── in_accel_hysteresis + │   ├── in_accel_offset + │   ├── in_accel_sampling_frequency + │   ├── in_accel_scale + │   ├── in_accel_x_raw + │   ├── in_accel_y_raw + │   ├── in_accel_z_raw + │   ├── name + │   ├── scan_elements + │   │   ├── in_accel_x_en + │   │   ├── in_accel_x_index + │   │   ├── in_accel_x_type + │   │   ├── in_accel_y_en + │   │   ├── in_accel_y_index + │   │   ├── in_accel_y_type + │   │   ├── in_accel_z_en + │   │   ├── in_accel_z_index + │   │   └── in_accel_z_type + ... + │   │   ├── devices + │   │   │   │   ├── buffer + │   │   │   │   │   ├── enable + │   │   │   │   │   ├── length + │   │   │   │   │   └── watermark + │   │   │   │   ├── dev + │   │   │   │   ├── in_intensity_both_raw + │   │   │   │   ├── in_intensity_hysteresis + │   │   │   │   ├── in_intensity_offset + │   │   │   │   ├── in_intensity_sampling_frequency + │   │   │   │   ├── in_intensity_scale + │   │   │   │   ├── name + │   │   │   │   ├── scan_elements + │   │   │   │   │   ├── in_intensity_both_en + │   │   │   │   │   ├── in_intensity_both_index + │   │   │   │   │   └── in_intensity_both_type + │   │   │   │   ├── trigger + │   │   │   │   │   └── current_trigger + ... + │   │   │   │   ├── buffer + │   │   │   │   │   ├── enable + │   │   │   │   │   ├── length + │   │   │   │   │   └── watermark + │   │   │   │   ├── dev + │   │   │   │   ├── in_magn_hysteresis + │   │   │   │   ├── in_magn_offset + │   │   │   │   ├── in_magn_sampling_frequency + │   │   │   │   ├── in_magn_scale + │   │   │   │   ├── in_magn_x_raw + │   │   │   │   ├── in_magn_y_raw + │   │   │   │   ├── in_magn_z_raw + │   │   │   │   ├── in_rot_from_north_magnetic_tilt_comp_raw + │   │   │   │   ├── in_rot_hysteresis + │   │   │   │   ├── in_rot_offset + │   │   │   │   ├── in_rot_sampling_frequency + │   │   │   │   ├── in_rot_scale + │   │   │   │   ├── name + ... + │   │   │   │   ├── scan_elements + │   │   │   │   │   ├── in_magn_x_en + │   │   │   │   │   ├── in_magn_x_index + │   │   │   │   │   ├── in_magn_x_type + │   │   │   │   │   ├── in_magn_y_en + │   │   │   │   │   ├── in_magn_y_index + │   │   │   │   │   ├── in_magn_y_type + │   │   │   │   │   ├── in_magn_z_en + │   │   │   │   │   ├── in_magn_z_index + │   │   │   │   │   ├── in_magn_z_type + │   │   │   │   │   ├── in_rot_from_north_magnetic_tilt_comp_en + │   │   │   │   │   ├── in_rot_from_north_magnetic_tilt_comp_index + │   │   │   │   │   └── in_rot_from_north_magnetic_tilt_comp_type + │   │   │   │   ├── trigger + │   │   │   │   │   └── current_trigger + ... + │   │   │   │   ├── buffer + │   │   │   │   │   ├── enable + │   │   │   │   │   ├── length + │   │   │   │   │   └── watermark + │   │   │   │   ├── dev + │   │   │   │   ├── in_anglvel_hysteresis + │   │   │   │   ├── in_anglvel_offset + │   │   │   │   ├── in_anglvel_sampling_frequency + │   │   │   │   ├── in_anglvel_scale + │   │   │   │   ├── in_anglvel_x_raw + │   │   │   │   ├── in_anglvel_y_raw + │   │   │   │   ├── in_anglvel_z_raw + │   │   │   │   ├── name + │   │   │   │   ├── scan_elements + │   │   │   │   │   ├── in_anglvel_x_en + │   │   │   │   │   ├── in_anglvel_x_index + │   │   │   │   │   ├── in_anglvel_x_type + │   │   │   │   │   ├── in_anglvel_y_en + │   │   │   │   │   ├── in_anglvel_y_index + │   │   │   │   │   ├── in_anglvel_y_type + │   │   │   │   │   ├── in_anglvel_z_en + │   │   │   │   │   ├── in_anglvel_z_index + │   │   │   │   │   └── in_anglvel_z_type + │   │   │   │   ├── trigger + │   │   │   │   │   └── current_trigger + ... + │   │   │   │   ├── buffer + │   │   │   │   │   ├── enable + │   │   │   │   │   ├── length + │   │   │   │   │   └── watermark + │   │   │   │   ├── dev + │   │   │   │   ├── in_anglvel_hysteresis + │   │   │   │   ├── in_anglvel_offset + │   │   │   │   ├── in_anglvel_sampling_frequency + │   │   │   │   ├── in_anglvel_scale + │   │   │   │   ├── in_anglvel_x_raw + │   │   │   │   ├── in_anglvel_y_raw + │   │   │   │   ├── in_anglvel_z_raw + │   │   │   │   ├── name + │   │   │   │   ├── scan_elements + │   │   │   │   │   ├── in_anglvel_x_en + │   │   │   │   │   ├── in_anglvel_x_index + │   │   │   │   │   ├── in_anglvel_x_type + │   │   │   │   │   ├── in_anglvel_y_en + │   │   │   │   │   ├── in_anglvel_y_index + │   │   │   │   │   ├── in_anglvel_y_type + │   │   │   │   │   ├── in_anglvel_z_en + │   │   │   │   │   ├── in_anglvel_z_index + │   │   │   │   │   └── in_anglvel_z_type + │   │   │   │   ├── trigger + │   │   │   │   │   └── current_trigger + ... diff --git a/Documentation/hid/intel-ish-hid.txt b/Documentation/hid/intel-ish-hid.txt deleted file mode 100644 index d48b21c71ddd..000000000000 --- a/Documentation/hid/intel-ish-hid.txt +++ /dev/null @@ -1,454 +0,0 @@ -Intel Integrated Sensor Hub (ISH) -=============================== - -A sensor hub enables the ability to offload sensor polling and algorithm -processing to a dedicated low power co-processor. This allows the core -processor to go into low power modes more often, resulting in the increased -battery life. - -There are many vendors providing external sensor hubs confirming to HID -Sensor usage tables, and used in several tablets, 2 in 1 convertible laptops -and embedded products. Linux had this support since Linux 3.9. - -Intel® introduced integrated sensor hubs as a part of the SoC starting from -Cherry Trail and now supported on multiple generations of CPU packages. There -are many commercial devices already shipped with Integrated Sensor Hubs (ISH). -These ISH also comply to HID sensor specification, but the difference is the -transport protocol used for communication. The current external sensor hubs -mainly use HID over i2C or USB. But ISH doesn't use either i2c or USB. - -1. Overview - -Using a analogy with a usbhid implementation, the ISH follows a similar model -for a very high speed communication: - - ----------------- ---------------------- - | USB HID | --> | ISH HID | - ----------------- ---------------------- - ----------------- ---------------------- - | USB protocol | --> | ISH Transport | - ----------------- ---------------------- - ----------------- ---------------------- - | EHCI/XHCI | --> | ISH IPC | - ----------------- ---------------------- - PCI PCI - ----------------- ---------------------- - |Host controller| --> | ISH processor | - ----------------- ---------------------- - USB Link - ----------------- ---------------------- - | USB End points| --> | ISH Clients | - ----------------- ---------------------- - -Like USB protocol provides a method for device enumeration, link management -and user data encapsulation, the ISH also provides similar services. But it is -very light weight tailored to manage and communicate with ISH client -applications implemented in the firmware. - -The ISH allows multiple sensor management applications executing in the -firmware. Like USB endpoints the messaging can be to/from a client. As part of -enumeration process, these clients are identified. These clients can be simple -HID sensor applications, sensor calibration application or senor firmware -update application. - -The implementation model is similar, like USB bus, ISH transport is also -implemented as a bus. Each client application executing in the ISH processor -is registered as a device on this bus. The driver, which binds each device -(ISH HID driver) identifies the device type and registers with the hid core. - -2. ISH Implementation: Block Diagram - - --------------------------- - | User Space Applications | - --------------------------- - -----------------IIO ABI---------------- - -------------------------- - | IIO Sensor Drivers | - -------------------------- - -------------------------- - | IIO core | - -------------------------- - -------------------------- - | HID Sensor Hub MFD | - -------------------------- - -------------------------- - | HID Core | - -------------------------- - -------------------------- - | HID over ISH Client | - -------------------------- - -------------------------- - | ISH Transport (ISHTP) | - -------------------------- - -------------------------- - | IPC Drivers | - -------------------------- -OS ----------------- PCI ----------------- -Hardware + Firmware - ---------------------------- - | ISH Hardware/Firmware(FW) | - ---------------------------- - -3. High level processing in above blocks - -3.1 Hardware Interface - -The ISH is exposed as "Non-VGA unclassified PCI device" to the host. The PCI -product and vendor IDs are changed from different generations of processors. So -the source code which enumerate drivers needs to update from generation to -generation. - -3.2 Inter Processor Communication (IPC) driver -Location: drivers/hid/intel-ish-hid/ipc - -The IPC message used memory mapped I/O. The registers are defined in -hw-ish-regs.h. - -3.2.1 IPC/FW message types - -There are two types of messages, one for management of link and other messages -are to and from transport layers. - -TX and RX of Transport messages - -A set of memory mapped register offers support of multi byte messages TX and -RX (E.g.IPC_REG_ISH2HOST_MSG, IPC_REG_HOST2ISH_MSG). The IPC layer maintains -internal queues to sequence messages and send them in order to the FW. -Optionally the caller can register handler to get notification of completion. -A door bell mechanism is used in messaging to trigger processing in host and -client firmware side. When ISH interrupt handler is called, the ISH2HOST -doorbell register is used by host drivers to determine that the interrupt -is for ISH. - -Each side has 32 32-bit message registers and a 32-bit doorbell. Doorbell -register has the following format: -Bits 0..6: fragment length (7 bits are used) -Bits 10..13: encapsulated protocol -Bits 16..19: management command (for IPC management protocol) -Bit 31: doorbell trigger (signal H/W interrupt to the other side) -Other bits are reserved, should be 0. - -3.2.2 Transport layer interface - -To abstract HW level IPC communication, a set of callbacks are registered. -The transport layer uses them to send and receive messages. -Refer to struct ishtp_hw_ops for callbacks. - -3.3 ISH Transport layer -Location: drivers/hid/intel-ish-hid/ishtp/ - -3.3.1 A Generic Transport Layer - -The transport layer is a bi-directional protocol, which defines: -- Set of commands to start, stop, connect, disconnect and flow control -(ishtp/hbm.h) for details -- A flow control mechanism to avoid buffer overflows - -This protocol resembles bus messages described in the following document: -http://www.intel.com/content/dam/www/public/us/en/documents/technical-\ -specifications/dcmi-hi-1-0-spec.pdf "Chapter 7: Bus Message Layer" - -3.3.2 Connection and Flow Control Mechanism - -Each FW client and a protocol is identified by an UUID. In order to communicate -to a FW client, a connection must be established using connect request and -response bus messages. If successful, a pair (host_client_id and fw_client_id) -will identify the connection. - -Once connection is established, peers send each other flow control bus messages -independently. Every peer may send a message only if it has received a -flow-control credit before. Once it sent a message, it may not send another one -before receiving the next flow control credit. -Either side can send disconnect request bus message to end communication. Also -the link will be dropped if major FW reset occurs. - -3.3.3 Peer to Peer data transfer - -Peer to Peer data transfer can happen with or without using DMA. Depending on -the sensor bandwidth requirement DMA can be enabled by using module parameter -ishtp_use_dma under intel_ishtp. - -Each side (host and FW) manages its DMA transfer memory independently. When an -ISHTP client from either host or FW side wants to send something, it decides -whether to send over IPC or over DMA; for each transfer the decision is -independent. The sending side sends DMA_XFER message when the message is in -the respective host buffer (TX when host client sends, RX when FW client -sends). The recipient of DMA message responds with DMA_XFER_ACK, indicating -the sender that the memory region for that message may be reused. - -DMA initialization is started with host sending DMA_ALLOC_NOTIFY bus message -(that includes RX buffer) and FW responds with DMA_ALLOC_NOTIFY_ACK. -Additionally to DMA address communication, this sequence checks capabilities: -if thw host doesn't support DMA, then it won't send DMA allocation, so FW can't -send DMA; if FW doesn't support DMA then it won't respond with -DMA_ALLOC_NOTIFY_ACK, in which case host will not use DMA transfers. -Here ISH acts as busmaster DMA controller. Hence when host sends DMA_XFER, -it's request to do host->ISH DMA transfer; when FW sends DMA_XFER, it means -that it already did DMA and the message resides at host. Thus, DMA_XFER -and DMA_XFER_ACK act as ownership indicators. - -At initial state all outgoing memory belongs to the sender (TX to host, RX to -FW), DMA_XFER transfers ownership on the region that contains ISHTP message to -the receiving side, DMA_XFER_ACK returns ownership to the sender. A sender -needs not wait for previous DMA_XFER to be ack'ed, and may send another message -as long as remaining continuous memory in its ownership is enough. -In principle, multiple DMA_XFER and DMA_XFER_ACK messages may be sent at once -(up to IPC MTU), thus allowing for interrupt throttling. -Currently, ISH FW decides to send over DMA if ISHTP message is more than 3 IPC -fragments and via IPC otherwise. - -3.3.4 Ring Buffers - -When a client initiate a connection, a ring or RX and TX buffers are allocated. -The size of ring can be specified by the client. HID client set 16 and 32 for -TX and RX buffers respectively. On send request from client, the data to be -sent is copied to one of the send ring buffer and scheduled to be sent using -bus message protocol. These buffers are required because the FW may have not -have processed the last message and may not have enough flow control credits -to send. Same thing holds true on receive side and flow control is required. - -3.3.5 Host Enumeration - -The host enumeration bus command allow discovery of clients present in the FW. -There can be multiple sensor clients and clients for calibration function. - -To ease in implantation and allow independent driver handle each client -this transport layer takes advantage of Linux Bus driver model. Each -client is registered as device on the the transport bus (ishtp bus). - -Enumeration sequence of messages: -- Host sends HOST_START_REQ_CMD, indicating that host ISHTP layer is up. -- FW responds with HOST_START_RES_CMD -- Host sends HOST_ENUM_REQ_CMD (enumerate FW clients) -- FW responds with HOST_ENUM_RES_CMD that includes bitmap of available FW -client IDs -- For each FW ID found in that bitmap host sends -HOST_CLIENT_PROPERTIES_REQ_CMD -- FW responds with HOST_CLIENT_PROPERTIES_RES_CMD. Properties include UUID, -max ISHTP message size, etc. -- Once host received properties for that last discovered client, it considers -ISHTP device fully functional (and allocates DMA buffers) - -3.4 HID over ISH Client -Location: drivers/hid/intel-ish-hid - -The ISHTP client driver is responsible for: -- enumerate HID devices under FW ISH client -- Get Report descriptor -- Register with HID core as a LL driver -- Process Get/Set feature request -- Get input reports - -3.5 HID Sensor Hub MFD and IIO sensor drivers - -The functionality in these drivers is the same as an external sensor hub. -Refer to -Documentation/hid/hid-sensor.txt for HID sensor -Documentation/ABI/testing/sysfs-bus-iio for IIO ABIs to user space - -3.6 End to End HID transport Sequence Diagram - -HID-ISH-CLN ISHTP IPC HW - | | | | - | | |-----WAKE UP------------------>| - | | | | - | | |-----HOST READY--------------->| - | | | | - | | |<----MNG_RESET_NOTIFY_ACK----- | - | | | | - | |<----ISHTP_START------ | | - | | | | - | |<-----------------HOST_START_RES_CMD-------------------| - | | | | - | |------------------QUERY_SUBSCRIBER-------------------->| - | | | | - | |------------------HOST_ENUM_REQ_CMD------------------->| - | | | | - | |<-----------------HOST_ENUM_RES_CMD--------------------| - | | | | - | |------------------HOST_CLIENT_PROPERTIES_REQ_CMD------>| - | | | | - | |<-----------------HOST_CLIENT_PROPERTIES_RES_CMD-------| - | Create new device on in ishtp bus | | - | | | | - | |------------------HOST_CLIENT_PROPERTIES_REQ_CMD------>| - | | | | - | |<-----------------HOST_CLIENT_PROPERTIES_RES_CMD-------| - | Create new device on in ishtp bus | | - | | | | - | |--Repeat HOST_CLIENT_PROPERTIES_REQ_CMD-till last one--| - | | | | - probed() - |----ishtp_cl_connect-->|----------------- CLIENT_CONNECT_REQ_CMD-------------->| - | | | | - | |<----------------CLIENT_CONNECT_RES_CMD----------------| - | | | | - |register event callback| | | - | | | | - |ishtp_cl_send( - HOSTIF_DM_ENUM_DEVICES) |----------fill ishtp_msg_hdr struct write to HW----- >| - | | | | - | | |<-----IRQ(IPC_PROTOCOL_ISHTP---| - | | | | - |<--ENUM_DEVICE RSP-----| | | - | | | | -for each enumerated device - |ishtp_cl_send( - HOSTIF_GET_HID_DESCRIPTOR |----------fill ishtp_msg_hdr struct write to HW--- >| - | | | | - ...Response - | | | | -for each enumerated device - |ishtp_cl_send( - HOSTIF_GET_REPORT_DESCRIPTOR |----------fill ishtp_msg_hdr struct write to HW- >| - | | | | - | | | | - hid_allocate_device - | | | | - hid_add_device | | | - | | | | - - -3.7 ISH Debugging - -To debug ISH, event tracing mechanism is used. To enable debug logs -echo 1 > /sys/kernel/debug/tracing/events/intel_ish/enable -cat sys/kernel/debug/tracing/trace - -3.8 ISH IIO sysfs Example on Lenovo thinkpad Yoga 260 - -root@otcpl-ThinkPad-Yoga-260:~# tree -l /sys/bus/iio/devices/ -/sys/bus/iio/devices/ -├── iio:device0 -> ../../../devices/0044:8086:22D8.0001/HID-SENSOR-200073.9.auto/iio:device0 -│   ├── buffer -│   │   ├── enable -│   │   ├── length -│   │   └── watermark -... -│   ├── in_accel_hysteresis -│   ├── in_accel_offset -│   ├── in_accel_sampling_frequency -│   ├── in_accel_scale -│   ├── in_accel_x_raw -│   ├── in_accel_y_raw -│   ├── in_accel_z_raw -│   ├── name -│   ├── scan_elements -│   │   ├── in_accel_x_en -│   │   ├── in_accel_x_index -│   │   ├── in_accel_x_type -│   │   ├── in_accel_y_en -│   │   ├── in_accel_y_index -│   │   ├── in_accel_y_type -│   │   ├── in_accel_z_en -│   │   ├── in_accel_z_index -│   │   └── in_accel_z_type -... -│   │   ├── devices -│   │   │   │   ├── buffer -│   │   │   │   │   ├── enable -│   │   │   │   │   ├── length -│   │   │   │   │   └── watermark -│   │   │   │   ├── dev -│   │   │   │   ├── in_intensity_both_raw -│   │   │   │   ├── in_intensity_hysteresis -│   │   │   │   ├── in_intensity_offset -│   │   │   │   ├── in_intensity_sampling_frequency -│   │   │   │   ├── in_intensity_scale -│   │   │   │   ├── name -│   │   │   │   ├── scan_elements -│   │   │   │   │   ├── in_intensity_both_en -│   │   │   │   │   ├── in_intensity_both_index -│   │   │   │   │   └── in_intensity_both_type -│   │   │   │   ├── trigger -│   │   │   │   │   └── current_trigger -... -│   │   │   │   ├── buffer -│   │   │   │   │   ├── enable -│   │   │   │   │   ├── length -│   │   │   │   │   └── watermark -│   │   │   │   ├── dev -│   │   │   │   ├── in_magn_hysteresis -│   │   │   │   ├── in_magn_offset -│   │   │   │   ├── in_magn_sampling_frequency -│   │   │   │   ├── in_magn_scale -│   │   │   │   ├── in_magn_x_raw -│   │   │   │   ├── in_magn_y_raw -│   │   │   │   ├── in_magn_z_raw -│   │   │   │   ├── in_rot_from_north_magnetic_tilt_comp_raw -│   │   │   │   ├── in_rot_hysteresis -│   │   │   │   ├── in_rot_offset -│   │   │   │   ├── in_rot_sampling_frequency -│   │   │   │   ├── in_rot_scale -│   │   │   │   ├── name -... -│   │   │   │   ├── scan_elements -│   │   │   │   │   ├── in_magn_x_en -│   │   │   │   │   ├── in_magn_x_index -│   │   │   │   │   ├── in_magn_x_type -│   │   │   │   │   ├── in_magn_y_en -│   │   │   │   │   ├── in_magn_y_index -│   │   │   │   │   ├── in_magn_y_type -│   │   │   │   │   ├── in_magn_z_en -│   │   │   │   │   ├── in_magn_z_index -│   │   │   │   │   ├── in_magn_z_type -│   │   │   │   │   ├── in_rot_from_north_magnetic_tilt_comp_en -│   │   │   │   │   ├── in_rot_from_north_magnetic_tilt_comp_index -│   │   │   │   │   └── in_rot_from_north_magnetic_tilt_comp_type -│   │   │   │   ├── trigger -│   │   │   │   │   └── current_trigger -... -│   │   │   │   ├── buffer -│   │   │   │   │   ├── enable -│   │   │   │   │   ├── length -│   │   │   │   │   └── watermark -│   │   │   │   ├── dev -│   │   │   │   ├── in_anglvel_hysteresis -│   │   │   │   ├── in_anglvel_offset -│   │   │   │   ├── in_anglvel_sampling_frequency -│   │   │   │   ├── in_anglvel_scale -│   │   │   │   ├── in_anglvel_x_raw -│   │   │   │   ├── in_anglvel_y_raw -│   │   │   │   ├── in_anglvel_z_raw -│   │   │   │   ├── name -│   │   │   │   ├── scan_elements -│   │   │   │   │   ├── in_anglvel_x_en -│   │   │   │   │   ├── in_anglvel_x_index -│   │   │   │   │   ├── in_anglvel_x_type -│   │   │   │   │   ├── in_anglvel_y_en -│   │   │   │   │   ├── in_anglvel_y_index -│   │   │   │   │   ├── in_anglvel_y_type -│   │   │   │   │   ├── in_anglvel_z_en -│   │   │   │   │   ├── in_anglvel_z_index -│   │   │   │   │   └── in_anglvel_z_type -│   │   │   │   ├── trigger -│   │   │   │   │   └── current_trigger -... -│   │   │   │   ├── buffer -│   │   │   │   │   ├── enable -│   │   │   │   │   ├── length -│   │   │   │   │   └── watermark -│   │   │   │   ├── dev -│   │   │   │   ├── in_anglvel_hysteresis -│   │   │   │   ├── in_anglvel_offset -│   │   │   │   ├── in_anglvel_sampling_frequency -│   │   │   │   ├── in_anglvel_scale -│   │   │   │   ├── in_anglvel_x_raw -│   │   │   │   ├── in_anglvel_y_raw -│   │   │   │   ├── in_anglvel_z_raw -│   │   │   │   ├── name -│   │   │   │   ├── scan_elements -│   │   │   │   │   ├── in_anglvel_x_en -│   │   │   │   │   ├── in_anglvel_x_index -│   │   │   │   │   ├── in_anglvel_x_type -│   │   │   │   │   ├── in_anglvel_y_en -│   │   │   │   │   ├── in_anglvel_y_index -│   │   │   │   │   ├── in_anglvel_y_type -│   │   │   │   │   ├── in_anglvel_z_en -│   │   │   │   │   ├── in_anglvel_z_index -│   │   │   │   │   └── in_anglvel_z_type -│   │   │   │   ├── trigger -│   │   │   │   │   └── current_trigger -... diff --git a/Documentation/hid/uhid.rst b/Documentation/hid/uhid.rst new file mode 100644 index 000000000000..b18cb96c885f --- /dev/null +++ b/Documentation/hid/uhid.rst @@ -0,0 +1,193 @@ +====================================================== +UHID - User-space I/O driver support for HID subsystem +====================================================== + +UHID allows user-space to implement HID transport drivers. Please see +hid-transport.txt for an introduction into HID transport drivers. This document +relies heavily on the definitions declared there. + +With UHID, a user-space transport driver can create kernel hid-devices for each +device connected to the user-space controlled bus. The UHID API defines the I/O +events provided from the kernel to user-space and vice versa. + +There is an example user-space application in ./samples/uhid/uhid-example.c + +The UHID API +------------ + +UHID is accessed through a character misc-device. The minor-number is allocated +dynamically so you need to rely on udev (or similar) to create the device node. +This is /dev/uhid by default. + +If a new device is detected by your HID I/O Driver and you want to register this +device with the HID subsystem, then you need to open /dev/uhid once for each +device you want to register. All further communication is done by read()'ing or +write()'ing "struct uhid_event" objects. Non-blocking operations are supported +by setting O_NONBLOCK:: + + struct uhid_event { + __u32 type; + union { + struct uhid_create2_req create2; + struct uhid_output_req output; + struct uhid_input2_req input2; + ... + } u; + }; + +The "type" field contains the ID of the event. Depending on the ID different +payloads are sent. You must not split a single event across multiple read()'s or +multiple write()'s. A single event must always be sent as a whole. Furthermore, +only a single event can be sent per read() or write(). Pending data is ignored. +If you want to handle multiple events in a single syscall, then use vectored +I/O with readv()/writev(). +The "type" field defines the payload. For each type, there is a +payload-structure available in the union "u" (except for empty payloads). This +payload contains management and/or device data. + +The first thing you should do is sending an UHID_CREATE2 event. This will +register the device. UHID will respond with an UHID_START event. You can now +start sending data to and reading data from UHID. However, unless UHID sends the +UHID_OPEN event, the internally attached HID Device Driver has no user attached. +That is, you might put your device asleep unless you receive the UHID_OPEN +event. If you receive the UHID_OPEN event, you should start I/O. If the last +user closes the HID device, you will receive an UHID_CLOSE event. This may be +followed by an UHID_OPEN event again and so on. There is no need to perform +reference-counting in user-space. That is, you will never receive multiple +UHID_OPEN events without an UHID_CLOSE event. The HID subsystem performs +ref-counting for you. +You may decide to ignore UHID_OPEN/UHID_CLOSE, though. I/O is allowed even +though the device may have no users. + +If you want to send data on the interrupt channel to the HID subsystem, you send +an HID_INPUT2 event with your raw data payload. If the kernel wants to send data +on the interrupt channel to the device, you will read an UHID_OUTPUT event. +Data requests on the control channel are currently limited to GET_REPORT and +SET_REPORT (no other data reports on the control channel are defined so far). +Those requests are always synchronous. That means, the kernel sends +UHID_GET_REPORT and UHID_SET_REPORT events and requires you to forward them to +the device on the control channel. Once the device responds, you must forward +the response via UHID_GET_REPORT_REPLY and UHID_SET_REPORT_REPLY to the kernel. +The kernel blocks internal driver-execution during such round-trips (times out +after a hard-coded period). + +If your device disconnects, you should send an UHID_DESTROY event. This will +unregister the device. You can now send UHID_CREATE2 again to register a new +device. +If you close() the fd, the device is automatically unregistered and destroyed +internally. + +write() +------- +write() allows you to modify the state of the device and feed input data into +the kernel. The kernel will parse the event immediately and if the event ID is +not supported, it will return -EOPNOTSUPP. If the payload is invalid, then +-EINVAL is returned, otherwise, the amount of data that was read is returned and +the request was handled successfully. O_NONBLOCK does not affect write() as +writes are always handled immediately in a non-blocking fashion. Future requests +might make use of O_NONBLOCK, though. + +UHID_CREATE2: + This creates the internal HID device. No I/O is possible until you send this + event to the kernel. The payload is of type struct uhid_create2_req and + contains information about your device. You can start I/O now. + +UHID_DESTROY: + This destroys the internal HID device. No further I/O will be accepted. There + may still be pending messages that you can receive with read() but no further + UHID_INPUT events can be sent to the kernel. + You can create a new device by sending UHID_CREATE2 again. There is no need to + reopen the character device. + +UHID_INPUT2: + You must send UHID_CREATE2 before sending input to the kernel! This event + contains a data-payload. This is the raw data that you read from your device + on the interrupt channel. The kernel will parse the HID reports. + +UHID_GET_REPORT_REPLY: + If you receive a UHID_GET_REPORT request you must answer with this request. + You must copy the "id" field from the request into the answer. Set the "err" + field to 0 if no error occurred or to EIO if an I/O error occurred. + If "err" is 0 then you should fill the buffer of the answer with the results + of the GET_REPORT request and set "size" correspondingly. + +UHID_SET_REPORT_REPLY: + This is the SET_REPORT equivalent of UHID_GET_REPORT_REPLY. Unlike GET_REPORT, + SET_REPORT never returns a data buffer, therefore, it's sufficient to set the + "id" and "err" fields correctly. + +read() +------ +read() will return a queued output report. No reaction is required to any of +them but you should handle them according to your needs. + +UHID_START: + This is sent when the HID device is started. Consider this as an answer to + UHID_CREATE2. This is always the first event that is sent. Note that this + event might not be available immediately after write(UHID_CREATE2) returns. + Device drivers might required delayed setups. + This event contains a payload of type uhid_start_req. The "dev_flags" field + describes special behaviors of a device. The following flags are defined: + + - UHID_DEV_NUMBERED_FEATURE_REPORTS + - UHID_DEV_NUMBERED_OUTPUT_REPORTS + - UHID_DEV_NUMBERED_INPUT_REPORTS + + Each of these flags defines whether a given report-type uses numbered + reports. If numbered reports are used for a type, all messages from + the kernel already have the report-number as prefix. Otherwise, no + prefix is added by the kernel. + For messages sent by user-space to the kernel, you must adjust the + prefixes according to these flags. + +UHID_STOP: + This is sent when the HID device is stopped. Consider this as an answer to + UHID_DESTROY. + + If you didn't destroy your device via UHID_DESTROY, but the kernel sends an + UHID_STOP event, this should usually be ignored. It means that the kernel + reloaded/changed the device driver loaded on your HID device (or some other + maintenance actions happened). + + You can usually ignored any UHID_STOP events safely. + +UHID_OPEN: + This is sent when the HID device is opened. That is, the data that the HID + device provides is read by some other process. You may ignore this event but + it is useful for power-management. As long as you haven't received this event + there is actually no other process that reads your data so there is no need to + send UHID_INPUT2 events to the kernel. + +UHID_CLOSE: + This is sent when there are no more processes which read the HID data. It is + the counterpart of UHID_OPEN and you may as well ignore this event. + +UHID_OUTPUT: + This is sent if the HID device driver wants to send raw data to the I/O + device on the interrupt channel. You should read the payload and forward it to + the device. The payload is of type "struct uhid_output_req". + This may be received even though you haven't received UHID_OPEN, yet. + +UHID_GET_REPORT: + This event is sent if the kernel driver wants to perform a GET_REPORT request + on the control channeld as described in the HID specs. The report-type and + report-number are available in the payload. + The kernel serializes GET_REPORT requests so there will never be two in + parallel. However, if you fail to respond with a UHID_GET_REPORT_REPLY, the + request might silently time out. + Once you read a GET_REPORT request, you shall forward it to the hid device and + remember the "id" field in the payload. Once your hid device responds to the + GET_REPORT (or if it fails), you must send a UHID_GET_REPORT_REPLY to the + kernel with the exact same "id" as in the request. If the request already + timed out, the kernel will ignore the response silently. The "id" field is + never re-used, so conflicts cannot happen. + +UHID_SET_REPORT: + This is the SET_REPORT equivalent of UHID_GET_REPORT. On receipt, you shall + send a SET_REPORT request to your hid device. Once it replies, you must tell + the kernel about it via UHID_SET_REPORT_REPLY. + The same restrictions as for UHID_GET_REPORT apply. + +---------------------------------------------------- + +Written 2012, David Herrmann diff --git a/Documentation/hid/uhid.txt b/Documentation/hid/uhid.txt deleted file mode 100644 index 958fff945304..000000000000 --- a/Documentation/hid/uhid.txt +++ /dev/null @@ -1,187 +0,0 @@ - UHID - User-space I/O driver support for HID subsystem - ======================================================== - -UHID allows user-space to implement HID transport drivers. Please see -hid-transport.txt for an introduction into HID transport drivers. This document -relies heavily on the definitions declared there. - -With UHID, a user-space transport driver can create kernel hid-devices for each -device connected to the user-space controlled bus. The UHID API defines the I/O -events provided from the kernel to user-space and vice versa. - -There is an example user-space application in ./samples/uhid/uhid-example.c - -The UHID API ------------- - -UHID is accessed through a character misc-device. The minor-number is allocated -dynamically so you need to rely on udev (or similar) to create the device node. -This is /dev/uhid by default. - -If a new device is detected by your HID I/O Driver and you want to register this -device with the HID subsystem, then you need to open /dev/uhid once for each -device you want to register. All further communication is done by read()'ing or -write()'ing "struct uhid_event" objects. Non-blocking operations are supported -by setting O_NONBLOCK. - -struct uhid_event { - __u32 type; - union { - struct uhid_create2_req create2; - struct uhid_output_req output; - struct uhid_input2_req input2; - ... - } u; -}; - -The "type" field contains the ID of the event. Depending on the ID different -payloads are sent. You must not split a single event across multiple read()'s or -multiple write()'s. A single event must always be sent as a whole. Furthermore, -only a single event can be sent per read() or write(). Pending data is ignored. -If you want to handle multiple events in a single syscall, then use vectored -I/O with readv()/writev(). -The "type" field defines the payload. For each type, there is a -payload-structure available in the union "u" (except for empty payloads). This -payload contains management and/or device data. - -The first thing you should do is sending an UHID_CREATE2 event. This will -register the device. UHID will respond with an UHID_START event. You can now -start sending data to and reading data from UHID. However, unless UHID sends the -UHID_OPEN event, the internally attached HID Device Driver has no user attached. -That is, you might put your device asleep unless you receive the UHID_OPEN -event. If you receive the UHID_OPEN event, you should start I/O. If the last -user closes the HID device, you will receive an UHID_CLOSE event. This may be -followed by an UHID_OPEN event again and so on. There is no need to perform -reference-counting in user-space. That is, you will never receive multiple -UHID_OPEN events without an UHID_CLOSE event. The HID subsystem performs -ref-counting for you. -You may decide to ignore UHID_OPEN/UHID_CLOSE, though. I/O is allowed even -though the device may have no users. - -If you want to send data on the interrupt channel to the HID subsystem, you send -an HID_INPUT2 event with your raw data payload. If the kernel wants to send data -on the interrupt channel to the device, you will read an UHID_OUTPUT event. -Data requests on the control channel are currently limited to GET_REPORT and -SET_REPORT (no other data reports on the control channel are defined so far). -Those requests are always synchronous. That means, the kernel sends -UHID_GET_REPORT and UHID_SET_REPORT events and requires you to forward them to -the device on the control channel. Once the device responds, you must forward -the response via UHID_GET_REPORT_REPLY and UHID_SET_REPORT_REPLY to the kernel. -The kernel blocks internal driver-execution during such round-trips (times out -after a hard-coded period). - -If your device disconnects, you should send an UHID_DESTROY event. This will -unregister the device. You can now send UHID_CREATE2 again to register a new -device. -If you close() the fd, the device is automatically unregistered and destroyed -internally. - -write() -------- -write() allows you to modify the state of the device and feed input data into -the kernel. The kernel will parse the event immediately and if the event ID is -not supported, it will return -EOPNOTSUPP. If the payload is invalid, then --EINVAL is returned, otherwise, the amount of data that was read is returned and -the request was handled successfully. O_NONBLOCK does not affect write() as -writes are always handled immediately in a non-blocking fashion. Future requests -might make use of O_NONBLOCK, though. - - UHID_CREATE2: - This creates the internal HID device. No I/O is possible until you send this - event to the kernel. The payload is of type struct uhid_create2_req and - contains information about your device. You can start I/O now. - - UHID_DESTROY: - This destroys the internal HID device. No further I/O will be accepted. There - may still be pending messages that you can receive with read() but no further - UHID_INPUT events can be sent to the kernel. - You can create a new device by sending UHID_CREATE2 again. There is no need to - reopen the character device. - - UHID_INPUT2: - You must send UHID_CREATE2 before sending input to the kernel! This event - contains a data-payload. This is the raw data that you read from your device - on the interrupt channel. The kernel will parse the HID reports. - - UHID_GET_REPORT_REPLY: - If you receive a UHID_GET_REPORT request you must answer with this request. - You must copy the "id" field from the request into the answer. Set the "err" - field to 0 if no error occurred or to EIO if an I/O error occurred. - If "err" is 0 then you should fill the buffer of the answer with the results - of the GET_REPORT request and set "size" correspondingly. - - UHID_SET_REPORT_REPLY: - This is the SET_REPORT equivalent of UHID_GET_REPORT_REPLY. Unlike GET_REPORT, - SET_REPORT never returns a data buffer, therefore, it's sufficient to set the - "id" and "err" fields correctly. - -read() ------- -read() will return a queued output report. No reaction is required to any of -them but you should handle them according to your needs. - - UHID_START: - This is sent when the HID device is started. Consider this as an answer to - UHID_CREATE2. This is always the first event that is sent. Note that this - event might not be available immediately after write(UHID_CREATE2) returns. - Device drivers might required delayed setups. - This event contains a payload of type uhid_start_req. The "dev_flags" field - describes special behaviors of a device. The following flags are defined: - UHID_DEV_NUMBERED_FEATURE_REPORTS: - UHID_DEV_NUMBERED_OUTPUT_REPORTS: - UHID_DEV_NUMBERED_INPUT_REPORTS: - Each of these flags defines whether a given report-type uses numbered - reports. If numbered reports are used for a type, all messages from - the kernel already have the report-number as prefix. Otherwise, no - prefix is added by the kernel. - For messages sent by user-space to the kernel, you must adjust the - prefixes according to these flags. - - UHID_STOP: - This is sent when the HID device is stopped. Consider this as an answer to - UHID_DESTROY. - If you didn't destroy your device via UHID_DESTROY, but the kernel sends an - UHID_STOP event, this should usually be ignored. It means that the kernel - reloaded/changed the device driver loaded on your HID device (or some other - maintenance actions happened). - You can usually ignored any UHID_STOP events safely. - - UHID_OPEN: - This is sent when the HID device is opened. That is, the data that the HID - device provides is read by some other process. You may ignore this event but - it is useful for power-management. As long as you haven't received this event - there is actually no other process that reads your data so there is no need to - send UHID_INPUT2 events to the kernel. - - UHID_CLOSE: - This is sent when there are no more processes which read the HID data. It is - the counterpart of UHID_OPEN and you may as well ignore this event. - - UHID_OUTPUT: - This is sent if the HID device driver wants to send raw data to the I/O - device on the interrupt channel. You should read the payload and forward it to - the device. The payload is of type "struct uhid_output_req". - This may be received even though you haven't received UHID_OPEN, yet. - - UHID_GET_REPORT: - This event is sent if the kernel driver wants to perform a GET_REPORT request - on the control channeld as described in the HID specs. The report-type and - report-number are available in the payload. - The kernel serializes GET_REPORT requests so there will never be two in - parallel. However, if you fail to respond with a UHID_GET_REPORT_REPLY, the - request might silently time out. - Once you read a GET_REPORT request, you shall forward it to the hid device and - remember the "id" field in the payload. Once your hid device responds to the - GET_REPORT (or if it fails), you must send a UHID_GET_REPORT_REPLY to the - kernel with the exact same "id" as in the request. If the request already - timed out, the kernel will ignore the response silently. The "id" field is - never re-used, so conflicts cannot happen. - - UHID_SET_REPORT: - This is the SET_REPORT equivalent of UHID_GET_REPORT. On receipt, you shall - send a SET_REPORT request to your hid device. Once it replies, you must tell - the kernel about it via UHID_SET_REPORT_REPLY. - The same restrictions as for UHID_GET_REPORT apply. - ----------------------------------------------------- -Written 2012, David Herrmann diff --git a/Documentation/input/input.rst b/Documentation/input/input.rst index 47f86a4bf16c..0eb61e67a7b7 100644 --- a/Documentation/input/input.rst +++ b/Documentation/input/input.rst @@ -188,7 +188,7 @@ LCDs and many other purposes. The monitor and speaker controls should be easy to add to the hid/input interface, but for the UPSs and LCDs it doesn't make much sense. For this, -the hiddev interface was designed. See Documentation/hid/hiddev.txt +the hiddev interface was designed. See Documentation/hid/hiddev.rst for more information about it. The usage of the usbhid module is very simple, it takes no parameters, diff --git a/MAINTAINERS b/MAINTAINERS index 3c4d72755127..4bbba4636d22 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -16319,7 +16319,7 @@ M: Benjamin Tissoires L: linux-usb@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid.git S: Maintained -F: Documentation/hid/hiddev.txt +F: Documentation/hid/hiddev.rst F: drivers/hid/usbhid/ USB INTEL XHCI ROLE MUX DRIVER -- cgit v1.2.3 From 6e2abc68585b0942257f6198944b8a0e24c67d8f Mon Sep 17 00:00:00 2001 From: Aaron Armstrong Skomra Date: Wed, 26 Jun 2019 15:48:48 -0700 Subject: HID: wacom: generic: add touchring adjustment for 2nd Gen Pro Small Add the product ID for the 2nd Generation Intuos Pro Small to the touchring coordinate adjustment block. Signed-off-by: Aaron Armstrong Skomra Reviewed-by: Ping Cheng Signed-off-by: Benjamin Tissoires --- drivers/hid/wacom_wac.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index e35d04451595..35942bba5390 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -2029,10 +2029,12 @@ static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field if (hdev->vendor == 0x56a && (hdev->product == 0x34d || hdev->product == 0x34e || /* MobileStudio Pro */ hdev->product == 0x357 || hdev->product == 0x358 || /* Intuos Pro 2 */ + hdev->product == 0x392 || /* Intuos Pro 2 */ hdev->product == 0x399)) { /* MobileStudio Pro */ value = (field->logical_maximum - value); - if (hdev->product == 0x357 || hdev->product == 0x358) + if (hdev->product == 0x357 || hdev->product == 0x358 || + hdev->product == 0x392) value = wacom_offset_rotation(input, usage, value, 3, 16); else if (hdev->product == 0x34d || hdev->product == 0x34e || hdev->product == 0x399) -- cgit v1.2.3 From 4c12954965fdf33d8ae3883c1931fc29ca023cfb Mon Sep 17 00:00:00 2001 From: Sebastian Parschauer Date: Mon, 1 Jul 2019 07:48:17 +0200 Subject: HID: Add another Primax PIXART OEM mouse quirk The PixArt OEM mice are known for disconnecting every minute in runlevel 1 or 3 if they are not always polled. So add quirk ALWAYS_POLL for this Alienware branded Primax mouse as well. Daniel Schepler (@dschepler) reported and tested the quirk. Reference: https://github.com/sriemer/fix-linux-mouse/issues/15 Signed-off-by: Sebastian Parschauer CC: stable@vger.kernel.org Signed-off-by: Jiri Kosina --- drivers/hid/hid-ids.h | 1 + drivers/hid/hid-quirks.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 134686012d75..bba2de1c3590 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -1244,6 +1244,7 @@ #define USB_DEVICE_ID_PRIMAX_KEYBOARD 0x4e05 #define USB_DEVICE_ID_PRIMAX_REZEL 0x4e72 #define USB_DEVICE_ID_PRIMAX_PIXART_MOUSE_4D0F 0x4d0f +#define USB_DEVICE_ID_PRIMAX_PIXART_MOUSE_4D65 0x4d65 #define USB_DEVICE_ID_PRIMAX_PIXART_MOUSE_4E22 0x4e22 diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c index 4fbba6a7fb66..b6c541d1f38f 100644 --- a/drivers/hid/hid-quirks.c +++ b/drivers/hid/hid-quirks.c @@ -133,6 +133,7 @@ static const struct hid_device_id hid_quirks[] = { { HID_USB_DEVICE(USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_USB_OPTICAL_MOUSE), HID_QUIRK_ALWAYS_POLL }, { HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_MOUSE_4D22), HID_QUIRK_ALWAYS_POLL }, { HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_PIXART_MOUSE_4D0F), HID_QUIRK_ALWAYS_POLL }, + { HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_PIXART_MOUSE_4D65), HID_QUIRK_ALWAYS_POLL }, { HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_PIXART_MOUSE_4E22), HID_QUIRK_ALWAYS_POLL }, { HID_USB_DEVICE(USB_VENDOR_ID_PRODIGE, USB_DEVICE_ID_PRODIGE_CORDLESS), HID_QUIRK_NOGET }, { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001), HID_QUIRK_NOGET }, -- cgit v1.2.3