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