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