36#include "ux_device_stack.h"
38#include "ux_utility.h"
107 if (tr->ux_slave_transfer_request_in_transfer_length != 0U &&
108 tr->ux_slave_transfer_request_data_pointer !=
nullptr) {
115 const uint16_t len = (uint16_t)tr->ux_slave_transfer_request_in_transfer_length;
118 return UX_TRANSFER_ERROR;
120 tr->ux_slave_transfer_request_actual_length = len;
124 return UX_TRANSFER_ERROR;
156#ifndef UX_DEVICE_STANDALONE
184 ULONG timeout = tr->ux_slave_transfer_request_timeout;
189 g_diag.xfer_req_pipe2_block++;
191 UINT sem_status = tx_semaphore_get(&tr->ux_slave_transfer_request_semaphore, timeout);
193 g_diag.xfer_req_pipe2_woken++;
198 g_dcd.pipes[pipe].xfer =
nullptr;
199 tr->ux_slave_transfer_request_completion_code = UX_TRANSFER_ERROR;
200 return UX_TRANSFER_ERROR;
202 return tr->ux_slave_transfer_request_completion_code;
237 const uint16_t req = (uint16_t)tr->ux_slave_transfer_request_requested_length;
238 const uint16_t mps =
g_dcd.pipes[pipe].max_pkt;
240 const uint16_t n = (held < req) ? held : req;
244 tr->ux_slave_transfer_request_actual_length = n;
246 bool done = (n >= req);
251 tr->ux_slave_transfer_request_completion_code = UX_SUCCESS;
252 g_dcd.pipes[pipe].xfer =
nullptr;
253#ifndef UX_DEVICE_STANDALONE
254 (void)tx_semaphore_put(&tr->ux_slave_transfer_request_semaphore);
260 g_dcd.pipes[pipe].xfer =
nullptr;
261 return UX_TRANSFER_ERROR;
291 uint32_t primask = 0U;
292 __asm__
volatile(
"mrs %0, primask" :
"=r"(primask));
293 __asm__
volatile(
"cpsid i" :::
"memory");
316 if ((primask & 1U) == 0U) {
317 __asm__
volatile(
"cpsie i" :::
"memory");
351 const uint16_t total = (uint16_t)tr->ux_slave_transfer_request_requested_length;
352 const uint16_t mps =
g_dcd.pipes[pipe].max_pkt;
353 const uint16_t chunk = (total > mps) ? mps : total;
360 g_dcd.pipes[pipe].xfer =
nullptr;
361 return UX_TRANSFER_ERROR;
363 tr->ux_slave_transfer_request_actual_length = chunk;
429 g_dcd.pipes[pipe].xfer =
nullptr;
430 return UX_TRANSFER_ERROR;
469 g_diag.xfer_req_null_arg++;
470 return UX_TRANSFER_ERROR;
472 if (tr->ux_slave_transfer_request_endpoint ==
nullptr) {
473 g_diag.xfer_req_null_arg++;
474 return UX_TRANSFER_ERROR;
477 UX_SLAVE_ENDPOINT* ep = tr->ux_slave_transfer_request_endpoint;
478 const uint8_t ep_addr = (uint8_t)ep->ux_slave_endpoint_descriptor.bEndpointAddress;
481 g_diag.xfer_req_bad_pipe++;
482 return UX_TRANSFER_ERROR;
485 g_diag.xfer_req_pipe2_in++;
487 g_diag.xfer_req_pipe2_out_dir++;
496 g_dcd.pipes[pipe].xfer = tr;
497 g_dcd.pipes[pipe].ep_addr = ep_addr;
498 g_dcd.pipes[pipe].dir_in =
500 g_dcd.pipes[pipe].max_pkt = (uint16_t)ep->ux_slave_endpoint_descriptor.wMaxPacketSize;
502 g_diag.xfer_req_pipe2_stashed++;
506 if (submit != UX_SUCCESS) {
510#ifndef UX_DEVICE_STANDALONE
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
Validation and Error-Checking Macros for ra8-firmware.
Event Link Controller (ELC) register layout for the Renesas RA8D2.
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
void * memcpy(void *dst, const void *src, size_t n)
Copy memory area between non-overlapping regions.
NVIC + ICU IELSR allocator.
Lightweight Logging Interface for ra8-firmware.
ra8_err_t ra8_usb_control_response(ra8_usb_speed_t speed, bool accept)
Issue a control-transfer status response on EP0.
ra8_err_t ra8_usb_rearm_out_pipe(ra8_usb_speed_t speed, uint8_t pipe_num)
Re-arm an OUT pipe that the controller has parked at PID=NAK.
ra8_err_t ra8_usb_queue_in(ra8_usb_speed_t speed, uint8_t pipe_num, const uint8_t *data, uint16_t len)
Queue an IN transfer (device -> host) on pipe_num.
ra8_err_t ra8_usb_dcp_in_data(ra8_usb_speed_t speed, const uint8_t *data, uint16_t len)
Push the EP0 / DCP IN data-stage payload for a control transfer.
USB Full-Speed + High-Speed controller layout for the Renesas RA8D2.
unsigned int UINT
ThreadX-compatible unsigned int (host stub).
unsigned long ULONG
ThreadX-compatible unsigned long (host stub).
USBX device-controller-driver (DCD) bridge to ra8_usb.
@ k_ux_dcd_ra8_usb_max_pipes
DCP + 9 PIPE entries (HUM 36.1).
USBX device-controller-driver bridge to ra8_usb – per-module cross-translation-unit contract.
void priv_trace_event(uint8_t kind, uint8_t code, uint16_t length)
Append one packed event to the JLink-readable trace ring.
uint16_t g_orphan_len
Held orphan byte count; 0 = empty.
ra8_usb_dcd_t g_dcd
The single bridge instance, defined in ux_dcd_ra8_usb.c.
@ k_dcd_trace_kind_ouse
Orphan packet fed to a transfer.
ra8_usb_dcd_diag_t g_diag
Bridge diagnostic counter block, defined in ux_dcd_ra8_usb.c.
@ k_ra8_usb_ep_addr_dir_in_bit
Direction bit set => IN endpoint.
@ k_ra8_usb_ep_addr_num_mask
Endpoint-number field (bits 3:0).
uint8_t g_orphan_buf[k_ra8_usb_orphan_bytes]
One held no-receiver bulk-OUT packet.
uint8_t g_orphan_pipe
Pipe the held orphan packet is on.
@ k_ra8_usb_orphan_bytes
One full-speed bulk MPS packet.
static unsigned int internal_ep0_transfer(struct UX_SLAVE_TRANSFER_STRUCT *tr)
Drive an EP0 / DCP control transfer (data or status stage).
static uint32_t internal_fifo_lock(void)
Enter a CFIFO critical section: mask interrupts.
uint8_t priv_ep_to_pipe(uint8_t ep_addr)
Map a USB EP number (1..9) into our PIPE table index.
static unsigned int internal_submit_in_pipe(struct UX_SLAVE_TRANSFER_STRUCT *tr, uint8_t pipe)
Stage the first chunk of an IN transfer (plus single-packet ZLP).
static unsigned int internal_submit_pipe(struct UX_SLAVE_TRANSFER_STRUCT *tr, uint8_t pipe, uint8_t ep_addr)
Submit the stashed IN/OUT transfer on a non-EP0 pipe.
static unsigned int internal_wait_completion(struct UX_SLAVE_TRANSFER_STRUCT *tr, uint8_t pipe)
Block on the USBX transfer semaphore until the IRQ posts completion.
static unsigned int internal_submit_consume_orphan(struct UX_SLAVE_TRANSFER_STRUCT *tr, uint8_t pipe)
Deliver a held orphan OUT packet to a freshly submitted transfer.
static void internal_fifo_unlock(uint32_t primask)
Leave a CFIFO critical section: restore the interrupt mask.
unsigned int priv_transfer_request(struct UX_SLAVE_TRANSFER_STRUCT *tr)
USBX UX_DCD_TRANSFER_REQUEST dispatcher entry point.