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