* [PATCH v3 1/2] platform: chrome: lightbar: Report number of segments @ 2026-01-28 3:02 Gwendal Grignou 2026-01-28 3:02 ` [PATCH v3 2/2] platform: chrome: lightbar: Add support for large sequence Gwendal Grignou 2026-01-28 5:10 ` [PATCH v3 1/2] platform: chrome: lightbar: Report number of segments Tzung-Bi Shih 0 siblings, 2 replies; 4+ messages in thread From: Gwendal Grignou @ 2026-01-28 3:02 UTC (permalink / raw) To: tzungbi; +Cc: chrome-platform, Gwendal Grignou Add attribue `num_segments` to return the number of exposed LED segments in the lightbar. It can be smaller than the number of physical leds in the lightbar. Test: Check the attribute is present and returns a value when read. Signed-off-by: Gwendal Grignou <gwendal@google.com> --- Changes in v3: - Use proper field "insize" when setting tunning response size. Changes in v2: - Put local variables at beginning of num_segments_show() - Cleanup return logic. drivers/platform/chrome/cros_ec_lightbar.c | 45 ++++++++++++++++++- .../linux/platform_data/cros_ec_commands.h | 11 +++++ 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/drivers/platform/chrome/cros_ec_lightbar.c b/drivers/platform/chrome/cros_ec_lightbar.c index 87634f6921b7..30f3e24c84c0 100644 --- a/drivers/platform/chrome/cros_ec_lightbar.c +++ b/drivers/platform/chrome/cros_ec_lightbar.c @@ -119,7 +119,7 @@ static int get_lightbar_version(struct cros_ec_dev *ec, param = (struct ec_params_lightbar *)msg->data; param->cmd = LIGHTBAR_CMD_VERSION; msg->outsize = sizeof(param->cmd); - msg->result = sizeof(resp->version); + msg->insize = sizeof(resp->version); ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); if (ret < 0 && ret != -EINVAL) { ret = 0; @@ -173,6 +173,47 @@ static ssize_t version_show(struct device *dev, return sysfs_emit(buf, "%d %d\n", version, flags); } +static ssize_t num_segments_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ec_params_lightbar *param; + struct ec_response_lightbar *resp; + struct cros_ec_command *msg; + struct cros_ec_dev *ec = to_cros_ec_dev(dev); + uint32_t num = 0; + int ret; + + ret = lb_throttle(); + if (ret) + return ret; + + msg = alloc_lightbar_cmd_msg(ec); + if (!msg) + return -ENOMEM; + + param = (struct ec_params_lightbar *)msg->data; + param->cmd = LIGHTBAR_CMD_GET_PARAMS_V3; + msg->outsize = sizeof(param->cmd); + msg->insize = sizeof(resp->get_params_v3); + ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); + if (ret < 0 && ret != -EINVAL) + goto exit; + + if (msg->result == EC_RES_SUCCESS) { + resp = (struct ec_response_lightbar *)msg->data; + num = resp->get_params_v3.reported_led_num; + } + + /* + * Anything else (ie, EC_RES_INVALID_COMMAND) - no direct control over + * LEDs, return that no leds are supported. + */ + ret = sysfs_emit(buf, "%u\n", num); +exit: + kfree(msg); + return ret; +} + static ssize_t brightness_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -505,6 +546,7 @@ static ssize_t userspace_control_store(struct device *dev, /* Module initialization */ static DEVICE_ATTR_RW(interval_msec); +static DEVICE_ATTR_RO(num_segments); static DEVICE_ATTR_RO(version); static DEVICE_ATTR_WO(brightness); static DEVICE_ATTR_WO(led_rgb); @@ -514,6 +556,7 @@ static DEVICE_ATTR_RW(userspace_control); static struct attribute *__lb_cmds_attrs[] = { &dev_attr_interval_msec.attr, + &dev_attr_num_segments.attr, &dev_attr_version.attr, &dev_attr_brightness.attr, &dev_attr_led_rgb.attr, diff --git a/include/linux/platform_data/cros_ec_commands.h b/include/linux/platform_data/cros_ec_commands.h index 69294f79cc88..9cbf024f56c3 100644 --- a/include/linux/platform_data/cros_ec_commands.h +++ b/include/linux/platform_data/cros_ec_commands.h @@ -2005,6 +2005,14 @@ struct lightbar_params_v2_colors { struct rgb_s color[8]; /* 0-3 are Google colors */ } __ec_todo_packed; +struct lightbar_params_v3 { + /* + * Number of LEDs reported by the EC. + * May be less than the actual number of LEDs in the lightbar. + */ + uint8_t reported_led_num; +} __ec_todo_packed; + /* Lightbar program. */ #define EC_LB_PROG_LEN 192 struct lightbar_program { @@ -2086,6 +2094,8 @@ struct ec_response_lightbar { struct lightbar_params_v2_thresholds get_params_v2_thlds; struct lightbar_params_v2_colors get_params_v2_colors; + struct lightbar_params_v3 get_params_v3; + struct __ec_todo_unpacked { uint32_t num; uint32_t flags; @@ -2143,6 +2153,7 @@ enum lightbar_command { LIGHTBAR_CMD_SET_PARAMS_V2_THRESHOLDS = 31, LIGHTBAR_CMD_GET_PARAMS_V2_COLORS = 32, LIGHTBAR_CMD_SET_PARAMS_V2_COLORS = 33, + LIGHTBAR_CMD_GET_PARAMS_V3 = 34, LIGHTBAR_NUM_CMDS }; -- 2.53.0.rc1.225.gd81095ad13-goog ^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH v3 2/2] platform: chrome: lightbar: Add support for large sequence 2026-01-28 3:02 [PATCH v3 1/2] platform: chrome: lightbar: Report number of segments Gwendal Grignou @ 2026-01-28 3:02 ` Gwendal Grignou 2026-01-28 5:10 ` Tzung-Bi Shih 2026-01-28 5:10 ` [PATCH v3 1/2] platform: chrome: lightbar: Report number of segments Tzung-Bi Shih 1 sibling, 1 reply; 4+ messages in thread From: Gwendal Grignou @ 2026-01-28 3:02 UTC (permalink / raw) To: tzungbi; +Cc: chrome-platform, Gwendal Grignou Current sequences are limited to 192 bytes. Increase support to whatever the EC support. If the sequence is too long, the EC will return an OVERFLOW error. Test: Check sending a large sequence is received by the EC. Signed-off-by: Gwendal Grignou <gwendal@google.com> --- Changes in v3: - Fix allocation size for lightbar command. Use the maximal allowed sizes by default. Changes in v2: - Default initilization for lb_version. - Minimal changes in local variables definitions in program_store(). - Fix errors in cros_ec_commands.h: use a variable length array for payload. drivers/platform/chrome/cros_ec_lightbar.c | 88 +++++++++++++------ .../linux/platform_data/cros_ec_commands.h | 13 +++ 2 files changed, 74 insertions(+), 27 deletions(-) diff --git a/drivers/platform/chrome/cros_ec_lightbar.c b/drivers/platform/chrome/cros_ec_lightbar.c index 30f3e24c84c0..c24be6aa19a3 100644 --- a/drivers/platform/chrome/cros_ec_lightbar.c +++ b/drivers/platform/chrome/cros_ec_lightbar.c @@ -30,6 +30,11 @@ static unsigned long lb_interval_jiffies = 50 * HZ / 1000; */ static bool userspace_control; +/* + * Lightbar version + */ +static int lb_version; + static ssize_t interval_msec_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -86,11 +91,8 @@ static int lb_throttle(void) static struct cros_ec_command *alloc_lightbar_cmd_msg(struct cros_ec_dev *ec) { + int len = max(ec->ec_dev->max_response, ec->ec_dev->max_request); struct cros_ec_command *msg; - int len; - - len = max(sizeof(struct ec_params_lightbar), - sizeof(struct ec_response_lightbar)); msg = kmalloc(sizeof(*msg) + len, GFP_KERNEL); if (!msg) @@ -98,6 +100,11 @@ static struct cros_ec_command *alloc_lightbar_cmd_msg(struct cros_ec_dev *ec) msg->version = 0; msg->command = EC_CMD_LIGHTBAR_CMD + ec->cmd_offset; + /* + * Default sizes for regular commands. + * Can be set smaller to optimize transfer, + * larger when sending large light sequences. + */ msg->outsize = sizeof(struct ec_params_lightbar); msg->insize = sizeof(struct ec_response_lightbar); @@ -464,10 +471,11 @@ static ssize_t sequence_store(struct device *dev, struct device_attribute *attr, static ssize_t program_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - int extra_bytes, max_size, ret; + size_t extra_bytes, max_size; struct ec_params_lightbar *param; struct cros_ec_command *msg; struct cros_ec_dev *ec = to_cros_ec_dev(dev); + int ret; /* * We might need to reject the program for size reasons. The EC @@ -475,14 +483,22 @@ static ssize_t program_store(struct device *dev, struct device_attribute *attr, * and send a program that is too big for the protocol. In order * to ensure the latter, we also need to ensure we have extra bytes * to represent the rest of the packet. + * With V3, larger program can be sent, limited only by the EC. + * Only the protocol limit the payload size. */ - extra_bytes = sizeof(*param) - sizeof(param->set_program.data); - max_size = min(EC_LB_PROG_LEN, ec->ec_dev->max_request - extra_bytes); - if (count > max_size) { - dev_err(dev, "Program is %u bytes, too long to send (max: %u)", - (unsigned int)count, max_size); - - return -EINVAL; + if (lb_version < 3) { + extra_bytes = sizeof(*param) - sizeof(param->set_program.data); + max_size = min(EC_LB_PROG_LEN, ec->ec_dev->max_request - extra_bytes); + if (count > max_size) { + dev_err(dev, "Program is %zu bytes, too long to send (max: %zu)", + count, max_size); + + return -EINVAL; + } + } else { + extra_bytes = sizeof(*param) - sizeof(param->set_program) + + sizeof(param->set_program_ex); + max_size = ec->ec_dev->max_request - extra_bytes; } msg = alloc_lightbar_cmd_msg(ec); @@ -492,26 +508,44 @@ static ssize_t program_store(struct device *dev, struct device_attribute *attr, ret = lb_throttle(); if (ret) goto exit; + param = (struct ec_params_lightbar *)msg->data; - dev_info(dev, "Copying %zu byte program to EC", count); + if (lb_version < 3) { + dev_info(dev, "Copying %zu byte program to EC", count); - param = (struct ec_params_lightbar *)msg->data; - param->cmd = LIGHTBAR_CMD_SET_PROGRAM; + param->cmd = LIGHTBAR_CMD_SET_PROGRAM; - param->set_program.size = count; - memcpy(param->set_program.data, buf, count); + param->set_program.size = count; + memcpy(param->set_program.data, buf, count); - /* - * We need to set the message size manually or else it will use - * EC_LB_PROG_LEN. This might be too long, and the program - * is unlikely to use all of the space. - */ - msg->outsize = count + extra_bytes; + /* + * We need to set the message size manually or else it will use + * EC_LB_PROG_LEN. This might be too long, and the program + * is unlikely to use all of the space. + */ + msg->outsize = count + extra_bytes; - ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); - if (ret < 0) - goto exit; + ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); + if (ret < 0) + goto exit; + } else { + size_t offset = 0; + size_t payload = 0; + + param->cmd = LIGHTBAR_CMD_SET_PROGRAM_EX; + while (offset < count) { + payload = min(max_size, count - offset); + param->set_program_ex.offset = offset; + param->set_program_ex.size = payload; + memcpy(param->set_program_ex.data, &buf[offset], payload); + msg->outsize = payload + extra_bytes; + ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); + if (ret < 0) + goto exit; + offset += payload; + } + } ret = count; exit: kfree(msg); @@ -589,7 +623,7 @@ static int cros_ec_lightbar_probe(struct platform_device *pd) * Ask then for the lightbar version, if it's 0 then the 'cros_ec' * doesn't have a lightbar. */ - if (!get_lightbar_version(ec_dev, NULL, NULL)) + if (!get_lightbar_version(ec_dev, &lb_version, NULL)) return -ENODEV; /* Take control of the lightbar from the EC. */ diff --git a/include/linux/platform_data/cros_ec_commands.h b/include/linux/platform_data/cros_ec_commands.h index 9cbf024f56c3..144243143034 100644 --- a/include/linux/platform_data/cros_ec_commands.h +++ b/include/linux/platform_data/cros_ec_commands.h @@ -2020,6 +2020,17 @@ struct lightbar_program { uint8_t data[EC_LB_PROG_LEN]; } __ec_todo_unpacked; +/* + * Lightbar program for large sequences. Sequences are sent in pieces, with + * increasing offset. The sequences are still limited by the amount reserved in + * EC RAM. + */ +struct lightbar_program_ex { + uint16_t offset; + uint8_t size; + uint8_t data[0]; +} __ec_todo_unpacked; + struct ec_params_lightbar { uint8_t cmd; /* Command (see enum lightbar_command) */ union { @@ -2066,6 +2077,7 @@ struct ec_params_lightbar { struct lightbar_params_v2_colors set_v2par_colors; struct lightbar_program set_program; + struct lightbar_program_ex set_program_ex; }; } __ec_todo_packed; @@ -2154,6 +2166,7 @@ enum lightbar_command { LIGHTBAR_CMD_GET_PARAMS_V2_COLORS = 32, LIGHTBAR_CMD_SET_PARAMS_V2_COLORS = 33, LIGHTBAR_CMD_GET_PARAMS_V3 = 34, + LIGHTBAR_CMD_SET_PROGRAM_EX = 35, LIGHTBAR_NUM_CMDS }; -- 2.53.0.rc1.225.gd81095ad13-goog ^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH v3 2/2] platform: chrome: lightbar: Add support for large sequence 2026-01-28 3:02 ` [PATCH v3 2/2] platform: chrome: lightbar: Add support for large sequence Gwendal Grignou @ 2026-01-28 5:10 ` Tzung-Bi Shih 0 siblings, 0 replies; 4+ messages in thread From: Tzung-Bi Shih @ 2026-01-28 5:10 UTC (permalink / raw) To: Gwendal Grignou; +Cc: chrome-platform, Gwendal Grignou On Tue, Jan 27, 2026 at 07:02:59PM -0800, Gwendal Grignou wrote: > @@ -475,14 +483,22 @@ static ssize_t program_store(struct device *dev, struct device_attribute *attr, > * and send a program that is too big for the protocol. In order > * to ensure the latter, we also need to ensure we have extra bytes > * to represent the rest of the packet. > + * With V3, larger program can be sent, limited only by the EC. > + * Only the protocol limit the payload size. > */ > - extra_bytes = sizeof(*param) - sizeof(param->set_program.data); > - max_size = min(EC_LB_PROG_LEN, ec->ec_dev->max_request - extra_bytes); > - if (count > max_size) { > - dev_err(dev, "Program is %u bytes, too long to send (max: %u)", > - (unsigned int)count, max_size); > - > - return -EINVAL; > + if (lb_version < 3) { > + extra_bytes = sizeof(*param) - sizeof(param->set_program.data); > + max_size = min(EC_LB_PROG_LEN, ec->ec_dev->max_request - extra_bytes); > + if (count > max_size) { > + dev_err(dev, "Program is %zu bytes, too long to send (max: %zu)", > + count, max_size); > + > + return -EINVAL; > + } > + } else { > + extra_bytes = sizeof(*param) - sizeof(param->set_program) + > + sizeof(param->set_program_ex); > + max_size = ec->ec_dev->max_request - extra_bytes; Not sure if you read comments from v1 [1]. I still think the calculation of `extra_bytes` is tricky. [1] https://lore.kernel.org/chrome-platform/aXhWlV6SyaAAum-Q@google.com/ > diff --git a/include/linux/platform_data/cros_ec_commands.h b/include/linux/platform_data/cros_ec_commands.h > index 9cbf024f56c3..144243143034 100644 > --- a/include/linux/platform_data/cros_ec_commands.h > +++ b/include/linux/platform_data/cros_ec_commands.h > @@ -2020,6 +2020,17 @@ struct lightbar_program { > uint8_t data[EC_LB_PROG_LEN]; > } __ec_todo_unpacked; > > +/* > + * Lightbar program for large sequences. Sequences are sent in pieces, with > + * increasing offset. The sequences are still limited by the amount reserved in > + * EC RAM. > + */ > +struct lightbar_program_ex { > + uint16_t offset; > + uint8_t size; > + uint8_t data[0]; > +} __ec_todo_unpacked; Not sure if you read comments from v1 [1]. Please use flexible array member (i.e., []) and evaluate if it needs any flexible array helpers. ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v3 1/2] platform: chrome: lightbar: Report number of segments 2026-01-28 3:02 [PATCH v3 1/2] platform: chrome: lightbar: Report number of segments Gwendal Grignou 2026-01-28 3:02 ` [PATCH v3 2/2] platform: chrome: lightbar: Add support for large sequence Gwendal Grignou @ 2026-01-28 5:10 ` Tzung-Bi Shih 1 sibling, 0 replies; 4+ messages in thread From: Tzung-Bi Shih @ 2026-01-28 5:10 UTC (permalink / raw) To: Gwendal Grignou; +Cc: chrome-platform, Gwendal Grignou On Tue, Jan 27, 2026 at 07:02:58PM -0800, Gwendal Grignou wrote: > diff --git a/drivers/platform/chrome/cros_ec_lightbar.c b/drivers/platform/chrome/cros_ec_lightbar.c > index 87634f6921b7..30f3e24c84c0 100644 > --- a/drivers/platform/chrome/cros_ec_lightbar.c > +++ b/drivers/platform/chrome/cros_ec_lightbar.c > @@ -119,7 +119,7 @@ static int get_lightbar_version(struct cros_ec_dev *ec, > param = (struct ec_params_lightbar *)msg->data; > param->cmd = LIGHTBAR_CMD_VERSION; > msg->outsize = sizeof(param->cmd); > - msg->result = sizeof(resp->version); > + msg->insize = sizeof(resp->version); > ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); > if (ret < 0 && ret != -EINVAL) { > ret = 0; The change is independent. Can you move the change to a separate patch so that we can submit the fix first? ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-01-28 5:10 UTC | newest] Thread overview: 4+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-01-28 3:02 [PATCH v3 1/2] platform: chrome: lightbar: Report number of segments Gwendal Grignou 2026-01-28 3:02 ` [PATCH v3 2/2] platform: chrome: lightbar: Add support for large sequence Gwendal Grignou 2026-01-28 5:10 ` Tzung-Bi Shih 2026-01-28 5:10 ` [PATCH v3 1/2] platform: chrome: lightbar: Report number of segments Tzung-Bi Shih
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox