0009-surface-typecover.patch 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573
  1. From 28ea3660b6680bfd528ca05c543e69b8a2ad412c Mon Sep 17 00:00:00 2001
  2. From: Maximilian Luz <luzmaximilian@gmail.com>
  3. Date: Sat, 18 Feb 2023 01:02:49 +0100
  4. Subject: [PATCH] USB: quirks: Add USB_QUIRK_DELAY_INIT for Surface Go 3
  5. Type-Cover
  6. The touchpad on the Type-Cover of the Surface Go 3 is sometimes not
  7. being initialized properly. Apply USB_QUIRK_DELAY_INIT to fix this
  8. issue.
  9. More specifically, the device in question is a fairly standard modern
  10. touchpad with pointer and touchpad input modes. During setup, the device
  11. needs to be switched from pointer- to touchpad-mode (which is done in
  12. hid-multitouch) to fully utilize it as intended. Unfortunately, however,
  13. this seems to occasionally fail silently, leaving the device in
  14. pointer-mode. Applying USB_QUIRK_DELAY_INIT seems to fix this.
  15. Link: https://github.com/linux-surface/linux-surface/issues/1059
  16. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  17. Patchset: surface-typecover
  18. ---
  19. drivers/usb/core/quirks.c | 3 +++
  20. 1 file changed, 3 insertions(+)
  21. diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
  22. index 15e9bd180a1d..0d70461d01e1 100644
  23. --- a/drivers/usb/core/quirks.c
  24. +++ b/drivers/usb/core/quirks.c
  25. @@ -220,6 +220,9 @@ static const struct usb_device_id usb_quirk_list[] = {
  26. /* Microsoft Surface Dock Ethernet (RTL8153 GigE) */
  27. { USB_DEVICE(0x045e, 0x07c6), .driver_info = USB_QUIRK_NO_LPM },
  28. + /* Microsoft Surface Go 3 Type-Cover */
  29. + { USB_DEVICE(0x045e, 0x09b5), .driver_info = USB_QUIRK_DELAY_INIT },
  30. +
  31. /* Cherry Stream G230 2.0 (G85-231) and 3.0 (G85-232) */
  32. { USB_DEVICE(0x046a, 0x0023), .driver_info = USB_QUIRK_RESET_RESUME },
  33. --
  34. 2.43.0
  35. From 039ed906cfe0578e78c40d786433e9b144c56785 Mon Sep 17 00:00:00 2001
  36. From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= <verdre@v0yd.nl>
  37. Date: Thu, 5 Nov 2020 13:09:45 +0100
  38. Subject: [PATCH] hid/multitouch: Turn off Type Cover keyboard backlight when
  39. suspending
  40. The Type Cover for Microsoft Surface devices supports a special usb
  41. control request to disable or enable the built-in keyboard backlight.
  42. On Windows, this request happens when putting the device into suspend or
  43. resuming it, without it the backlight of the Type Cover will remain
  44. enabled for some time even though the computer is suspended, which looks
  45. weird to the user.
  46. So add support for this special usb control request to hid-multitouch,
  47. which is the driver that's handling the Type Cover.
  48. The reason we have to use a pm_notifier for this instead of the usual
  49. suspend/resume methods is that those won't get called in case the usb
  50. device is already autosuspended.
  51. Also, if the device is autosuspended, we have to briefly autoresume it
  52. in order to send the request. Doing that should be fine, the usb-core
  53. driver does something similar during suspend inside choose_wakeup().
  54. To make sure we don't send that request to every device but only to
  55. devices which support it, add a new quirk
  56. MT_CLS_WIN_8_MS_SURFACE_TYPE_COVER to hid-multitouch. For now this quirk
  57. is only enabled for the usb id of the Surface Pro 2017 Type Cover, which
  58. is where I confirmed that it's working.
  59. Patchset: surface-typecover
  60. ---
  61. drivers/hid/hid-multitouch.c | 100 ++++++++++++++++++++++++++++++++++-
  62. 1 file changed, 98 insertions(+), 2 deletions(-)
  63. diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
  64. index fd5b0637dad6..0f49d8fa6333 100644
  65. --- a/drivers/hid/hid-multitouch.c
  66. +++ b/drivers/hid/hid-multitouch.c
  67. @@ -34,7 +34,10 @@
  68. #include <linux/device.h>
  69. #include <linux/hid.h>
  70. #include <linux/module.h>
  71. +#include <linux/pm_runtime.h>
  72. #include <linux/slab.h>
  73. +#include <linux/suspend.h>
  74. +#include <linux/usb.h>
  75. #include <linux/input/mt.h>
  76. #include <linux/jiffies.h>
  77. #include <linux/string.h>
  78. @@ -47,6 +50,7 @@ MODULE_DESCRIPTION("HID multitouch panels");
  79. MODULE_LICENSE("GPL");
  80. #include "hid-ids.h"
  81. +#include "usbhid/usbhid.h"
  82. /* quirks to control the device */
  83. #define MT_QUIRK_NOT_SEEN_MEANS_UP BIT(0)
  84. @@ -72,12 +76,15 @@ MODULE_LICENSE("GPL");
  85. #define MT_QUIRK_FORCE_MULTI_INPUT BIT(20)
  86. #define MT_QUIRK_DISABLE_WAKEUP BIT(21)
  87. #define MT_QUIRK_ORIENTATION_INVERT BIT(22)
  88. +#define MT_QUIRK_HAS_TYPE_COVER_BACKLIGHT BIT(23)
  89. #define MT_INPUTMODE_TOUCHSCREEN 0x02
  90. #define MT_INPUTMODE_TOUCHPAD 0x03
  91. #define MT_BUTTONTYPE_CLICKPAD 0
  92. +#define MS_TYPE_COVER_FEATURE_REPORT_USAGE 0xff050086
  93. +
  94. enum latency_mode {
  95. HID_LATENCY_NORMAL = 0,
  96. HID_LATENCY_HIGH = 1,
  97. @@ -169,6 +176,8 @@ struct mt_device {
  98. struct list_head applications;
  99. struct list_head reports;
  100. +
  101. + struct notifier_block pm_notifier;
  102. };
  103. static void mt_post_parse_default_settings(struct mt_device *td,
  104. @@ -213,6 +222,7 @@ static void mt_post_parse(struct mt_device *td, struct mt_application *app);
  105. #define MT_CLS_GOOGLE 0x0111
  106. #define MT_CLS_RAZER_BLADE_STEALTH 0x0112
  107. #define MT_CLS_SMART_TECH 0x0113
  108. +#define MT_CLS_WIN_8_MS_SURFACE_TYPE_COVER 0x0114
  109. #define MT_DEFAULT_MAXCONTACT 10
  110. #define MT_MAX_MAXCONTACT 250
  111. @@ -397,6 +407,16 @@ static const struct mt_class mt_classes[] = {
  112. MT_QUIRK_CONTACT_CNT_ACCURATE |
  113. MT_QUIRK_SEPARATE_APP_REPORT,
  114. },
  115. + { .name = MT_CLS_WIN_8_MS_SURFACE_TYPE_COVER,
  116. + .quirks = MT_QUIRK_HAS_TYPE_COVER_BACKLIGHT |
  117. + MT_QUIRK_ALWAYS_VALID |
  118. + MT_QUIRK_IGNORE_DUPLICATES |
  119. + MT_QUIRK_HOVERING |
  120. + MT_QUIRK_CONTACT_CNT_ACCURATE |
  121. + MT_QUIRK_STICKY_FINGERS |
  122. + MT_QUIRK_WIN8_PTP_BUTTONS,
  123. + .export_all_inputs = true
  124. + },
  125. { }
  126. };
  127. @@ -1721,6 +1741,69 @@ static void mt_expired_timeout(struct timer_list *t)
  128. clear_bit_unlock(MT_IO_FLAGS_RUNNING, &td->mt_io_flags);
  129. }
  130. +static void get_type_cover_backlight_field(struct hid_device *hdev,
  131. + struct hid_field **field)
  132. +{
  133. + struct hid_report_enum *rep_enum;
  134. + struct hid_report *rep;
  135. + struct hid_field *cur_field;
  136. + int i, j;
  137. +
  138. + rep_enum = &hdev->report_enum[HID_FEATURE_REPORT];
  139. + list_for_each_entry(rep, &rep_enum->report_list, list) {
  140. + for (i = 0; i < rep->maxfield; i++) {
  141. + cur_field = rep->field[i];
  142. +
  143. + for (j = 0; j < cur_field->maxusage; j++) {
  144. + if (cur_field->usage[j].hid
  145. + == MS_TYPE_COVER_FEATURE_REPORT_USAGE) {
  146. + *field = cur_field;
  147. + return;
  148. + }
  149. + }
  150. + }
  151. + }
  152. +}
  153. +
  154. +static void update_keyboard_backlight(struct hid_device *hdev, bool enabled)
  155. +{
  156. + struct usb_device *udev = hid_to_usb_dev(hdev);
  157. + struct hid_field *field = NULL;
  158. +
  159. + /* Wake up the device in case it's already suspended */
  160. + pm_runtime_get_sync(&udev->dev);
  161. +
  162. + get_type_cover_backlight_field(hdev, &field);
  163. + if (!field) {
  164. + hid_err(hdev, "couldn't find backlight field\n");
  165. + goto out;
  166. + }
  167. +
  168. + field->value[field->index] = enabled ? 0x01ff00ff : 0x00ff00ff;
  169. + hid_hw_request(hdev, field->report, HID_REQ_SET_REPORT);
  170. +
  171. +out:
  172. + pm_runtime_put_sync(&udev->dev);
  173. +}
  174. +
  175. +static int mt_pm_notifier(struct notifier_block *notifier,
  176. + unsigned long pm_event,
  177. + void *unused)
  178. +{
  179. + struct mt_device *td =
  180. + container_of(notifier, struct mt_device, pm_notifier);
  181. + struct hid_device *hdev = td->hdev;
  182. +
  183. + if (td->mtclass.quirks & MT_QUIRK_HAS_TYPE_COVER_BACKLIGHT) {
  184. + if (pm_event == PM_SUSPEND_PREPARE)
  185. + update_keyboard_backlight(hdev, 0);
  186. + else if (pm_event == PM_POST_SUSPEND)
  187. + update_keyboard_backlight(hdev, 1);
  188. + }
  189. +
  190. + return NOTIFY_DONE;
  191. +}
  192. +
  193. static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
  194. {
  195. int ret, i;
  196. @@ -1744,6 +1827,9 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
  197. td->inputmode_value = MT_INPUTMODE_TOUCHSCREEN;
  198. hid_set_drvdata(hdev, td);
  199. + td->pm_notifier.notifier_call = mt_pm_notifier;
  200. + register_pm_notifier(&td->pm_notifier);
  201. +
  202. INIT_LIST_HEAD(&td->applications);
  203. INIT_LIST_HEAD(&td->reports);
  204. @@ -1782,15 +1868,19 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
  205. timer_setup(&td->release_timer, mt_expired_timeout, 0);
  206. ret = hid_parse(hdev);
  207. - if (ret != 0)
  208. + if (ret != 0) {
  209. + unregister_pm_notifier(&td->pm_notifier);
  210. return ret;
  211. + }
  212. if (mtclass->quirks & MT_QUIRK_FIX_CONST_CONTACT_ID)
  213. mt_fix_const_fields(hdev, HID_DG_CONTACTID);
  214. ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
  215. - if (ret)
  216. + if (ret) {
  217. + unregister_pm_notifier(&td->pm_notifier);
  218. return ret;
  219. + }
  220. ret = sysfs_create_group(&hdev->dev.kobj, &mt_attribute_group);
  221. if (ret)
  222. @@ -1840,6 +1930,7 @@ static void mt_remove(struct hid_device *hdev)
  223. {
  224. struct mt_device *td = hid_get_drvdata(hdev);
  225. + unregister_pm_notifier(&td->pm_notifier);
  226. del_timer_sync(&td->release_timer);
  227. sysfs_remove_group(&hdev->dev.kobj, &mt_attribute_group);
  228. @@ -2226,6 +2317,11 @@ static const struct hid_device_id mt_devices[] = {
  229. MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
  230. USB_DEVICE_ID_XIROKU_CSR2) },
  231. + /* Microsoft Surface type cover */
  232. + { .driver_data = MT_CLS_WIN_8_MS_SURFACE_TYPE_COVER,
  233. + HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY,
  234. + USB_VENDOR_ID_MICROSOFT, 0x09c0) },
  235. +
  236. /* Google MT devices */
  237. { .driver_data = MT_CLS_GOOGLE,
  238. HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY, USB_VENDOR_ID_GOOGLE,
  239. --
  240. 2.43.0
  241. From 97419c9be08b7b3e4311aa989fa8f91d0549a469 Mon Sep 17 00:00:00 2001
  242. From: PJungkamp <p.jungkamp@gmail.com>
  243. Date: Fri, 25 Feb 2022 12:04:25 +0100
  244. Subject: [PATCH] hid/multitouch: Add support for surface pro type cover tablet
  245. switch
  246. The Surface Pro Type Cover has several non standard HID usages in it's
  247. hid report descriptor.
  248. I noticed that, upon folding the typecover back, a vendor specific range
  249. of 4 32 bit integer hid usages is transmitted.
  250. Only the first byte of the message seems to convey reliable information
  251. about the keyboard state.
  252. 0x22 => Normal (keys enabled)
  253. 0x33 => Folded back (keys disabled)
  254. 0x53 => Rotated left/right side up (keys disabled)
  255. 0x13 => Cover closed (keys disabled)
  256. 0x43 => Folded back and Tablet upside down (keys disabled)
  257. This list may not be exhaustive.
  258. The tablet mode switch will be disabled for a value of 0x22 and enabled
  259. on any other value.
  260. Patchset: surface-typecover
  261. ---
  262. drivers/hid/hid-multitouch.c | 148 +++++++++++++++++++++++++++++------
  263. 1 file changed, 122 insertions(+), 26 deletions(-)
  264. diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
  265. index 0f49d8fa6333..1fad1199775b 100644
  266. --- a/drivers/hid/hid-multitouch.c
  267. +++ b/drivers/hid/hid-multitouch.c
  268. @@ -77,6 +77,7 @@ MODULE_LICENSE("GPL");
  269. #define MT_QUIRK_DISABLE_WAKEUP BIT(21)
  270. #define MT_QUIRK_ORIENTATION_INVERT BIT(22)
  271. #define MT_QUIRK_HAS_TYPE_COVER_BACKLIGHT BIT(23)
  272. +#define MT_QUIRK_HAS_TYPE_COVER_TABLET_MODE_SWITCH BIT(24)
  273. #define MT_INPUTMODE_TOUCHSCREEN 0x02
  274. #define MT_INPUTMODE_TOUCHPAD 0x03
  275. @@ -84,6 +85,8 @@ MODULE_LICENSE("GPL");
  276. #define MT_BUTTONTYPE_CLICKPAD 0
  277. #define MS_TYPE_COVER_FEATURE_REPORT_USAGE 0xff050086
  278. +#define MS_TYPE_COVER_TABLET_MODE_SWITCH_USAGE 0xff050072
  279. +#define MS_TYPE_COVER_APPLICATION 0xff050050
  280. enum latency_mode {
  281. HID_LATENCY_NORMAL = 0,
  282. @@ -409,6 +412,7 @@ static const struct mt_class mt_classes[] = {
  283. },
  284. { .name = MT_CLS_WIN_8_MS_SURFACE_TYPE_COVER,
  285. .quirks = MT_QUIRK_HAS_TYPE_COVER_BACKLIGHT |
  286. + MT_QUIRK_HAS_TYPE_COVER_TABLET_MODE_SWITCH |
  287. MT_QUIRK_ALWAYS_VALID |
  288. MT_QUIRK_IGNORE_DUPLICATES |
  289. MT_QUIRK_HOVERING |
  290. @@ -1390,6 +1394,9 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
  291. field->application != HID_CP_CONSUMER_CONTROL &&
  292. field->application != HID_GD_WIRELESS_RADIO_CTLS &&
  293. field->application != HID_GD_SYSTEM_MULTIAXIS &&
  294. + !(field->application == MS_TYPE_COVER_APPLICATION &&
  295. + application->quirks & MT_QUIRK_HAS_TYPE_COVER_TABLET_MODE_SWITCH &&
  296. + usage->hid == MS_TYPE_COVER_TABLET_MODE_SWITCH_USAGE) &&
  297. !(field->application == HID_VD_ASUS_CUSTOM_MEDIA_KEYS &&
  298. application->quirks & MT_QUIRK_ASUS_CUSTOM_UP))
  299. return -1;
  300. @@ -1417,6 +1424,21 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
  301. return 1;
  302. }
  303. + /*
  304. + * The Microsoft Surface Pro Typecover has a non-standard HID
  305. + * tablet mode switch on a vendor specific usage page with vendor
  306. + * specific usage.
  307. + */
  308. + if (field->application == MS_TYPE_COVER_APPLICATION &&
  309. + application->quirks & MT_QUIRK_HAS_TYPE_COVER_TABLET_MODE_SWITCH &&
  310. + usage->hid == MS_TYPE_COVER_TABLET_MODE_SWITCH_USAGE) {
  311. + usage->type = EV_SW;
  312. + usage->code = SW_TABLET_MODE;
  313. + *max = SW_MAX;
  314. + *bit = hi->input->swbit;
  315. + return 1;
  316. + }
  317. +
  318. if (rdata->is_mt_collection)
  319. return mt_touch_input_mapping(hdev, hi, field, usage, bit, max,
  320. application);
  321. @@ -1438,6 +1460,7 @@ static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi,
  322. {
  323. struct mt_device *td = hid_get_drvdata(hdev);
  324. struct mt_report_data *rdata;
  325. + struct input_dev *input;
  326. rdata = mt_find_report_data(td, field->report);
  327. if (rdata && rdata->is_mt_collection) {
  328. @@ -1445,6 +1468,19 @@ static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi,
  329. return -1;
  330. }
  331. + /*
  332. + * We own an input device which acts as a tablet mode switch for
  333. + * the Surface Pro Typecover.
  334. + */
  335. + if (field->application == MS_TYPE_COVER_APPLICATION &&
  336. + rdata->application->quirks & MT_QUIRK_HAS_TYPE_COVER_TABLET_MODE_SWITCH &&
  337. + usage->hid == MS_TYPE_COVER_TABLET_MODE_SWITCH_USAGE) {
  338. + input = hi->input;
  339. + input_set_capability(input, EV_SW, SW_TABLET_MODE);
  340. + input_report_switch(input, SW_TABLET_MODE, 0);
  341. + return -1;
  342. + }
  343. +
  344. /* let hid-core decide for the others */
  345. return 0;
  346. }
  347. @@ -1454,11 +1490,21 @@ static int mt_event(struct hid_device *hid, struct hid_field *field,
  348. {
  349. struct mt_device *td = hid_get_drvdata(hid);
  350. struct mt_report_data *rdata;
  351. + struct input_dev *input;
  352. rdata = mt_find_report_data(td, field->report);
  353. if (rdata && rdata->is_mt_collection)
  354. return mt_touch_event(hid, field, usage, value);
  355. + if (field->application == MS_TYPE_COVER_APPLICATION &&
  356. + rdata->application->quirks & MT_QUIRK_HAS_TYPE_COVER_TABLET_MODE_SWITCH &&
  357. + usage->hid == MS_TYPE_COVER_TABLET_MODE_SWITCH_USAGE) {
  358. + input = field->hidinput->input;
  359. + input_report_switch(input, SW_TABLET_MODE, (value & 0xFF) != 0x22);
  360. + input_sync(input);
  361. + return 1;
  362. + }
  363. +
  364. return 0;
  365. }
  366. @@ -1611,6 +1657,42 @@ static void mt_post_parse(struct mt_device *td, struct mt_application *app)
  367. app->quirks &= ~MT_QUIRK_CONTACT_CNT_ACCURATE;
  368. }
  369. +static int get_type_cover_field(struct hid_report_enum *rep_enum,
  370. + struct hid_field **field, int usage)
  371. +{
  372. + struct hid_report *rep;
  373. + struct hid_field *cur_field;
  374. + int i, j;
  375. +
  376. + list_for_each_entry(rep, &rep_enum->report_list, list) {
  377. + for (i = 0; i < rep->maxfield; i++) {
  378. + cur_field = rep->field[i];
  379. + if (cur_field->application != MS_TYPE_COVER_APPLICATION)
  380. + continue;
  381. + for (j = 0; j < cur_field->maxusage; j++) {
  382. + if (cur_field->usage[j].hid == usage) {
  383. + *field = cur_field;
  384. + return true;
  385. + }
  386. + }
  387. + }
  388. + }
  389. + return false;
  390. +}
  391. +
  392. +static void request_type_cover_tablet_mode_switch(struct hid_device *hdev)
  393. +{
  394. + struct hid_field *field;
  395. +
  396. + if (get_type_cover_field(&hdev->report_enum[HID_INPUT_REPORT],
  397. + &field,
  398. + MS_TYPE_COVER_TABLET_MODE_SWITCH_USAGE)) {
  399. + hid_hw_request(hdev, field->report, HID_REQ_GET_REPORT);
  400. + } else {
  401. + hid_err(hdev, "couldn't find tablet mode field\n");
  402. + }
  403. +}
  404. +
  405. static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
  406. {
  407. struct mt_device *td = hid_get_drvdata(hdev);
  408. @@ -1659,6 +1741,13 @@ static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
  409. /* force BTN_STYLUS to allow tablet matching in udev */
  410. __set_bit(BTN_STYLUS, hi->input->keybit);
  411. break;
  412. + case MS_TYPE_COVER_APPLICATION:
  413. + if (td->mtclass.quirks & MT_QUIRK_HAS_TYPE_COVER_TABLET_MODE_SWITCH) {
  414. + suffix = "Tablet Mode Switch";
  415. + request_type_cover_tablet_mode_switch(hdev);
  416. + break;
  417. + }
  418. + fallthrough;
  419. default:
  420. suffix = "UNKNOWN";
  421. break;
  422. @@ -1741,30 +1830,6 @@ static void mt_expired_timeout(struct timer_list *t)
  423. clear_bit_unlock(MT_IO_FLAGS_RUNNING, &td->mt_io_flags);
  424. }
  425. -static void get_type_cover_backlight_field(struct hid_device *hdev,
  426. - struct hid_field **field)
  427. -{
  428. - struct hid_report_enum *rep_enum;
  429. - struct hid_report *rep;
  430. - struct hid_field *cur_field;
  431. - int i, j;
  432. -
  433. - rep_enum = &hdev->report_enum[HID_FEATURE_REPORT];
  434. - list_for_each_entry(rep, &rep_enum->report_list, list) {
  435. - for (i = 0; i < rep->maxfield; i++) {
  436. - cur_field = rep->field[i];
  437. -
  438. - for (j = 0; j < cur_field->maxusage; j++) {
  439. - if (cur_field->usage[j].hid
  440. - == MS_TYPE_COVER_FEATURE_REPORT_USAGE) {
  441. - *field = cur_field;
  442. - return;
  443. - }
  444. - }
  445. - }
  446. - }
  447. -}
  448. -
  449. static void update_keyboard_backlight(struct hid_device *hdev, bool enabled)
  450. {
  451. struct usb_device *udev = hid_to_usb_dev(hdev);
  452. @@ -1773,8 +1838,9 @@ static void update_keyboard_backlight(struct hid_device *hdev, bool enabled)
  453. /* Wake up the device in case it's already suspended */
  454. pm_runtime_get_sync(&udev->dev);
  455. - get_type_cover_backlight_field(hdev, &field);
  456. - if (!field) {
  457. + if (!get_type_cover_field(&hdev->report_enum[HID_FEATURE_REPORT],
  458. + &field,
  459. + MS_TYPE_COVER_FEATURE_REPORT_USAGE)) {
  460. hid_err(hdev, "couldn't find backlight field\n");
  461. goto out;
  462. }
  463. @@ -1908,13 +1974,24 @@ static int mt_suspend(struct hid_device *hdev, pm_message_t state)
  464. static int mt_reset_resume(struct hid_device *hdev)
  465. {
  466. + struct mt_device *td = hid_get_drvdata(hdev);
  467. +
  468. mt_release_contacts(hdev);
  469. mt_set_modes(hdev, HID_LATENCY_NORMAL, true, true);
  470. +
  471. + /* Request an update on the typecover folding state on resume
  472. + * after reset.
  473. + */
  474. + if (td->mtclass.quirks & MT_QUIRK_HAS_TYPE_COVER_TABLET_MODE_SWITCH)
  475. + request_type_cover_tablet_mode_switch(hdev);
  476. +
  477. return 0;
  478. }
  479. static int mt_resume(struct hid_device *hdev)
  480. {
  481. + struct mt_device *td = hid_get_drvdata(hdev);
  482. +
  483. /* Some Elan legacy devices require SET_IDLE to be set on resume.
  484. * It should be safe to send it to other devices too.
  485. * Tested on 3M, Stantum, Cypress, Zytronic, eGalax, and Elan panels. */
  486. @@ -1923,12 +2000,31 @@ static int mt_resume(struct hid_device *hdev)
  487. mt_set_modes(hdev, HID_LATENCY_NORMAL, true, true);
  488. + /* Request an update on the typecover folding state on resume. */
  489. + if (td->mtclass.quirks & MT_QUIRK_HAS_TYPE_COVER_TABLET_MODE_SWITCH)
  490. + request_type_cover_tablet_mode_switch(hdev);
  491. +
  492. return 0;
  493. }
  494. static void mt_remove(struct hid_device *hdev)
  495. {
  496. struct mt_device *td = hid_get_drvdata(hdev);
  497. + struct hid_field *field;
  498. + struct input_dev *input;
  499. +
  500. + /* Reset tablet mode switch on disconnect. */
  501. + if (td->mtclass.quirks & MT_QUIRK_HAS_TYPE_COVER_TABLET_MODE_SWITCH) {
  502. + if (get_type_cover_field(&hdev->report_enum[HID_INPUT_REPORT],
  503. + &field,
  504. + MS_TYPE_COVER_TABLET_MODE_SWITCH_USAGE)) {
  505. + input = field->hidinput->input;
  506. + input_report_switch(input, SW_TABLET_MODE, 0);
  507. + input_sync(input);
  508. + } else {
  509. + hid_err(hdev, "couldn't find tablet mode field\n");
  510. + }
  511. + }
  512. unregister_pm_notifier(&td->pm_notifier);
  513. del_timer_sync(&td->release_timer);
  514. --
  515. 2.43.0