|
76 | 76 |
|
77 | 77 | #define APPLETB_MAX_DIM_TIME 30 |
78 | 78 |
|
| 79 | +#define APPLE_MAGIC_KBD_BL_MAX 60 |
| 80 | + |
79 | 81 | static int appletb_tb_def_idle_timeout = 5 * 60; |
80 | 82 | module_param_named(idle_timeout, appletb_tb_def_idle_timeout, int, 0444); |
81 | 83 | MODULE_PARM_DESC(idle_timeout, "Default touch bar idle timeout:\n" |
@@ -199,6 +201,24 @@ static const struct appletb_key_translation appletb_fn_codes[] = { |
199 | 201 | { KEY_F12, KEY_VOLUMEUP }, |
200 | 202 | }; |
201 | 203 |
|
| 204 | +struct apple_magic_backlight { |
| 205 | + struct led_classdev cdev; |
| 206 | + struct usb_device dev; |
| 207 | +}; |
| 208 | + |
| 209 | +struct apple_magic_keyboard_backlight_report { |
| 210 | + u8 report_id; /* 0x01 */ |
| 211 | + u8 mode; /* If 0x00, brightness can turn off backlight */ |
| 212 | + u8 brightness; |
| 213 | + u8 override_1; /* If these are non-zero, backlight is overridden to max brightness */ |
| 214 | + u8 override_2; |
| 215 | + u8 max; /* The lower this is, the brighter each brightness value is. |
| 216 | + * Only takes affect after turning it off and on again. */ |
| 217 | + u8 rate; |
| 218 | + u8 magic_1; /* If these are non-zero, we are ignored. */ |
| 219 | + u8 magic_2; |
| 220 | +}; |
| 221 | + |
202 | 222 | static struct appletb_device *appletb_dev; |
203 | 223 |
|
204 | 224 | static int appletb_send_usb_ctrl(struct appletb_iface_info *iface_info, |
@@ -319,6 +339,77 @@ static int appletb_send_hid_report(struct appletb_iface_info *iface_info, |
319 | 339 | return rc; |
320 | 340 | } |
321 | 341 |
|
| 342 | +static int apple_magic_keyboard_backlight_set(struct apple_magic_backlight *backlight, char brightness, char rate) |
| 343 | +{ |
| 344 | + int tries = 0; |
| 345 | + int rc; |
| 346 | + struct apple_magic_keyboard_backlight_report *rep; |
| 347 | + |
| 348 | + rep = kmalloc(sizeof(*rep), GFP_KERNEL); |
| 349 | + if (rep == NULL) |
| 350 | + return -ENOMEM; |
| 351 | + |
| 352 | + rep->report_id = 0x01; |
| 353 | + rep->mode = brightness; |
| 354 | + rep->brightness = brightness; |
| 355 | + rep->max = 0x5e; |
| 356 | + rep->rate = rate; |
| 357 | + |
| 358 | + do { |
| 359 | + /* |
| 360 | + * FIXME: use appletb_send_hid_report, don't hard code all of this |
| 361 | + * Need to get apple_tb_send_hid_report to use wIndex=0x01 |
| 362 | + */ |
| 363 | + rc = usb_control_msg(&backlight->dev, |
| 364 | + usb_sndctrlpipe(&backlight->dev, 0), |
| 365 | + HID_REQ_SET_REPORT, USB_DIR_OUT | |
| 366 | + USB_TYPE_CLASS | USB_RECIP_INTERFACE, |
| 367 | + 0x0301, 0x01, rep, sizeof(*rep), |
| 368 | + 2000); |
| 369 | + if (rc != -EPIPE) |
| 370 | + break; |
| 371 | + |
| 372 | + usleep_range(1000 << tries, 3000 << tries); |
| 373 | + } while (++tries < 5); |
| 374 | + |
| 375 | + kfree(rep); |
| 376 | + return (rc > 0) ? 0 : rc; |
| 377 | +} |
| 378 | + |
| 379 | +static int apple_magic_keyboard_backlight_led_set(struct led_classdev *led_cdev, |
| 380 | + enum led_brightness brightness) |
| 381 | +{ |
| 382 | + struct apple_magic_backlight *backlight = container_of(led_cdev, |
| 383 | + struct apple_magic_backlight, cdev); |
| 384 | + |
| 385 | + return apple_magic_keyboard_backlight_set(backlight, brightness, 1); |
| 386 | +} |
| 387 | + |
| 388 | +static int apple_magic_keyboard_backlight_init(struct appletb_device *tb_dev) |
| 389 | +{ |
| 390 | + int ret; |
| 391 | + struct apple_magic_backlight *backlight; |
| 392 | + |
| 393 | + backlight = devm_kzalloc(tb_dev->log_dev, sizeof(*backlight), GFP_KERNEL); |
| 394 | + if (!backlight) |
| 395 | + return -ENOMEM; |
| 396 | + |
| 397 | + backlight->dev = *interface_to_usbdev(tb_dev->disp_iface.usb_iface); |
| 398 | + backlight->cdev.name = "apple::kbd_backlight"; |
| 399 | + backlight->cdev.max_brightness = APPLE_MAGIC_KBD_BL_MAX; |
| 400 | + backlight->cdev.brightness_set_blocking = apple_magic_keyboard_backlight_led_set; |
| 401 | + |
| 402 | + ret = apple_magic_keyboard_backlight_set(backlight, 0, 0); |
| 403 | + if (ret) { |
| 404 | + dev_err(tb_dev->log_dev, "Failed to initialise Magic Keyboard Backlight (%d)\n", ret); |
| 405 | + kfree(backlight); |
| 406 | + return ret; |
| 407 | + } |
| 408 | + |
| 409 | + ret = devm_led_classdev_register(tb_dev->log_dev, &backlight->cdev); |
| 410 | + return ret; |
| 411 | +} |
| 412 | + |
322 | 413 | static int appletb_set_tb_disp(struct appletb_device *tb_dev, |
323 | 414 | unsigned char disp) |
324 | 415 | { |
@@ -884,6 +975,13 @@ static int appletb_inp_connect(struct input_handler *handler, |
884 | 975 | if (id->driver_info == APPLETB_DEVID_KEYBOARD) { |
885 | 976 | handle = &tb_dev->kbd_handle; |
886 | 977 | handle->name = "tbkbd"; |
| 978 | + switch(dev->id.product) { |
| 979 | + case 0x0340u: /* MacBookPro16,1/4 */ |
| 980 | + case 0x027eu: /* MacBookPro16,2 */ |
| 981 | + case 0x027fu: /* MacBookPro16,3 */ |
| 982 | + apple_magic_keyboard_backlight_init(tb_dev); |
| 983 | + break; |
| 984 | + } |
887 | 985 | } else if (id->driver_info == APPLETB_DEVID_TOUCHPAD) { |
888 | 986 | handle = &tb_dev->tpd_handle; |
889 | 987 | handle->name = "tbtpad"; |
|
0 commit comments