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