Commit fa1054a2 authored by Jiri Kosina's avatar Jiri Kosina

Merge branches 'for-3.15/multitouch', 'for-3.15/sony' and 'for-3.15/uhid' into for-linus

...@@ -93,6 +93,11 @@ the request was handled successfully. ...@@ -93,6 +93,11 @@ the request was handled successfully.
event to the kernel. The payload is of type struct uhid_create_req and event to the kernel. The payload is of type struct uhid_create_req and
contains information about your device. You can start I/O now. contains information about your device. You can start I/O now.
UHID_CREATE2:
Same as UHID_CREATE, but the HID report descriptor data (rd_data) is an array
inside struct uhid_create2_req, instead of a pointer to a separate array.
Enables use from languages that don't support pointers, e.g. Python.
UHID_DESTROY: UHID_DESTROY:
This destroys the internal HID device. No further I/O will be accepted. There 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 may still be pending messages that you can receive with read() but no further
...@@ -105,6 +110,12 @@ the request was handled successfully. ...@@ -105,6 +110,12 @@ the request was handled successfully.
contains a data-payload. This is the raw data that you read from your device. contains a data-payload. This is the raw data that you read from your device.
The kernel will parse the HID reports and react on it. The kernel will parse the HID reports and react on it.
UHID_INPUT2:
Same as UHID_INPUT, but the data array is the last field of uhid_input2_req.
Enables userspace to write only the required bytes to kernel (ev.type +
ev.u.input2.size + the part of the data array that matters), instead of
the entire struct uhid_input2_req.
UHID_FEATURE_ANSWER: UHID_FEATURE_ANSWER:
If you receive a UHID_FEATURE request you must answer with this request. You If you receive a UHID_FEATURE request you must answer with this request. You
must copy the "id" field from the request into the answer. Set the "err" field must copy the "id" field from the request into the answer. Set the "err" field
......
...@@ -67,6 +67,9 @@ ...@@ -67,6 +67,9 @@
#define USB_VENDOR_ID_ALPS 0x0433 #define USB_VENDOR_ID_ALPS 0x0433
#define USB_DEVICE_ID_IBM_GAMEPAD 0x1101 #define USB_DEVICE_ID_IBM_GAMEPAD 0x1101
#define USB_VENDOR_ID_ANTON 0x1130
#define USB_DEVICE_ID_ANTON_TOUCH_PAD 0x3101
#define USB_VENDOR_ID_APPLE 0x05ac #define USB_VENDOR_ID_APPLE 0x05ac
#define USB_DEVICE_ID_APPLE_MIGHTYMOUSE 0x0304 #define USB_DEVICE_ID_APPLE_MIGHTYMOUSE 0x0304
#define USB_DEVICE_ID_APPLE_MAGICMOUSE 0x030d #define USB_DEVICE_ID_APPLE_MAGICMOUSE 0x030d
......
This diff is collapsed.
...@@ -863,7 +863,7 @@ static void sixaxis_parse_report(struct sony_sc *sc, __u8 *rd, int size) ...@@ -863,7 +863,7 @@ static void sixaxis_parse_report(struct sony_sc *sc, __u8 *rd, int size)
battery_capacity = sixaxis_battery_capacity[index]; battery_capacity = sixaxis_battery_capacity[index];
battery_charging = 0; battery_charging = 0;
} }
cable_state = !((rd[31] >> 4) & 0x01); cable_state = !(rd[31] & 0x04);
spin_lock_irqsave(&sc->lock, flags); spin_lock_irqsave(&sc->lock, flags);
sc->cable_state = cable_state; sc->cable_state = cable_state;
...@@ -1632,11 +1632,21 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) ...@@ -1632,11 +1632,21 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
sc->worker_initialized = 1; sc->worker_initialized = 1;
INIT_WORK(&sc->state_worker, sixaxis_state_worker); INIT_WORK(&sc->state_worker, sixaxis_state_worker);
} else if (sc->quirks & SIXAXIS_CONTROLLER_BT) { } else if (sc->quirks & SIXAXIS_CONTROLLER_BT) {
/*
* The Sixaxis wants output reports sent on the ctrl endpoint
* when connected via Bluetooth.
*/
hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP;
ret = sixaxis_set_operational_bt(hdev); ret = sixaxis_set_operational_bt(hdev);
sc->worker_initialized = 1; sc->worker_initialized = 1;
INIT_WORK(&sc->state_worker, sixaxis_state_worker); INIT_WORK(&sc->state_worker, sixaxis_state_worker);
} else if (sc->quirks & DUALSHOCK4_CONTROLLER) { } else if (sc->quirks & DUALSHOCK4_CONTROLLER) {
if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) { if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) {
/*
* The DualShock 4 wants output reports sent on the ctrl
* endpoint when connected via Bluetooth.
*/
hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP;
ret = dualshock4_set_operational_bt(hdev); ret = dualshock4_set_operational_bt(hdev);
if (ret < 0) { if (ret < 0) {
hid_err(hdev, "failed to set the Dualshock 4 operational mode\n"); hid_err(hdev, "failed to set the Dualshock 4 operational mode\n");
......
...@@ -428,6 +428,67 @@ static int uhid_dev_create(struct uhid_device *uhid, ...@@ -428,6 +428,67 @@ static int uhid_dev_create(struct uhid_device *uhid,
return ret; return ret;
} }
static int uhid_dev_create2(struct uhid_device *uhid,
const struct uhid_event *ev)
{
struct hid_device *hid;
int ret;
if (uhid->running)
return -EALREADY;
uhid->rd_size = ev->u.create2.rd_size;
if (uhid->rd_size <= 0 || uhid->rd_size > HID_MAX_DESCRIPTOR_SIZE)
return -EINVAL;
uhid->rd_data = kmalloc(uhid->rd_size, GFP_KERNEL);
if (!uhid->rd_data)
return -ENOMEM;
memcpy(uhid->rd_data, ev->u.create2.rd_data, uhid->rd_size);
hid = hid_allocate_device();
if (IS_ERR(hid)) {
ret = PTR_ERR(hid);
goto err_free;
}
strncpy(hid->name, ev->u.create2.name, 127);
hid->name[127] = 0;
strncpy(hid->phys, ev->u.create2.phys, 63);
hid->phys[63] = 0;
strncpy(hid->uniq, ev->u.create2.uniq, 63);
hid->uniq[63] = 0;
hid->ll_driver = &uhid_hid_driver;
hid->bus = ev->u.create2.bus;
hid->vendor = ev->u.create2.vendor;
hid->product = ev->u.create2.product;
hid->version = ev->u.create2.version;
hid->country = ev->u.create2.country;
hid->driver_data = uhid;
hid->dev.parent = uhid_misc.this_device;
uhid->hid = hid;
uhid->running = true;
ret = hid_add_device(hid);
if (ret) {
hid_err(hid, "Cannot register HID device\n");
goto err_hid;
}
return 0;
err_hid:
hid_destroy_device(hid);
uhid->hid = NULL;
uhid->running = false;
err_free:
kfree(uhid->rd_data);
return ret;
}
static int uhid_dev_destroy(struct uhid_device *uhid) static int uhid_dev_destroy(struct uhid_device *uhid)
{ {
if (!uhid->running) if (!uhid->running)
...@@ -456,6 +517,17 @@ static int uhid_dev_input(struct uhid_device *uhid, struct uhid_event *ev) ...@@ -456,6 +517,17 @@ static int uhid_dev_input(struct uhid_device *uhid, struct uhid_event *ev)
return 0; return 0;
} }
static int uhid_dev_input2(struct uhid_device *uhid, struct uhid_event *ev)
{
if (!uhid->running)
return -EINVAL;
hid_input_report(uhid->hid, HID_INPUT_REPORT, ev->u.input2.data,
min_t(size_t, ev->u.input2.size, UHID_DATA_MAX), 0);
return 0;
}
static int uhid_dev_feature_answer(struct uhid_device *uhid, static int uhid_dev_feature_answer(struct uhid_device *uhid,
struct uhid_event *ev) struct uhid_event *ev)
{ {
...@@ -592,12 +664,18 @@ static ssize_t uhid_char_write(struct file *file, const char __user *buffer, ...@@ -592,12 +664,18 @@ static ssize_t uhid_char_write(struct file *file, const char __user *buffer,
case UHID_CREATE: case UHID_CREATE:
ret = uhid_dev_create(uhid, &uhid->input_buf); ret = uhid_dev_create(uhid, &uhid->input_buf);
break; break;
case UHID_CREATE2:
ret = uhid_dev_create2(uhid, &uhid->input_buf);
break;
case UHID_DESTROY: case UHID_DESTROY:
ret = uhid_dev_destroy(uhid); ret = uhid_dev_destroy(uhid);
break; break;
case UHID_INPUT: case UHID_INPUT:
ret = uhid_dev_input(uhid, &uhid->input_buf); ret = uhid_dev_input(uhid, &uhid->input_buf);
break; break;
case UHID_INPUT2:
ret = uhid_dev_input2(uhid, &uhid->input_buf);
break;
case UHID_FEATURE_ANSWER: case UHID_FEATURE_ANSWER:
ret = uhid_dev_feature_answer(uhid, &uhid->input_buf); ret = uhid_dev_feature_answer(uhid, &uhid->input_buf);
break; break;
......
...@@ -201,6 +201,7 @@ struct hid_item { ...@@ -201,6 +201,7 @@ struct hid_item {
#define HID_GD_VBRZ 0x00010045 #define HID_GD_VBRZ 0x00010045
#define HID_GD_VNO 0x00010046 #define HID_GD_VNO 0x00010046
#define HID_GD_FEATURE 0x00010047 #define HID_GD_FEATURE 0x00010047
#define HID_GD_SYSTEM_CONTROL 0x00010080
#define HID_GD_UP 0x00010090 #define HID_GD_UP 0x00010090
#define HID_GD_DOWN 0x00010091 #define HID_GD_DOWN 0x00010091
#define HID_GD_RIGHT 0x00010092 #define HID_GD_RIGHT 0x00010092
...@@ -208,6 +209,8 @@ struct hid_item { ...@@ -208,6 +209,8 @@ struct hid_item {
#define HID_DC_BATTERYSTRENGTH 0x00060020 #define HID_DC_BATTERYSTRENGTH 0x00060020
#define HID_CP_CONSUMER_CONTROL 0x000c0001
#define HID_DG_DIGITIZER 0x000d0001 #define HID_DG_DIGITIZER 0x000d0001
#define HID_DG_PEN 0x000d0002 #define HID_DG_PEN 0x000d0002
#define HID_DG_LIGHTPEN 0x000d0003 #define HID_DG_LIGHTPEN 0x000d0003
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <linux/input.h> #include <linux/input.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/hid.h>
enum uhid_event_type { enum uhid_event_type {
UHID_CREATE, UHID_CREATE,
...@@ -34,6 +35,8 @@ enum uhid_event_type { ...@@ -34,6 +35,8 @@ enum uhid_event_type {
UHID_INPUT, UHID_INPUT,
UHID_FEATURE, UHID_FEATURE,
UHID_FEATURE_ANSWER, UHID_FEATURE_ANSWER,
UHID_CREATE2,
UHID_INPUT2,
}; };
struct uhid_create_req { struct uhid_create_req {
...@@ -50,6 +53,19 @@ struct uhid_create_req { ...@@ -50,6 +53,19 @@ struct uhid_create_req {
__u32 country; __u32 country;
} __attribute__((__packed__)); } __attribute__((__packed__));
struct uhid_create2_req {
__u8 name[128];
__u8 phys[64];
__u8 uniq[64];
__u16 rd_size;
__u16 bus;
__u32 vendor;
__u32 product;
__u32 version;
__u32 country;
__u8 rd_data[HID_MAX_DESCRIPTOR_SIZE];
} __attribute__((__packed__));
#define UHID_DATA_MAX 4096 #define UHID_DATA_MAX 4096
enum uhid_report_type { enum uhid_report_type {
...@@ -63,6 +79,11 @@ struct uhid_input_req { ...@@ -63,6 +79,11 @@ struct uhid_input_req {
__u16 size; __u16 size;
} __attribute__((__packed__)); } __attribute__((__packed__));
struct uhid_input2_req {
__u16 size;
__u8 data[UHID_DATA_MAX];
} __attribute__((__packed__));
struct uhid_output_req { struct uhid_output_req {
__u8 data[UHID_DATA_MAX]; __u8 data[UHID_DATA_MAX];
__u16 size; __u16 size;
...@@ -100,6 +121,8 @@ struct uhid_event { ...@@ -100,6 +121,8 @@ struct uhid_event {
struct uhid_output_ev_req output_ev; struct uhid_output_ev_req output_ev;
struct uhid_feature_req feature; struct uhid_feature_req feature;
struct uhid_feature_answer_req feature_answer; struct uhid_feature_answer_req feature_answer;
struct uhid_create2_req create2;
struct uhid_input2_req input2;
} u; } u;
} __attribute__((__packed__)); } __attribute__((__packed__));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment