mirror of
https://github.com/torvalds/linux.git
synced 2024-12-28 05:41:55 +00:00
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid
Pull HID subsystem fixes from Jiri Kosina: - syzkaller-reported error handling fixes in various drivers, from various people - increase of HID report buffer size to 8K, which is apparently needed by certain modern devices - a few new device-ID-specific fixes / quirks - battery charging status reporting fix in logitech-hidpp, from Filipe Laíns * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid: HID: hid-bigbenff: fix race condition for scheduled work during removal HID: hid-bigbenff: call hid_hw_stop() in case of error HID: hid-bigbenff: fix general protection fault caused by double kfree HID: i2c-hid: add Trekstor Surfbook E11B to descriptor override HID: alps: Fix an error handling path in 'alps_input_configured()' HID: hiddev: Fix race in in hiddev_disconnect() HID: core: increase HID report buffer size to 8KiB HID: core: fix off-by-one memset in hid_report_raw_event() HID: apple: Add support for recent firmware on Magic Keyboards HID: ite: Only bind to keyboard USB interface on Acer SW5-012 keyboard dock HID: logitech-hidpp: BatteryVoltage: only read chargeStatus if extPower is active
This commit is contained in:
commit
278de45e14
@ -730,7 +730,7 @@ static int alps_input_configured(struct hid_device *hdev, struct hid_input *hi)
|
||||
if (data->has_sp) {
|
||||
input2 = input_allocate_device();
|
||||
if (!input2) {
|
||||
input_free_device(input2);
|
||||
ret = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
@ -340,7 +340,8 @@ static int apple_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
||||
unsigned long **bit, int *max)
|
||||
{
|
||||
if (usage->hid == (HID_UP_CUSTOM | 0x0003) ||
|
||||
usage->hid == (HID_UP_MSVENDOR | 0x0003)) {
|
||||
usage->hid == (HID_UP_MSVENDOR | 0x0003) ||
|
||||
usage->hid == (HID_UP_HPVENDOR2 | 0x0003)) {
|
||||
/* The fn key on Apple USB keyboards */
|
||||
set_bit(EV_REP, hi->input->evbit);
|
||||
hid_map_usage_clear(hi, usage, bit, max, EV_KEY, KEY_FN);
|
||||
|
@ -174,6 +174,7 @@ static __u8 pid0902_rdesc_fixed[] = {
|
||||
struct bigben_device {
|
||||
struct hid_device *hid;
|
||||
struct hid_report *report;
|
||||
bool removed;
|
||||
u8 led_state; /* LED1 = 1 .. LED4 = 8 */
|
||||
u8 right_motor_on; /* right motor off/on 0/1 */
|
||||
u8 left_motor_force; /* left motor force 0-255 */
|
||||
@ -190,6 +191,9 @@ static void bigben_worker(struct work_struct *work)
|
||||
struct bigben_device, worker);
|
||||
struct hid_field *report_field = bigben->report->field[0];
|
||||
|
||||
if (bigben->removed)
|
||||
return;
|
||||
|
||||
if (bigben->work_led) {
|
||||
bigben->work_led = false;
|
||||
report_field->value[0] = 0x01; /* 1 = led message */
|
||||
@ -220,10 +224,16 @@ static void bigben_worker(struct work_struct *work)
|
||||
static int hid_bigben_play_effect(struct input_dev *dev, void *data,
|
||||
struct ff_effect *effect)
|
||||
{
|
||||
struct bigben_device *bigben = data;
|
||||
struct hid_device *hid = input_get_drvdata(dev);
|
||||
struct bigben_device *bigben = hid_get_drvdata(hid);
|
||||
u8 right_motor_on;
|
||||
u8 left_motor_force;
|
||||
|
||||
if (!bigben) {
|
||||
hid_err(hid, "no device data\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (effect->type != FF_RUMBLE)
|
||||
return 0;
|
||||
|
||||
@ -298,8 +308,8 @@ static void bigben_remove(struct hid_device *hid)
|
||||
{
|
||||
struct bigben_device *bigben = hid_get_drvdata(hid);
|
||||
|
||||
bigben->removed = true;
|
||||
cancel_work_sync(&bigben->worker);
|
||||
hid_hw_close(hid);
|
||||
hid_hw_stop(hid);
|
||||
}
|
||||
|
||||
@ -319,6 +329,7 @@ static int bigben_probe(struct hid_device *hid,
|
||||
return -ENOMEM;
|
||||
hid_set_drvdata(hid, bigben);
|
||||
bigben->hid = hid;
|
||||
bigben->removed = false;
|
||||
|
||||
error = hid_parse(hid);
|
||||
if (error) {
|
||||
@ -341,10 +352,10 @@ static int bigben_probe(struct hid_device *hid,
|
||||
|
||||
INIT_WORK(&bigben->worker, bigben_worker);
|
||||
|
||||
error = input_ff_create_memless(hidinput->input, bigben,
|
||||
error = input_ff_create_memless(hidinput->input, NULL,
|
||||
hid_bigben_play_effect);
|
||||
if (error)
|
||||
return error;
|
||||
goto error_hw_stop;
|
||||
|
||||
name_sz = strlen(dev_name(&hid->dev)) + strlen(":red:bigben#") + 1;
|
||||
|
||||
@ -354,8 +365,10 @@ static int bigben_probe(struct hid_device *hid,
|
||||
sizeof(struct led_classdev) + name_sz,
|
||||
GFP_KERNEL
|
||||
);
|
||||
if (!led)
|
||||
return -ENOMEM;
|
||||
if (!led) {
|
||||
error = -ENOMEM;
|
||||
goto error_hw_stop;
|
||||
}
|
||||
name = (void *)(&led[1]);
|
||||
snprintf(name, name_sz,
|
||||
"%s:red:bigben%d",
|
||||
@ -369,7 +382,7 @@ static int bigben_probe(struct hid_device *hid,
|
||||
bigben->leds[n] = led;
|
||||
error = devm_led_classdev_register(&hid->dev, led);
|
||||
if (error)
|
||||
return error;
|
||||
goto error_hw_stop;
|
||||
}
|
||||
|
||||
/* initial state: LED1 is on, no rumble effect */
|
||||
@ -383,6 +396,10 @@ static int bigben_probe(struct hid_device *hid,
|
||||
hid_info(hid, "LED and force feedback support for BigBen gamepad\n");
|
||||
|
||||
return 0;
|
||||
|
||||
error_hw_stop:
|
||||
hid_hw_stop(hid);
|
||||
return error;
|
||||
}
|
||||
|
||||
static __u8 *bigben_report_fixup(struct hid_device *hid, __u8 *rdesc,
|
||||
|
@ -1741,7 +1741,9 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size,
|
||||
|
||||
rsize = ((report->size - 1) >> 3) + 1;
|
||||
|
||||
if (rsize > HID_MAX_BUFFER_SIZE)
|
||||
if (report_enum->numbered && rsize >= HID_MAX_BUFFER_SIZE)
|
||||
rsize = HID_MAX_BUFFER_SIZE - 1;
|
||||
else if (rsize > HID_MAX_BUFFER_SIZE)
|
||||
rsize = HID_MAX_BUFFER_SIZE;
|
||||
|
||||
if (csize < rsize) {
|
||||
|
@ -41,8 +41,9 @@ static const struct hid_device_id ite_devices[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ITE, USB_DEVICE_ID_ITE8595) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_258A, USB_DEVICE_ID_258A_6A88) },
|
||||
/* ITE8595 USB kbd ctlr, with Synaptics touchpad connected to it. */
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS,
|
||||
USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5_012) },
|
||||
{ HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
|
||||
USB_VENDOR_ID_SYNAPTICS,
|
||||
USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5_012) },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(hid, ite_devices);
|
||||
|
@ -1256,36 +1256,35 @@ static int hidpp20_battery_map_status_voltage(u8 data[3], int *voltage,
|
||||
{
|
||||
int status;
|
||||
|
||||
long charge_sts = (long)data[2];
|
||||
long flags = (long) data[2];
|
||||
|
||||
*level = POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN;
|
||||
switch (data[2] & 0xe0) {
|
||||
case 0x00:
|
||||
status = POWER_SUPPLY_STATUS_CHARGING;
|
||||
break;
|
||||
case 0x20:
|
||||
status = POWER_SUPPLY_STATUS_FULL;
|
||||
*level = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
|
||||
break;
|
||||
case 0x40:
|
||||
if (flags & 0x80)
|
||||
switch (flags & 0x07) {
|
||||
case 0:
|
||||
status = POWER_SUPPLY_STATUS_CHARGING;
|
||||
break;
|
||||
case 1:
|
||||
status = POWER_SUPPLY_STATUS_FULL;
|
||||
*level = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
|
||||
break;
|
||||
case 2:
|
||||
status = POWER_SUPPLY_STATUS_NOT_CHARGING;
|
||||
break;
|
||||
default:
|
||||
status = POWER_SUPPLY_STATUS_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
else
|
||||
status = POWER_SUPPLY_STATUS_DISCHARGING;
|
||||
break;
|
||||
case 0xe0:
|
||||
status = POWER_SUPPLY_STATUS_NOT_CHARGING;
|
||||
break;
|
||||
default:
|
||||
status = POWER_SUPPLY_STATUS_UNKNOWN;
|
||||
}
|
||||
|
||||
*charge_type = POWER_SUPPLY_CHARGE_TYPE_STANDARD;
|
||||
if (test_bit(3, &charge_sts)) {
|
||||
if (test_bit(3, &flags)) {
|
||||
*charge_type = POWER_SUPPLY_CHARGE_TYPE_FAST;
|
||||
}
|
||||
if (test_bit(4, &charge_sts)) {
|
||||
if (test_bit(4, &flags)) {
|
||||
*charge_type = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
|
||||
}
|
||||
|
||||
if (test_bit(5, &charge_sts)) {
|
||||
if (test_bit(5, &flags)) {
|
||||
*level = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
|
||||
}
|
||||
|
||||
|
@ -341,6 +341,14 @@ static const struct dmi_system_id i2c_hid_dmi_desc_override_table[] = {
|
||||
},
|
||||
.driver_data = (void *)&sipodev_desc
|
||||
},
|
||||
{
|
||||
.ident = "Trekstor SURFBOOK E11B",
|
||||
.matches = {
|
||||
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TREKSTOR"),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "SURFBOOK E11B"),
|
||||
},
|
||||
.driver_data = (void *)&sipodev_desc
|
||||
},
|
||||
{
|
||||
.ident = "Direkt-Tek DTLAPY116-2",
|
||||
.matches = {
|
||||
|
@ -932,9 +932,9 @@ void hiddev_disconnect(struct hid_device *hid)
|
||||
hiddev->exist = 0;
|
||||
|
||||
if (hiddev->open) {
|
||||
mutex_unlock(&hiddev->existancelock);
|
||||
hid_hw_close(hiddev->hid);
|
||||
wake_up_interruptible(&hiddev->wait);
|
||||
mutex_unlock(&hiddev->existancelock);
|
||||
} else {
|
||||
mutex_unlock(&hiddev->existancelock);
|
||||
kfree(hiddev);
|
||||
|
@ -492,7 +492,7 @@ struct hid_report_enum {
|
||||
};
|
||||
|
||||
#define HID_MIN_BUFFER_SIZE 64 /* make sure there is at least a packet size of space */
|
||||
#define HID_MAX_BUFFER_SIZE 4096 /* 4kb */
|
||||
#define HID_MAX_BUFFER_SIZE 8192 /* 8kb */
|
||||
#define HID_CONTROL_FIFO_SIZE 256 /* to init devices with >100 reports */
|
||||
#define HID_OUTPUT_FIFO_SIZE 64
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user