Merge branches 'for-3.15/multitouch', 'for-3.15/sony' and 'for-3.15/uhid' into for-linus
This commit is contained in:
commit
fa1054a29b
7 changed files with 233 additions and 178 deletions
|
@ -93,6 +93,11 @@ the request was handled successfully.
|
|||
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.
|
||||
|
||||
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:
|
||||
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
|
||||
|
@ -105,6 +110,12 @@ the request was handled successfully.
|
|||
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.
|
||||
|
||||
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:
|
||||
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
|
||||
|
|
|
@ -67,6 +67,9 @@
|
|||
#define USB_VENDOR_ID_ALPS 0x0433
|
||||
#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_DEVICE_ID_APPLE_MIGHTYMOUSE 0x0304
|
||||
#define USB_DEVICE_ID_APPLE_MAGICMOUSE 0x030d
|
||||
|
|
|
@ -68,6 +68,9 @@ MODULE_LICENSE("GPL");
|
|||
#define MT_QUIRK_HOVERING (1 << 11)
|
||||
#define MT_QUIRK_CONTACT_CNT_ACCURATE (1 << 12)
|
||||
|
||||
#define MT_INPUTMODE_TOUCHSCREEN 0x02
|
||||
#define MT_INPUTMODE_TOUCHPAD 0x03
|
||||
|
||||
struct mt_slot {
|
||||
__s32 x, y, cx, cy, p, w, h;
|
||||
__s32 contactid; /* the device ContactID assigned to this slot */
|
||||
|
@ -84,6 +87,7 @@ struct mt_class {
|
|||
__s32 sn_pressure; /* Signal/noise ratio for pressure events */
|
||||
__u8 maxcontacts;
|
||||
bool is_indirect; /* true for touchpads */
|
||||
bool export_all_inputs; /* do not ignore mouse, keyboards, etc... */
|
||||
};
|
||||
|
||||
struct mt_fields {
|
||||
|
@ -100,11 +104,11 @@ struct mt_device {
|
|||
int cc_value_index; /* contact count value index in the field */
|
||||
unsigned last_slot_field; /* the last field of a slot */
|
||||
unsigned mt_report_id; /* the report ID of the multitouch device */
|
||||
unsigned pen_report_id; /* the report ID of the pen device */
|
||||
__s16 inputmode; /* InputMode HID feature, -1 if non-existent */
|
||||
__s16 inputmode_index; /* InputMode HID feature index in the report */
|
||||
__s16 maxcontact_report_id; /* Maximum Contact Number HID feature,
|
||||
-1 if non-existent */
|
||||
__u8 inputmode_value; /* InputMode HID feature value */
|
||||
__u8 num_received; /* how many contacts we received */
|
||||
__u8 num_expected; /* expected last contact index */
|
||||
__u8 maxcontacts;
|
||||
|
@ -128,16 +132,17 @@ static void mt_post_parse(struct mt_device *td);
|
|||
#define MT_CLS_CONFIDENCE_MINUS_ONE 0x0005
|
||||
#define MT_CLS_DUAL_INRANGE_CONTACTID 0x0006
|
||||
#define MT_CLS_DUAL_INRANGE_CONTACTNUMBER 0x0007
|
||||
#define MT_CLS_DUAL_NSMU_CONTACTID 0x0008
|
||||
/* reserved 0x0008 */
|
||||
#define MT_CLS_INRANGE_CONTACTNUMBER 0x0009
|
||||
#define MT_CLS_NSMU 0x000a
|
||||
#define MT_CLS_DUAL_CONTACT_NUMBER 0x0010
|
||||
#define MT_CLS_DUAL_CONTACT_ID 0x0011
|
||||
/* reserved 0x0010 */
|
||||
/* reserved 0x0011 */
|
||||
#define MT_CLS_WIN_8 0x0012
|
||||
#define MT_CLS_EXPORT_ALL_INPUTS 0x0013
|
||||
|
||||
/* vendor specific classes */
|
||||
#define MT_CLS_3M 0x0101
|
||||
#define MT_CLS_CYPRESS 0x0102
|
||||
/* reserved 0x0102 */
|
||||
#define MT_CLS_EGALAX 0x0103
|
||||
#define MT_CLS_EGALAX_SERIAL 0x0104
|
||||
#define MT_CLS_TOPSEED 0x0105
|
||||
|
@ -189,28 +194,18 @@ static struct mt_class mt_classes[] = {
|
|||
.quirks = MT_QUIRK_VALID_IS_INRANGE |
|
||||
MT_QUIRK_SLOT_IS_CONTACTNUMBER,
|
||||
.maxcontacts = 2 },
|
||||
{ .name = MT_CLS_DUAL_NSMU_CONTACTID,
|
||||
.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP |
|
||||
MT_QUIRK_SLOT_IS_CONTACTID,
|
||||
.maxcontacts = 2 },
|
||||
{ .name = MT_CLS_INRANGE_CONTACTNUMBER,
|
||||
.quirks = MT_QUIRK_VALID_IS_INRANGE |
|
||||
MT_QUIRK_SLOT_IS_CONTACTNUMBER },
|
||||
{ .name = MT_CLS_DUAL_CONTACT_NUMBER,
|
||||
.quirks = MT_QUIRK_ALWAYS_VALID |
|
||||
MT_QUIRK_CONTACT_CNT_ACCURATE |
|
||||
MT_QUIRK_SLOT_IS_CONTACTNUMBER,
|
||||
.maxcontacts = 2 },
|
||||
{ .name = MT_CLS_DUAL_CONTACT_ID,
|
||||
.quirks = MT_QUIRK_ALWAYS_VALID |
|
||||
MT_QUIRK_CONTACT_CNT_ACCURATE |
|
||||
MT_QUIRK_SLOT_IS_CONTACTID,
|
||||
.maxcontacts = 2 },
|
||||
{ .name = MT_CLS_WIN_8,
|
||||
.quirks = MT_QUIRK_ALWAYS_VALID |
|
||||
MT_QUIRK_IGNORE_DUPLICATES |
|
||||
MT_QUIRK_HOVERING |
|
||||
MT_QUIRK_CONTACT_CNT_ACCURATE },
|
||||
{ .name = MT_CLS_EXPORT_ALL_INPUTS,
|
||||
.quirks = MT_QUIRK_ALWAYS_VALID |
|
||||
MT_QUIRK_CONTACT_CNT_ACCURATE,
|
||||
.export_all_inputs = true },
|
||||
|
||||
/*
|
||||
* vendor specific classes
|
||||
|
@ -223,10 +218,6 @@ static struct mt_class mt_classes[] = {
|
|||
.sn_height = 128,
|
||||
.maxcontacts = 60,
|
||||
},
|
||||
{ .name = MT_CLS_CYPRESS,
|
||||
.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP |
|
||||
MT_QUIRK_CYPRESS,
|
||||
.maxcontacts = 10 },
|
||||
{ .name = MT_CLS_EGALAX,
|
||||
.quirks = MT_QUIRK_SLOT_IS_CONTACTID |
|
||||
MT_QUIRK_VALID_IS_INRANGE,
|
||||
|
@ -360,45 +351,6 @@ static void mt_store_field(struct hid_usage *usage, struct mt_device *td,
|
|||
f->usages[f->length++] = usage->hid;
|
||||
}
|
||||
|
||||
static int mt_pen_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
||||
struct hid_field *field, struct hid_usage *usage,
|
||||
unsigned long **bit, int *max)
|
||||
{
|
||||
struct mt_device *td = hid_get_drvdata(hdev);
|
||||
|
||||
td->pen_report_id = field->report->id;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt_pen_input_mapped(struct hid_device *hdev, struct hid_input *hi,
|
||||
struct hid_field *field, struct hid_usage *usage,
|
||||
unsigned long **bit, int *max)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt_pen_event(struct hid_device *hid, struct hid_field *field,
|
||||
struct hid_usage *usage, __s32 value)
|
||||
{
|
||||
/* let hid-input handle it */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mt_pen_report(struct hid_device *hid, struct hid_report *report)
|
||||
{
|
||||
struct hid_field *field = report->field[0];
|
||||
|
||||
input_sync(field->hidinput->input);
|
||||
}
|
||||
|
||||
static void mt_pen_input_configured(struct hid_device *hdev,
|
||||
struct hid_input *hi)
|
||||
{
|
||||
/* force BTN_STYLUS to allow tablet matching in udev */
|
||||
__set_bit(BTN_STYLUS, hi->input->keybit);
|
||||
}
|
||||
|
||||
static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
||||
struct hid_field *field, struct hid_usage *usage,
|
||||
unsigned long **bit, int *max)
|
||||
|
@ -415,8 +367,10 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
|||
* Model touchscreens providing buttons as touchpads.
|
||||
*/
|
||||
if (field->application == HID_DG_TOUCHPAD ||
|
||||
(usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON)
|
||||
(usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON) {
|
||||
td->mt_flags |= INPUT_MT_POINTER;
|
||||
td->inputmode_value = MT_INPUTMODE_TOUCHPAD;
|
||||
}
|
||||
|
||||
if (usage->usage_index)
|
||||
prev_usage = &field->usage[usage->usage_index - 1];
|
||||
|
@ -776,28 +730,52 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
|||
struct hid_field *field, struct hid_usage *usage,
|
||||
unsigned long **bit, int *max)
|
||||
{
|
||||
/* 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 &&
|
||||
struct mt_device *td = hid_get_drvdata(hdev);
|
||||
|
||||
/*
|
||||
* If mtclass.export_all_inputs is not set, 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 (!td->mtclass.export_all_inputs &&
|
||||
field->application != HID_DG_TOUCHSCREEN &&
|
||||
field->application != HID_DG_PEN &&
|
||||
field->application != HID_DG_TOUCHPAD)
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* some egalax touchscreens have "application == HID_DG_TOUCHSCREEN"
|
||||
* for the stylus.
|
||||
*/
|
||||
if (field->physical == HID_DG_STYLUS)
|
||||
return mt_pen_input_mapping(hdev, hi, field, usage, bit, max);
|
||||
return 0;
|
||||
|
||||
return mt_touch_input_mapping(hdev, hi, field, usage, bit, max);
|
||||
if (field->application == HID_DG_TOUCHSCREEN ||
|
||||
field->application == HID_DG_TOUCHPAD)
|
||||
return mt_touch_input_mapping(hdev, hi, field, usage, bit, max);
|
||||
|
||||
/* let hid-core decide for the others */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi,
|
||||
struct hid_field *field, struct hid_usage *usage,
|
||||
unsigned long **bit, int *max)
|
||||
{
|
||||
/*
|
||||
* some egalax touchscreens have "application == HID_DG_TOUCHSCREEN"
|
||||
* for the stylus.
|
||||
*/
|
||||
if (field->physical == HID_DG_STYLUS)
|
||||
return mt_pen_input_mapped(hdev, hi, field, usage, bit, max);
|
||||
return 0;
|
||||
|
||||
return mt_touch_input_mapped(hdev, hi, field, usage, bit, max);
|
||||
if (field->application == HID_DG_TOUCHSCREEN ||
|
||||
field->application == HID_DG_TOUCHPAD)
|
||||
return mt_touch_input_mapped(hdev, hi, field, usage, bit, max);
|
||||
|
||||
/* let hid-core decide for the others */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt_event(struct hid_device *hid, struct hid_field *field,
|
||||
|
@ -808,25 +786,22 @@ static int mt_event(struct hid_device *hid, struct hid_field *field,
|
|||
if (field->report->id == td->mt_report_id)
|
||||
return mt_touch_event(hid, field, usage, value);
|
||||
|
||||
if (field->report->id == td->pen_report_id)
|
||||
return mt_pen_event(hid, field, usage, value);
|
||||
|
||||
/* ignore other reports */
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mt_report(struct hid_device *hid, struct hid_report *report)
|
||||
{
|
||||
struct mt_device *td = hid_get_drvdata(hid);
|
||||
struct hid_field *field = report->field[0];
|
||||
|
||||
if (!(hid->claimed & HID_CLAIMED_INPUT))
|
||||
return;
|
||||
|
||||
if (report->id == td->mt_report_id)
|
||||
mt_touch_report(hid, report);
|
||||
return mt_touch_report(hid, report);
|
||||
|
||||
if (report->id == td->pen_report_id)
|
||||
mt_pen_report(hid, report);
|
||||
if (field && field->hidinput && field->hidinput->input)
|
||||
input_sync(field->hidinput->input);
|
||||
}
|
||||
|
||||
static void mt_set_input_mode(struct hid_device *hdev)
|
||||
|
@ -841,7 +816,7 @@ static void mt_set_input_mode(struct hid_device *hdev)
|
|||
re = &(hdev->report_enum[HID_FEATURE_REPORT]);
|
||||
r = re->report_id_hash[td->inputmode];
|
||||
if (r) {
|
||||
r->field[0]->value[td->inputmode_index] = 0x02;
|
||||
r->field[0]->value[td->inputmode_index] = td->inputmode_value;
|
||||
hid_hw_request(hdev, r, HID_REQ_SET_REPORT);
|
||||
}
|
||||
}
|
||||
|
@ -907,13 +882,49 @@ static void mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
|
|||
struct mt_device *td = hid_get_drvdata(hdev);
|
||||
char *name;
|
||||
const char *suffix = NULL;
|
||||
struct hid_field *field = hi->report->field[0];
|
||||
|
||||
if (hi->report->id == td->mt_report_id)
|
||||
mt_touch_input_configured(hdev, hi);
|
||||
|
||||
/*
|
||||
* some egalax touchscreens have "application == HID_DG_TOUCHSCREEN"
|
||||
* for the stylus. Check this first, and then rely on the application
|
||||
* field.
|
||||
*/
|
||||
if (hi->report->field[0]->physical == HID_DG_STYLUS) {
|
||||
suffix = "Pen";
|
||||
mt_pen_input_configured(hdev, hi);
|
||||
/* force BTN_STYLUS to allow tablet matching in udev */
|
||||
__set_bit(BTN_STYLUS, hi->input->keybit);
|
||||
} else {
|
||||
switch (field->application) {
|
||||
case HID_GD_KEYBOARD:
|
||||
suffix = "Keyboard";
|
||||
break;
|
||||
case HID_GD_KEYPAD:
|
||||
suffix = "Keypad";
|
||||
break;
|
||||
case HID_GD_MOUSE:
|
||||
suffix = "Mouse";
|
||||
break;
|
||||
case HID_DG_STYLUS:
|
||||
suffix = "Pen";
|
||||
/* force BTN_STYLUS to allow tablet matching in udev */
|
||||
__set_bit(BTN_STYLUS, hi->input->keybit);
|
||||
break;
|
||||
case HID_DG_TOUCHSCREEN:
|
||||
/* we do not set suffix = "Touchscreen" */
|
||||
break;
|
||||
case HID_GD_SYSTEM_CONTROL:
|
||||
suffix = "System Control";
|
||||
break;
|
||||
case HID_CP_CONSUMER_CONTROL:
|
||||
suffix = "Consumer Control";
|
||||
break;
|
||||
default:
|
||||
suffix = "UNKNOWN";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (suffix) {
|
||||
|
@ -973,9 +984,9 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
td->mtclass = *mtclass;
|
||||
td->inputmode = -1;
|
||||
td->maxcontact_report_id = -1;
|
||||
td->inputmode_value = MT_INPUTMODE_TOUCHSCREEN;
|
||||
td->cc_index = -1;
|
||||
td->mt_report_id = -1;
|
||||
td->pen_report_id = -1;
|
||||
hid_set_drvdata(hdev, td);
|
||||
|
||||
td->fields = devm_kzalloc(&hdev->dev, sizeof(struct mt_fields),
|
||||
|
@ -1034,6 +1045,12 @@ static void mt_remove(struct hid_device *hdev)
|
|||
hid_hw_stop(hdev);
|
||||
}
|
||||
|
||||
/*
|
||||
* This list contains only:
|
||||
* - VID/PID of products not working with the default multitouch handling
|
||||
* - 2 generic rules.
|
||||
* So there is no point in adding here any device with MT_CLS_DEFAULT.
|
||||
*/
|
||||
static const struct hid_device_id mt_devices[] = {
|
||||
|
||||
/* 3M panels */
|
||||
|
@ -1047,15 +1064,12 @@ static const struct hid_device_id mt_devices[] = {
|
|||
MT_USB_DEVICE(USB_VENDOR_ID_3M,
|
||||
USB_DEVICE_ID_3M3266) },
|
||||
|
||||
/* ActionStar panels */
|
||||
{ .driver_data = MT_CLS_NSMU,
|
||||
MT_USB_DEVICE(USB_VENDOR_ID_ACTIONSTAR,
|
||||
USB_DEVICE_ID_ACTIONSTAR_1011) },
|
||||
/* Anton devices */
|
||||
{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
|
||||
MT_USB_DEVICE(USB_VENDOR_ID_ANTON,
|
||||
USB_DEVICE_ID_ANTON_TOUCH_PAD) },
|
||||
|
||||
/* Atmel panels */
|
||||
{ .driver_data = MT_CLS_SERIAL,
|
||||
MT_USB_DEVICE(USB_VENDOR_ID_ATMEL,
|
||||
USB_DEVICE_ID_ATMEL_MULTITOUCH) },
|
||||
{ .driver_data = MT_CLS_SERIAL,
|
||||
MT_USB_DEVICE(USB_VENDOR_ID_ATMEL,
|
||||
USB_DEVICE_ID_ATMEL_MXT_DIGITIZER) },
|
||||
|
@ -1064,16 +1078,11 @@ static const struct hid_device_id mt_devices[] = {
|
|||
{ .driver_data = MT_CLS_NSMU,
|
||||
MT_USB_DEVICE(USB_VENDOR_ID_BAANTO,
|
||||
USB_DEVICE_ID_BAANTO_MT_190W2) },
|
||||
|
||||
/* Cando panels */
|
||||
{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
|
||||
MT_USB_DEVICE(USB_VENDOR_ID_CANDO,
|
||||
USB_DEVICE_ID_CANDO_MULTI_TOUCH) },
|
||||
{ .driver_data = MT_CLS_DUAL_CONTACT_NUMBER,
|
||||
MT_USB_DEVICE(USB_VENDOR_ID_CANDO,
|
||||
USB_DEVICE_ID_CANDO_MULTI_TOUCH_10_1) },
|
||||
{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
|
||||
MT_USB_DEVICE(USB_VENDOR_ID_CANDO,
|
||||
USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) },
|
||||
{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
|
||||
MT_USB_DEVICE(USB_VENDOR_ID_CANDO,
|
||||
USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) },
|
||||
|
@ -1088,16 +1097,6 @@ static const struct hid_device_id mt_devices[] = {
|
|||
MT_USB_DEVICE(USB_VENDOR_ID_CVTOUCH,
|
||||
USB_DEVICE_ID_CVTOUCH_SCREEN) },
|
||||
|
||||
/* Cypress panel */
|
||||
{ .driver_data = MT_CLS_CYPRESS,
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS,
|
||||
USB_DEVICE_ID_CYPRESS_TRUETOUCH) },
|
||||
|
||||
/* Data Modul easyMaxTouch */
|
||||
{ .driver_data = MT_CLS_DEFAULT,
|
||||
MT_USB_DEVICE(USB_VENDOR_ID_DATA_MODUL,
|
||||
USB_VENDOR_ID_DATA_MODUL_EASYMAXTOUCH) },
|
||||
|
||||
/* eGalax devices (resistive) */
|
||||
{ .driver_data = MT_CLS_EGALAX,
|
||||
MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
|
||||
|
@ -1156,11 +1155,6 @@ static const struct hid_device_id mt_devices[] = {
|
|||
MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
|
||||
USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001) },
|
||||
|
||||
/* Elo TouchSystems IntelliTouch Plus panel */
|
||||
{ .driver_data = MT_CLS_DUAL_CONTACT_ID,
|
||||
MT_USB_DEVICE(USB_VENDOR_ID_ELO,
|
||||
USB_DEVICE_ID_ELO_TS2515) },
|
||||
|
||||
/* Flatfrog Panels */
|
||||
{ .driver_data = MT_CLS_FLATFROG,
|
||||
MT_USB_DEVICE(USB_VENDOR_ID_FLATFROG,
|
||||
|
@ -1209,37 +1203,11 @@ static const struct hid_device_id mt_devices[] = {
|
|||
MT_USB_DEVICE(USB_VENDOR_ID_HANVON_ALT,
|
||||
USB_DEVICE_ID_HANVON_ALT_MULTITOUCH) },
|
||||
|
||||
/* Ideacom panel */
|
||||
{ .driver_data = MT_CLS_SERIAL,
|
||||
MT_USB_DEVICE(USB_VENDOR_ID_IDEACOM,
|
||||
USB_DEVICE_ID_IDEACOM_IDC6650) },
|
||||
{ .driver_data = MT_CLS_SERIAL,
|
||||
MT_USB_DEVICE(USB_VENDOR_ID_IDEACOM,
|
||||
USB_DEVICE_ID_IDEACOM_IDC6651) },
|
||||
|
||||
/* Ilitek dual touch panel */
|
||||
{ .driver_data = MT_CLS_NSMU,
|
||||
MT_USB_DEVICE(USB_VENDOR_ID_ILITEK,
|
||||
USB_DEVICE_ID_ILITEK_MULTITOUCH) },
|
||||
|
||||
/* IRTOUCH panels */
|
||||
{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID,
|
||||
MT_USB_DEVICE(USB_VENDOR_ID_IRTOUCHSYSTEMS,
|
||||
USB_DEVICE_ID_IRTOUCH_INFRARED_USB) },
|
||||
|
||||
/* LG Display panels */
|
||||
{ .driver_data = MT_CLS_DEFAULT,
|
||||
MT_USB_DEVICE(USB_VENDOR_ID_LG,
|
||||
USB_DEVICE_ID_LG_MULTITOUCH) },
|
||||
|
||||
/* Lumio panels */
|
||||
{ .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
|
||||
MT_USB_DEVICE(USB_VENDOR_ID_LUMIO,
|
||||
USB_DEVICE_ID_CRYSTALTOUCH) },
|
||||
{ .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
|
||||
MT_USB_DEVICE(USB_VENDOR_ID_LUMIO,
|
||||
USB_DEVICE_ID_CRYSTALTOUCH_DUAL) },
|
||||
|
||||
/* MosArt panels */
|
||||
{ .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
|
||||
MT_USB_DEVICE(USB_VENDOR_ID_ASUS,
|
||||
|
@ -1251,11 +1219,6 @@ static const struct hid_device_id mt_devices[] = {
|
|||
MT_USB_DEVICE(USB_VENDOR_ID_TURBOX,
|
||||
USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART) },
|
||||
|
||||
/* Nexio panels */
|
||||
{ .driver_data = MT_CLS_DEFAULT,
|
||||
MT_USB_DEVICE(USB_VENDOR_ID_NEXIO,
|
||||
USB_DEVICE_ID_NEXIO_MULTITOUCH_420)},
|
||||
|
||||
/* Panasonic panels */
|
||||
{ .driver_data = MT_CLS_PANASONIC,
|
||||
MT_USB_DEVICE(USB_VENDOR_ID_PANASONIC,
|
||||
|
@ -1269,11 +1232,6 @@ static const struct hid_device_id mt_devices[] = {
|
|||
MT_USB_DEVICE(USB_VENDOR_ID_NOVATEK,
|
||||
USB_DEVICE_ID_NOVATEK_PCT) },
|
||||
|
||||
/* PenMount panels */
|
||||
{ .driver_data = MT_CLS_CONFIDENCE,
|
||||
MT_USB_DEVICE(USB_VENDOR_ID_PENMOUNT,
|
||||
USB_DEVICE_ID_PENMOUNT_PCI) },
|
||||
|
||||
/* PixArt optical touch screen */
|
||||
{ .driver_data = MT_CLS_INRANGE_CONTACTNUMBER,
|
||||
MT_USB_DEVICE(USB_VENDOR_ID_PIXART,
|
||||
|
@ -1286,45 +1244,19 @@ static const struct hid_device_id mt_devices[] = {
|
|||
USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2) },
|
||||
|
||||
/* PixCir-based panels */
|
||||
{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID,
|
||||
MT_USB_DEVICE(USB_VENDOR_ID_HANVON,
|
||||
USB_DEVICE_ID_HANVON_MULTITOUCH) },
|
||||
{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID,
|
||||
MT_USB_DEVICE(USB_VENDOR_ID_CANDO,
|
||||
USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) },
|
||||
|
||||
/* Quanta-based panels */
|
||||
{ .driver_data = MT_CLS_CONFIDENCE_CONTACT_ID,
|
||||
MT_USB_DEVICE(USB_VENDOR_ID_QUANTA,
|
||||
USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) },
|
||||
{ .driver_data = MT_CLS_CONFIDENCE_CONTACT_ID,
|
||||
MT_USB_DEVICE(USB_VENDOR_ID_QUANTA,
|
||||
USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001) },
|
||||
{ .driver_data = MT_CLS_CONFIDENCE_CONTACT_ID,
|
||||
MT_USB_DEVICE(USB_VENDOR_ID_QUANTA,
|
||||
USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008) },
|
||||
|
||||
/* SiS panels */
|
||||
{ .driver_data = MT_CLS_DEFAULT,
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH,
|
||||
USB_DEVICE_ID_SIS9200_TOUCH) },
|
||||
{ .driver_data = MT_CLS_DEFAULT,
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH,
|
||||
USB_DEVICE_ID_SIS817_TOUCH) },
|
||||
{ .driver_data = MT_CLS_DEFAULT,
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH,
|
||||
USB_DEVICE_ID_SIS1030_TOUCH) },
|
||||
|
||||
/* Stantum panels */
|
||||
{ .driver_data = MT_CLS_CONFIDENCE,
|
||||
MT_USB_DEVICE(USB_VENDOR_ID_STANTUM,
|
||||
USB_DEVICE_ID_MTP)},
|
||||
{ .driver_data = MT_CLS_CONFIDENCE,
|
||||
MT_USB_DEVICE(USB_VENDOR_ID_STANTUM_STM,
|
||||
USB_DEVICE_ID_MTP_STM)},
|
||||
{ .driver_data = MT_CLS_DEFAULT,
|
||||
MT_USB_DEVICE(USB_VENDOR_ID_STANTUM_SITRONIX,
|
||||
USB_DEVICE_ID_MTP_SITRONIX)},
|
||||
|
||||
/* TopSeed panels */
|
||||
{ .driver_data = MT_CLS_TOPSEED,
|
||||
|
@ -1383,11 +1315,6 @@ static const struct hid_device_id mt_devices[] = {
|
|||
MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
|
||||
USB_DEVICE_ID_XIROKU_CSR2) },
|
||||
|
||||
/* Zytronic panels */
|
||||
{ .driver_data = MT_CLS_SERIAL,
|
||||
MT_USB_DEVICE(USB_VENDOR_ID_ZYTRONIC,
|
||||
USB_DEVICE_ID_ZYTRONIC_ZXY100) },
|
||||
|
||||
/* Generic MT device */
|
||||
{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_MULTITOUCH, HID_ANY_ID, HID_ANY_ID) },
|
||||
|
||||
|
|
|
@ -863,7 +863,7 @@ static void sixaxis_parse_report(struct sony_sc *sc, __u8 *rd, int size)
|
|||
battery_capacity = sixaxis_battery_capacity[index];
|
||||
battery_charging = 0;
|
||||
}
|
||||
cable_state = !((rd[31] >> 4) & 0x01);
|
||||
cable_state = !(rd[31] & 0x04);
|
||||
|
||||
spin_lock_irqsave(&sc->lock, flags);
|
||||
sc->cable_state = cable_state;
|
||||
|
@ -1632,11 +1632,21 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
sc->worker_initialized = 1;
|
||||
INIT_WORK(&sc->state_worker, sixaxis_state_worker);
|
||||
} 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);
|
||||
sc->worker_initialized = 1;
|
||||
INIT_WORK(&sc->state_worker, sixaxis_state_worker);
|
||||
} else if (sc->quirks & DUALSHOCK4_CONTROLLER) {
|
||||
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);
|
||||
if (ret < 0) {
|
||||
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,
|
|||
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)
|
||||
{
|
||||
if (!uhid->running)
|
||||
|
@ -456,6 +517,17 @@ static int uhid_dev_input(struct uhid_device *uhid, struct uhid_event *ev)
|
|||
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,
|
||||
struct uhid_event *ev)
|
||||
{
|
||||
|
@ -592,12 +664,18 @@ static ssize_t uhid_char_write(struct file *file, const char __user *buffer,
|
|||
case UHID_CREATE:
|
||||
ret = uhid_dev_create(uhid, &uhid->input_buf);
|
||||
break;
|
||||
case UHID_CREATE2:
|
||||
ret = uhid_dev_create2(uhid, &uhid->input_buf);
|
||||
break;
|
||||
case UHID_DESTROY:
|
||||
ret = uhid_dev_destroy(uhid);
|
||||
break;
|
||||
case UHID_INPUT:
|
||||
ret = uhid_dev_input(uhid, &uhid->input_buf);
|
||||
break;
|
||||
case UHID_INPUT2:
|
||||
ret = uhid_dev_input2(uhid, &uhid->input_buf);
|
||||
break;
|
||||
case UHID_FEATURE_ANSWER:
|
||||
ret = uhid_dev_feature_answer(uhid, &uhid->input_buf);
|
||||
break;
|
||||
|
|
|
@ -201,6 +201,7 @@ struct hid_item {
|
|||
#define HID_GD_VBRZ 0x00010045
|
||||
#define HID_GD_VNO 0x00010046
|
||||
#define HID_GD_FEATURE 0x00010047
|
||||
#define HID_GD_SYSTEM_CONTROL 0x00010080
|
||||
#define HID_GD_UP 0x00010090
|
||||
#define HID_GD_DOWN 0x00010091
|
||||
#define HID_GD_RIGHT 0x00010092
|
||||
|
@ -208,6 +209,8 @@ struct hid_item {
|
|||
|
||||
#define HID_DC_BATTERYSTRENGTH 0x00060020
|
||||
|
||||
#define HID_CP_CONSUMER_CONTROL 0x000c0001
|
||||
|
||||
#define HID_DG_DIGITIZER 0x000d0001
|
||||
#define HID_DG_PEN 0x000d0002
|
||||
#define HID_DG_LIGHTPEN 0x000d0003
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include <linux/input.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/hid.h>
|
||||
|
||||
enum uhid_event_type {
|
||||
UHID_CREATE,
|
||||
|
@ -34,6 +35,8 @@ enum uhid_event_type {
|
|||
UHID_INPUT,
|
||||
UHID_FEATURE,
|
||||
UHID_FEATURE_ANSWER,
|
||||
UHID_CREATE2,
|
||||
UHID_INPUT2,
|
||||
};
|
||||
|
||||
struct uhid_create_req {
|
||||
|
@ -50,6 +53,19 @@ struct uhid_create_req {
|
|||
__u32 country;
|
||||
} __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
|
||||
|
||||
enum uhid_report_type {
|
||||
|
@ -63,6 +79,11 @@ struct uhid_input_req {
|
|||
__u16 size;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
struct uhid_input2_req {
|
||||
__u16 size;
|
||||
__u8 data[UHID_DATA_MAX];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
struct uhid_output_req {
|
||||
__u8 data[UHID_DATA_MAX];
|
||||
__u16 size;
|
||||
|
@ -100,6 +121,8 @@ struct uhid_event {
|
|||
struct uhid_output_ev_req output_ev;
|
||||
struct uhid_feature_req feature;
|
||||
struct uhid_feature_answer_req feature_answer;
|
||||
struct uhid_create2_req create2;
|
||||
struct uhid_input2_req input2;
|
||||
} u;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue