diff options
Diffstat (limited to 'drivers/hid/hid-logitech-hidpp.c')
-rw-r--r-- | drivers/hid/hid-logitech-hidpp.c | 81 |
1 files changed, 55 insertions, 26 deletions
diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c index a93cefe0e522..e77658cd037c 100644 --- a/drivers/hid/hid-logitech-hidpp.c +++ b/drivers/hid/hid-logitech-hidpp.c | |||
@@ -89,6 +89,7 @@ struct hidpp_device { | |||
89 | struct hid_device *hid_dev; | 89 | struct hid_device *hid_dev; |
90 | struct mutex send_mutex; | 90 | struct mutex send_mutex; |
91 | void *send_receive_buf; | 91 | void *send_receive_buf; |
92 | char *name; /* will never be NULL and should not be freed */ | ||
92 | wait_queue_head_t wait; | 93 | wait_queue_head_t wait; |
93 | bool answer_available; | 94 | bool answer_available; |
94 | u8 protocol_major; | 95 | u8 protocol_major; |
@@ -105,6 +106,7 @@ struct hidpp_device { | |||
105 | }; | 106 | }; |
106 | 107 | ||
107 | 108 | ||
109 | /* HID++ 1.0 error codes */ | ||
108 | #define HIDPP_ERROR 0x8f | 110 | #define HIDPP_ERROR 0x8f |
109 | #define HIDPP_ERROR_SUCCESS 0x00 | 111 | #define HIDPP_ERROR_SUCCESS 0x00 |
110 | #define HIDPP_ERROR_INVALID_SUBID 0x01 | 112 | #define HIDPP_ERROR_INVALID_SUBID 0x01 |
@@ -119,6 +121,8 @@ struct hidpp_device { | |||
119 | #define HIDPP_ERROR_REQUEST_UNAVAILABLE 0x0a | 121 | #define HIDPP_ERROR_REQUEST_UNAVAILABLE 0x0a |
120 | #define HIDPP_ERROR_INVALID_PARAM_VALUE 0x0b | 122 | #define HIDPP_ERROR_INVALID_PARAM_VALUE 0x0b |
121 | #define HIDPP_ERROR_WRONG_PIN_CODE 0x0c | 123 | #define HIDPP_ERROR_WRONG_PIN_CODE 0x0c |
124 | /* HID++ 2.0 error codes */ | ||
125 | #define HIDPP20_ERROR 0xff | ||
122 | 126 | ||
123 | static void hidpp_connect_event(struct hidpp_device *hidpp_dev); | 127 | static void hidpp_connect_event(struct hidpp_device *hidpp_dev); |
124 | 128 | ||
@@ -192,9 +196,16 @@ static int hidpp_send_message_sync(struct hidpp_device *hidpp, | |||
192 | } | 196 | } |
193 | 197 | ||
194 | if (response->report_id == REPORT_ID_HIDPP_SHORT && | 198 | if (response->report_id == REPORT_ID_HIDPP_SHORT && |
195 | response->fap.feature_index == HIDPP_ERROR) { | 199 | response->rap.sub_id == HIDPP_ERROR) { |
200 | ret = response->rap.params[1]; | ||
201 | dbg_hid("%s:got hidpp error %02X\n", __func__, ret); | ||
202 | goto exit; | ||
203 | } | ||
204 | |||
205 | if (response->report_id == REPORT_ID_HIDPP_LONG && | ||
206 | response->fap.feature_index == HIDPP20_ERROR) { | ||
196 | ret = response->fap.params[1]; | 207 | ret = response->fap.params[1]; |
197 | dbg_hid("__hidpp_send_report got hidpp error %02X\n", ret); | 208 | dbg_hid("%s:got hidpp 2.0 error %02X\n", __func__, ret); |
198 | goto exit; | 209 | goto exit; |
199 | } | 210 | } |
200 | 211 | ||
@@ -271,7 +282,8 @@ static inline bool hidpp_match_answer(struct hidpp_report *question, | |||
271 | static inline bool hidpp_match_error(struct hidpp_report *question, | 282 | static inline bool hidpp_match_error(struct hidpp_report *question, |
272 | struct hidpp_report *answer) | 283 | struct hidpp_report *answer) |
273 | { | 284 | { |
274 | return (answer->fap.feature_index == HIDPP_ERROR) && | 285 | return ((answer->rap.sub_id == HIDPP_ERROR) || |
286 | (answer->fap.feature_index == HIDPP20_ERROR)) && | ||
275 | (answer->fap.funcindex_clientid == question->fap.feature_index) && | 287 | (answer->fap.funcindex_clientid == question->fap.feature_index) && |
276 | (answer->fap.params[0] == question->fap.funcindex_clientid); | 288 | (answer->fap.params[0] == question->fap.funcindex_clientid); |
277 | } | 289 | } |
@@ -903,24 +915,24 @@ static int wtp_allocate(struct hid_device *hdev, const struct hid_device_id *id) | |||
903 | return 0; | 915 | return 0; |
904 | }; | 916 | }; |
905 | 917 | ||
906 | static void wtp_connect(struct hid_device *hdev, bool connected) | 918 | static int wtp_connect(struct hid_device *hdev, bool connected) |
907 | { | 919 | { |
908 | struct hidpp_device *hidpp = hid_get_drvdata(hdev); | 920 | struct hidpp_device *hidpp = hid_get_drvdata(hdev); |
909 | struct wtp_data *wd = hidpp->private_data; | 921 | struct wtp_data *wd = hidpp->private_data; |
910 | int ret; | 922 | int ret; |
911 | 923 | ||
912 | if (!connected) | 924 | if (!connected) |
913 | return; | 925 | return 0; |
914 | 926 | ||
915 | if (!wd->x_size) { | 927 | if (!wd->x_size) { |
916 | ret = wtp_get_config(hidpp); | 928 | ret = wtp_get_config(hidpp); |
917 | if (ret) { | 929 | if (ret) { |
918 | hid_err(hdev, "Can not get wtp config: %d\n", ret); | 930 | hid_err(hdev, "Can not get wtp config: %d\n", ret); |
919 | return; | 931 | return ret; |
920 | } | 932 | } |
921 | } | 933 | } |
922 | 934 | ||
923 | hidpp_touchpad_set_raw_report_state(hidpp, wd->mt_feature_index, | 935 | return hidpp_touchpad_set_raw_report_state(hidpp, wd->mt_feature_index, |
924 | true, true); | 936 | true, true); |
925 | } | 937 | } |
926 | 938 | ||
@@ -965,7 +977,7 @@ static int hidpp_raw_hidpp_event(struct hidpp_device *hidpp, u8 *data, | |||
965 | 977 | ||
966 | /* | 978 | /* |
967 | * If the mutex is locked then we have a pending answer from a | 979 | * If the mutex is locked then we have a pending answer from a |
968 | * previoulsly sent command | 980 | * previously sent command. |
969 | */ | 981 | */ |
970 | if (unlikely(mutex_is_locked(&hidpp->send_mutex))) { | 982 | if (unlikely(mutex_is_locked(&hidpp->send_mutex))) { |
971 | /* | 983 | /* |
@@ -996,9 +1008,6 @@ static int hidpp_raw_hidpp_event(struct hidpp_device *hidpp, u8 *data, | |||
996 | return 1; | 1008 | return 1; |
997 | } | 1009 | } |
998 | 1010 | ||
999 | if (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP) | ||
1000 | return wtp_raw_event(hidpp->hid_dev, data, size); | ||
1001 | |||
1002 | return 0; | 1011 | return 0; |
1003 | } | 1012 | } |
1004 | 1013 | ||
@@ -1006,7 +1015,9 @@ static int hidpp_raw_event(struct hid_device *hdev, struct hid_report *report, | |||
1006 | u8 *data, int size) | 1015 | u8 *data, int size) |
1007 | { | 1016 | { |
1008 | struct hidpp_device *hidpp = hid_get_drvdata(hdev); | 1017 | struct hidpp_device *hidpp = hid_get_drvdata(hdev); |
1018 | int ret = 0; | ||
1009 | 1019 | ||
1020 | /* Generic HID++ processing. */ | ||
1010 | switch (data[0]) { | 1021 | switch (data[0]) { |
1011 | case REPORT_ID_HIDPP_LONG: | 1022 | case REPORT_ID_HIDPP_LONG: |
1012 | if (size != HIDPP_REPORT_LONG_LENGTH) { | 1023 | if (size != HIDPP_REPORT_LONG_LENGTH) { |
@@ -1014,16 +1025,23 @@ static int hidpp_raw_event(struct hid_device *hdev, struct hid_report *report, | |||
1014 | size); | 1025 | size); |
1015 | return 1; | 1026 | return 1; |
1016 | } | 1027 | } |
1017 | return hidpp_raw_hidpp_event(hidpp, data, size); | 1028 | ret = hidpp_raw_hidpp_event(hidpp, data, size); |
1029 | break; | ||
1018 | case REPORT_ID_HIDPP_SHORT: | 1030 | case REPORT_ID_HIDPP_SHORT: |
1019 | if (size != HIDPP_REPORT_SHORT_LENGTH) { | 1031 | if (size != HIDPP_REPORT_SHORT_LENGTH) { |
1020 | hid_err(hdev, "received hid++ report of bad size (%d)", | 1032 | hid_err(hdev, "received hid++ report of bad size (%d)", |
1021 | size); | 1033 | size); |
1022 | return 1; | 1034 | return 1; |
1023 | } | 1035 | } |
1024 | return hidpp_raw_hidpp_event(hidpp, data, size); | 1036 | ret = hidpp_raw_hidpp_event(hidpp, data, size); |
1037 | break; | ||
1025 | } | 1038 | } |
1026 | 1039 | ||
1040 | /* If no report is available for further processing, skip calling | ||
1041 | * raw_event of subclasses. */ | ||
1042 | if (ret != 0) | ||
1043 | return ret; | ||
1044 | |||
1027 | if (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP) | 1045 | if (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP) |
1028 | return wtp_raw_event(hdev, data, size); | 1046 | return wtp_raw_event(hdev, data, size); |
1029 | 1047 | ||
@@ -1070,6 +1088,7 @@ static void hidpp_input_close(struct input_dev *dev) | |||
1070 | static struct input_dev *hidpp_allocate_input(struct hid_device *hdev) | 1088 | static struct input_dev *hidpp_allocate_input(struct hid_device *hdev) |
1071 | { | 1089 | { |
1072 | struct input_dev *input_dev = devm_input_allocate_device(&hdev->dev); | 1090 | struct input_dev *input_dev = devm_input_allocate_device(&hdev->dev); |
1091 | struct hidpp_device *hidpp = hid_get_drvdata(hdev); | ||
1073 | 1092 | ||
1074 | if (!input_dev) | 1093 | if (!input_dev) |
1075 | return NULL; | 1094 | return NULL; |
@@ -1078,7 +1097,7 @@ static struct input_dev *hidpp_allocate_input(struct hid_device *hdev) | |||
1078 | input_dev->open = hidpp_input_open; | 1097 | input_dev->open = hidpp_input_open; |
1079 | input_dev->close = hidpp_input_close; | 1098 | input_dev->close = hidpp_input_close; |
1080 | 1099 | ||
1081 | input_dev->name = hdev->name; | 1100 | input_dev->name = hidpp->name; |
1082 | input_dev->phys = hdev->phys; | 1101 | input_dev->phys = hdev->phys; |
1083 | input_dev->uniq = hdev->uniq; | 1102 | input_dev->uniq = hdev->uniq; |
1084 | input_dev->id.bustype = hdev->bus; | 1103 | input_dev->id.bustype = hdev->bus; |
@@ -1098,8 +1117,11 @@ static void hidpp_connect_event(struct hidpp_device *hidpp) | |||
1098 | struct input_dev *input; | 1117 | struct input_dev *input; |
1099 | char *name, *devm_name; | 1118 | char *name, *devm_name; |
1100 | 1119 | ||
1101 | if (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP) | 1120 | if (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP) { |
1102 | wtp_connect(hdev, connected); | 1121 | ret = wtp_connect(hdev, connected); |
1122 | if (ret) | ||
1123 | return; | ||
1124 | } | ||
1103 | 1125 | ||
1104 | if (!connected || hidpp->delayed_input) | 1126 | if (!connected || hidpp->delayed_input) |
1105 | return; | 1127 | return; |
@@ -1117,22 +1139,28 @@ static void hidpp_connect_event(struct hidpp_device *hidpp) | |||
1117 | hid_info(hdev, "HID++ %u.%u device connected.\n", | 1139 | hid_info(hdev, "HID++ %u.%u device connected.\n", |
1118 | hidpp->protocol_major, hidpp->protocol_minor); | 1140 | hidpp->protocol_major, hidpp->protocol_minor); |
1119 | 1141 | ||
1142 | if (!hidpp->name || hidpp->name == hdev->name) { | ||
1143 | name = hidpp_get_device_name(hidpp); | ||
1144 | if (!name) { | ||
1145 | hid_err(hdev, | ||
1146 | "unable to retrieve the name of the device"); | ||
1147 | return; | ||
1148 | } | ||
1149 | |||
1150 | devm_name = devm_kasprintf(&hdev->dev, GFP_KERNEL, "%s", name); | ||
1151 | kfree(name); | ||
1152 | if (!devm_name) | ||
1153 | return; | ||
1154 | |||
1155 | hidpp->name = devm_name; | ||
1156 | } | ||
1157 | |||
1120 | input = hidpp_allocate_input(hdev); | 1158 | input = hidpp_allocate_input(hdev); |
1121 | if (!input) { | 1159 | if (!input) { |
1122 | hid_err(hdev, "cannot allocate new input device: %d\n", ret); | 1160 | hid_err(hdev, "cannot allocate new input device: %d\n", ret); |
1123 | return; | 1161 | return; |
1124 | } | 1162 | } |
1125 | 1163 | ||
1126 | name = hidpp_get_device_name(hidpp); | ||
1127 | if (!name) { | ||
1128 | hid_err(hdev, "unable to retrieve the name of the device"); | ||
1129 | } else { | ||
1130 | devm_name = devm_kasprintf(&hdev->dev, GFP_KERNEL, "%s", name); | ||
1131 | if (devm_name) | ||
1132 | input->name = devm_name; | ||
1133 | kfree(name); | ||
1134 | } | ||
1135 | |||
1136 | hidpp_populate_input(hidpp, input, false); | 1164 | hidpp_populate_input(hidpp, input, false); |
1137 | 1165 | ||
1138 | ret = input_register_device(input); | 1166 | ret = input_register_device(input); |
@@ -1155,6 +1183,7 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
1155 | return -ENOMEM; | 1183 | return -ENOMEM; |
1156 | 1184 | ||
1157 | hidpp->hid_dev = hdev; | 1185 | hidpp->hid_dev = hdev; |
1186 | hidpp->name = hdev->name; | ||
1158 | hid_set_drvdata(hdev, hidpp); | 1187 | hid_set_drvdata(hdev, hidpp); |
1159 | 1188 | ||
1160 | hidpp->quirks = id->driver_data; | 1189 | hidpp->quirks = id->driver_data; |