1 // SPDX-License-Identifier: GPL-2.0+ 2 // Expose the Chromebook Pixel lightbar to userspace 3 // 4 // Copyright (C) 2014 Google, Inc. 5 6 #include <linux/ctype.h> 7 #include <linux/delay.h> 8 #include <linux/device.h> 9 #include <linux/fs.h> 10 #include <linux/kobject.h> 11 #include <linux/kstrtox.h> 12 #include <linux/mod_devicetable.h> 13 #include <linux/module.h> 14 #include <linux/platform_data/cros_ec_commands.h> 15 #include <linux/platform_data/cros_ec_proto.h> 16 #include <linux/platform_device.h> 17 #include <linux/sched.h> 18 #include <linux/types.h> 19 #include <linux/uaccess.h> 20 #include <linux/slab.h> 21 22 #define DRV_NAME "cros-ec-lightbar" 23 24 /* Rate-limit the lightbar interface to prevent DoS. */ 25 static unsigned long lb_interval_jiffies = 50 * HZ / 1000; 26 27 /* 28 * Whether or not we have given userspace control of the lightbar. 29 * If this is true, we won't do anything during suspend/resume. 30 */ 31 static bool userspace_control; 32 33 /* 34 * Whether or not the lightbar supports the manual suspend commands. 35 * The Pixel 2013 (Link) does not while all other devices with a 36 * lightbar do. 37 */ 38 static bool has_manual_suspend; 39 40 /* 41 * Lightbar version 42 */ 43 static int lb_version; 44 45 static ssize_t interval_msec_show(struct device *dev, 46 struct device_attribute *attr, char *buf) 47 { 48 unsigned long msec = lb_interval_jiffies * 1000 / HZ; 49 50 return sysfs_emit(buf, "%lu\n", msec); 51 } 52 53 static ssize_t interval_msec_store(struct device *dev, 54 struct device_attribute *attr, 55 const char *buf, size_t count) 56 { 57 unsigned long msec; 58 59 if (kstrtoul(buf, 0, &msec)) 60 return -EINVAL; 61 62 lb_interval_jiffies = msec * HZ / 1000; 63 64 return count; 65 } 66 67 static DEFINE_MUTEX(lb_mutex); 68 /* Return 0 if able to throttle correctly, error otherwise */ 69 static int lb_throttle(void) 70 { 71 static unsigned long last_access; 72 unsigned long now, next_timeslot; 73 long delay; 74 int ret = 0; 75 76 mutex_lock(&lb_mutex); 77 78 now = jiffies; 79 next_timeslot = last_access + lb_interval_jiffies; 80 81 if (time_before(now, next_timeslot)) { 82 delay = (long)(next_timeslot) - (long)now; 83 set_current_state(TASK_INTERRUPTIBLE); 84 if (schedule_timeout(delay) > 0) { 85 /* interrupted - just abort */ 86 ret = -EINTR; 87 goto out; 88 } 89 now = jiffies; 90 } 91 92 last_access = now; 93 out: 94 mutex_unlock(&lb_mutex); 95 96 return ret; 97 } 98 99 static struct cros_ec_command *alloc_lightbar_cmd_msg(struct cros_ec_dev *ec) 100 { 101 int len = max(ec->ec_dev->max_response, ec->ec_dev->max_request); 102 struct cros_ec_command *msg; 103 104 msg = kmalloc(sizeof(*msg) + len, GFP_KERNEL); 105 if (!msg) 106 return NULL; 107 108 msg->version = 0; 109 msg->command = EC_CMD_LIGHTBAR_CMD + ec->cmd_offset; 110 /* 111 * Default sizes for regular commands. 112 * Can be set smaller to optimize transfer, 113 * larger when sending large light sequences. 114 */ 115 msg->outsize = sizeof(struct ec_params_lightbar); 116 msg->insize = sizeof(struct ec_response_lightbar); 117 118 return msg; 119 } 120 121 static int get_lightbar_version(struct cros_ec_dev *ec, 122 uint32_t *ver_ptr, uint32_t *flg_ptr) 123 { 124 struct ec_params_lightbar *param; 125 struct ec_response_lightbar *resp; 126 struct cros_ec_command *msg; 127 int ret; 128 129 msg = alloc_lightbar_cmd_msg(ec); 130 if (!msg) 131 return 0; 132 133 param = (struct ec_params_lightbar *)msg->data; 134 param->cmd = LIGHTBAR_CMD_VERSION; 135 msg->outsize = sizeof(param->cmd); 136 msg->insize = sizeof(resp->version); 137 ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); 138 if (ret < 0 && ret != -EINVAL) { 139 ret = 0; 140 goto exit; 141 } 142 143 switch (msg->result) { 144 case EC_RES_INVALID_PARAM: 145 /* Pixel had no version command. */ 146 if (ver_ptr) 147 *ver_ptr = 0; 148 if (flg_ptr) 149 *flg_ptr = 0; 150 ret = 1; 151 goto exit; 152 153 case EC_RES_SUCCESS: 154 resp = (struct ec_response_lightbar *)msg->data; 155 156 /* Future devices w/lightbars should implement this command */ 157 if (ver_ptr) 158 *ver_ptr = resp->version.num; 159 if (flg_ptr) 160 *flg_ptr = resp->version.flags; 161 ret = 1; 162 goto exit; 163 } 164 165 /* Anything else (ie, EC_RES_INVALID_COMMAND) - no lightbar */ 166 ret = 0; 167 exit: 168 kfree(msg); 169 return ret; 170 } 171 172 static ssize_t version_show(struct device *dev, 173 struct device_attribute *attr, char *buf) 174 { 175 uint32_t version = 0, flags = 0; 176 struct cros_ec_dev *ec = to_cros_ec_dev(dev); 177 int ret; 178 179 ret = lb_throttle(); 180 if (ret) 181 return ret; 182 183 /* This should always succeed, because we check during init. */ 184 if (!get_lightbar_version(ec, &version, &flags)) 185 return -EIO; 186 187 return sysfs_emit(buf, "%d %d\n", version, flags); 188 } 189 190 static ssize_t num_segments_show(struct device *dev, 191 struct device_attribute *attr, char *buf) 192 { 193 struct ec_params_lightbar *param; 194 struct ec_response_lightbar *resp; 195 struct cros_ec_command *msg; 196 struct cros_ec_dev *ec = to_cros_ec_dev(dev); 197 uint32_t num = 0; 198 int ret; 199 200 ret = lb_throttle(); 201 if (ret) 202 return ret; 203 204 msg = alloc_lightbar_cmd_msg(ec); 205 if (!msg) 206 return -ENOMEM; 207 208 param = (struct ec_params_lightbar *)msg->data; 209 param->cmd = LIGHTBAR_CMD_GET_PARAMS_V3; 210 msg->outsize = sizeof(param->cmd); 211 msg->insize = sizeof(resp->get_params_v3); 212 ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); 213 if (ret < 0 && ret != -EINVAL) 214 goto exit; 215 216 if (msg->result == EC_RES_SUCCESS) { 217 resp = (struct ec_response_lightbar *)msg->data; 218 num = resp->get_params_v3.reported_led_num; 219 } 220 221 /* 222 * Anything else (ie, EC_RES_INVALID_COMMAND) - no direct control over 223 * LEDs, return that no leds are supported. 224 */ 225 ret = sysfs_emit(buf, "%u\n", num); 226 exit: 227 kfree(msg); 228 return ret; 229 } 230 231 static ssize_t brightness_store(struct device *dev, 232 struct device_attribute *attr, 233 const char *buf, size_t count) 234 { 235 struct ec_params_lightbar *param; 236 struct cros_ec_command *msg; 237 int ret; 238 unsigned int val; 239 struct cros_ec_dev *ec = to_cros_ec_dev(dev); 240 241 if (kstrtouint(buf, 0, &val)) 242 return -EINVAL; 243 244 msg = alloc_lightbar_cmd_msg(ec); 245 if (!msg) 246 return -ENOMEM; 247 248 param = (struct ec_params_lightbar *)msg->data; 249 param->cmd = LIGHTBAR_CMD_SET_BRIGHTNESS; 250 param->set_brightness.num = val; 251 ret = lb_throttle(); 252 if (ret) 253 goto exit; 254 255 ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); 256 if (ret < 0) 257 goto exit; 258 259 ret = count; 260 exit: 261 kfree(msg); 262 return ret; 263 } 264 265 266 /* 267 * We expect numbers, and we'll keep reading until we find them, skipping over 268 * any whitespace (sysfs guarantees that the input is null-terminated). Every 269 * four numbers are sent to the lightbar as <LED,R,G,B>. We fail at the first 270 * parsing error, if we don't parse any numbers, or if we have numbers left 271 * over. 272 */ 273 static ssize_t led_rgb_store(struct device *dev, struct device_attribute *attr, 274 const char *buf, size_t count) 275 { 276 struct ec_params_lightbar *param; 277 struct cros_ec_command *msg; 278 struct cros_ec_dev *ec = to_cros_ec_dev(dev); 279 unsigned int val[4]; 280 int ret, i = 0, j = 0, ok = 0; 281 282 msg = alloc_lightbar_cmd_msg(ec); 283 if (!msg) 284 return -ENOMEM; 285 286 do { 287 /* Skip any whitespace */ 288 while (*buf && isspace(*buf)) 289 buf++; 290 291 if (!*buf) 292 break; 293 294 ret = sscanf(buf, "%i", &val[i++]); 295 if (ret == 0) 296 goto exit; 297 298 if (i == 4) { 299 param = (struct ec_params_lightbar *)msg->data; 300 param->cmd = LIGHTBAR_CMD_SET_RGB; 301 param->set_rgb.led = val[0]; 302 param->set_rgb.red = val[1]; 303 param->set_rgb.green = val[2]; 304 param->set_rgb.blue = val[3]; 305 /* 306 * Throttle only the first of every four transactions, 307 * so that the user can update all four LEDs at once. 308 */ 309 if ((j++ % 4) == 0) { 310 ret = lb_throttle(); 311 if (ret) 312 goto exit; 313 } 314 315 ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); 316 if (ret < 0) 317 goto exit; 318 319 i = 0; 320 ok = 1; 321 } 322 323 /* Skip over the number we just read */ 324 while (*buf && !isspace(*buf)) 325 buf++; 326 327 } while (*buf); 328 329 exit: 330 kfree(msg); 331 return (ok && i == 0) ? count : -EINVAL; 332 } 333 334 static char const *seqname[] = { 335 "ERROR", "S5", "S3", "S0", "S5S3", "S3S0", 336 "S0S3", "S3S5", "STOP", "RUN", "KONAMI", 337 "TAP", "PROGRAM", 338 }; 339 340 static ssize_t sequence_show(struct device *dev, 341 struct device_attribute *attr, char *buf) 342 { 343 struct ec_params_lightbar *param; 344 struct ec_response_lightbar *resp; 345 struct cros_ec_command *msg; 346 int ret; 347 struct cros_ec_dev *ec = to_cros_ec_dev(dev); 348 349 msg = alloc_lightbar_cmd_msg(ec); 350 if (!msg) 351 return -ENOMEM; 352 353 param = (struct ec_params_lightbar *)msg->data; 354 param->cmd = LIGHTBAR_CMD_GET_SEQ; 355 ret = lb_throttle(); 356 if (ret) 357 goto exit; 358 359 ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); 360 if (ret < 0) { 361 ret = sysfs_emit(buf, "XFER / EC ERROR %d / %d\n", ret, msg->result); 362 goto exit; 363 } 364 365 resp = (struct ec_response_lightbar *)msg->data; 366 if (resp->get_seq.num >= ARRAY_SIZE(seqname)) 367 ret = sysfs_emit(buf, "%d\n", resp->get_seq.num); 368 else 369 ret = sysfs_emit(buf, "%s\n", seqname[resp->get_seq.num]); 370 371 exit: 372 kfree(msg); 373 return ret; 374 } 375 376 static int lb_send_empty_cmd(struct cros_ec_dev *ec, uint8_t cmd) 377 { 378 struct ec_params_lightbar *param; 379 struct cros_ec_command *msg; 380 int ret; 381 382 msg = alloc_lightbar_cmd_msg(ec); 383 if (!msg) 384 return -ENOMEM; 385 386 param = (struct ec_params_lightbar *)msg->data; 387 param->cmd = cmd; 388 389 ret = lb_throttle(); 390 if (ret) 391 goto error; 392 393 ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); 394 if (ret < 0) 395 goto error; 396 397 ret = 0; 398 error: 399 kfree(msg); 400 401 return ret; 402 } 403 404 static int lb_manual_suspend_ctrl(struct cros_ec_dev *ec, uint8_t enable) 405 { 406 struct ec_params_lightbar *param; 407 struct cros_ec_command *msg; 408 int ret; 409 410 msg = alloc_lightbar_cmd_msg(ec); 411 if (!msg) 412 return -ENOMEM; 413 414 param = (struct ec_params_lightbar *)msg->data; 415 416 param->cmd = LIGHTBAR_CMD_MANUAL_SUSPEND_CTRL; 417 param->manual_suspend_ctrl.enable = enable; 418 419 ret = lb_throttle(); 420 if (ret) 421 goto error; 422 423 ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); 424 if (ret < 0) 425 goto error; 426 427 ret = 0; 428 error: 429 kfree(msg); 430 431 return ret; 432 } 433 434 static ssize_t sequence_store(struct device *dev, struct device_attribute *attr, 435 const char *buf, size_t count) 436 { 437 struct ec_params_lightbar *param; 438 struct cros_ec_command *msg; 439 unsigned int num; 440 int ret, len; 441 struct cros_ec_dev *ec = to_cros_ec_dev(dev); 442 443 for (len = 0; len < count; len++) 444 if (!isalnum(buf[len])) 445 break; 446 447 for (num = 0; num < ARRAY_SIZE(seqname); num++) 448 if (!strncasecmp(seqname[num], buf, len)) 449 break; 450 451 if (num >= ARRAY_SIZE(seqname)) { 452 ret = kstrtouint(buf, 0, &num); 453 if (ret) 454 return ret; 455 } 456 457 msg = alloc_lightbar_cmd_msg(ec); 458 if (!msg) 459 return -ENOMEM; 460 461 param = (struct ec_params_lightbar *)msg->data; 462 param->cmd = LIGHTBAR_CMD_SEQ; 463 param->seq.num = num; 464 ret = lb_throttle(); 465 if (ret) 466 goto exit; 467 468 ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); 469 if (ret < 0) 470 goto exit; 471 472 ret = count; 473 exit: 474 kfree(msg); 475 return ret; 476 } 477 478 static ssize_t program_store(struct device *dev, struct device_attribute *attr, 479 const char *buf, size_t count) 480 { 481 size_t extra_bytes, max_size; 482 struct ec_params_lightbar *param; 483 struct cros_ec_command *msg; 484 struct cros_ec_dev *ec = to_cros_ec_dev(dev); 485 int ret; 486 487 /* 488 * We might need to reject the program for size reasons. The EC 489 * enforces a maximum program size, but we also don't want to try 490 * and send a program that is too big for the protocol. In order 491 * to ensure the latter, we also need to ensure we have extra bytes 492 * to represent the rest of the packet. 493 * With V3, larger program can be sent, limited only by the EC. 494 * Only the protocol limit the payload size. 495 */ 496 if (lb_version < 3) { 497 extra_bytes = sizeof(*param) - sizeof(param->set_program.data); 498 max_size = min(EC_LB_PROG_LEN, ec->ec_dev->max_request - extra_bytes); 499 if (count > max_size) { 500 dev_err(dev, "Program is %zu bytes, too long to send (max: %zu)", 501 count, max_size); 502 503 return -EINVAL; 504 } 505 } else { 506 extra_bytes = offsetof(typeof(*param), set_program_ex) + 507 sizeof(param->set_program_ex); 508 max_size = ec->ec_dev->max_request - extra_bytes; 509 } 510 511 msg = alloc_lightbar_cmd_msg(ec); 512 if (!msg) 513 return -ENOMEM; 514 515 ret = lb_throttle(); 516 if (ret) 517 goto exit; 518 param = (struct ec_params_lightbar *)msg->data; 519 520 if (lb_version < 3) { 521 dev_info(dev, "Copying %zu byte program to EC", count); 522 523 param->cmd = LIGHTBAR_CMD_SET_PROGRAM; 524 525 param->set_program.size = count; 526 memcpy(param->set_program.data, buf, count); 527 528 /* 529 * We need to set the message size manually or else it will use 530 * EC_LB_PROG_LEN. This might be too long, and the program 531 * is unlikely to use all of the space. 532 */ 533 msg->outsize = count + extra_bytes; 534 535 ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); 536 if (ret < 0) 537 goto exit; 538 } else { 539 size_t offset = 0; 540 size_t payload = 0; 541 542 param->cmd = LIGHTBAR_CMD_SET_PROGRAM_EX; 543 while (offset < count) { 544 payload = min(max_size, count - offset); 545 param->set_program_ex.offset = offset; 546 param->set_program_ex.size = payload; 547 memcpy(param->set_program_ex.data, &buf[offset], payload); 548 msg->outsize = payload + extra_bytes; 549 550 ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); 551 if (ret < 0) 552 goto exit; 553 offset += payload; 554 } 555 } 556 ret = count; 557 exit: 558 kfree(msg); 559 560 return ret; 561 } 562 563 static ssize_t userspace_control_show(struct device *dev, 564 struct device_attribute *attr, 565 char *buf) 566 { 567 return sysfs_emit(buf, "%d\n", userspace_control); 568 } 569 570 static ssize_t userspace_control_store(struct device *dev, 571 struct device_attribute *attr, 572 const char *buf, 573 size_t count) 574 { 575 bool enable; 576 int ret; 577 578 ret = kstrtobool(buf, &enable); 579 if (ret < 0) 580 return ret; 581 582 userspace_control = enable; 583 584 return count; 585 } 586 587 /* Module initialization */ 588 589 static DEVICE_ATTR_RW(interval_msec); 590 static DEVICE_ATTR_RO(num_segments); 591 static DEVICE_ATTR_RO(version); 592 static DEVICE_ATTR_WO(brightness); 593 static DEVICE_ATTR_WO(led_rgb); 594 static DEVICE_ATTR_RW(sequence); 595 static DEVICE_ATTR_WO(program); 596 static DEVICE_ATTR_RW(userspace_control); 597 598 static struct attribute *__lb_cmds_attrs[] = { 599 &dev_attr_interval_msec.attr, 600 &dev_attr_num_segments.attr, 601 &dev_attr_version.attr, 602 &dev_attr_brightness.attr, 603 &dev_attr_led_rgb.attr, 604 &dev_attr_sequence.attr, 605 &dev_attr_program.attr, 606 &dev_attr_userspace_control.attr, 607 NULL, 608 }; 609 610 static const struct attribute_group cros_ec_lightbar_attr_group = { 611 .name = "lightbar", 612 .attrs = __lb_cmds_attrs, 613 }; 614 615 static int cros_ec_lightbar_probe(struct platform_device *pd) 616 { 617 struct cros_ec_dev *ec_dev = dev_get_drvdata(pd->dev.parent); 618 struct cros_ec_platform *pdata = dev_get_platdata(ec_dev->dev); 619 struct device *dev = &pd->dev; 620 int ret; 621 622 /* 623 * Only instantiate the lightbar if the EC name is 'cros_ec'. Other EC 624 * devices like 'cros_pd' doesn't have a lightbar. 625 */ 626 if (strcmp(pdata->ec_name, CROS_EC_DEV_NAME) != 0) 627 return -ENODEV; 628 629 /* 630 * Ask then for the lightbar version, if it's 0 then the 'cros_ec' 631 * doesn't have a lightbar. 632 */ 633 if (!get_lightbar_version(ec_dev, &lb_version, NULL)) 634 return -ENODEV; 635 636 /* Take control of the lightbar from the EC. */ 637 has_manual_suspend = (lb_manual_suspend_ctrl(ec_dev, 1) != -EINVAL); 638 639 ret = sysfs_create_group(&ec_dev->class_dev.kobj, 640 &cros_ec_lightbar_attr_group); 641 if (ret < 0) 642 dev_err(dev, "failed to create %s attributes. err=%d\n", 643 cros_ec_lightbar_attr_group.name, ret); 644 645 return ret; 646 } 647 648 static void cros_ec_lightbar_remove(struct platform_device *pd) 649 { 650 struct cros_ec_dev *ec_dev = dev_get_drvdata(pd->dev.parent); 651 652 sysfs_remove_group(&ec_dev->class_dev.kobj, 653 &cros_ec_lightbar_attr_group); 654 655 /* Let the EC take over the lightbar again. */ 656 if (has_manual_suspend) 657 lb_manual_suspend_ctrl(ec_dev, 0); 658 } 659 660 static int __maybe_unused cros_ec_lightbar_resume(struct device *dev) 661 { 662 struct cros_ec_dev *ec_dev = dev_get_drvdata(dev->parent); 663 664 if (userspace_control || !has_manual_suspend) 665 return 0; 666 667 return lb_send_empty_cmd(ec_dev, LIGHTBAR_CMD_RESUME); 668 } 669 670 static int __maybe_unused cros_ec_lightbar_suspend(struct device *dev) 671 { 672 struct cros_ec_dev *ec_dev = dev_get_drvdata(dev->parent); 673 674 if (userspace_control || !has_manual_suspend) 675 return 0; 676 677 return lb_send_empty_cmd(ec_dev, LIGHTBAR_CMD_SUSPEND); 678 } 679 680 static SIMPLE_DEV_PM_OPS(cros_ec_lightbar_pm_ops, 681 cros_ec_lightbar_suspend, cros_ec_lightbar_resume); 682 683 static const struct platform_device_id cros_ec_lightbar_id[] = { 684 { DRV_NAME, 0 }, 685 {} 686 }; 687 MODULE_DEVICE_TABLE(platform, cros_ec_lightbar_id); 688 689 static struct platform_driver cros_ec_lightbar_driver = { 690 .driver = { 691 .name = DRV_NAME, 692 .pm = &cros_ec_lightbar_pm_ops, 693 .probe_type = PROBE_PREFER_ASYNCHRONOUS, 694 }, 695 .probe = cros_ec_lightbar_probe, 696 .remove = cros_ec_lightbar_remove, 697 .id_table = cros_ec_lightbar_id, 698 }; 699 700 module_platform_driver(cros_ec_lightbar_driver); 701 702 MODULE_LICENSE("GPL"); 703 MODULE_DESCRIPTION("Expose the Chromebook Pixel's lightbar to userspace"); 704