This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 5e3a85a54a0cfb92d77729a7081400b6ca229261
Author: Marco Casaroli <[email protected]>
AuthorDate: Mon Nov 2 10:12:28 2026 +0100

    drivers/leds/ws2812: Bound the byte order transformation to the LED chain.
    
    With CONFIG_WS2812_COMPONENT_TRANSFORM, a device with a byte order
    transformation sends the data through byte_order_buffer, which holds
    WS2812_RW_PIXEL_SIZE * nleds bytes.  ws2812_write() transformed the
    full request into this buffer, so a write past the end of the chain
    overflowed the buffer.  The lower half limits the length only after
    this copy.  ws2812_read() transformed the requested number of pixels
    also when the lower half returned fewer bytes or an error, so it copied
    memory after the buffer to the caller.
    
    Limit the length to the LEDs from the file position to the end of the
    chain before the transformation, as the lower halves do.  In the read
    path, transform only the bytes that the lower half returned.
    
    The transformation came with the AVR DA/DB WS2812 driver (#21338).  No
    in-tree lower half turns it on yet.
    
    Assisted-by: Claude Code:claude-opus-5-5
    Signed-off-by: Marco Casaroli <[email protected]>
---
 drivers/leds/ws2812.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 46 insertions(+), 5 deletions(-)

diff --git a/drivers/leds/ws2812.c b/drivers/leds/ws2812.c
index 26c23de9001..beb7b26bb96 100644
--- a/drivers/leds/ws2812.c
+++ b/drivers/leds/ws2812.c
@@ -279,6 +279,42 @@ static void ws2812_byte_order_transform_rgb(FAR const char 
*src,
     }
 }
 
+/****************************************************************************
+ * Name: ws2812_byte_order_len
+ *
+ * Description:
+ *   Limit a transfer through byte_order_buffer to the LEDs from the file
+ *   position to the end of the chain, so that it fits in the buffer.
+ *
+ * Input Parameters:
+ *   filep - Pointer system file data
+ *   priv  - The device
+ *   len   - Requested length in bytes
+ *
+ * Returned Value:
+ *   The length in bytes to transfer.
+ *
+ ****************************************************************************/
+
+static size_t ws2812_byte_order_len(FAR struct file *filep,
+                                    FAR struct ws2812_dev_s *priv,
+                                    size_t len)
+{
+  off_t size = (off_t)priv->nleds * WS2812_RW_PIXEL_SIZE;
+
+  if (filep->f_pos >= size)
+    {
+      return 0;
+    }
+
+  if (len > (size_t)(size - filep->f_pos))
+    {
+      len = size - filep->f_pos;
+    }
+
+  return len;
+}
+
 #  endif
 
 /****************************************************************************
@@ -402,6 +438,7 @@ ssize_t ws2812_write(FAR struct file *filep,
 #    ifdef CONFIG_WS2812_COMPONENT_TRANSFORM_RGB
           case WS2812_COMPONENT_TRANSFORM_RGB:
             {
+              len = ws2812_byte_order_len(filep, priv, len);
               ws2812_byte_order_transform_rgb(
                   data,
                   priv->byte_order_buffer,
@@ -497,12 +534,16 @@ ssize_t ws2812_read(FAR struct file *filep,
 #    ifdef CONFIG_WS2812_COMPONENT_TRANSFORM_RGB
           case WS2812_COMPONENT_TRANSFORM_RGB:
             {
+              len = ws2812_byte_order_len(filep, priv, len);
               res = priv->read(filep, priv->byte_order_buffer, len);
-              ws2812_byte_order_transform_rgb(
-                  priv->byte_order_buffer,
-                  data,
-                  len >> 2
-              );
+              if (res > 0)
+                {
+                  ws2812_byte_order_transform_rgb(
+                      priv->byte_order_buffer,
+                      data,
+                      res >> 2
+                  );
+                }
             }
             break;
 #    endif /* CONFIG_WS2812_COMPONENT_TRANSFORM_RGB */

Reply via email to