xref: /linux/drivers/hid/hid-msi.c (revision a9517958e828429ffd88558a8dae80f49f8cfbea)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  *  HID driver for MSI Claw Handheld PC gamepads.
4  *
5  *  Provides configuration support for the MSI Claw series of handheld PC
6  *  gamepads. Multiple iterations of the device firmware has led to some
7  *  quirks for how certain attributes are handled. The original firmware
8  *  did not support remapping of the M1 (right) and M2 (left) rear paddles.
9  *  Additionally, the MCU RAM address for writing configuration data has
10  *  changed twice. Checks are done during probe to enumerate these variances.
11  *
12  *  Copyright (c) 2026 Zhouwang Huang <honjow311@gmail.com>
13  *  Copyright (c) 2026 Denis Benato <denis.benato@linux.dev>
14  *  Copyright (c) 2026 Valve Corporation
15  */
16 
17 #include <linux/array_size.h>
18 #include <linux/cleanup.h>
19 #include <linux/completion.h>
20 #include <linux/container_of.h>
21 #include <linux/delay.h>
22 #include <linux/device.h>
23 #include <linux/hid.h>
24 #include <linux/kobject.h>
25 #include <linux/leds.h>
26 #include <linux/module.h>
27 #include <linux/mutex.h>
28 #include <linux/pm.h>
29 #include <linux/spinlock.h>
30 #include <linux/sysfs.h>
31 #include <linux/types.h>
32 #include <linux/unaligned.h>
33 #include <linux/usb.h>
34 #include <linux/workqueue.h>
35 
36 #include "hid-ids.h"
37 
38 #define CLAW_OUTPUT_REPORT_ID	0x0f
39 #define CLAW_INPUT_REPORT_ID	0x10
40 
41 #define CLAW_PACKET_SIZE	64
42 
43 #define CLAW_DINPUT_CFG_INTF_IN	0x82
44 #define CLAW_XINPUT_CFG_INTF_IN	0x83
45 
46 enum claw_command_index {
47 	CLAW_COMMAND_TYPE_NONE =			0x00,
48 	CLAW_COMMAND_TYPE_READ_PROFILE =		0x04,
49 	CLAW_COMMAND_TYPE_READ_PROFILE_ACK =		0x05,
50 	CLAW_COMMAND_TYPE_ACK =				0x06,
51 	CLAW_COMMAND_TYPE_WRITE_PROFILE_DATA =		0x21,
52 	CLAW_COMMAND_TYPE_SYNC_TO_ROM =			0x22,
53 	CLAW_COMMAND_TYPE_SWITCH_MODE =			0x24,
54 	CLAW_COMMAND_TYPE_READ_GAMEPAD_MODE =		0x26,
55 	CLAW_COMMAND_TYPE_GAMEPAD_MODE_ACK =		0x27,
56 	CLAW_COMMAND_TYPE_RESET_DEVICE =		0x28,
57 };
58 
59 enum claw_gamepad_mode_index {
60 	CLAW_GAMEPAD_MODE_XINPUT =	0x01,
61 	CLAW_GAMEPAD_MODE_DINPUT =	0x02,
62 	CLAW_GAMEPAD_MODE_DESKTOP =	0x04,
63 };
64 
65 static const char * const claw_gamepad_mode_text[] = {
66 	[CLAW_GAMEPAD_MODE_XINPUT] =	"xinput",
67 	[CLAW_GAMEPAD_MODE_DINPUT] =	"dinput",
68 	[CLAW_GAMEPAD_MODE_DESKTOP] =	"desktop",
69 };
70 
71 enum claw_mkeys_function_index {
72 	CLAW_MKEY_FUNCTION_MACRO,
73 	CLAW_MKEY_FUNCTION_DISABLED,
74 	CLAW_MKEY_FUNCTION_COMBO,
75 };
76 
77 enum claw_mode_field {
78 	CLAW_FIELD_GAMEPAD_MODE,
79 	CLAW_FIELD_MKEYS_FUNCTION,
80 };
81 
82 static const char * const claw_mkeys_function_text[] = {
83 	[CLAW_MKEY_FUNCTION_MACRO] =	"macro",
84 	[CLAW_MKEY_FUNCTION_DISABLED] =	"disabled",
85 	[CLAW_MKEY_FUNCTION_COMBO] =	"combination",
86 };
87 
88 struct claw_command_report {
89 	u8 report_id;
90 	u8 padding[2];
91 	u8 header_tail;
92 	u8 cmd;
93 	u8 data[59];
94 } __packed;
95 
96 struct claw_drvdata {
97 	/* MCU General Variables */
98 	struct completion orphan_ack_complete;
99 	struct completion send_cmd_complete;
100 	struct delayed_work cfg_resume;
101 	struct delayed_work cfg_setup;
102 	spinlock_t registration_lock; /* Lock for registration read/write */
103 	struct hid_device *hdev;
104 	bool orphan_ack_pending;
105 	struct mutex cfg_mutex; /* mutex for synchronous data */
106 	spinlock_t cmd_lock; /* Lock for cmd data read/write */
107 	u8 waiting_cmd;
108 	int cmd_status;
109 	u8 ep;
110 
111 	/* Gamepad Variables */
112 	enum claw_mkeys_function_index mkeys_function;
113 	enum claw_gamepad_mode_index gamepad_mode;
114 	spinlock_t mode_lock; /* Lock for mode data read/write */
115 	bool gp_registered;
116 };
117 
118 static int get_endpoint_address(struct hid_device *hdev)
119 {
120 	struct usb_host_endpoint *ep;
121 	struct usb_interface *intf;
122 
123 	intf = to_usb_interface(hdev->dev.parent);
124 	ep = intf->cur_altsetting->endpoint;
125 	if (ep)
126 		return ep->desc.bEndpointAddress;
127 
128 	return -ENODEV;
129 }
130 
131 static int claw_gamepad_mode_event(struct claw_drvdata *drvdata,
132 				   struct claw_command_report *cmd_rep)
133 {
134 	if (cmd_rep->data[0] >= ARRAY_SIZE(claw_gamepad_mode_text) ||
135 	    !claw_gamepad_mode_text[cmd_rep->data[0]] ||
136 	    cmd_rep->data[1] >= ARRAY_SIZE(claw_mkeys_function_text))
137 		return -EINVAL;
138 
139 	scoped_guard(spinlock_irqsave, &drvdata->mode_lock) {
140 		drvdata->gamepad_mode = cmd_rep->data[0];
141 		drvdata->mkeys_function = cmd_rep->data[1];
142 	}
143 
144 	return 0;
145 }
146 
147 static int claw_raw_event(struct claw_drvdata *drvdata, struct hid_report *report,
148 			  u8 *data, int size)
149 {
150 	struct claw_command_report *cmd_rep;
151 	int ret = 0;
152 
153 	if (size != CLAW_PACKET_SIZE)
154 		return 0;
155 
156 	cmd_rep = (struct claw_command_report *)data;
157 
158 	if (cmd_rep->report_id != CLAW_INPUT_REPORT_ID || cmd_rep->header_tail != 0x3c)
159 		return 0;
160 
161 	dev_dbg(&drvdata->hdev->dev, "Rx data as raw input report: [%*ph]\n",
162 		CLAW_PACKET_SIZE, data);
163 
164 	guard(spinlock_irqsave)(&drvdata->cmd_lock);
165 	switch (cmd_rep->cmd) {
166 	case CLAW_COMMAND_TYPE_GAMEPAD_MODE_ACK:
167 		ret = claw_gamepad_mode_event(drvdata, cmd_rep);
168 		if (drvdata->waiting_cmd == CLAW_COMMAND_TYPE_READ_GAMEPAD_MODE) {
169 			drvdata->cmd_status = ret;
170 			complete(&drvdata->send_cmd_complete);
171 		}
172 
173 		break;
174 	case CLAW_COMMAND_TYPE_ACK:
175 		if (drvdata->orphan_ack_pending) {
176 			drvdata->orphan_ack_pending = false;
177 			complete(&drvdata->orphan_ack_complete);
178 			break;
179 		}
180 
181 		if (drvdata->waiting_cmd == CLAW_COMMAND_TYPE_NONE) {
182 			dev_warn(&drvdata->hdev->dev, "Got unexpected ACK from MCU, ignoring\n");
183 			break;
184 		}
185 
186 		drvdata->cmd_status = 0;
187 		complete(&drvdata->send_cmd_complete);
188 
189 		dev_dbg(&drvdata->hdev->dev, "Waiting CMD: %x\n", drvdata->waiting_cmd);
190 
191 		break;
192 	default:
193 		dev_dbg(&drvdata->hdev->dev, "Unknown command: %x\n", cmd_rep->cmd);
194 		return 0;
195 	}
196 
197 	return ret;
198 }
199 
200 static int msi_raw_event(struct hid_device *hdev, struct hid_report *report,
201 			 u8 *data, int size)
202 {
203 	struct claw_drvdata *drvdata = hid_get_drvdata(hdev);
204 
205 	if (!drvdata || (drvdata->ep != CLAW_XINPUT_CFG_INTF_IN &&
206 			 drvdata->ep != CLAW_DINPUT_CFG_INTF_IN))
207 		return 0;
208 
209 	return claw_raw_event(drvdata, report, data, size);
210 }
211 
212 /* Caller must hold drvdata->cfg_mutex. */
213 static int __claw_hw_output_report(struct hid_device *hdev, u8 index, u8 *data,
214 				   size_t len, unsigned int timeout)
215 {
216 	unsigned char *dmabuf __free(kfree) = NULL;
217 	u8 header[] = { CLAW_OUTPUT_REPORT_ID, 0, 0, 0x3c, index };
218 	struct claw_drvdata *drvdata = hid_get_drvdata(hdev);
219 	size_t header_size = ARRAY_SIZE(header);
220 	bool orphaned;
221 	int ret;
222 
223 	lockdep_assert_held(&drvdata->cfg_mutex);
224 
225 	/* If expecting an orphan ack, hold next event until MCU has time to clear it */
226 	scoped_guard(spinlock_irqsave, &drvdata->cmd_lock)
227 		orphaned = drvdata->orphan_ack_pending;
228 
229 	if (orphaned) {
230 		wait_for_completion_timeout(&drvdata->orphan_ack_complete, msecs_to_jiffies(25));
231 		scoped_guard(spinlock_irqsave, &drvdata->cmd_lock)
232 			drvdata->orphan_ack_pending = false;
233 	}
234 
235 	if (header_size + len > CLAW_PACKET_SIZE)
236 		return -EINVAL;
237 
238 	/* We can't use a devm_alloc reusable buffer without side effects during suspend */
239 	dmabuf = kzalloc(CLAW_PACKET_SIZE, GFP_KERNEL);
240 	if (!dmabuf)
241 		return -ENOMEM;
242 
243 	memcpy(dmabuf, header, header_size);
244 	if (data && len)
245 		memcpy(dmabuf + header_size, data, len);
246 
247 	reinit_completion(&drvdata->send_cmd_complete);
248 
249 	scoped_guard(spinlock_irqsave, &drvdata->cmd_lock) {
250 		if (timeout) {
251 			drvdata->waiting_cmd = index;
252 			drvdata->cmd_status = -ETIMEDOUT;
253 		} else {
254 			reinit_completion(&drvdata->orphan_ack_complete);
255 			drvdata->waiting_cmd = CLAW_COMMAND_TYPE_NONE;
256 			drvdata->orphan_ack_pending = true;
257 		}
258 	}
259 
260 	dev_dbg(&hdev->dev, "Send data as raw output report: [%*ph]\n",
261 		CLAW_PACKET_SIZE, dmabuf);
262 
263 	ret = hid_hw_output_report(hdev, dmabuf, CLAW_PACKET_SIZE);
264 	if (ret < 0)
265 		goto err;
266 
267 	ret = ret == CLAW_PACKET_SIZE ? 0 : -EIO;
268 	if (ret)
269 		goto err;
270 
271 	if (timeout) {
272 		ret = wait_for_completion_interruptible_timeout(&drvdata->send_cmd_complete,
273 								msecs_to_jiffies(timeout));
274 
275 		dev_dbg(&hdev->dev, "Remaining timeout: %u\n", ret);
276 		ret = ret > 0 ? drvdata->cmd_status : ret ?: -EBUSY;
277 		if (ret)
278 			goto err;
279 	}
280 
281 	scoped_guard(spinlock_irqsave, &drvdata->cmd_lock)
282 		drvdata->waiting_cmd = CLAW_COMMAND_TYPE_NONE;
283 
284 	return ret;
285 
286 err:
287 	scoped_guard(spinlock_irqsave, &drvdata->cmd_lock) {
288 		drvdata->waiting_cmd = CLAW_COMMAND_TYPE_NONE;
289 		drvdata->orphan_ack_pending = false;
290 	}
291 	return ret;
292 }
293 
294 static int claw_hw_output_report(struct hid_device *hdev, u8 index, u8 *data,
295 				 size_t len, unsigned int timeout)
296 {
297 	struct claw_drvdata *drvdata = hid_get_drvdata(hdev);
298 
299 	guard(mutex)(&drvdata->cfg_mutex);
300 	return __claw_hw_output_report(hdev, index, data, len, timeout);
301 }
302 
303 static int claw_switch_mode(struct hid_device *hdev, enum claw_mode_field field, u8 val)
304 {
305 	struct claw_drvdata *drvdata = hid_get_drvdata(hdev);
306 	u8 data[2];
307 
308 	guard(mutex)(&drvdata->cfg_mutex);
309 
310 	scoped_guard(spinlock_irqsave, &drvdata->mode_lock) {
311 		switch (field) {
312 		case CLAW_FIELD_GAMEPAD_MODE:
313 			data[0] = val;
314 			data[1] = drvdata->mkeys_function;
315 			break;
316 		case CLAW_FIELD_MKEYS_FUNCTION:
317 			data[0] = drvdata->gamepad_mode;
318 			data[1] = val;
319 			break;
320 		}
321 	}
322 
323 	return __claw_hw_output_report(hdev, CLAW_COMMAND_TYPE_SWITCH_MODE, data,
324 				       ARRAY_SIZE(data), 0);
325 }
326 
327 static ssize_t gamepad_mode_store(struct device *dev, struct device_attribute *attr,
328 				  const char *buf, size_t count)
329 {
330 	struct hid_device *hdev = to_hid_device(dev);
331 	struct claw_drvdata *drvdata = hid_get_drvdata(hdev);
332 	int i, ret = -EINVAL;
333 
334 	scoped_guard(spinlock_irqsave, &drvdata->registration_lock) {
335 		/* Pairs with smp_store_release from cfg_setup_fn in system_wq context */
336 		if (!smp_load_acquire(&drvdata->gp_registered))
337 			return -ENODEV;
338 	}
339 
340 	for (i = 0; i < ARRAY_SIZE(claw_gamepad_mode_text); i++) {
341 		if (claw_gamepad_mode_text[i] && sysfs_streq(buf, claw_gamepad_mode_text[i])) {
342 			ret = i;
343 			break;
344 		}
345 	}
346 	if (ret < 0)
347 		return ret;
348 
349 	ret = claw_switch_mode(hdev, CLAW_FIELD_GAMEPAD_MODE, ret);
350 	if (ret)
351 		return ret;
352 
353 	return count;
354 }
355 
356 static ssize_t gamepad_mode_show(struct device *dev,
357 				 struct device_attribute *attr, char *buf)
358 {
359 	struct hid_device *hdev = to_hid_device(dev);
360 	struct claw_drvdata *drvdata = hid_get_drvdata(hdev);
361 	int ret, i;
362 
363 	scoped_guard(spinlock_irqsave, &drvdata->registration_lock) {
364 		/* Pairs with smp_store_release from cfg_setup_fn in system_wq context */
365 		if (!smp_load_acquire(&drvdata->gp_registered))
366 			return -ENODEV;
367 	}
368 
369 	ret = claw_hw_output_report(hdev, CLAW_COMMAND_TYPE_READ_GAMEPAD_MODE, NULL, 0, 25);
370 	if (ret)
371 		return ret;
372 
373 	scoped_guard(spinlock_irqsave, &drvdata->mode_lock)
374 		i = drvdata->gamepad_mode;
375 
376 	if (!claw_gamepad_mode_text[i] || claw_gamepad_mode_text[i][0] == '\0')
377 		return sysfs_emit(buf, "unsupported\n");
378 
379 	return sysfs_emit(buf, "%s\n", claw_gamepad_mode_text[i]);
380 }
381 static DEVICE_ATTR_RW(gamepad_mode);
382 
383 static ssize_t gamepad_mode_index_show(struct device *dev,
384 				       struct device_attribute *attr, char *buf)
385 {
386 	ssize_t count = 0;
387 	int i;
388 
389 	for (i = 0; i < ARRAY_SIZE(claw_gamepad_mode_text); i++) {
390 		if (!claw_gamepad_mode_text[i] || claw_gamepad_mode_text[i][0] == '\0')
391 			continue;
392 		count += sysfs_emit_at(buf, count, "%s ", claw_gamepad_mode_text[i]);
393 	}
394 
395 	if (count)
396 		buf[count - 1] = '\n';
397 
398 	return count;
399 }
400 static DEVICE_ATTR_RO(gamepad_mode_index);
401 
402 static ssize_t mkeys_function_store(struct device *dev, struct device_attribute *attr,
403 				    const char *buf, size_t count)
404 {
405 	struct hid_device *hdev = to_hid_device(dev);
406 	struct claw_drvdata *drvdata = hid_get_drvdata(hdev);
407 	int i, ret = -EINVAL;
408 
409 	scoped_guard(spinlock_irqsave, &drvdata->registration_lock) {
410 		/* Pairs with smp_store_release from cfg_setup_fn in system_wq context */
411 		if (!smp_load_acquire(&drvdata->gp_registered))
412 			return -ENODEV;
413 	}
414 
415 	for (i = 0; i < ARRAY_SIZE(claw_mkeys_function_text); i++) {
416 		if (claw_mkeys_function_text[i] && sysfs_streq(buf, claw_mkeys_function_text[i])) {
417 			ret = i;
418 			break;
419 		}
420 	}
421 	if (ret < 0)
422 		return ret;
423 
424 	ret = claw_switch_mode(hdev, CLAW_FIELD_MKEYS_FUNCTION, ret);
425 	if (ret)
426 		return ret;
427 
428 	return count;
429 }
430 
431 static ssize_t mkeys_function_show(struct device *dev, struct device_attribute *attr,
432 				   char *buf)
433 {
434 	struct hid_device *hdev = to_hid_device(dev);
435 	struct claw_drvdata *drvdata = hid_get_drvdata(hdev);
436 	int ret, i;
437 
438 	scoped_guard(spinlock_irqsave, &drvdata->registration_lock) {
439 		/* Pairs with smp_store_release from cfg_setup_fn in system_wq context */
440 		if (!smp_load_acquire(&drvdata->gp_registered))
441 			return -ENODEV;
442 	}
443 
444 	ret = claw_hw_output_report(hdev, CLAW_COMMAND_TYPE_READ_GAMEPAD_MODE, NULL, 0, 25);
445 	if (ret)
446 		return ret;
447 
448 	scoped_guard(spinlock_irqsave, &drvdata->mode_lock)
449 		i = drvdata->mkeys_function;
450 
451 	if (i >= ARRAY_SIZE(claw_mkeys_function_text))
452 		return sysfs_emit(buf, "unsupported\n");
453 
454 	return sysfs_emit(buf, "%s\n", claw_mkeys_function_text[i]);
455 }
456 static DEVICE_ATTR_RW(mkeys_function);
457 
458 static ssize_t mkeys_function_index_show(struct device *dev,
459 					 struct device_attribute *attr, char *buf)
460 {
461 	int i, count = 0;
462 
463 	for (i = 0; i < ARRAY_SIZE(claw_mkeys_function_text); i++)
464 		count += sysfs_emit_at(buf, count, "%s ", claw_mkeys_function_text[i]);
465 
466 	if (count)
467 		buf[count - 1] = '\n';
468 
469 	return count;
470 }
471 static DEVICE_ATTR_RO(mkeys_function_index);
472 
473 static ssize_t reset_store(struct device *dev, struct device_attribute *attr,
474 			   const char *buf, size_t count)
475 {
476 	struct hid_device *hdev = to_hid_device(dev);
477 	struct claw_drvdata *drvdata = hid_get_drvdata(hdev);
478 	bool val;
479 	int ret;
480 
481 	scoped_guard(spinlock_irqsave, &drvdata->registration_lock) {
482 		/* Pairs with smp_store_release from cfg_setup_fn in system_wq context */
483 		if (!smp_load_acquire(&drvdata->gp_registered))
484 			return -ENODEV;
485 	}
486 
487 	ret = kstrtobool(buf, &val);
488 	if (ret)
489 		return ret;
490 
491 	if (!val)
492 		return -EINVAL;
493 
494 	ret = claw_hw_output_report(hdev, CLAW_COMMAND_TYPE_RESET_DEVICE, NULL, 0, 0);
495 	if (ret)
496 		return ret;
497 
498 	return count;
499 }
500 static DEVICE_ATTR_WO(reset);
501 
502 static umode_t claw_gamepad_attr_is_visible(struct kobject *kobj, struct attribute *attr,
503 					    int n)
504 {
505 	struct hid_device *hdev = to_hid_device(kobj_to_dev(kobj));
506 	struct claw_drvdata *drvdata = hid_get_drvdata(hdev);
507 
508 	if (!drvdata) {
509 		dev_warn(&hdev->dev,
510 			 "Failed to get drvdata from kobj. Gamepad attributes are not available.\n");
511 		return 0;
512 	}
513 
514 	return attr->mode;
515 }
516 
517 static struct attribute *claw_gamepad_attrs[] = {
518 	&dev_attr_gamepad_mode.attr,
519 	&dev_attr_gamepad_mode_index.attr,
520 	&dev_attr_mkeys_function.attr,
521 	&dev_attr_mkeys_function_index.attr,
522 	&dev_attr_reset.attr,
523 	NULL,
524 };
525 
526 static const struct attribute_group claw_gamepad_attr_group = {
527 	.attrs = claw_gamepad_attrs,
528 	.is_visible = claw_gamepad_attr_is_visible,
529 };
530 
531 static void cfg_setup_fn(struct work_struct *work)
532 {
533 	struct delayed_work *dwork = container_of(work, struct delayed_work, work);
534 	struct claw_drvdata *drvdata = container_of(dwork, struct claw_drvdata, cfg_setup);
535 	int ret;
536 
537 	ret = claw_hw_output_report(drvdata->hdev, CLAW_COMMAND_TYPE_READ_GAMEPAD_MODE,
538 				    NULL, 0, 25);
539 	if (ret) {
540 		dev_err(&drvdata->hdev->dev,
541 			"Failed to setup device, can't read gamepad mode: %d\n", ret);
542 		return;
543 	}
544 
545 	/* Add sysfs attributes after we get the device state */
546 	ret = device_add_group(&drvdata->hdev->dev, &claw_gamepad_attr_group);
547 	if (ret) {
548 		dev_err(&drvdata->hdev->dev,
549 			"Failed to setup device, can't create gamepad attrs: %d\n", ret);
550 		return;
551 	}
552 	scoped_guard(spinlock_irqsave, &drvdata->registration_lock)
553 		/* Pairs with smp_load_acquire in attribute show/store functions */
554 		smp_store_release(&drvdata->gp_registered, true);
555 
556 	kobject_uevent(&drvdata->hdev->dev.kobj, KOBJ_CHANGE);
557 }
558 
559 static void cfg_resume_fn(struct work_struct *work)
560 {
561 	struct delayed_work *dwork = container_of(work, struct delayed_work, work);
562 	struct claw_drvdata *drvdata = container_of(dwork, struct claw_drvdata, cfg_resume);
563 
564 	guard(spinlock_irqsave)(&drvdata->registration_lock);
565 	/* Pairs with smp_store_release from cfg_setup_fn in system_wq context */
566 	if (!smp_load_acquire(&drvdata->gp_registered))
567 		schedule_delayed_work(&drvdata->cfg_setup, msecs_to_jiffies(500));
568 }
569 
570 static int claw_probe(struct hid_device *hdev, u8 ep)
571 {
572 	struct claw_drvdata *drvdata;
573 	int ret;
574 
575 	drvdata = devm_kzalloc(&hdev->dev, sizeof(*drvdata), GFP_KERNEL);
576 	if (!drvdata)
577 		return -ENOMEM;
578 
579 	drvdata->gamepad_mode = CLAW_GAMEPAD_MODE_XINPUT;
580 	drvdata->hdev = hdev;
581 	drvdata->ep = ep;
582 
583 	mutex_init(&drvdata->cfg_mutex);
584 	spin_lock_init(&drvdata->registration_lock);
585 	spin_lock_init(&drvdata->cmd_lock);
586 	spin_lock_init(&drvdata->mode_lock);
587 	init_completion(&drvdata->orphan_ack_complete);
588 	init_completion(&drvdata->send_cmd_complete);
589 	INIT_DELAYED_WORK(&drvdata->cfg_resume, &cfg_resume_fn);
590 	INIT_DELAYED_WORK(&drvdata->cfg_setup, &cfg_setup_fn);
591 
592 	/* For control interface: open the HID transport for sending commands. */
593 	ret = hid_hw_open(hdev);
594 	if (ret)
595 		return ret;
596 
597 	hid_set_drvdata(hdev, drvdata);
598 	schedule_delayed_work(&drvdata->cfg_setup, msecs_to_jiffies(500));
599 
600 	return 0;
601 }
602 
603 static int msi_probe(struct hid_device *hdev, const struct hid_device_id *id)
604 {
605 	int ret;
606 	u8 ep;
607 
608 	if (!hid_is_usb(hdev)) {
609 		ret = -ENODEV;
610 		goto err_probe;
611 	}
612 
613 	ret = hid_parse(hdev);
614 	if (ret)
615 		goto err_probe;
616 
617 	/* Set quirk to create separate input devices per HID application */
618 	hdev->quirks |= HID_QUIRK_INPUT_PER_APP | HID_QUIRK_MULTI_INPUT;
619 	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
620 	if (ret)
621 		goto err_probe;
622 
623 	/* For non-control interfaces (keyboard/mouse), allow userspace to grab the devices. */
624 	ret = get_endpoint_address(hdev);
625 	if (ret < 0)
626 		goto err_stop_hw;
627 
628 	ep = ret;
629 	if (ep == CLAW_XINPUT_CFG_INTF_IN || ep == CLAW_DINPUT_CFG_INTF_IN) {
630 		ret = claw_probe(hdev, ep);
631 		if (ret)
632 			goto err_stop_hw;
633 	}
634 
635 	return 0;
636 
637 err_stop_hw:
638 	hid_hw_stop(hdev);
639 err_probe:
640 	return dev_err_probe(&hdev->dev, ret, "Failed to init device\n");
641 }
642 
643 static void claw_remove(struct hid_device *hdev)
644 {
645 	struct claw_drvdata *drvdata = hid_get_drvdata(hdev);
646 	bool gp_registered;
647 
648 	if (!drvdata)
649 		return;
650 
651 	cancel_delayed_work_sync(&drvdata->cfg_resume);
652 	cancel_delayed_work_sync(&drvdata->cfg_setup);
653 
654 	scoped_guard(spinlock_irqsave, &drvdata->registration_lock) {
655 		/* Pairs with smp_store_release from cfg_setup_fn in system_wq context */
656 		gp_registered = smp_load_acquire(&drvdata->gp_registered);
657 		/* Pairs with smp_load_acquire in attribute show/store functions */
658 		smp_store_release(&drvdata->gp_registered, false);
659 	}
660 
661 	if (gp_registered)
662 		device_remove_group(&hdev->dev, &claw_gamepad_attr_group);
663 
664 	hid_hw_close(hdev);
665 }
666 
667 static void msi_remove(struct hid_device *hdev)
668 {
669 	int ret;
670 	u8 ep;
671 
672 	/* Safe assumption. SET_INTERFACE ioctl can't be used while driver is bound */
673 	ret = get_endpoint_address(hdev);
674 	if (ret <= 0)
675 		goto hw_stop;
676 
677 	ep = ret;
678 	if (ep == CLAW_XINPUT_CFG_INTF_IN || ep == CLAW_DINPUT_CFG_INTF_IN)
679 		claw_remove(hdev);
680 
681 hw_stop:
682 	hid_hw_stop(hdev);
683 }
684 
685 static int claw_resume(struct hid_device *hdev)
686 {
687 	struct claw_drvdata *drvdata = hid_get_drvdata(hdev);
688 
689 	if (!drvdata)
690 		return -ENODEV;
691 
692 	/* MCU can take up to 500ms to be ready after resume */
693 	schedule_delayed_work(&drvdata->cfg_resume, msecs_to_jiffies(500));
694 	return 0;
695 }
696 
697 static int msi_resume(struct hid_device *hdev)
698 {
699 	int ret;
700 	u8 ep;
701 
702 	/* Safe assumption. SET_INTERFACE ioctl can't be used while driver is bound */
703 	ret = get_endpoint_address(hdev);
704 	if (ret <= 0)
705 		return 0;
706 
707 	ep = ret;
708 	if (ep == CLAW_XINPUT_CFG_INTF_IN || ep == CLAW_DINPUT_CFG_INTF_IN)
709 		return claw_resume(hdev);
710 
711 	return 0;
712 }
713 
714 static int claw_suspend(struct hid_device *hdev)
715 {
716 	struct claw_drvdata *drvdata = hid_get_drvdata(hdev);
717 
718 	if (!drvdata)
719 		return -ENODEV;
720 
721 	cancel_delayed_work_sync(&drvdata->cfg_resume);
722 	cancel_delayed_work_sync(&drvdata->cfg_setup);
723 
724 	return 0;
725 }
726 
727 static int msi_suspend(struct hid_device *hdev, pm_message_t msg)
728 {
729 	int ret;
730 	u8 ep;
731 
732 	/* Safe assumption. SET_INTERFACE ioctl can't be used while driver is bound */
733 	ret = get_endpoint_address(hdev);
734 	if (ret <= 0)
735 		return 0;
736 
737 	ep = ret;
738 	if (ep == CLAW_XINPUT_CFG_INTF_IN || ep == CLAW_DINPUT_CFG_INTF_IN)
739 		return claw_suspend(hdev);
740 
741 	return 0;
742 }
743 
744 static const struct hid_device_id msi_devices[] = {
745 	{ HID_USB_DEVICE(USB_VENDOR_ID_MSI_2, USB_DEVICE_ID_MSI_CLAW_XINPUT) },
746 	{ HID_USB_DEVICE(USB_VENDOR_ID_MSI_2, USB_DEVICE_ID_MSI_CLAW_DINPUT) },
747 	{ HID_USB_DEVICE(USB_VENDOR_ID_MSI_2, USB_DEVICE_ID_MSI_CLAW_DESKTOP) },
748 	{ HID_USB_DEVICE(USB_VENDOR_ID_MSI_2, USB_DEVICE_ID_MSI_CLAW_BIOS) },
749 	{ }
750 };
751 MODULE_DEVICE_TABLE(hid, msi_devices);
752 
753 static struct hid_driver msi_driver = {
754 	.name		= "hid-msi",
755 	.id_table	= msi_devices,
756 	.raw_event	= msi_raw_event,
757 	.probe		= msi_probe,
758 	.remove		= msi_remove,
759 	.resume		= pm_ptr(msi_resume),
760 	.suspend	= pm_ptr(msi_suspend),
761 };
762 module_hid_driver(msi_driver);
763 
764 MODULE_LICENSE("GPL");
765 MODULE_AUTHOR("Denis Benato <denis.benato@linux.dev>");
766 MODULE_AUTHOR("Zhouwang Huang <honjow311@gmail.com>");
767 MODULE_AUTHOR("Derek J. Clark <derekjohn.clark@gmail.com>");
768 MODULE_DESCRIPTION("HID driver for MSI Claw Handheld PC gamepads");
769