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