Skip to content

Commit b4dd05d

Browse files
committed
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid
Pull HID updates from Jiri Kosina: - support for U2F Zero device, from Andrej Shadura - logitech-dj has historically been treating devices behind non-unifying receivers as generic devices, using the HID emulation in the receiver. That had several shortcomings (special keys handling, battery level monitoring, etc). The driver has been reworked to enumarate (and directly communicate with) the devices behind the receiver, to avoid the (too) generic HID implementation in the receiver itself. All the work done by Benjamin Tissoires and Hans de Goede. - restructuring of intel-ish driver in order to allow for multiple clients of the ISH implementation, from Srinivas Pandruvada - several other smaller fixes and assorted device ID additions * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid: (68 commits) HID: logitech-dj: fix spelling in printk HID: input: fix assignment of .value HID: input: make sure the wheel high resolution multiplier is set HID: logitech-dj: add usbhid dependency in Kconfig HID: logitech-hidpp: add support for HID++ 1.0 consumer keys reports HID: logitech-hidpp: add support for HID++ 1.0 extra mouse buttons reports HID: logitech-hidpp: add support for HID++ 1.0 wheel reports HID: logitech-hidpp: make hidpp10_set_register_bit a bit more generic HID: logitech-hidpp: add input_device ptr to struct hidpp_device HID: logitech-hidpp: do not hardcode very long report length HID: logitech-hidpp: handle devices attached to 27MHz wireless receivers HID: logitech-hidpp: use RAP instead of FAP to get the protocol version HID: logitech-hidpp: remove unused origin_is_hid_core function parameter HID: logitech-hidpp: remove double assignment from __hidpp_send_report HID: logitech-hidpp: do not make failure to get the name fatal HID: logitech-hidpp: ignore very-short or empty names HID: logitech-hidpp: make .probe usbhid capable HID: logitech-hidpp: allow non HID++ devices to be handled by this module HID: logitech-dj: add support for Logitech Bluetooth Mini-Receiver HID: logitech-dj: make appending of the HID++ descriptors conditional ...
2 parents 80104bb + 63b6f0b commit b4dd05d

29 files changed

+3518
-690
lines changed

drivers/hid/Kconfig

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,16 @@ config HID_COUGAR
231231
Supported devices:
232232
- Cougar 500k Gaming Keyboard
233233

234+
config HID_MACALLY
235+
tristate "Macally devices"
236+
depends on HID
237+
help
238+
Support for Macally devices that are not fully compliant with the
239+
HID standard.
240+
241+
supported devices:
242+
- Macally ikey keyboard
243+
234244
config HID_PRODIKEYS
235245
tristate "Prodikeys PC-MIDI Keyboard support"
236246
depends on HID && SND
@@ -511,6 +521,7 @@ config HID_LOGITECH
511521

512522
config HID_LOGITECH_DJ
513523
tristate "Logitech Unifying receivers full support"
524+
depends on USB_HID
514525
depends on HIDRAW
515526
depends on HID_LOGITECH
516527
select HID_LOGITECH_HIDPP
@@ -1003,6 +1014,22 @@ config HID_UDRAW_PS3
10031014
Say Y here if you want to use the THQ uDraw gaming tablet for
10041015
the PS3.
10051016

1017+
config HID_U2FZERO
1018+
tristate "U2F Zero LED and RNG support"
1019+
depends on USB_HID
1020+
depends on LEDS_CLASS
1021+
depends on HW_RANDOM
1022+
help
1023+
Support for the LED of the U2F Zero device.
1024+
1025+
U2F Zero supports custom commands for blinking the LED
1026+
and getting data from the internal hardware RNG.
1027+
The internal hardware can be used to feed the enthropy pool.
1028+
1029+
U2F Zero only supports blinking its LED, so this driver doesn't
1030+
allow setting the brightness to anything but 1, which will
1031+
trigger a single blink and immediately reset to back 0.
1032+
10061033
config HID_WACOM
10071034
tristate "Wacom Intuos/Graphire tablet support (USB)"
10081035
depends on USB_HID

drivers/hid/Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ obj-$(CONFIG_HID_LENOVO) += hid-lenovo.o
6565
obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o
6666
obj-$(CONFIG_HID_LOGITECH_DJ) += hid-logitech-dj.o
6767
obj-$(CONFIG_HID_LOGITECH_HIDPP) += hid-logitech-hidpp.o
68+
obj-$(CONFIG_HID_MACALLY) += hid-macally.o
6869
obj-$(CONFIG_HID_MAGICMOUSE) += hid-magicmouse.o
6970
obj-$(CONFIG_HID_MALTRON) += hid-maltron.o
7071
obj-$(CONFIG_HID_MAYFLASH) += hid-mf.o
@@ -109,6 +110,7 @@ obj-$(CONFIG_HID_THRUSTMASTER) += hid-tmff.o
109110
obj-$(CONFIG_HID_TIVO) += hid-tivo.o
110111
obj-$(CONFIG_HID_TOPSEED) += hid-topseed.o
111112
obj-$(CONFIG_HID_TWINHAN) += hid-twinhan.o
113+
obj-$(CONFIG_HID_U2FZERO) += hid-u2fzero.o
112114
hid-uclogic-objs := hid-uclogic-core.o \
113115
hid-uclogic-rdesc.o \
114116
hid-uclogic-params.o
@@ -134,3 +136,4 @@ obj-$(CONFIG_USB_KBD) += usbhid/
134136
obj-$(CONFIG_I2C_HID) += i2c-hid/
135137

136138
obj-$(CONFIG_INTEL_ISH_HID) += intel-ish-hid/
139+
obj-$(INTEL_ISH_FIRMWARE_DOWNLOADER) += intel-ish-hid/

drivers/hid/hid-core.c

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include <linux/vmalloc.h>
3131
#include <linux/sched.h>
3232
#include <linux/semaphore.h>
33+
#include <linux/async.h>
3334

3435
#include <linux/hid.h>
3536
#include <linux/hiddev.h>
@@ -218,13 +219,14 @@ static unsigned hid_lookup_collection(struct hid_parser *parser, unsigned type)
218219
* Add a usage to the temporary parser table.
219220
*/
220221

221-
static int hid_add_usage(struct hid_parser *parser, unsigned usage)
222+
static int hid_add_usage(struct hid_parser *parser, unsigned usage, u8 size)
222223
{
223224
if (parser->local.usage_index >= HID_MAX_USAGES) {
224225
hid_err(parser->device, "usage index exceeded\n");
225226
return -1;
226227
}
227228
parser->local.usage[parser->local.usage_index] = usage;
229+
parser->local.usage_size[parser->local.usage_index] = size;
228230
parser->local.collection_index[parser->local.usage_index] =
229231
parser->collection_stack_ptr ?
230232
parser->collection_stack[parser->collection_stack_ptr - 1] : 0;
@@ -486,10 +488,7 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
486488
return 0;
487489
}
488490

489-
if (item->size <= 2)
490-
data = (parser->global.usage_page << 16) + data;
491-
492-
return hid_add_usage(parser, data);
491+
return hid_add_usage(parser, data, item->size);
493492

494493
case HID_LOCAL_ITEM_TAG_USAGE_MINIMUM:
495494

@@ -498,9 +497,6 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
498497
return 0;
499498
}
500499

501-
if (item->size <= 2)
502-
data = (parser->global.usage_page << 16) + data;
503-
504500
parser->local.usage_minimum = data;
505501
return 0;
506502

@@ -511,9 +507,6 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
511507
return 0;
512508
}
513509

514-
if (item->size <= 2)
515-
data = (parser->global.usage_page << 16) + data;
516-
517510
count = data - parser->local.usage_minimum;
518511
if (count + parser->local.usage_index >= HID_MAX_USAGES) {
519512
/*
@@ -533,7 +526,7 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
533526
}
534527

535528
for (n = parser->local.usage_minimum; n <= data; n++)
536-
if (hid_add_usage(parser, n)) {
529+
if (hid_add_usage(parser, n, item->size)) {
537530
dbg_hid("hid_add_usage failed\n");
538531
return -1;
539532
}
@@ -547,6 +540,22 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
547540
return 0;
548541
}
549542

543+
/*
544+
* Concatenate Usage Pages into Usages where relevant:
545+
* As per specification, 6.2.2.8: "When the parser encounters a main item it
546+
* concatenates the last declared Usage Page with a Usage to form a complete
547+
* usage value."
548+
*/
549+
550+
static void hid_concatenate_usage_page(struct hid_parser *parser)
551+
{
552+
int i;
553+
554+
for (i = 0; i < parser->local.usage_index; i++)
555+
if (parser->local.usage_size[i] <= 2)
556+
parser->local.usage[i] += parser->global.usage_page << 16;
557+
}
558+
550559
/*
551560
* Process a main item.
552561
*/
@@ -556,6 +565,8 @@ static int hid_parser_main(struct hid_parser *parser, struct hid_item *item)
556565
__u32 data;
557566
int ret;
558567

568+
hid_concatenate_usage_page(parser);
569+
559570
data = item_udata(item);
560571

561572
switch (item->tag) {
@@ -765,6 +776,8 @@ static int hid_scan_main(struct hid_parser *parser, struct hid_item *item)
765776
__u32 data;
766777
int i;
767778

779+
hid_concatenate_usage_page(parser);
780+
768781
data = item_udata(item);
769782

770783
switch (item->tag) {
@@ -1624,7 +1637,7 @@ static struct hid_report *hid_get_report(struct hid_report_enum *report_enum,
16241637
* Implement a generic .request() callback, using .raw_request()
16251638
* DO NOT USE in hid drivers directly, but through hid_hw_request instead.
16261639
*/
1627-
void __hid_request(struct hid_device *hid, struct hid_report *report,
1640+
int __hid_request(struct hid_device *hid, struct hid_report *report,
16281641
int reqtype)
16291642
{
16301643
char *buf;
@@ -1633,7 +1646,7 @@ void __hid_request(struct hid_device *hid, struct hid_report *report,
16331646

16341647
buf = hid_alloc_report_buf(report, GFP_KERNEL);
16351648
if (!buf)
1636-
return;
1649+
return -ENOMEM;
16371650

16381651
len = hid_report_len(report);
16391652

@@ -1650,8 +1663,11 @@ void __hid_request(struct hid_device *hid, struct hid_report *report,
16501663
if (reqtype == HID_REQ_GET_REPORT)
16511664
hid_input_report(hid, report->type, buf, ret, 0);
16521665

1666+
ret = 0;
1667+
16531668
out:
16541669
kfree(buf);
1670+
return ret;
16551671
}
16561672
EXPORT_SYMBOL_GPL(__hid_request);
16571673

@@ -2349,6 +2365,15 @@ int hid_add_device(struct hid_device *hdev)
23492365
dev_set_name(&hdev->dev, "%04X:%04X:%04X.%04X", hdev->bus,
23502366
hdev->vendor, hdev->product, atomic_inc_return(&id));
23512367

2368+
/*
2369+
* Try loading the module for the device before the add, so that we do
2370+
* not first have hid-generic binding only to have it replaced
2371+
* immediately afterwards with a specialized driver.
2372+
*/
2373+
if (!current_is_async())
2374+
request_module("hid:b%04Xg%04Xv%08Xp%08X", hdev->bus,
2375+
hdev->group, hdev->vendor, hdev->product);
2376+
23522377
hid_debug_register(hdev, dev_name(&hdev->dev));
23532378
ret = device_add(&hdev->dev);
23542379
if (!ret)

drivers/hid/hid-ids.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@
323323
#define USB_DEVICE_ID_CYGNAL_RADIO_SI470X 0x818a
324324
#define USB_DEVICE_ID_FOCALTECH_FTXXXX_MULTITOUCH 0x81b9
325325
#define USB_DEVICE_ID_CYGNAL_CP2112 0xea90
326+
#define USB_DEVICE_ID_U2F_ZERO 0x8acf
326327

327328
#define USB_DEVICE_ID_CYGNAL_RADIO_SI4713 0x8244
328329

@@ -762,8 +763,12 @@
762763
#define USB_DEVICE_ID_S510_RECEIVER_2 0xc517
763764
#define USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500 0xc512
764765
#define USB_DEVICE_ID_MX3000_RECEIVER 0xc513
766+
#define USB_DEVICE_ID_LOGITECH_27MHZ_MOUSE_RECEIVER 0xc51b
765767
#define USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER 0xc52b
768+
#define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER 0xc52f
766769
#define USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER_2 0xc532
770+
#define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_2 0xc534
771+
#define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_GAMING 0xc539
767772
#define USB_DEVICE_ID_SPACETRAVELLER 0xc623
768773
#define USB_DEVICE_ID_SPACENAVIGATOR 0xc626
769774
#define USB_DEVICE_ID_DINOVO_DESKTOP 0xc704
@@ -1034,6 +1039,7 @@
10341039
#define USB_DEVICE_ID_SINO_LITE_CONTROLLER 0x3008
10351040

10361041
#define USB_VENDOR_ID_SOLID_YEAR 0x060b
1042+
#define USB_DEVICE_ID_MACALLY_IKEY_KEYBOARD 0x0001
10371043
#define USB_DEVICE_ID_COUGAR_500K_GAMING_KEYBOARD 0x500a
10381044
#define USB_DEVICE_ID_COUGAR_700K_GAMING_KEYBOARD 0x700a
10391045

@@ -1083,7 +1089,6 @@
10831089
#define USB_DEVICE_ID_SYNAPTICS_HD 0x0ac3
10841090
#define USB_DEVICE_ID_SYNAPTICS_QUAD_HD 0x1ac3
10851091
#define USB_DEVICE_ID_SYNAPTICS_TP_V103 0x5710
1086-
#define I2C_DEVICE_ID_SYNAPTICS_7E7E 0x7e7e
10871092

10881093
#define USB_VENDOR_ID_TEXAS_INSTRUMENTS 0x2047
10891094
#define USB_DEVICE_ID_TEXAS_INSTRUMENTS_LENOVO_YOGA 0x0855

drivers/hid/hid-input.c

Lines changed: 50 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1557,52 +1557,71 @@ static void hidinput_close(struct input_dev *dev)
15571557
hid_hw_close(hid);
15581558
}
15591559

1560-
static void hidinput_change_resolution_multipliers(struct hid_device *hid)
1560+
static bool __hidinput_change_resolution_multipliers(struct hid_device *hid,
1561+
struct hid_report *report, bool use_logical_max)
15611562
{
1562-
struct hid_report_enum *rep_enum;
1563-
struct hid_report *rep;
15641563
struct hid_usage *usage;
1564+
bool update_needed = false;
15651565
int i, j;
15661566

1567-
rep_enum = &hid->report_enum[HID_FEATURE_REPORT];
1568-
list_for_each_entry(rep, &rep_enum->report_list, list) {
1569-
bool update_needed = false;
1567+
if (report->maxfield == 0)
1568+
return false;
15701569

1571-
if (rep->maxfield == 0)
1572-
continue;
1570+
/*
1571+
* If we have more than one feature within this report we
1572+
* need to fill in the bits from the others before we can
1573+
* overwrite the ones for the Resolution Multiplier.
1574+
*/
1575+
if (report->maxfield > 1) {
1576+
hid_hw_request(hid, report, HID_REQ_GET_REPORT);
1577+
hid_hw_wait(hid);
1578+
}
15731579

1574-
/*
1575-
* If we have more than one feature within this report we
1576-
* need to fill in the bits from the others before we can
1577-
* overwrite the ones for the Resolution Multiplier.
1580+
for (i = 0; i < report->maxfield; i++) {
1581+
__s32 value = use_logical_max ?
1582+
report->field[i]->logical_maximum :
1583+
report->field[i]->logical_minimum;
1584+
1585+
/* There is no good reason for a Resolution
1586+
* Multiplier to have a count other than 1.
1587+
* Ignore that case.
15781588
*/
1579-
if (rep->maxfield > 1) {
1580-
hid_hw_request(hid, rep, HID_REQ_GET_REPORT);
1581-
hid_hw_wait(hid);
1582-
}
1589+
if (report->field[i]->report_count != 1)
1590+
continue;
15831591

1584-
for (i = 0; i < rep->maxfield; i++) {
1585-
__s32 logical_max = rep->field[i]->logical_maximum;
1592+
for (j = 0; j < report->field[i]->maxusage; j++) {
1593+
usage = &report->field[i]->usage[j];
15861594

1587-
/* There is no good reason for a Resolution
1588-
* Multiplier to have a count other than 1.
1589-
* Ignore that case.
1590-
*/
1591-
if (rep->field[i]->report_count != 1)
1595+
if (usage->hid != HID_GD_RESOLUTION_MULTIPLIER)
15921596
continue;
15931597

1594-
for (j = 0; j < rep->field[i]->maxusage; j++) {
1595-
usage = &rep->field[i]->usage[j];
1598+
report->field[i]->value[j] = value;
1599+
update_needed = true;
1600+
}
1601+
}
1602+
1603+
return update_needed;
1604+
}
15961605

1597-
if (usage->hid != HID_GD_RESOLUTION_MULTIPLIER)
1598-
continue;
1606+
static void hidinput_change_resolution_multipliers(struct hid_device *hid)
1607+
{
1608+
struct hid_report_enum *rep_enum;
1609+
struct hid_report *rep;
1610+
int ret;
15991611

1600-
*rep->field[i]->value = logical_max;
1601-
update_needed = true;
1612+
rep_enum = &hid->report_enum[HID_FEATURE_REPORT];
1613+
list_for_each_entry(rep, &rep_enum->report_list, list) {
1614+
bool update_needed = __hidinput_change_resolution_multipliers(hid,
1615+
rep, true);
1616+
1617+
if (update_needed) {
1618+
ret = __hid_request(hid, rep, HID_REQ_SET_REPORT);
1619+
if (ret) {
1620+
__hidinput_change_resolution_multipliers(hid,
1621+
rep, false);
1622+
return;
16021623
}
16031624
}
1604-
if (update_needed)
1605-
hid_hw_request(hid, rep, HID_REQ_SET_REPORT);
16061625
}
16071626

16081627
/* refresh our structs */

drivers/hid/hid-lg.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -876,8 +876,6 @@ static const struct hid_device_id lg_devices[] = {
876876
.driver_data = LG_RDESC | LG_WIRELESS },
877877
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER),
878878
.driver_data = LG_RDESC | LG_WIRELESS },
879-
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2),
880-
.driver_data = LG_RDESC | LG_WIRELESS },
881879

882880
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RECEIVER),
883881
.driver_data = LG_BAD_RELATIVE_KEYS },

0 commit comments

Comments
 (0)