summaryrefslogtreecommitdiff
path: root/drivers/hid
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hid')
-rw-r--r--drivers/hid/hid-input.c10
-rw-r--r--drivers/hid/hid-multitouch.c24
-rw-r--r--drivers/hid/hid-sony.c25
-rw-r--r--drivers/hid/i2c-hid/Kconfig1
-rw-r--r--drivers/hid/i2c-hid/i2c-hid.c40
5 files changed, 89 insertions, 11 deletions
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 012880a2228c..90c718f6eded 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -1338,8 +1338,9 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
* UGCI) cram a lot of unrelated inputs into the
* same interface. */
hidinput->report = report;
- if (drv->input_configured)
- drv->input_configured(hid, hidinput);
+ if (drv->input_configured &&
+ drv->input_configured(hid, hidinput))
+ goto out_cleanup;
if (input_register_device(hidinput->input))
goto out_cleanup;
hidinput = NULL;
@@ -1360,8 +1361,9 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
}
if (hidinput) {
- if (drv->input_configured)
- drv->input_configured(hid, hidinput);
+ if (drv->input_configured &&
+ drv->input_configured(hid, hidinput))
+ goto out_cleanup;
if (input_register_device(hidinput->input))
goto out_cleanup;
}
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index b6701cec80ff..bb6fe3ee0030 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -443,6 +443,16 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
(usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON)
td->mt_flags |= INPUT_MT_POINTER;
+ /* Only map fields from TouchScreen or TouchPad collections.
+ * We need to ignore fields that belong to other collections
+ * such as Mouse that might have the same GenericDesktop usages. */
+ if (field->application == HID_DG_TOUCHSCREEN)
+ set_bit(INPUT_PROP_DIRECT, hi->input->propbit);
+ else if (field->application == HID_DG_TOUCHPAD)
+ set_bit(INPUT_PROP_POINTER, hi->input->propbit);
+ else
+ return 0;
+
if (usage->usage_index)
prev_usage = &field->usage[usage->usage_index - 1];
@@ -772,12 +782,13 @@ static void mt_touch_report(struct hid_device *hid, struct hid_report *report)
mt_sync_frame(td, report->field[0]->hidinput->input);
}
-static void mt_touch_input_configured(struct hid_device *hdev,
+static int mt_touch_input_configured(struct hid_device *hdev,
struct hid_input *hi)
{
struct mt_device *td = hid_get_drvdata(hdev);
struct mt_class *cls = &td->mtclass;
struct input_dev *input = hi->input;
+ int ret;
if (!td->maxcontacts)
td->maxcontacts = MT_DEFAULT_MAXCONTACT;
@@ -792,9 +803,12 @@ static void mt_touch_input_configured(struct hid_device *hdev,
if (cls->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP)
td->mt_flags |= INPUT_MT_DROP_UNUSED;
- input_mt_init_slots(input, td->maxcontacts, td->mt_flags);
+ ret = input_mt_init_slots(input, td->maxcontacts, td->mt_flags);
+ if (ret)
+ return ret;
td->mt_flags = 0;
+ return 0;
}
static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
@@ -927,19 +941,21 @@ static void mt_post_parse(struct mt_device *td)
cls->quirks &= ~MT_QUIRK_CONTACT_CNT_ACCURATE;
}
-static void mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
+static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
{
struct mt_device *td = hid_get_drvdata(hdev);
char *name = kstrdup(hdev->name, GFP_KERNEL);
+ int ret = 0;
if (name)
hi->input->name = name;
if (hi->report->id == td->mt_report_id)
- mt_touch_input_configured(hdev, hi);
+ ret = mt_touch_input_configured(hdev, hi);
if (hi->report->id == td->pen_report_id)
mt_pen_input_configured(hdev, hi);
+ return ret;
}
static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index 312098e4af4f..489c44864d32 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -192,6 +192,26 @@ static int sixaxis_set_operational_bt(struct hid_device *hdev)
return hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT);
}
+static void sixaxis_set_led_bt(struct hid_device *hdev)
+{
+ /* set first LED on BT connection */
+ unsigned char led_data[] = {
+ 0x01,
+ /* rumble values */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ /* LED settings 0x02=LED1 .. 0x10=LED4 */
+ 0x02,
+ 0xff, 0x27, 0x10, 0x00, 0x32, /* LED 4 */
+ 0xff, 0x27, 0x10, 0x00, 0x32, /* LED 3 */
+ 0xff, 0x27, 0x10, 0x00, 0x32, /* LED 2 */
+ 0xff, 0x27, 0x10, 0x00, 0x32, /* LED 1 */
+ 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+ hid_info(hdev, "set LED BT\n");
+ hdev->hid_output_raw_report(hdev, led_data, sizeof(led_data),
+ HID_OUTPUT_REPORT);
+}
+
static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
{
int ret;
@@ -224,8 +244,11 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
hdev->hid_output_raw_report = sixaxis_usb_output_raw_report;
ret = sixaxis_set_operational_usb(hdev);
}
- else if (sc->quirks & SIXAXIS_CONTROLLER_BT)
+ else if (sc->quirks & SIXAXIS_CONTROLLER_BT) {
ret = sixaxis_set_operational_bt(hdev);
+ if (ret >= 0)
+ sixaxis_set_led_bt(hdev);
+ }
else
ret = 0;
diff --git a/drivers/hid/i2c-hid/Kconfig b/drivers/hid/i2c-hid/Kconfig
index b66617a020bd..26c7d535ce5a 100644
--- a/drivers/hid/i2c-hid/Kconfig
+++ b/drivers/hid/i2c-hid/Kconfig
@@ -5,7 +5,6 @@ config I2C_HID
tristate "HID over I2C transport layer"
default n
depends on I2C && INPUT
- select HID
---help---
Say Y here if you use a keyboard, a touchpad, a touchscreen, or any
other HID based devices which is connected to your computer via I2C.
diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c
index 2b1799a3b212..8274ba275286 100644
--- a/drivers/hid/i2c-hid/i2c-hid.c
+++ b/drivers/hid/i2c-hid/i2c-hid.c
@@ -1089,7 +1089,45 @@ static struct i2c_driver i2c_hid_driver = {
.id_table = i2c_hid_id_table,
};
-module_i2c_driver(i2c_hid_driver);
+static const struct hid_device_id hid_i2chid_table[] = {
+ { HID_DEVICE(BUS_I2C, HID_GROUP_GENERIC, HID_ANY_ID, HID_ANY_ID) },
+ { }
+};
+
+static struct hid_driver hid_i2chid_driver = {
+ .name = "generic-i2c",
+ .id_table = hid_i2chid_table,
+};
+
+static int __init i2chid_init(void)
+{
+ int retval;
+
+ retval = hid_register_driver(&hid_i2chid_driver);
+ if (retval)
+ goto hid_register_fail;
+
+ retval = i2c_add_driver(&i2c_hid_driver);
+ if (retval)
+ goto i2c_register_fail;
+
+ return 0;
+
+i2c_register_fail:
+ hid_unregister_driver(&hid_i2chid_driver);
+
+hid_register_fail:
+ return retval;
+}
+
+static void __exit i2chid_exit(void)
+{
+ i2c_del_driver(&i2c_hid_driver);
+ hid_unregister_driver(&hid_i2chid_driver);
+}
+
+module_init(i2chid_init);
+module_exit(i2chid_exit);
MODULE_DESCRIPTION("HID over I2C core driver");
MODULE_AUTHOR("Benjamin Tissoires <benjamin.tissoires@gmail.com>");