xref: /linux/drivers/hid/hid-oxp.c (revision bba2c3615bd6cfee7456d1130f2e6b01b3f4e9ba)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  *  HID driver for OneXPlayer gamepad configuration devices.
4  *
5  *  Copyright (c) 2026 Valve Corporation
6  */
7 
8 #include <linux/array_size.h>
9 #include <linux/cleanup.h>
10 #include <linux/delay.h>
11 #include <linux/dev_printk.h>
12 #include <linux/device.h>
13 #include <linux/dmi.h>
14 #include <linux/hid.h>
15 #include <linux/jiffies.h>
16 #include <linux/kstrtox.h>
17 #include <linux/led-class-multicolor.h>
18 #include <linux/mutex.h>
19 #include <linux/sysfs.h>
20 #include <linux/types.h>
21 #include <linux/workqueue.h>
22 
23 #include "hid-ids.h"
24 
25 #define OXP_PACKET_SIZE 64
26 
27 #define GEN1_MESSAGE_ID	0xff
28 #define GEN2_MESSAGE_ID	0x3f
29 
30 #define GEN1_USAGE_PAGE	0xff01
31 #define GEN2_USAGE_PAGE	0xff00
32 
33 enum oxp_function_index {
34 	OXP_FID_GEN1_RGB_SET =		0x07,
35 	OXP_FID_GEN1_RGB_REPLY =	0x0f,
36 	OXP_FID_GEN2_TOGGLE_MODE =	0xb2,
37 	OXP_FID_GEN2_RUMBLE_SET =	0xb3,
38 	OXP_FID_GEN2_KEY_STATE =	0xb4,
39 	OXP_FID_GEN2_STATUS_EVENT =	0xb8,
40 };
41 
42 #define OXP_MAPPING_GAMEPAD	0x01
43 #define OXP_MAPPING_KEYBOARD	0x02
44 
45 struct oxp_button_data {
46 	u8 mode;
47 	u8 index;
48 	u8 key_id;
49 	u8 padding[2];
50 } __packed;
51 
52 struct oxp_button_entry {
53 	struct oxp_button_data data;
54 	const char *name;
55 };
56 
57 static const struct oxp_button_entry oxp_button_table[] = {
58 	/* Gamepad Buttons */
59 	{ { OXP_MAPPING_GAMEPAD, 0x01 }, "BTN_A" },
60 	{ { OXP_MAPPING_GAMEPAD, 0x02 }, "BTN_B" },
61 	{ { OXP_MAPPING_GAMEPAD, 0x03 }, "BTN_X" },
62 	{ { OXP_MAPPING_GAMEPAD, 0x04 }, "BTN_Y" },
63 	{ { OXP_MAPPING_GAMEPAD, 0x05 }, "BTN_LB" },
64 	{ { OXP_MAPPING_GAMEPAD, 0x06 }, "BTN_RB" },
65 	{ { OXP_MAPPING_GAMEPAD, 0x07 }, "BTN_LT" },
66 	{ { OXP_MAPPING_GAMEPAD, 0x08 }, "BTN_RT" },
67 	{ { OXP_MAPPING_GAMEPAD, 0x09 }, "BTN_START" },
68 	{ { OXP_MAPPING_GAMEPAD, 0x0a }, "BTN_SELECT" },
69 	{ { OXP_MAPPING_GAMEPAD, 0x0b }, "BTN_L3" },
70 	{ { OXP_MAPPING_GAMEPAD, 0x0c }, "BTN_R3" },
71 	{ { OXP_MAPPING_GAMEPAD, 0x0d }, "DPAD_UP" },
72 	{ { OXP_MAPPING_GAMEPAD, 0x0e }, "DPAD_DOWN" },
73 	{ { OXP_MAPPING_GAMEPAD, 0x0f }, "DPAD_LEFT" },
74 	{ { OXP_MAPPING_GAMEPAD, 0x10 }, "DPAD_RIGHT" },
75 	{ { OXP_MAPPING_GAMEPAD, 0x11 }, "JOY_L_UP" },
76 	{ { OXP_MAPPING_GAMEPAD, 0x12 }, "JOY_L_UP_RIGHT" },
77 	{ { OXP_MAPPING_GAMEPAD, 0x13 }, "JOY_L_RIGHT" },
78 	{ { OXP_MAPPING_GAMEPAD, 0x14 }, "JOY_L_DOWN_RIGHT" },
79 	{ { OXP_MAPPING_GAMEPAD, 0x15 }, "JOY_L_DOWN" },
80 	{ { OXP_MAPPING_GAMEPAD, 0x16 }, "JOY_L_DOWN_LEFT" },
81 	{ { OXP_MAPPING_GAMEPAD, 0x17 }, "JOY_L_LEFT" },
82 	{ { OXP_MAPPING_GAMEPAD, 0x18 }, "JOY_L_UP_LEFT" },
83 	{ { OXP_MAPPING_GAMEPAD, 0x19 }, "JOY_R_UP" },
84 	{ { OXP_MAPPING_GAMEPAD, 0x1a }, "JOY_R_UP_RIGHT" },
85 	{ { OXP_MAPPING_GAMEPAD, 0x1b }, "JOY_R_RIGHT" },
86 	{ { OXP_MAPPING_GAMEPAD, 0x1c }, "JOY_R_DOWN_RIGHT" },
87 	{ { OXP_MAPPING_GAMEPAD, 0x1d }, "JOY_R_DOWN" },
88 	{ { OXP_MAPPING_GAMEPAD, 0x1e }, "JOY_R_DOWN_LEFT" },
89 	{ { OXP_MAPPING_GAMEPAD, 0x1f }, "JOY_R_LEFT" },
90 	{ { OXP_MAPPING_GAMEPAD, 0x20 }, "JOY_R_UP_LEFT" },
91 	{ { OXP_MAPPING_GAMEPAD, 0x22 }, "BTN_GUIDE" },
92 	/* Keyboard Keys */
93 	{ { OXP_MAPPING_KEYBOARD, 0x01, 0x5a }, "KEY_F1" },
94 	{ { OXP_MAPPING_KEYBOARD, 0x01, 0x5b }, "KEY_F2" },
95 	{ { OXP_MAPPING_KEYBOARD, 0x01, 0x5c }, "KEY_F3" },
96 	{ { OXP_MAPPING_KEYBOARD, 0x01, 0x5d }, "KEY_F4" },
97 	{ { OXP_MAPPING_KEYBOARD, 0x01, 0x5e }, "KEY_F5" },
98 	{ { OXP_MAPPING_KEYBOARD, 0x01, 0x5f }, "KEY_F6" },
99 	{ { OXP_MAPPING_KEYBOARD, 0x01, 0x60 }, "KEY_F7" },
100 	{ { OXP_MAPPING_KEYBOARD, 0x01, 0x61 }, "KEY_F8" },
101 	{ { OXP_MAPPING_KEYBOARD, 0x01, 0x62 }, "KEY_F9" },
102 	{ { OXP_MAPPING_KEYBOARD, 0x01, 0x63 }, "KEY_F10" },
103 	{ { OXP_MAPPING_KEYBOARD, 0x01, 0x64 }, "KEY_F11" },
104 	{ { OXP_MAPPING_KEYBOARD, 0x01, 0x65 }, "KEY_F12" },
105 	{ { OXP_MAPPING_KEYBOARD, 0x01, 0x66 }, "KEY_F13" },
106 	{ { OXP_MAPPING_KEYBOARD, 0x01, 0x67 }, "KEY_F14" },
107 	{ { OXP_MAPPING_KEYBOARD, 0x01, 0x68 }, "KEY_F15" },
108 	{ { OXP_MAPPING_KEYBOARD, 0x01, 0x69 }, "KEY_F16" },
109 	{ { OXP_MAPPING_KEYBOARD, 0x01, 0x6a }, "KEY_F17" },
110 	{ { OXP_MAPPING_KEYBOARD, 0x01, 0x6b }, "KEY_F18" },
111 	{ { OXP_MAPPING_KEYBOARD, 0x01, 0x6c }, "KEY_F19" },
112 	{ { OXP_MAPPING_KEYBOARD, 0x01, 0x6d }, "KEY_F20" },
113 	{ { OXP_MAPPING_KEYBOARD, 0x01, 0x6e }, "KEY_F21" },
114 	{ { OXP_MAPPING_KEYBOARD, 0x01, 0x6f }, "KEY_F22" },
115 	{ { OXP_MAPPING_KEYBOARD, 0x01, 0x70 }, "KEY_F23" },
116 	{ { OXP_MAPPING_KEYBOARD, 0x01, 0x71 }, "KEY_F24" },
117 };
118 
119 enum oxp_joybutton_index {
120 	BUTTON_A =	0x01,
121 	BUTTON_B,
122 	BUTTON_X,
123 	BUTTON_Y,
124 	BUTTON_LB,
125 	BUTTON_RB,
126 	BUTTON_LT,
127 	BUTTON_RT,
128 	BUTTON_START,
129 	BUTTON_SELECT,
130 	BUTTON_L3,
131 	BUTTON_R3,
132 	BUTTON_DUP,
133 	BUTTON_DDOWN,
134 	BUTTON_DLEFT,
135 	BUTTON_DRIGHT,
136 	BUTTON_M1 =	0x22,
137 	BUTTON_M2,
138 	/* These are unused currently, reserved for future devices */
139 	BUTTON_M3,
140 	BUTTON_M4,
141 	BUTTON_M5,
142 	BUTTON_M6,
143 };
144 
145 struct oxp_button_idx {
146 	enum oxp_joybutton_index button_idx;
147 	u8 mapping_idx;
148 } __packed;
149 
150 struct oxp_bmap_page_1 {
151 	struct oxp_button_idx btn_a;
152 	struct oxp_button_idx btn_b;
153 	struct oxp_button_idx btn_x;
154 	struct oxp_button_idx btn_y;
155 	struct oxp_button_idx btn_lb;
156 	struct oxp_button_idx btn_rb;
157 	struct oxp_button_idx btn_lt;
158 	struct oxp_button_idx btn_rt;
159 	struct oxp_button_idx btn_start;
160 } __packed;
161 
162 struct oxp_bmap_page_2 {
163 	struct oxp_button_idx btn_select;
164 	struct oxp_button_idx btn_l3;
165 	struct oxp_button_idx btn_r3;
166 	struct oxp_button_idx btn_dup;
167 	struct oxp_button_idx btn_ddown;
168 	struct oxp_button_idx btn_dleft;
169 	struct oxp_button_idx btn_dright;
170 	struct oxp_button_idx btn_m1;
171 	struct oxp_button_idx btn_m2;
172 } __packed;
173 
174 static struct oxp_hid_cfg {
175 	struct delayed_work oxp_rgb_queue;
176 	struct delayed_work oxp_btn_queue;
177 	struct oxp_bmap_page_1 *bmap_1;
178 	struct oxp_bmap_page_2 *bmap_2;
179 	struct delayed_work oxp_mcu_init;
180 	struct led_classdev_mc *led_mc;
181 	struct hid_device *hdev;
182 	struct mutex cfg_mutex; /*ensure single synchronous output report*/
183 	u8 rgb_brightness;
184 	u8 gamepad_mode;
185 	u8 rumble_intensity;
186 	u8 rgb_effect;
187 	u8 rgb_speed;
188 	u8 rgb_en;
189 } drvdata;
190 
191 #define OXP_FILL_PAGE_SLOT(page, btn)            \
192 	{ .button_idx = (page)->btn.button_idx,  \
193 	  .mapping_idx = (page)->btn.mapping_idx }
194 
195 enum oxp_gamepad_mode_index {
196 	OXP_GP_MODE_XINPUT = 0x00,
197 	OXP_GP_MODE_DEBUG = 0x03,
198 };
199 
200 static const char *const oxp_gamepad_mode_text[] = {
201 	[OXP_GP_MODE_XINPUT] = "xinput",
202 	[OXP_GP_MODE_DEBUG] = "debug",
203 };
204 
205 enum oxp_feature_en_index {
206 	OXP_FEAT_DISABLED,
207 	OXP_FEAT_ENABLED,
208 };
209 
210 static const char *const oxp_feature_en_text[] = {
211 	[OXP_FEAT_DISABLED] = "false",
212 	[OXP_FEAT_ENABLED] = "true",
213 };
214 
215 enum oxp_rgb_effect_index {
216 	OXP_UNKNOWN,
217 	OXP_EFFECT_AURORA,
218 	OXP_EFFECT_BIRTHDAY,
219 	OXP_EFFECT_FLOWING,
220 	OXP_EFFECT_CHROMA_1,
221 	OXP_EFFECT_NEON,
222 	OXP_EFFECT_CHROMA_2,
223 	OXP_EFFECT_DREAMY,
224 	OXP_EFFECT_WARM,
225 	OXP_EFFECT_CYBERPUNK,
226 	OXP_EFFECT_SEA,
227 	OXP_EFFECT_SUNSET,
228 	OXP_EFFECT_COLORFUL,
229 	OXP_EFFECT_MONSTER,
230 	OXP_EFFECT_GREEN,
231 	OXP_EFFECT_BLUE,
232 	OXP_EFFECT_YELLOW,
233 	OXP_EFFECT_TEAL,
234 	OXP_EFFECT_PURPLE,
235 	OXP_EFFECT_FOGGY,
236 	OXP_EFFECT_MONO_LIST, /* placeholder for effect_index_show */
237 };
238 
239 /* These belong to rgb_effect_index, but we want to hide them from
240  * rgb_effect_text
241  */
242 
243 #define OXP_GET_PROPERTY 0xfc
244 #define OXP_SET_PROPERTY 0xfd
245 #define OXP_EFFECT_MONO_TRUE 0xfe /* actual index for monocolor */
246 
247 static const char *const oxp_rgb_effect_text[] = {
248 	[OXP_UNKNOWN] = "unknown",
249 	[OXP_EFFECT_AURORA] = "aurora",
250 	[OXP_EFFECT_BIRTHDAY] = "birthday_cake",
251 	[OXP_EFFECT_FLOWING] = "flowing_light",
252 	[OXP_EFFECT_CHROMA_1] = "chroma_popping",
253 	[OXP_EFFECT_NEON] = "neon",
254 	[OXP_EFFECT_CHROMA_2] = "chroma_breathing",
255 	[OXP_EFFECT_DREAMY] = "dreamy",
256 	[OXP_EFFECT_WARM] = "warm_sun",
257 	[OXP_EFFECT_CYBERPUNK] = "cyberpunk",
258 	[OXP_EFFECT_SEA] = "sea_foam",
259 	[OXP_EFFECT_SUNSET] = "sunset_afterglow",
260 	[OXP_EFFECT_COLORFUL] = "colorful",
261 	[OXP_EFFECT_MONSTER] = "monster_woke",
262 	[OXP_EFFECT_GREEN] = "green_breathing",
263 	[OXP_EFFECT_BLUE] = "blue_breathing",
264 	[OXP_EFFECT_YELLOW] = "yellow_breathing",
265 	[OXP_EFFECT_TEAL] = "teal_breathing",
266 	[OXP_EFFECT_PURPLE] = "purple_breathing",
267 	[OXP_EFFECT_FOGGY] = "foggy_haze",
268 	[OXP_EFFECT_MONO_LIST] = "monocolor",
269 };
270 
271 enum oxp_rumble_side_index {
272 	OXP_RUMBLE_LEFT = 0x00,
273 	OXP_RUMBLE_RIGHT,
274 };
275 
276 struct oxp_gen_1_rgb_report {
277 	u8 report_id;
278 	u8 message_id;
279 	u8 padding_2[2];
280 	u8 effect;
281 	u8 enabled;
282 	u8 speed;
283 	u8 brightness;
284 	u8 red;
285 	u8 green;
286 	u8 blue;
287 } __packed;
288 
289 struct oxp_gen_2_rgb_report {
290 	u8 report_id;
291 	u8 header_id;
292 	u8 padding_2;
293 	u8 message_id;
294 	u8 padding_4[2];
295 	u8 enabled;
296 	u8 speed;
297 	u8 brightness;
298 	u8 red;
299 	u8 green;
300 	u8 blue;
301 	u8 padding_12[3];
302 	u8 effect;
303 } __packed;
304 
305 struct oxp_attr {
306 	u8 index;
307 };
308 
309 static u16 get_usage_page(struct hid_device *hdev)
310 {
311 	return hdev->collection[0].usage >> 16;
312 }
313 
314 static int oxp_hid_raw_event_gen_1(struct hid_device *hdev,
315 				   struct hid_report *report, u8 *data,
316 				   int size)
317 {
318 	struct led_classdev_mc *led_mc = drvdata.led_mc;
319 	struct oxp_gen_1_rgb_report *rgb_rep;
320 
321 	if (data[1] != OXP_FID_GEN1_RGB_REPLY)
322 		return 0;
323 
324 	rgb_rep = (struct oxp_gen_1_rgb_report *)data;
325 	/* Ensure we save monocolor as the list value */
326 	drvdata.rgb_effect = rgb_rep->effect == OXP_EFFECT_MONO_TRUE ?
327 			     OXP_EFFECT_MONO_LIST :
328 			     rgb_rep->effect;
329 	drvdata.rgb_speed = rgb_rep->speed;
330 	drvdata.rgb_en = rgb_rep->enabled == 0 ? OXP_FEAT_DISABLED :
331 						 OXP_FEAT_ENABLED;
332 	drvdata.rgb_brightness = rgb_rep->brightness;
333 	led_mc->led_cdev.brightness = rgb_rep->brightness / 4 *
334 				      led_mc->led_cdev.max_brightness;
335 	/* If monocolor had less than 100% brightness on the previous boot,
336 	 * there will be no reliable way to determine the real intensity.
337 	 * Since intensity scaling is used with a hardware brightness set at max,
338 	 * our brightness will always look like 100%. Use the last set value to
339 	 * prevent successive boots from lowering the brightness further.
340 	 * Brightness will be "wrong" but the effect will remain the same visually.
341 	 */
342 	led_mc->subled_info[0].intensity = rgb_rep->red;
343 	led_mc->subled_info[1].intensity = rgb_rep->green;
344 	led_mc->subled_info[2].intensity = rgb_rep->blue;
345 
346 	return 0;
347 }
348 
349 static int oxp_gen_2_property_out(enum oxp_function_index fid, u8 *data, u8 data_size);
350 static int oxp_set_buttons(void);
351 static int oxp_rumble_intensity_set(u8 intensity);
352 
353 static void oxp_mcu_init_fn(struct work_struct *work)
354 {
355 	u8 gp_mode_data[3] = { OXP_GP_MODE_DEBUG, 0x01, 0x02 };
356 	int ret;
357 
358 	/* Re-apply the button mapping */
359 	ret = oxp_set_buttons();
360 	if (ret)
361 		dev_err(&drvdata.hdev->dev,
362 			"Error: Failed to set button mapping: %i\n", ret);
363 
364 	/* Cycle the gamepad mode */
365 	ret = oxp_gen_2_property_out(OXP_FID_GEN2_TOGGLE_MODE, gp_mode_data, 3);
366 	if (ret)
367 		dev_err(&drvdata.hdev->dev,
368 			"Error: Failed to set gamepad mode: %i\n", ret);
369 
370 	/* Remainder only applies for xinput mode */
371 	if (drvdata.gamepad_mode == OXP_GP_MODE_DEBUG)
372 		return;
373 
374 	gp_mode_data[0] = OXP_GP_MODE_XINPUT;
375 	ret = oxp_gen_2_property_out(OXP_FID_GEN2_TOGGLE_MODE, gp_mode_data, 3);
376 	if (ret)
377 		dev_err(&drvdata.hdev->dev,
378 			"Error: Failed to set gamepad mode: %i\n", ret);
379 
380 	/* Set vibration level */
381 	ret = oxp_rumble_intensity_set(drvdata.rumble_intensity);
382 	if (ret)
383 		dev_err(&drvdata.hdev->dev,
384 			"Error: Failed to set rumble intensity: %i\n", ret);
385 }
386 
387 static int oxp_hid_raw_event_gen_2(struct hid_device *hdev,
388 				   struct hid_report *report, u8 *data,
389 				   int size)
390 {
391 	struct led_classdev_mc *led_mc = drvdata.led_mc;
392 	struct oxp_gen_2_rgb_report *rgb_rep;
393 
394 	if (data[0] != OXP_FID_GEN2_STATUS_EVENT)
395 		return 0;
396 
397 	/* Sent ~6s after resume event, indicating the MCU has fully reset.
398 	 * Re-apply our settings after this has been received.
399 	 */
400 	if (data[3] == OXP_EFFECT_MONO_TRUE) {
401 		mod_delayed_work(system_wq, &drvdata.oxp_mcu_init, msecs_to_jiffies(50));
402 		return 0;
403 	}
404 
405 	if (data[3] != OXP_GET_PROPERTY)
406 		return 0;
407 
408 	rgb_rep = (struct oxp_gen_2_rgb_report *)data;
409 	/* Ensure we save monocolor as the list value */
410 	drvdata.rgb_effect = rgb_rep->effect == OXP_EFFECT_MONO_TRUE ?
411 			     OXP_EFFECT_MONO_LIST :
412 			     rgb_rep->effect;
413 	drvdata.rgb_speed = rgb_rep->speed;
414 	drvdata.rgb_en = rgb_rep->enabled == 0 ? OXP_FEAT_DISABLED :
415 						 OXP_FEAT_ENABLED;
416 	drvdata.rgb_brightness = rgb_rep->brightness;
417 	led_mc->led_cdev.brightness = rgb_rep->brightness / 4 *
418 				      led_mc->led_cdev.max_brightness;
419 	/* If monocolor had less than 100% brightness on the previous boot,
420 	 * there will be no reliable way to determine the real intensity.
421 	 * Since intensity scaling is used with a hardware brightness set at max,
422 	 * our brightness will always look like 100%. Use the last set value to
423 	 * prevent successive boots from lowering the brightness further.
424 	 * Brightness will be "wrong" but the effect will remain the same visually.
425 	 */
426 	led_mc->subled_info[0].intensity = rgb_rep->red;
427 	led_mc->subled_info[1].intensity = rgb_rep->green;
428 	led_mc->subled_info[2].intensity = rgb_rep->blue;
429 
430 	return 0;
431 }
432 
433 static int oxp_hid_raw_event(struct hid_device *hdev, struct hid_report *report,
434 			     u8 *data, int size)
435 {
436 	u16 up = get_usage_page(hdev);
437 
438 	dev_dbg(&hdev->dev, "raw event data: [%*ph]\n", OXP_PACKET_SIZE, data);
439 
440 	switch (up) {
441 	case GEN1_USAGE_PAGE:
442 		return oxp_hid_raw_event_gen_1(hdev, report, data, size);
443 	case GEN2_USAGE_PAGE:
444 		return oxp_hid_raw_event_gen_2(hdev, report, data, size);
445 	default:
446 		break;
447 	}
448 
449 	return 0;
450 }
451 
452 static int mcu_property_out(u8 *header, size_t header_size, u8 *data,
453 			    size_t data_size, u8 *footer, size_t footer_size)
454 {
455 	unsigned char *dmabuf __free(kfree) = kzalloc(OXP_PACKET_SIZE, GFP_KERNEL);
456 	int ret;
457 
458 	if (!dmabuf)
459 		return -ENOMEM;
460 
461 	if (header_size + data_size + footer_size > OXP_PACKET_SIZE)
462 		return -EINVAL;
463 
464 	guard(mutex)(&drvdata.cfg_mutex);
465 	memcpy(dmabuf, header, header_size);
466 	memcpy(dmabuf + header_size, data, data_size);
467 	if (footer_size)
468 		memcpy(dmabuf + OXP_PACKET_SIZE - footer_size, footer, footer_size);
469 
470 	dev_dbg(&drvdata.hdev->dev, "raw data: [%*ph]\n", OXP_PACKET_SIZE, dmabuf);
471 
472 	ret = hid_hw_output_report(drvdata.hdev, dmabuf, OXP_PACKET_SIZE);
473 	if (ret < 0)
474 		return ret;
475 
476 	/* MCU takes 200ms to be ready for another command. */
477 	msleep(200);
478 	return ret == OXP_PACKET_SIZE ? 0 : -EIO;
479 }
480 
481 static int oxp_gen_1_property_out(enum oxp_function_index fid, u8 *data,
482 				  u8 data_size)
483 {
484 	u8 header[] = { fid, GEN1_MESSAGE_ID };
485 	size_t header_size = ARRAY_SIZE(header);
486 
487 	return mcu_property_out(header, header_size, data, data_size, NULL, 0);
488 }
489 
490 static int oxp_gen_2_property_out(enum oxp_function_index fid, u8 *data,
491 				  u8 data_size)
492 {
493 	u8 header[] = { fid, GEN2_MESSAGE_ID, 0x01 };
494 	u8 footer[] = { GEN2_MESSAGE_ID, fid };
495 	size_t header_size = ARRAY_SIZE(header);
496 	size_t footer_size = ARRAY_SIZE(footer);
497 
498 	return mcu_property_out(header, header_size, data, data_size, footer,
499 				footer_size);
500 }
501 
502 static ssize_t gamepad_mode_store(struct device *dev,
503 				  struct device_attribute *attr, const char *buf,
504 				  size_t count)
505 {
506 	u16 up = get_usage_page(drvdata.hdev);
507 	u8 data[3] = { 0x00, 0x01, 0x02 };
508 	int ret = -EINVAL;
509 	int i;
510 
511 	if (up != GEN2_USAGE_PAGE)
512 		return ret;
513 
514 	for (i = 0; i < ARRAY_SIZE(oxp_gamepad_mode_text); i++) {
515 		if (oxp_gamepad_mode_text[i] && sysfs_streq(buf, oxp_gamepad_mode_text[i])) {
516 			ret = i;
517 			break;
518 		}
519 	}
520 	if (ret < 0)
521 		return ret;
522 
523 	data[0] = ret;
524 
525 	ret = oxp_gen_2_property_out(OXP_FID_GEN2_TOGGLE_MODE, data, 3);
526 	if (ret)
527 		return ret;
528 
529 	drvdata.gamepad_mode = data[0];
530 
531 	if (drvdata.gamepad_mode == OXP_GP_MODE_DEBUG)
532 		return count;
533 
534 	/* Re-apply rumble settings as switching gamepad mode will override */
535 	ret = oxp_rumble_intensity_set(drvdata.rumble_intensity);
536 	if (ret)
537 		return ret;
538 
539 	return count;
540 }
541 
542 static ssize_t gamepad_mode_show(struct device *dev,
543 				 struct device_attribute *attr, char *buf)
544 {
545 	return sysfs_emit(buf, "%s\n", oxp_gamepad_mode_text[drvdata.gamepad_mode]);
546 }
547 static DEVICE_ATTR_RW(gamepad_mode);
548 
549 static ssize_t gamepad_mode_index_show(struct device *dev,
550 				       struct device_attribute *attr,
551 				       char *buf)
552 {
553 	ssize_t count = 0;
554 	unsigned int i;
555 
556 	for (i = 0; i < ARRAY_SIZE(oxp_gamepad_mode_text); i++) {
557 		if (!oxp_gamepad_mode_text[i] ||
558 		    oxp_gamepad_mode_text[i][0] == '\0')
559 			continue;
560 
561 		count += sysfs_emit_at(buf, count, "%s ", oxp_gamepad_mode_text[i]);
562 	}
563 
564 	if (count)
565 		buf[count - 1] = '\n';
566 
567 	return count;
568 }
569 static DEVICE_ATTR_RO(gamepad_mode_index);
570 
571 static void oxp_set_defaults_bmap_1(struct oxp_bmap_page_1 *bmap)
572 {
573 	bmap->btn_a.button_idx = BUTTON_A;
574 	bmap->btn_a.mapping_idx = 0;
575 	bmap->btn_b.button_idx = BUTTON_B;
576 	bmap->btn_b.mapping_idx = 1;
577 	bmap->btn_x.button_idx = BUTTON_X;
578 	bmap->btn_x.mapping_idx = 2;
579 	bmap->btn_y.button_idx = BUTTON_Y;
580 	bmap->btn_y.mapping_idx = 3;
581 	bmap->btn_lb.button_idx = BUTTON_LB;
582 	bmap->btn_lb.mapping_idx = 4;
583 	bmap->btn_rb.button_idx = BUTTON_RB;
584 	bmap->btn_rb.mapping_idx = 5;
585 	bmap->btn_lt.button_idx = BUTTON_LT;
586 	bmap->btn_lt.mapping_idx = 6;
587 	bmap->btn_rt.button_idx = BUTTON_RT;
588 	bmap->btn_rt.mapping_idx = 7;
589 	bmap->btn_start.button_idx = BUTTON_START;
590 	bmap->btn_start.mapping_idx = 8;
591 }
592 
593 static void oxp_set_defaults_bmap_2(struct oxp_bmap_page_2 *bmap)
594 {
595 	bmap->btn_select.button_idx = BUTTON_SELECT;
596 	bmap->btn_select.mapping_idx = 9;
597 	bmap->btn_l3.button_idx = BUTTON_L3;
598 	bmap->btn_l3.mapping_idx = 10;
599 	bmap->btn_r3.button_idx = BUTTON_R3;
600 	bmap->btn_r3.mapping_idx = 11;
601 	bmap->btn_dup.button_idx = BUTTON_DUP;
602 	bmap->btn_dup.mapping_idx = 12;
603 	bmap->btn_ddown.button_idx = BUTTON_DDOWN;
604 	bmap->btn_ddown.mapping_idx = 13;
605 	bmap->btn_dleft.button_idx = BUTTON_DLEFT;
606 	bmap->btn_dleft.mapping_idx = 14;
607 	bmap->btn_dright.button_idx = BUTTON_DRIGHT;
608 	bmap->btn_dright.mapping_idx = 15;
609 	bmap->btn_m1.button_idx = BUTTON_M1;
610 	bmap->btn_m1.mapping_idx = 48; /* KEY_F15 */
611 	bmap->btn_m2.button_idx = BUTTON_M2;
612 	bmap->btn_m2.mapping_idx = 49; /* KEY_F16 */
613 }
614 
615 static void oxp_page_fill_data(char *buf, const struct oxp_button_idx *buttons,
616 			       size_t len)
617 {
618 	size_t offset_increment = sizeof(u8) + sizeof(struct oxp_button_idx);
619 	size_t offset = 5;
620 	unsigned int i;
621 
622 	for (i = 0; i < len; i++, offset += offset_increment) {
623 		buf[offset] = (u8)buttons[i].button_idx;
624 		memcpy(buf + offset + 1,
625 		       &oxp_button_table[buttons[i].mapping_idx].data,
626 		       sizeof(struct oxp_button_data));
627 	}
628 }
629 
630 static int oxp_set_buttons(void)
631 {
632 	u8 page_1[59] = { 0x02, 0x38, 0x20, 0x01, 0x01 };
633 	u8 page_2[59] = { 0x02, 0x38, 0x20, 0x02, 0x01 };
634 	u16 up = get_usage_page(drvdata.hdev);
635 	int ret;
636 
637 	if (up != GEN2_USAGE_PAGE)
638 		return -EINVAL;
639 
640 	const struct oxp_button_idx p1[] = {
641 		OXP_FILL_PAGE_SLOT(drvdata.bmap_1, btn_a),
642 		OXP_FILL_PAGE_SLOT(drvdata.bmap_1, btn_b),
643 		OXP_FILL_PAGE_SLOT(drvdata.bmap_1, btn_x),
644 		OXP_FILL_PAGE_SLOT(drvdata.bmap_1, btn_y),
645 		OXP_FILL_PAGE_SLOT(drvdata.bmap_1, btn_lb),
646 		OXP_FILL_PAGE_SLOT(drvdata.bmap_1, btn_rb),
647 		OXP_FILL_PAGE_SLOT(drvdata.bmap_1, btn_lt),
648 		OXP_FILL_PAGE_SLOT(drvdata.bmap_1, btn_rt),
649 		OXP_FILL_PAGE_SLOT(drvdata.bmap_1, btn_start),
650 	};
651 
652 	const struct oxp_button_idx p2[] = {
653 		OXP_FILL_PAGE_SLOT(drvdata.bmap_2, btn_select),
654 		OXP_FILL_PAGE_SLOT(drvdata.bmap_2, btn_l3),
655 		OXP_FILL_PAGE_SLOT(drvdata.bmap_2, btn_r3),
656 		OXP_FILL_PAGE_SLOT(drvdata.bmap_2, btn_dup),
657 		OXP_FILL_PAGE_SLOT(drvdata.bmap_2, btn_ddown),
658 		OXP_FILL_PAGE_SLOT(drvdata.bmap_2, btn_dleft),
659 		OXP_FILL_PAGE_SLOT(drvdata.bmap_2, btn_dright),
660 		OXP_FILL_PAGE_SLOT(drvdata.bmap_2, btn_m1),
661 		OXP_FILL_PAGE_SLOT(drvdata.bmap_2, btn_m2),
662 	};
663 
664 	oxp_page_fill_data(page_1, p1, ARRAY_SIZE(p1));
665 	oxp_page_fill_data(page_2, p2, ARRAY_SIZE(p2));
666 
667 	ret = oxp_gen_2_property_out(OXP_FID_GEN2_KEY_STATE, page_1, ARRAY_SIZE(page_1));
668 	if (ret)
669 		return ret;
670 
671 	return oxp_gen_2_property_out(OXP_FID_GEN2_KEY_STATE, page_2, ARRAY_SIZE(page_2));
672 }
673 
674 static void oxp_reset_buttons(void)
675 {
676 	oxp_set_defaults_bmap_1(drvdata.bmap_1);
677 	oxp_set_defaults_bmap_2(drvdata.bmap_2);
678 }
679 
680 static ssize_t reset_buttons_store(struct device *dev,
681 				   struct device_attribute *attr, const char *buf,
682 				   size_t count)
683 {
684 	int val, ret;
685 
686 	ret = kstrtoint(buf, 10, &val);
687 	if (ret)
688 		return ret;
689 
690 	if (val != 1)
691 		return -EINVAL;
692 
693 	oxp_reset_buttons();
694 	ret = oxp_set_buttons();
695 	if (ret)
696 		return ret;
697 
698 	return count;
699 }
700 static DEVICE_ATTR_WO(reset_buttons);
701 
702 static void oxp_btn_queue_fn(struct work_struct *work)
703 {
704 	int ret;
705 
706 	ret = oxp_set_buttons();
707 	if (ret)
708 		dev_err(&drvdata.hdev->dev,
709 			"Error: Failed to write button mapping: %i\n", ret);
710 }
711 
712 static int oxp_button_idx_from_str(const char *buf)
713 {
714 	int i;
715 
716 	for (i = 0; i < ARRAY_SIZE(oxp_button_table); i++)
717 		if (sysfs_streq(buf, oxp_button_table[i].name))
718 			return i;
719 
720 	return -EINVAL;
721 }
722 
723 static ssize_t map_button_store(struct device *dev,
724 				struct device_attribute *attr, const char *buf,
725 				size_t count, u8 index)
726 {
727 	int idx;
728 
729 	idx = oxp_button_idx_from_str(buf);
730 	if (idx < 0)
731 		return idx;
732 
733 	switch (index) {
734 	case BUTTON_A:
735 		drvdata.bmap_1->btn_a.mapping_idx = idx;
736 		break;
737 	case BUTTON_B:
738 		drvdata.bmap_1->btn_b.mapping_idx = idx;
739 		break;
740 	case BUTTON_X:
741 		drvdata.bmap_1->btn_x.mapping_idx = idx;
742 		break;
743 	case BUTTON_Y:
744 		drvdata.bmap_1->btn_y.mapping_idx = idx;
745 		break;
746 	case BUTTON_LB:
747 		drvdata.bmap_1->btn_lb.mapping_idx = idx;
748 		break;
749 	case BUTTON_RB:
750 		drvdata.bmap_1->btn_rb.mapping_idx = idx;
751 		break;
752 	case BUTTON_LT:
753 		drvdata.bmap_1->btn_lt.mapping_idx = idx;
754 		break;
755 	case BUTTON_RT:
756 		drvdata.bmap_1->btn_rt.mapping_idx = idx;
757 		break;
758 	case BUTTON_START:
759 		drvdata.bmap_1->btn_start.mapping_idx = idx;
760 		break;
761 	case BUTTON_SELECT:
762 		drvdata.bmap_2->btn_select.mapping_idx = idx;
763 		break;
764 	case BUTTON_L3:
765 		drvdata.bmap_2->btn_l3.mapping_idx = idx;
766 		break;
767 	case BUTTON_R3:
768 		drvdata.bmap_2->btn_r3.mapping_idx = idx;
769 		break;
770 	case BUTTON_DUP:
771 		drvdata.bmap_2->btn_dup.mapping_idx = idx;
772 		break;
773 	case BUTTON_DDOWN:
774 		drvdata.bmap_2->btn_ddown.mapping_idx = idx;
775 		break;
776 	case BUTTON_DLEFT:
777 		drvdata.bmap_2->btn_dleft.mapping_idx = idx;
778 		break;
779 	case BUTTON_DRIGHT:
780 		drvdata.bmap_2->btn_dright.mapping_idx = idx;
781 		break;
782 	case BUTTON_M1:
783 		drvdata.bmap_2->btn_m1.mapping_idx = idx;
784 		break;
785 	case BUTTON_M2:
786 		drvdata.bmap_2->btn_m2.mapping_idx = idx;
787 		break;
788 	default:
789 		return -EINVAL;
790 	}
791 	mod_delayed_work(system_wq, &drvdata.oxp_btn_queue, msecs_to_jiffies(50));
792 	return count;
793 }
794 
795 static ssize_t map_button_show(struct device *dev,
796 			       struct device_attribute *attr, char *buf,
797 			       u8 index)
798 {
799 	u8 i;
800 
801 	switch (index) {
802 	case BUTTON_A:
803 		i = drvdata.bmap_1->btn_a.mapping_idx;
804 		break;
805 	case BUTTON_B:
806 		i = drvdata.bmap_1->btn_b.mapping_idx;
807 		break;
808 	case BUTTON_X:
809 		i = drvdata.bmap_1->btn_x.mapping_idx;
810 		break;
811 	case BUTTON_Y:
812 		i = drvdata.bmap_1->btn_y.mapping_idx;
813 		break;
814 	case BUTTON_LB:
815 		i = drvdata.bmap_1->btn_lb.mapping_idx;
816 		break;
817 	case BUTTON_RB:
818 		i = drvdata.bmap_1->btn_rb.mapping_idx;
819 		break;
820 	case BUTTON_LT:
821 		i = drvdata.bmap_1->btn_lt.mapping_idx;
822 		break;
823 	case BUTTON_RT:
824 		i = drvdata.bmap_1->btn_rt.mapping_idx;
825 		break;
826 	case BUTTON_START:
827 		i = drvdata.bmap_1->btn_start.mapping_idx;
828 		break;
829 	case BUTTON_SELECT:
830 		i = drvdata.bmap_2->btn_select.mapping_idx;
831 		break;
832 	case BUTTON_L3:
833 		i = drvdata.bmap_2->btn_l3.mapping_idx;
834 		break;
835 	case BUTTON_R3:
836 		i = drvdata.bmap_2->btn_r3.mapping_idx;
837 		break;
838 	case BUTTON_DUP:
839 		i = drvdata.bmap_2->btn_dup.mapping_idx;
840 		break;
841 	case BUTTON_DDOWN:
842 		i = drvdata.bmap_2->btn_ddown.mapping_idx;
843 		break;
844 	case BUTTON_DLEFT:
845 		i = drvdata.bmap_2->btn_dleft.mapping_idx;
846 		break;
847 	case BUTTON_DRIGHT:
848 		i = drvdata.bmap_2->btn_dright.mapping_idx;
849 		break;
850 	case BUTTON_M1:
851 		i = drvdata.bmap_2->btn_m1.mapping_idx;
852 		break;
853 	case BUTTON_M2:
854 		i = drvdata.bmap_2->btn_m2.mapping_idx;
855 		break;
856 	default:
857 		return -EINVAL;
858 	}
859 
860 	if (i >= ARRAY_SIZE(oxp_button_table))
861 		return -EINVAL;
862 
863 	return sysfs_emit(buf, "%s\n", oxp_button_table[i].name);
864 }
865 
866 static ssize_t button_mapping_options_show(struct device *dev,
867 					   struct device_attribute *attr, char *buf)
868 {
869 	ssize_t count = 0;
870 	unsigned int i;
871 
872 	for (i = 0; i < ARRAY_SIZE(oxp_button_table); i++)
873 		count += sysfs_emit_at(buf, count, "%s ", oxp_button_table[i].name);
874 
875 	if (count)
876 		buf[count - 1] = '\n';
877 
878 	return count;
879 }
880 static DEVICE_ATTR_RO(button_mapping_options);
881 
882 static int oxp_rumble_intensity_set(u8 intensity)
883 {
884 	u8 header[15] = { 0x02, 0x38, 0x02, 0xe3, 0x39, 0xe3, 0x39, 0xe3,
885 			  0x39, 0x01, intensity, 0x05, 0xe3, 0x39, 0xe3 };
886 	u8 footer[9] = { 0x39, 0xe3, 0x39, 0xe3, 0xe3, 0x02, 0x04, 0x39, 0x39 };
887 	size_t footer_size = ARRAY_SIZE(footer);
888 	size_t header_size = ARRAY_SIZE(header);
889 	u8 data[59] = { 0x0 };
890 	size_t data_size = ARRAY_SIZE(data);
891 
892 	memcpy(data, header, header_size);
893 	memcpy(data + data_size - footer_size, footer, footer_size);
894 
895 	return oxp_gen_2_property_out(OXP_FID_GEN2_RUMBLE_SET, data, data_size);
896 }
897 
898 static ssize_t rumble_intensity_store(struct device *dev,
899 				      struct device_attribute *attr, const char *buf,
900 				      size_t count)
901 {
902 	int ret;
903 	u8 val;
904 
905 	ret = kstrtou8(buf, 10, &val);
906 	if (ret)
907 		return ret;
908 
909 	if (val < 0 || val > 5)
910 		return -EINVAL;
911 
912 	ret = oxp_rumble_intensity_set(val);
913 	if (ret)
914 		return ret;
915 
916 	drvdata.rumble_intensity = val;
917 
918 	return count;
919 }
920 
921 static ssize_t rumble_intensity_show(struct device *dev,
922 				     struct device_attribute *attr, char *buf)
923 {
924 	return sysfs_emit(buf, "%i\n", drvdata.rumble_intensity);
925 }
926 static DEVICE_ATTR_RW(rumble_intensity);
927 
928 static ssize_t rumble_intensity_range_show(struct device *dev,
929 					   struct device_attribute *attr, char *buf)
930 {
931 	return sysfs_emit(buf, "0-5\n");
932 }
933 static DEVICE_ATTR_RO(rumble_intensity_range);
934 
935 #define OXP_DEVICE_ATTR_RW(_name, _group)                                     \
936 	static ssize_t _name##_store(struct device *dev,                      \
937 				     struct device_attribute *attr,           \
938 				     const char *buf, size_t count)           \
939 	{                                                                     \
940 		return _group##_store(dev, attr, buf, count, _name.index);    \
941 	}                                                                     \
942 	static ssize_t _name##_show(struct device *dev,                       \
943 				    struct device_attribute *attr, char *buf) \
944 	{                                                                     \
945 		return _group##_show(dev, attr, buf, _name.index);            \
946 	}                                                                     \
947 	static DEVICE_ATTR_RW(_name)
948 
949 static struct oxp_attr button_a = { BUTTON_A };
950 OXP_DEVICE_ATTR_RW(button_a, map_button);
951 
952 static struct oxp_attr button_b = { BUTTON_B };
953 OXP_DEVICE_ATTR_RW(button_b, map_button);
954 
955 static struct oxp_attr button_x = { BUTTON_X };
956 OXP_DEVICE_ATTR_RW(button_x, map_button);
957 
958 static struct oxp_attr button_y = { BUTTON_Y };
959 OXP_DEVICE_ATTR_RW(button_y, map_button);
960 
961 static struct oxp_attr button_lb = { BUTTON_LB };
962 OXP_DEVICE_ATTR_RW(button_lb, map_button);
963 
964 static struct oxp_attr button_rb = { BUTTON_RB };
965 OXP_DEVICE_ATTR_RW(button_rb, map_button);
966 
967 static struct oxp_attr button_lt = { BUTTON_LT };
968 OXP_DEVICE_ATTR_RW(button_lt, map_button);
969 
970 static struct oxp_attr button_rt = { BUTTON_RT };
971 OXP_DEVICE_ATTR_RW(button_rt, map_button);
972 
973 static struct oxp_attr button_start = { BUTTON_START };
974 OXP_DEVICE_ATTR_RW(button_start, map_button);
975 
976 static struct oxp_attr button_select = { BUTTON_SELECT };
977 OXP_DEVICE_ATTR_RW(button_select, map_button);
978 
979 static struct oxp_attr button_l3 = { BUTTON_L3 };
980 OXP_DEVICE_ATTR_RW(button_l3, map_button);
981 
982 static struct oxp_attr button_r3 = { BUTTON_R3 };
983 OXP_DEVICE_ATTR_RW(button_r3, map_button);
984 
985 static struct oxp_attr button_d_up = { BUTTON_DUP };
986 OXP_DEVICE_ATTR_RW(button_d_up, map_button);
987 
988 static struct oxp_attr button_d_down = { BUTTON_DDOWN };
989 OXP_DEVICE_ATTR_RW(button_d_down, map_button);
990 
991 static struct oxp_attr button_d_left = { BUTTON_DLEFT };
992 OXP_DEVICE_ATTR_RW(button_d_left, map_button);
993 
994 static struct oxp_attr button_d_right = { BUTTON_DRIGHT };
995 OXP_DEVICE_ATTR_RW(button_d_right, map_button);
996 
997 static struct oxp_attr button_m1 = { BUTTON_M1 };
998 OXP_DEVICE_ATTR_RW(button_m1, map_button);
999 
1000 static struct oxp_attr button_m2 = { BUTTON_M2 };
1001 OXP_DEVICE_ATTR_RW(button_m2, map_button);
1002 
1003 static struct attribute *oxp_cfg_attrs[] = {
1004 	&dev_attr_button_a.attr,
1005 	&dev_attr_button_b.attr,
1006 	&dev_attr_button_d_down.attr,
1007 	&dev_attr_button_d_left.attr,
1008 	&dev_attr_button_d_right.attr,
1009 	&dev_attr_button_d_up.attr,
1010 	&dev_attr_button_l3.attr,
1011 	&dev_attr_button_lb.attr,
1012 	&dev_attr_button_lt.attr,
1013 	&dev_attr_button_m1.attr,
1014 	&dev_attr_button_m2.attr,
1015 	&dev_attr_button_mapping_options.attr,
1016 	&dev_attr_button_r3.attr,
1017 	&dev_attr_button_rb.attr,
1018 	&dev_attr_button_rt.attr,
1019 	&dev_attr_button_select.attr,
1020 	&dev_attr_button_start.attr,
1021 	&dev_attr_button_x.attr,
1022 	&dev_attr_button_y.attr,
1023 	&dev_attr_gamepad_mode.attr,
1024 	&dev_attr_gamepad_mode_index.attr,
1025 	&dev_attr_reset_buttons.attr,
1026 	&dev_attr_rumble_intensity.attr,
1027 	&dev_attr_rumble_intensity_range.attr,
1028 	NULL,
1029 };
1030 
1031 static const struct attribute_group oxp_cfg_attrs_group = {
1032 	.attrs = oxp_cfg_attrs,
1033 };
1034 
1035 static int oxp_rgb_status_store(u8 enabled, u8 speed, u8 brightness)
1036 {
1037 	u16 up = get_usage_page(drvdata.hdev);
1038 	u8 *data;
1039 
1040 	/* Always default to max brightness and use intensity scaling when in
1041 	 * monocolor mode.
1042 	 */
1043 	switch (up) {
1044 	case GEN1_USAGE_PAGE:
1045 		data = (u8[4]) { OXP_SET_PROPERTY, enabled, speed, brightness };
1046 		if (drvdata.rgb_effect == OXP_EFFECT_MONO_LIST)
1047 			data[3] = 0x04;
1048 		return oxp_gen_1_property_out(OXP_FID_GEN1_RGB_SET, data, 4);
1049 	case GEN2_USAGE_PAGE:
1050 		data = (u8[6]) { OXP_SET_PROPERTY, 0x00, 0x02, enabled, speed, brightness };
1051 		if (drvdata.rgb_effect == OXP_EFFECT_MONO_LIST)
1052 			data[5] = 0x04;
1053 		return oxp_gen_2_property_out(OXP_FID_GEN2_STATUS_EVENT, data, 6);
1054 	default:
1055 		return -ENODEV;
1056 	}
1057 }
1058 
1059 static ssize_t oxp_rgb_status_show(void)
1060 {
1061 	u16 up = get_usage_page(drvdata.hdev);
1062 	u8 *data;
1063 
1064 	switch (up) {
1065 	case GEN1_USAGE_PAGE:
1066 		data = (u8[1]) { OXP_GET_PROPERTY };
1067 		return oxp_gen_1_property_out(OXP_FID_GEN1_RGB_SET, data, 1);
1068 	case GEN2_USAGE_PAGE:
1069 		data = (u8[3]) { OXP_GET_PROPERTY, 0x00, 0x02 };
1070 		return oxp_gen_2_property_out(OXP_FID_GEN2_STATUS_EVENT, data, 3);
1071 	default:
1072 		return -ENODEV;
1073 	}
1074 }
1075 
1076 static int oxp_rgb_color_set(void)
1077 {
1078 	u8 max_br = drvdata.led_mc->led_cdev.max_brightness;
1079 	u8 br = drvdata.led_mc->led_cdev.brightness;
1080 	u16 up = get_usage_page(drvdata.hdev);
1081 	u8 green, red, blue;
1082 	size_t size;
1083 	u8 *data;
1084 	int i;
1085 
1086 	red = br * drvdata.led_mc->subled_info[0].intensity / max_br;
1087 	green = br * drvdata.led_mc->subled_info[1].intensity / max_br;
1088 	blue = br * drvdata.led_mc->subled_info[2].intensity / max_br;
1089 
1090 	switch (up) {
1091 	case GEN1_USAGE_PAGE:
1092 		size = 55;
1093 		data = (u8[55]) { OXP_EFFECT_MONO_TRUE };
1094 
1095 		for (i = 0; i < (size - 1) / 3; i++) {
1096 			data[3 * i + 1] = red;
1097 			data[3 * i + 2] = green;
1098 			data[3 * i + 3] = blue;
1099 		}
1100 		return oxp_gen_1_property_out(OXP_FID_GEN1_RGB_SET, data, size);
1101 	case GEN2_USAGE_PAGE:
1102 		size = 57;
1103 		data = (u8[57]) { OXP_EFFECT_MONO_TRUE, 0x00, 0x02 };
1104 
1105 		for (i = 1; i < size / 3; i++) {
1106 			data[3 * i] = red;
1107 			data[3 * i + 1] = green;
1108 			data[3 * i + 2] = blue;
1109 		}
1110 		return oxp_gen_2_property_out(OXP_FID_GEN2_STATUS_EVENT, data, size);
1111 	default:
1112 		return -ENODEV;
1113 	}
1114 }
1115 
1116 static int oxp_rgb_effect_set(u8 effect)
1117 {
1118 	u16 up = get_usage_page(drvdata.hdev);
1119 	u8 *data;
1120 	int ret;
1121 
1122 	switch (effect) {
1123 	case OXP_EFFECT_AURORA:
1124 	case OXP_EFFECT_BIRTHDAY:
1125 	case OXP_EFFECT_FLOWING:
1126 	case OXP_EFFECT_CHROMA_1:
1127 	case OXP_EFFECT_NEON:
1128 	case OXP_EFFECT_CHROMA_2:
1129 	case OXP_EFFECT_DREAMY:
1130 	case OXP_EFFECT_WARM:
1131 	case OXP_EFFECT_CYBERPUNK:
1132 	case OXP_EFFECT_SEA:
1133 	case OXP_EFFECT_SUNSET:
1134 	case OXP_EFFECT_COLORFUL:
1135 	case OXP_EFFECT_MONSTER:
1136 	case OXP_EFFECT_GREEN:
1137 	case OXP_EFFECT_BLUE:
1138 	case OXP_EFFECT_YELLOW:
1139 	case OXP_EFFECT_TEAL:
1140 	case OXP_EFFECT_PURPLE:
1141 	case OXP_EFFECT_FOGGY:
1142 		switch (up) {
1143 		case GEN1_USAGE_PAGE:
1144 			data = (u8[1]) { effect };
1145 			ret = oxp_gen_1_property_out(OXP_FID_GEN1_RGB_SET, data, 1);
1146 			break;
1147 		case GEN2_USAGE_PAGE:
1148 			data = (u8[3]) { effect, 0x00, 0x02 };
1149 			ret = oxp_gen_2_property_out(OXP_FID_GEN2_STATUS_EVENT, data, 3);
1150 			break;
1151 		default:
1152 			ret = -ENODEV;
1153 		}
1154 		break;
1155 	case OXP_EFFECT_MONO_LIST:
1156 		ret = oxp_rgb_color_set();
1157 		break;
1158 	default:
1159 		return -EINVAL;
1160 	}
1161 
1162 	if (ret)
1163 		return ret;
1164 
1165 	drvdata.rgb_effect = effect;
1166 
1167 	return 0;
1168 }
1169 
1170 static ssize_t enabled_store(struct device *dev, struct device_attribute *attr,
1171 			     const char *buf, size_t count)
1172 {
1173 	int ret;
1174 	u8 val;
1175 
1176 	ret = sysfs_match_string(oxp_feature_en_text, buf);
1177 	if (ret < 0)
1178 		return ret;
1179 	val = ret;
1180 
1181 	ret = oxp_rgb_status_store(val, drvdata.rgb_speed,
1182 				   drvdata.rgb_brightness);
1183 	if (ret)
1184 		return ret;
1185 
1186 	drvdata.rgb_en = val;
1187 	return count;
1188 }
1189 
1190 static ssize_t enabled_show(struct device *dev, struct device_attribute *attr,
1191 			    char *buf)
1192 {
1193 	int ret;
1194 
1195 	ret = oxp_rgb_status_show();
1196 	if (ret)
1197 		return ret;
1198 
1199 	if (drvdata.rgb_en >= ARRAY_SIZE(oxp_feature_en_text))
1200 		return -EINVAL;
1201 
1202 	return sysfs_emit(buf, "%s\n", oxp_feature_en_text[drvdata.rgb_en]);
1203 }
1204 static DEVICE_ATTR_RW(enabled);
1205 
1206 static ssize_t enabled_index_show(struct device *dev,
1207 				  struct device_attribute *attr, char *buf)
1208 {
1209 	size_t count = 0;
1210 	unsigned int i;
1211 
1212 	for (i = 0; i < ARRAY_SIZE(oxp_feature_en_text); i++)
1213 		count += sysfs_emit_at(buf, count, "%s ", oxp_feature_en_text[i]);
1214 
1215 	if (count)
1216 		buf[count - 1] = '\n';
1217 
1218 	return count;
1219 }
1220 static DEVICE_ATTR_RO(enabled_index);
1221 
1222 static ssize_t effect_store(struct device *dev, struct device_attribute *attr,
1223 			    const char *buf, size_t count)
1224 {
1225 	int ret;
1226 	u8 val;
1227 
1228 	ret = sysfs_match_string(oxp_rgb_effect_text, buf);
1229 	if (ret < 0)
1230 		return ret;
1231 
1232 	val = ret;
1233 
1234 	ret = oxp_rgb_status_store(drvdata.rgb_en, drvdata.rgb_speed,
1235 				   drvdata.rgb_brightness);
1236 	if (ret)
1237 		return ret;
1238 
1239 	ret = oxp_rgb_effect_set(val);
1240 	if (ret)
1241 		return ret;
1242 
1243 	return count;
1244 }
1245 
1246 static ssize_t effect_show(struct device *dev, struct device_attribute *attr,
1247 			   char *buf)
1248 {
1249 	int ret;
1250 
1251 	ret = oxp_rgb_status_show();
1252 	if (ret)
1253 		return ret;
1254 
1255 	if (drvdata.rgb_effect >= ARRAY_SIZE(oxp_rgb_effect_text))
1256 		return -EINVAL;
1257 
1258 	return sysfs_emit(buf, "%s\n", oxp_rgb_effect_text[drvdata.rgb_effect]);
1259 }
1260 
1261 static DEVICE_ATTR_RW(effect);
1262 
1263 static ssize_t effect_index_show(struct device *dev,
1264 				 struct device_attribute *attr, char *buf)
1265 {
1266 	size_t count = 0;
1267 	unsigned int i;
1268 
1269 	for (i = 1; i < ARRAY_SIZE(oxp_rgb_effect_text); i++)
1270 		count += sysfs_emit_at(buf, count, "%s ", oxp_rgb_effect_text[i]);
1271 
1272 	if (count)
1273 		buf[count - 1] = '\n';
1274 
1275 	return count;
1276 }
1277 static DEVICE_ATTR_RO(effect_index);
1278 
1279 static ssize_t speed_store(struct device *dev, struct device_attribute *attr,
1280 			   const char *buf, size_t count)
1281 {
1282 	int ret;
1283 	u8 val;
1284 
1285 	ret = kstrtou8(buf, 10, &val);
1286 	if (ret)
1287 		return ret;
1288 
1289 	if (val > 9)
1290 		return -EINVAL;
1291 
1292 	ret = oxp_rgb_status_store(drvdata.rgb_en, val, drvdata.rgb_brightness);
1293 	if (ret)
1294 		return ret;
1295 
1296 	drvdata.rgb_speed = val;
1297 	return count;
1298 }
1299 
1300 static ssize_t speed_show(struct device *dev, struct device_attribute *attr,
1301 			  char *buf)
1302 {
1303 	int ret;
1304 
1305 	ret = oxp_rgb_status_show();
1306 	if (ret)
1307 		return ret;
1308 
1309 	if (drvdata.rgb_speed > 9)
1310 		return -EINVAL;
1311 
1312 	return sysfs_emit(buf, "%hhu\n", drvdata.rgb_speed);
1313 }
1314 static DEVICE_ATTR_RW(speed);
1315 
1316 static ssize_t speed_range_show(struct device *dev,
1317 				struct device_attribute *attr, char *buf)
1318 {
1319 	return sysfs_emit(buf, "0-9\n");
1320 }
1321 static DEVICE_ATTR_RO(speed_range);
1322 
1323 static void oxp_rgb_queue_fn(struct work_struct *work)
1324 {
1325 	unsigned int max_brightness = drvdata.led_mc->led_cdev.max_brightness;
1326 	unsigned int brightness = drvdata.led_mc->led_cdev.brightness;
1327 	u8 val = 4 * brightness / max_brightness;
1328 	int ret;
1329 
1330 	if (drvdata.rgb_brightness != val) {
1331 		ret = oxp_rgb_status_store(drvdata.rgb_en, drvdata.rgb_speed, val);
1332 		if (ret)
1333 			dev_err(drvdata.led_mc->led_cdev.dev,
1334 				"Error: Failed to write RGB Status: %i\n", ret);
1335 
1336 		drvdata.rgb_brightness = val;
1337 	}
1338 
1339 	if (drvdata.rgb_effect != OXP_EFFECT_MONO_LIST)
1340 		return;
1341 
1342 	ret = oxp_rgb_effect_set(drvdata.rgb_effect);
1343 	if (ret)
1344 		dev_err(drvdata.led_mc->led_cdev.dev, "Error: Failed to write RGB color: %i\n",
1345 			ret);
1346 }
1347 
1348 static void oxp_rgb_brightness_set(struct led_classdev *led_cdev,
1349 				   enum led_brightness brightness)
1350 {
1351 	led_cdev->brightness = brightness;
1352 	mod_delayed_work(system_wq, &drvdata.oxp_rgb_queue, msecs_to_jiffies(50));
1353 }
1354 
1355 static struct attribute *oxp_rgb_attrs[] = {
1356 	&dev_attr_effect.attr,
1357 	&dev_attr_effect_index.attr,
1358 	&dev_attr_enabled.attr,
1359 	&dev_attr_enabled_index.attr,
1360 	&dev_attr_speed.attr,
1361 	&dev_attr_speed_range.attr,
1362 	NULL,
1363 };
1364 
1365 static const struct attribute_group oxp_rgb_attr_group = {
1366 	.attrs = oxp_rgb_attrs,
1367 };
1368 
1369 static struct mc_subled oxp_rgb_subled_info[] = {
1370 	{
1371 		.color_index = LED_COLOR_ID_RED,
1372 		.intensity = 0x24,
1373 		.channel = 0x1,
1374 	},
1375 	{
1376 		.color_index = LED_COLOR_ID_GREEN,
1377 		.intensity = 0x22,
1378 		.channel = 0x2,
1379 	},
1380 	{
1381 		.color_index = LED_COLOR_ID_BLUE,
1382 		.intensity = 0x99,
1383 		.channel = 0x3,
1384 	},
1385 };
1386 
1387 static struct led_classdev_mc oxp_cdev_rgb = {
1388 	.led_cdev = {
1389 		.name = "oxp:rgb:joystick_rings",
1390 		.color = LED_COLOR_ID_RGB,
1391 		.brightness = 0x64,
1392 		.max_brightness = 0x64,
1393 		.brightness_set = oxp_rgb_brightness_set,
1394 	},
1395 	.num_colors = ARRAY_SIZE(oxp_rgb_subled_info),
1396 	.subled_info = oxp_rgb_subled_info,
1397 };
1398 
1399 struct quirk_entry {
1400 	bool hybrid_mcu;
1401 };
1402 
1403 static struct quirk_entry quirk_hybrid_mcu = {
1404 	.hybrid_mcu = true,
1405 };
1406 
1407 static const struct dmi_system_id oxp_hybrid_mcu_list[] = {
1408 	{
1409 		.ident = "OneXPlayer Apex",
1410 		.matches = {
1411 			DMI_MATCH(DMI_SYS_VENDOR, "ONE-NETBOOK"),
1412 			DMI_MATCH(DMI_PRODUCT_NAME, "ONEXPLAYER APEX"),
1413 		},
1414 		.driver_data = &quirk_hybrid_mcu,
1415 	},
1416 	{
1417 		.ident = "OneXPlayer G1 AMD",
1418 		.matches = {
1419 			DMI_MATCH(DMI_SYS_VENDOR, "ONE-NETBOOK"),
1420 			DMI_MATCH(DMI_PRODUCT_NAME, "ONEXPLAYER G1 A"),
1421 		},
1422 		.driver_data = &quirk_hybrid_mcu,
1423 	},
1424 	{
1425 		.ident = "OneXPlayer G1 Intel",
1426 		.matches = {
1427 			DMI_MATCH(DMI_SYS_VENDOR, "ONE-NETBOOK"),
1428 			DMI_MATCH(DMI_PRODUCT_NAME, "ONEXPLAYER G1 i"),
1429 		},
1430 		.driver_data = &quirk_hybrid_mcu,
1431 	},
1432 	{},
1433 };
1434 
1435 static bool oxp_hybrid_mcu_device(void)
1436 {
1437 	const struct dmi_system_id *dmi_id;
1438 	struct quirk_entry *quirks;
1439 
1440 	dmi_id = dmi_first_match(oxp_hybrid_mcu_list);
1441 	if (!dmi_id)
1442 		return false;
1443 
1444 	quirks = dmi_id->driver_data;
1445 
1446 	return quirks->hybrid_mcu;
1447 }
1448 
1449 static int oxp_cfg_probe(struct hid_device *hdev, u16 up)
1450 {
1451 	struct oxp_bmap_page_1 *bmap_1;
1452 	struct oxp_bmap_page_2 *bmap_2;
1453 	int ret;
1454 
1455 	hid_set_drvdata(hdev, &drvdata);
1456 	mutex_init(&drvdata.cfg_mutex);
1457 	drvdata.hdev = hdev;
1458 
1459 	if (up == GEN2_USAGE_PAGE && oxp_hybrid_mcu_device())
1460 		goto skip_rgb;
1461 
1462 	drvdata.led_mc = &oxp_cdev_rgb;
1463 
1464 	INIT_DELAYED_WORK(&drvdata.oxp_rgb_queue, oxp_rgb_queue_fn);
1465 	ret = devm_led_classdev_multicolor_register(&hdev->dev, &oxp_cdev_rgb);
1466 	if (ret)
1467 		return dev_err_probe(&hdev->dev, ret,
1468 				     "Failed to create RGB device\n");
1469 
1470 	ret = devm_device_add_group(drvdata.led_mc->led_cdev.dev,
1471 				    &oxp_rgb_attr_group);
1472 	if (ret)
1473 		return dev_err_probe(drvdata.led_mc->led_cdev.dev, ret,
1474 				     "Failed to create RGB configuration attributes\n");
1475 
1476 	ret = oxp_rgb_status_show();
1477 	if (ret)
1478 		dev_warn(drvdata.led_mc->led_cdev.dev,
1479 			 "Failed to query RGB initial state: %i\n", ret);
1480 
1481 	/* Below features are only implemented in gen 2 */
1482 	if (up != GEN2_USAGE_PAGE)
1483 		return 0;
1484 
1485 skip_rgb:
1486 	bmap_1 = devm_kzalloc(&hdev->dev, sizeof(struct oxp_bmap_page_1), GFP_KERNEL);
1487 	if (!bmap_1)
1488 		return dev_err_probe(&hdev->dev, -ENOMEM,
1489 				     "Unable to allocate button map page 1\n");
1490 
1491 	bmap_2 = devm_kzalloc(&hdev->dev, sizeof(struct oxp_bmap_page_2), GFP_KERNEL);
1492 	if (!bmap_2)
1493 		return dev_err_probe(&hdev->dev, -ENOMEM,
1494 				     "Unable to allocate button map page 2\n");
1495 
1496 	drvdata.bmap_1 = bmap_1;
1497 	drvdata.bmap_2 = bmap_2;
1498 	oxp_reset_buttons();
1499 	INIT_DELAYED_WORK(&drvdata.oxp_btn_queue, oxp_btn_queue_fn);
1500 
1501 	drvdata.gamepad_mode = OXP_GP_MODE_XINPUT;
1502 	drvdata.rumble_intensity = 5;
1503 
1504 	INIT_DELAYED_WORK(&drvdata.oxp_mcu_init, oxp_mcu_init_fn);
1505 	mod_delayed_work(system_wq, &drvdata.oxp_mcu_init, msecs_to_jiffies(50));
1506 
1507 	ret = devm_device_add_group(&hdev->dev, &oxp_cfg_attrs_group);
1508 	if (ret)
1509 		return dev_err_probe(&hdev->dev, ret,
1510 				     "Failed to attach configuration attributes\n");
1511 
1512 	return 0;
1513 }
1514 
1515 static int oxp_hid_probe(struct hid_device *hdev,
1516 			 const struct hid_device_id *id)
1517 {
1518 	int ret;
1519 	u16 up;
1520 
1521 	ret = hid_parse(hdev);
1522 	if (ret)
1523 		return dev_err_probe(&hdev->dev, ret, "Failed to parse HID device\n");
1524 
1525 	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
1526 	if (ret)
1527 		return dev_err_probe(&hdev->dev, ret, "Failed to start HID device\n");
1528 
1529 	ret = hid_hw_open(hdev);
1530 	if (ret) {
1531 		hid_hw_stop(hdev);
1532 		return dev_err_probe(&hdev->dev, ret, "Failed to open HID device\n");
1533 	}
1534 
1535 	up = get_usage_page(hdev);
1536 	dev_dbg(&hdev->dev, "Got usage page %04x\n", up);
1537 
1538 	switch (up) {
1539 	case GEN1_USAGE_PAGE:
1540 	case GEN2_USAGE_PAGE:
1541 		ret = oxp_cfg_probe(hdev, up);
1542 		if (ret) {
1543 			hid_hw_close(hdev);
1544 			hid_hw_stop(hdev);
1545 		}
1546 
1547 		return ret;
1548 	default:
1549 		return 0;
1550 	}
1551 }
1552 
1553 static void oxp_hid_remove(struct hid_device *hdev)
1554 {
1555 	cancel_delayed_work(&drvdata.oxp_rgb_queue);
1556 	cancel_delayed_work(&drvdata.oxp_btn_queue);
1557 	cancel_delayed_work(&drvdata.oxp_mcu_init);
1558 	hid_hw_close(hdev);
1559 	hid_hw_stop(hdev);
1560 }
1561 
1562 static const struct hid_device_id oxp_devices[] = {
1563 	{ HID_USB_DEVICE(USB_VENDOR_ID_CRSC, USB_DEVICE_ID_ONEXPLAYER_GEN1) },
1564 	{ HID_USB_DEVICE(USB_VENDOR_ID_WCH, USB_DEVICE_ID_ONEXPLAYER_GEN2) },
1565 	{}
1566 };
1567 
1568 MODULE_DEVICE_TABLE(hid, oxp_devices);
1569 static struct hid_driver hid_oxp = {
1570 	.name = "hid-oxp",
1571 	.id_table = oxp_devices,
1572 	.probe = oxp_hid_probe,
1573 	.remove = oxp_hid_remove,
1574 	.raw_event = oxp_hid_raw_event,
1575 };
1576 module_hid_driver(hid_oxp);
1577 
1578 MODULE_AUTHOR("Derek J. Clark <derekjohn.clark@gmail.com>");
1579 MODULE_DESCRIPTION("Driver for OneXPlayer HID Interfaces");
1580 MODULE_LICENSE("GPL");
1581