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