aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform/chrome/cros_ec_lightbar.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/platform/chrome/cros_ec_lightbar.c')
-rw-r--r--drivers/platform/chrome/cros_ec_lightbar.c152
1 files changed, 103 insertions, 49 deletions
diff --git a/drivers/platform/chrome/cros_ec_lightbar.c b/drivers/platform/chrome/cros_ec_lightbar.c
index b4ff47a9069a..560e5d41b7ae 100644
--- a/drivers/platform/chrome/cros_ec_lightbar.c
+++ b/drivers/platform/chrome/cros_ec_lightbar.c
@@ -31,6 +31,7 @@
31#include <linux/sched.h> 31#include <linux/sched.h>
32#include <linux/types.h> 32#include <linux/types.h>
33#include <linux/uaccess.h> 33#include <linux/uaccess.h>
34#include <linux/slab.h>
34 35
35#include "cros_ec_dev.h" 36#include "cros_ec_dev.h"
36 37
@@ -91,54 +92,79 @@ out:
91 return ret; 92 return ret;
92} 93}
93 94
94#define INIT_MSG(P, R) { \ 95static struct cros_ec_command *alloc_lightbar_cmd_msg(void)
95 .command = EC_CMD_LIGHTBAR_CMD, \ 96{
96 .outsize = sizeof(*P), \ 97 struct cros_ec_command *msg;
97 .insize = sizeof(*R), \ 98 int len;
98 } 99
100 len = max(sizeof(struct ec_params_lightbar),
101 sizeof(struct ec_response_lightbar));
102
103 msg = kmalloc(sizeof(*msg) + len, GFP_KERNEL);
104 if (!msg)
105 return NULL;
106
107 msg->version = 0;
108 msg->command = EC_CMD_LIGHTBAR_CMD;
109 msg->outsize = sizeof(struct ec_params_lightbar);
110 msg->insize = sizeof(struct ec_response_lightbar);
111
112 return msg;
113}
99 114
100static int get_lightbar_version(struct cros_ec_device *ec, 115static int get_lightbar_version(struct cros_ec_device *ec,
101 uint32_t *ver_ptr, uint32_t *flg_ptr) 116 uint32_t *ver_ptr, uint32_t *flg_ptr)
102{ 117{
103 struct ec_params_lightbar *param; 118 struct ec_params_lightbar *param;
104 struct ec_response_lightbar *resp; 119 struct ec_response_lightbar *resp;
105 struct cros_ec_command msg = INIT_MSG(param, resp); 120 struct cros_ec_command *msg;
106 int ret; 121 int ret;
107 122
108 param = (struct ec_params_lightbar *)msg.outdata; 123 msg = alloc_lightbar_cmd_msg();
109 param->cmd = LIGHTBAR_CMD_VERSION; 124 if (!msg)
110 ret = cros_ec_cmd_xfer(ec, &msg);
111 if (ret < 0)
112 return 0; 125 return 0;
113 126
114 switch (msg.result) { 127 param = (struct ec_params_lightbar *)msg->data;
128 param->cmd = LIGHTBAR_CMD_VERSION;
129 ret = cros_ec_cmd_xfer(ec, msg);
130 if (ret < 0) {
131 ret = 0;
132 goto exit;
133 }
134
135 switch (msg->result) {
115 case EC_RES_INVALID_PARAM: 136 case EC_RES_INVALID_PARAM:
116 /* Pixel had no version command. */ 137 /* Pixel had no version command. */
117 if (ver_ptr) 138 if (ver_ptr)
118 *ver_ptr = 0; 139 *ver_ptr = 0;
119 if (flg_ptr) 140 if (flg_ptr)
120 *flg_ptr = 0; 141 *flg_ptr = 0;
121 return 1; 142 ret = 1;
143 goto exit;
122 144
123 case EC_RES_SUCCESS: 145 case EC_RES_SUCCESS:
124 resp = (struct ec_response_lightbar *)msg.indata; 146 resp = (struct ec_response_lightbar *)msg->data;
125 147
126 /* Future devices w/lightbars should implement this command */ 148 /* Future devices w/lightbars should implement this command */
127 if (ver_ptr) 149 if (ver_ptr)
128 *ver_ptr = resp->version.num; 150 *ver_ptr = resp->version.num;
129 if (flg_ptr) 151 if (flg_ptr)
130 *flg_ptr = resp->version.flags; 152 *flg_ptr = resp->version.flags;
131 return 1; 153 ret = 1;
154 goto exit;
132 } 155 }
133 156
134 /* Anything else (ie, EC_RES_INVALID_COMMAND) - no lightbar */ 157 /* Anything else (ie, EC_RES_INVALID_COMMAND) - no lightbar */
135 return 0; 158 ret = 0;
159exit:
160 kfree(msg);
161 return ret;
136} 162}
137 163
138static ssize_t version_show(struct device *dev, 164static ssize_t version_show(struct device *dev,
139 struct device_attribute *attr, char *buf) 165 struct device_attribute *attr, char *buf)
140{ 166{
141 uint32_t version, flags; 167 uint32_t version = 0, flags = 0;
142 struct cros_ec_device *ec = dev_get_drvdata(dev); 168 struct cros_ec_device *ec = dev_get_drvdata(dev);
143 int ret; 169 int ret;
144 170
@@ -158,8 +184,7 @@ static ssize_t brightness_store(struct device *dev,
158 const char *buf, size_t count) 184 const char *buf, size_t count)
159{ 185{
160 struct ec_params_lightbar *param; 186 struct ec_params_lightbar *param;
161 struct ec_response_lightbar *resp; 187 struct cros_ec_command *msg;
162 struct cros_ec_command msg = INIT_MSG(param, resp);
163 int ret; 188 int ret;
164 unsigned int val; 189 unsigned int val;
165 struct cros_ec_device *ec = dev_get_drvdata(dev); 190 struct cros_ec_device *ec = dev_get_drvdata(dev);
@@ -167,21 +192,30 @@ static ssize_t brightness_store(struct device *dev,
167 if (kstrtouint(buf, 0, &val)) 192 if (kstrtouint(buf, 0, &val))
168 return -EINVAL; 193 return -EINVAL;
169 194
170 param = (struct ec_params_lightbar *)msg.outdata; 195 msg = alloc_lightbar_cmd_msg();
196 if (!msg)
197 return -ENOMEM;
198
199 param = (struct ec_params_lightbar *)msg->data;
171 param->cmd = LIGHTBAR_CMD_BRIGHTNESS; 200 param->cmd = LIGHTBAR_CMD_BRIGHTNESS;
172 param->brightness.num = val; 201 param->brightness.num = val;
173 ret = lb_throttle(); 202 ret = lb_throttle();
174 if (ret) 203 if (ret)
175 return ret; 204 goto exit;
176 205
177 ret = cros_ec_cmd_xfer(ec, &msg); 206 ret = cros_ec_cmd_xfer(ec, msg);
178 if (ret < 0) 207 if (ret < 0)
179 return ret; 208 goto exit;
180 209
181 if (msg.result != EC_RES_SUCCESS) 210 if (msg->result != EC_RES_SUCCESS) {
182 return -EINVAL; 211 ret = -EINVAL;
212 goto exit;
213 }
183 214
184 return count; 215 ret = count;
216exit:
217 kfree(msg);
218 return ret;
185} 219}
186 220
187 221
@@ -196,12 +230,15 @@ static ssize_t led_rgb_store(struct device *dev, struct device_attribute *attr,
196 const char *buf, size_t count) 230 const char *buf, size_t count)
197{ 231{
198 struct ec_params_lightbar *param; 232 struct ec_params_lightbar *param;
199 struct ec_response_lightbar *resp; 233 struct cros_ec_command *msg;
200 struct cros_ec_command msg = INIT_MSG(param, resp);
201 struct cros_ec_device *ec = dev_get_drvdata(dev); 234 struct cros_ec_device *ec = dev_get_drvdata(dev);
202 unsigned int val[4]; 235 unsigned int val[4];
203 int ret, i = 0, j = 0, ok = 0; 236 int ret, i = 0, j = 0, ok = 0;
204 237
238 msg = alloc_lightbar_cmd_msg();
239 if (!msg)
240 return -ENOMEM;
241
205 do { 242 do {
206 /* Skip any whitespace */ 243 /* Skip any whitespace */
207 while (*buf && isspace(*buf)) 244 while (*buf && isspace(*buf))
@@ -215,7 +252,7 @@ static ssize_t led_rgb_store(struct device *dev, struct device_attribute *attr,
215 return -EINVAL; 252 return -EINVAL;
216 253
217 if (i == 4) { 254 if (i == 4) {
218 param = (struct ec_params_lightbar *)msg.outdata; 255 param = (struct ec_params_lightbar *)msg->data;
219 param->cmd = LIGHTBAR_CMD_RGB; 256 param->cmd = LIGHTBAR_CMD_RGB;
220 param->rgb.led = val[0]; 257 param->rgb.led = val[0];
221 param->rgb.red = val[1]; 258 param->rgb.red = val[1];
@@ -231,12 +268,14 @@ static ssize_t led_rgb_store(struct device *dev, struct device_attribute *attr,
231 return ret; 268 return ret;
232 } 269 }
233 270
234 ret = cros_ec_cmd_xfer(ec, &msg); 271 ret = cros_ec_cmd_xfer(ec, msg);
235 if (ret < 0) 272 if (ret < 0)
236 return ret; 273 goto exit;
237 274
238 if (msg.result != EC_RES_SUCCESS) 275 if (msg->result != EC_RES_SUCCESS) {
239 return -EINVAL; 276 ret = -EINVAL;
277 goto exit;
278 }
240 279
241 i = 0; 280 i = 0;
242 ok = 1; 281 ok = 1;
@@ -248,6 +287,8 @@ static ssize_t led_rgb_store(struct device *dev, struct device_attribute *attr,
248 287
249 } while (*buf); 288 } while (*buf);
250 289
290exit:
291 kfree(msg);
251 return (ok && i == 0) ? count : -EINVAL; 292 return (ok && i == 0) ? count : -EINVAL;
252} 293}
253 294
@@ -261,42 +302,55 @@ static ssize_t sequence_show(struct device *dev,
261{ 302{
262 struct ec_params_lightbar *param; 303 struct ec_params_lightbar *param;
263 struct ec_response_lightbar *resp; 304 struct ec_response_lightbar *resp;
264 struct cros_ec_command msg = INIT_MSG(param, resp); 305 struct cros_ec_command *msg;
265 int ret; 306 int ret;
266 struct cros_ec_device *ec = dev_get_drvdata(dev); 307 struct cros_ec_device *ec = dev_get_drvdata(dev);
267 308
268 param = (struct ec_params_lightbar *)msg.outdata; 309 msg = alloc_lightbar_cmd_msg();
310 if (!msg)
311 return -ENOMEM;
312
313 param = (struct ec_params_lightbar *)msg->data;
269 param->cmd = LIGHTBAR_CMD_GET_SEQ; 314 param->cmd = LIGHTBAR_CMD_GET_SEQ;
270 ret = lb_throttle(); 315 ret = lb_throttle();
271 if (ret) 316 if (ret)
272 return ret; 317 goto exit;
273 318
274 ret = cros_ec_cmd_xfer(ec, &msg); 319 ret = cros_ec_cmd_xfer(ec, msg);
275 if (ret < 0) 320 if (ret < 0)
276 return ret; 321 goto exit;
277 322
278 if (msg.result != EC_RES_SUCCESS) 323 if (msg->result != EC_RES_SUCCESS) {
279 return scnprintf(buf, PAGE_SIZE, 324 ret = scnprintf(buf, PAGE_SIZE,
280 "ERROR: EC returned %d\n", msg.result); 325 "ERROR: EC returned %d\n", msg->result);
326 goto exit;
327 }
281 328
282 resp = (struct ec_response_lightbar *)msg.indata; 329 resp = (struct ec_response_lightbar *)msg->data;
283 if (resp->get_seq.num >= ARRAY_SIZE(seqname)) 330 if (resp->get_seq.num >= ARRAY_SIZE(seqname))
284 return scnprintf(buf, PAGE_SIZE, "%d\n", resp->get_seq.num); 331 ret = scnprintf(buf, PAGE_SIZE, "%d\n", resp->get_seq.num);
285 else 332 else
286 return scnprintf(buf, PAGE_SIZE, "%s\n", 333 ret = scnprintf(buf, PAGE_SIZE, "%s\n",
287 seqname[resp->get_seq.num]); 334 seqname[resp->get_seq.num]);
335
336exit:
337 kfree(msg);
338 return ret;
288} 339}
289 340
290static ssize_t sequence_store(struct device *dev, struct device_attribute *attr, 341static ssize_t sequence_store(struct device *dev, struct device_attribute *attr,
291 const char *buf, size_t count) 342 const char *buf, size_t count)
292{ 343{
293 struct ec_params_lightbar *param; 344 struct ec_params_lightbar *param;
294 struct ec_response_lightbar *resp; 345 struct cros_ec_command *msg;
295 struct cros_ec_command msg = INIT_MSG(param, resp);
296 unsigned int num; 346 unsigned int num;
297 int ret, len; 347 int ret, len;
298 struct cros_ec_device *ec = dev_get_drvdata(dev); 348 struct cros_ec_device *ec = dev_get_drvdata(dev);
299 349
350 msg = alloc_lightbar_cmd_msg();
351 if (!msg)
352 return -ENOMEM;
353
300 for (len = 0; len < count; len++) 354 for (len = 0; len < count; len++)
301 if (!isalnum(buf[len])) 355 if (!isalnum(buf[len]))
302 break; 356 break;
@@ -311,18 +365,18 @@ static ssize_t sequence_store(struct device *dev, struct device_attribute *attr,
311 return ret; 365 return ret;
312 } 366 }
313 367
314 param = (struct ec_params_lightbar *)msg.outdata; 368 param = (struct ec_params_lightbar *)msg->data;
315 param->cmd = LIGHTBAR_CMD_SEQ; 369 param->cmd = LIGHTBAR_CMD_SEQ;
316 param->seq.num = num; 370 param->seq.num = num;
317 ret = lb_throttle(); 371 ret = lb_throttle();
318 if (ret) 372 if (ret)
319 return ret; 373 return ret;
320 374
321 ret = cros_ec_cmd_xfer(ec, &msg); 375 ret = cros_ec_cmd_xfer(ec, msg);
322 if (ret < 0) 376 if (ret < 0)
323 return ret; 377 return ret;
324 378
325 if (msg.result != EC_RES_SUCCESS) 379 if (msg->result != EC_RES_SUCCESS)
326 return -EINVAL; 380 return -EINVAL;
327 381
328 return count; 382 return count;