diff options
| author | Jaeyeong Lee <[email protected]> | 2026-08-29 20:48:24 +0900 |
|---|---|---|
| committer | Rbb666 <[email protected]> | 2026-10-11 17:37:11 +0800 |
| commit | 8a3ca7bfa3fb0b779fe24fd912a3a72cc2aeb59d (patch) | |
| tree | 3c816b64788d3f5bb77372fe1804e63a2a60eb90 /components | |
| parent | 3577e7a6ed0f183534e207179de5251e155fd49e (diff) | |
fix[usb]: stop aliasing rt_ringbuffer as rt_serial_rx_fifo in VCOM
With RT_USB_DEVICE_CDC and RT_USING_SERIAL_V2 both enabled, _function_enable
assigned the embedded rx_ringbuffer to serial.serial_rx. Serial V2 reads that
pointer as a struct rt_serial_rx_fifo, whose first member is a rt_ringbuffer,
so ring-buffer access happened to work while rx_cpt, rx_cpt_index and
rx_timeout landed on the following members of struct vcom, corrupting tx_rbp.
The layout shifts again with RT_SERIAL_USING_DMA, which inserts dma_ping_rb
ahead of those fields.
Serial V2 already owns the receive FIFO: dev_serial_v2.c allocates it with
rt_malloc on open and releases it with rt_free on close, so the assignment
also made rt_free run on memory inside struct vcom.
Drop the assignment and read the FIFO Serial V2 owns. rt_hw_serial_isr
reports RX_IND from serial_rx->rb, so the endpoint handler now fills that
ring buffer and _vcom_getc drains it. The Serial V1 path is unchanged.
Fixes #11739
Signed-off-by: Jaeyeong Lee <[email protected]>
Diffstat (limited to 'components')
| -rw-r--r-- | components/legacy/usb/usbdevice/class/cdc_vcom.c | 27 |
1 files changed, 23 insertions, 4 deletions
diff --git a/components/legacy/usb/usbdevice/class/cdc_vcom.c b/components/legacy/usb/usbdevice/class/cdc_vcom.c index 44f013f005..7d4463ea89 100644 --- a/components/legacy/usb/usbdevice/class/cdc_vcom.c +++ b/components/legacy/usb/usbdevice/class/cdc_vcom.c @@ -338,6 +338,9 @@ static rt_err_t _ep_out_handler(ufunction_t func, rt_size_t size) { rt_base_t level; struct vcom *data; +#ifdef RT_USING_SERIAL_V2 + struct rt_serial_rx_fifo *rx_fifo; +#endif RT_ASSERT(func != RT_NULL); @@ -351,7 +354,15 @@ static rt_err_t _ep_out_handler(ufunction_t func, rt_size_t size) /* receive data from USB VCOM */ level = rt_hw_interrupt_disable(); +#ifdef RT_USING_SERIAL_V2 + rx_fifo = (struct rt_serial_rx_fifo *)data->serial.serial_rx; + if (rx_fifo != RT_NULL) + { + rt_ringbuffer_put(&rx_fifo->rb, data->ep_out->buffer, size); + } +#else rt_ringbuffer_put(&data->rx_ringbuffer, data->ep_out->buffer, size); +#endif rt_hw_interrupt_enable(level); /* notify receive data */ @@ -514,10 +525,6 @@ static rt_err_t _function_enable(ufunction_t func) data->ep_out->buffer = rt_malloc(CDC_RX_BUFSIZE); RT_ASSERT(data->ep_out->buffer != RT_NULL); -#ifdef RT_USING_SERIAL_V2 - data->serial.serial_rx = &data->rx_ringbuffer; -#endif - data->ep_out->request.buffer = data->ep_out->buffer; data->ep_out->request.size = EP_MAXPACKET(data->ep_out); @@ -719,18 +726,30 @@ static int _vcom_getc(struct rt_serial_device *serial) rt_base_t level; struct ufunction *func; struct vcom *data; +#ifdef RT_USING_SERIAL_V2 + struct rt_serial_rx_fifo *rx_fifo; +#endif func = (struct ufunction*)serial->parent.user_data; data = (struct vcom*)func->user_data; + RT_UNUSED(data); result = -1; level = rt_hw_interrupt_disable(); +#ifdef RT_USING_SERIAL_V2 + rx_fifo = (struct rt_serial_rx_fifo *)serial->serial_rx; + if(rx_fifo != RT_NULL && rt_ringbuffer_getchar(&rx_fifo->rb, &ch) != 0) + { + result = ch; + } +#else if(rt_ringbuffer_getchar(&data->rx_ringbuffer, &ch) != 0) { result = ch; } +#endif rt_hw_interrupt_enable(level); |
