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