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