Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow vendor class to be used without FIFO. #2450

Merged
merged 16 commits into from
Sep 11, 2024
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions .idea/cmake.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

124 changes: 46 additions & 78 deletions examples/device/webusb_serial/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,7 @@ static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED;

#define URL "example.tinyusb.org/webusb-serial/index.html"

const tusb_desc_webusb_url_t desc_url =
{
const tusb_desc_webusb_url_t desc_url = {
.bLength = 3 + sizeof(URL) - 1,
.bDescriptorType = 3, // WEBUSB URL type
.bScheme = 1, // 0: http, 1: https
Expand All @@ -86,11 +85,9 @@ static bool web_serial_connected = false;
//------------- prototypes -------------//
void led_blinking_task(void);
void cdc_task(void);
void webserial_task(void);

/*------------- MAIN -------------*/
int main(void)
{
int main(void) {
board_init();

// init device stack on configured roothub port
Expand All @@ -100,33 +97,28 @@ int main(void)
board_init_after_tusb();
}

while (1)
{
while (1) {
tud_task(); // tinyusb device task
cdc_task();
webserial_task();
led_blinking_task();
}
}

// send characters to both CDC and WebUSB
void echo_all(uint8_t buf[], uint32_t count)
{
void echo_all(const uint8_t buf[], uint32_t count) {
// echo to web serial
if ( web_serial_connected )
{
if (web_serial_connected) {
tud_vendor_write(buf, count);
tud_vendor_write_flush();
}

// echo to cdc
if ( tud_cdc_connected() )
{
for(uint32_t i=0; i<count; i++)
{
if (tud_cdc_connected()) {
for (uint32_t i = 0; i < count; i++) {
tud_cdc_write_char(buf[i]);

if ( buf[i] == '\r' ) tud_cdc_write_char('\n');
if (buf[i] == '\r') {
tud_cdc_write_char('\n');
}
}
tud_cdc_write_flush();
}
Expand All @@ -137,29 +129,25 @@ void echo_all(uint8_t buf[], uint32_t count)
//--------------------------------------------------------------------+

// Invoked when device is mounted
void tud_mount_cb(void)
{
void tud_mount_cb(void) {
blink_interval_ms = BLINK_MOUNTED;
}

// Invoked when device is unmounted
void tud_umount_cb(void)
{
void tud_umount_cb(void) {
blink_interval_ms = BLINK_NOT_MOUNTED;
}

// Invoked when usb bus is suspended
// remote_wakeup_en : if host allow us to perform remote wakeup
// Within 7ms, device must draw an average of current less than 2.5 mA from bus
void tud_suspend_cb(bool remote_wakeup_en)
{
(void) remote_wakeup_en;
void tud_suspend_cb(bool remote_wakeup_en) {
(void)remote_wakeup_en;
blink_interval_ms = BLINK_SUSPENDED;
}

// Invoked when usb bus is resumed
void tud_resume_cb(void)
{
void tud_resume_cb(void) {
blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED;
}

Expand All @@ -170,61 +158,53 @@ void tud_resume_cb(void)
// Invoked when a control transfer occurred on an interface of this class
// Driver response accordingly to the request and the transfer stage (setup/data/ack)
// return false to stall control endpoint (e.g unsupported request)
bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request)
{
bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const* request) {
// nothing to with DATA & ACK stage
if (stage != CONTROL_STAGE_SETUP) return true;

switch (request->bmRequestType_bit.type)
{
switch (request->bmRequestType_bit.type) {
case TUSB_REQ_TYPE_VENDOR:
switch (request->bRequest)
{
switch (request->bRequest) {
case VENDOR_REQUEST_WEBUSB:
// match vendor request in BOS descriptor
// Get landing page url
return tud_control_xfer(rhport, request, (void*)(uintptr_t) &desc_url, desc_url.bLength);
return tud_control_xfer(rhport, request, (void*)(uintptr_t)&desc_url, desc_url.bLength);

case VENDOR_REQUEST_MICROSOFT:
if ( request->wIndex == 7 )
{
if (request->wIndex == 7) {
// Get Microsoft OS 2.0 compatible descriptor
uint16_t total_len;
memcpy(&total_len, desc_ms_os_20+8, 2);
memcpy(&total_len, desc_ms_os_20 + 8, 2);

return tud_control_xfer(rhport, request, (void*)(uintptr_t) desc_ms_os_20, total_len);
}else
{
return tud_control_xfer(rhport, request, (void*)(uintptr_t)desc_ms_os_20, total_len);
} else {
return false;
}

default: break;
}
break;
break;

case TUSB_REQ_TYPE_CLASS:
if (request->bRequest == 0x22)
{
if (request->bRequest == 0x22) {
// Webserial simulate the CDC_REQUEST_SET_CONTROL_LINE_STATE (0x22) to connect and disconnect.
web_serial_connected = (request->wValue != 0);

// Always lit LED if connected
if ( web_serial_connected )
{
if (web_serial_connected) {
board_led_write(true);
blink_interval_ms = BLINK_ALWAYS_ON;

tud_vendor_write_str("\r\nWebUSB interface connected\r\n");
tud_vendor_write_flush();
}else
{
} else {
blink_interval_ms = BLINK_MOUNTED;
}

// response with status OK
return tud_control_status(rhport, request);
}
break;
break;

default: break;
}
Expand All @@ -233,32 +213,24 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_requ
return false;
}

void webserial_task(void)
{
if ( web_serial_connected )
{
if ( tud_vendor_available() )
{
uint8_t buf[64];
uint32_t count = tud_vendor_read(buf, sizeof(buf));
void tud_vendor_rx_cb(uint8_t itf, uint8_t const* buffer, uint16_t bufsize) {
(void) itf;

// echo back to both web serial and cdc
echo_all(buf, count);
}
}
}
echo_all(buffer, bufsize);

// if using RX buffered is enabled, we need to flush the buffer to make room for new data
#if CFG_TUD_VENDOR_RX_BUFSIZE > 0
tud_vendor_read_flush();
#endif
}

//--------------------------------------------------------------------+
// USB CDC
//--------------------------------------------------------------------+
void cdc_task(void)
{
if ( tud_cdc_connected() )
{
void cdc_task(void) {
if (tud_cdc_connected()) {
// connected and there are data available
if ( tud_cdc_available() )
{
if (tud_cdc_available()) {
uint8_t buf[64];

uint32_t count = tud_cdc_read(buf, sizeof(buf));
Expand All @@ -270,34 +242,30 @@ void cdc_task(void)
}

// Invoked when cdc when line state changed e.g connected/disconnected
void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts)
{
(void) itf;
void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) {
(void)itf;

// connected
if ( dtr && rts )
{
if (dtr && rts) {
// print initial message when connected
tud_cdc_write_str("\r\nTinyUSB WebUSB device example\r\n");
}
}

// Invoked when CDC interface received data from host
void tud_cdc_rx_cb(uint8_t itf)
{
(void) itf;
void tud_cdc_rx_cb(uint8_t itf) {
(void)itf;
}

//--------------------------------------------------------------------+
// BLINKING TASK
//--------------------------------------------------------------------+
void led_blinking_task(void)
{
void led_blinking_task(void) {
static uint32_t start_ms = 0;
static bool led_state = false;

// Blink every interval ms
if ( board_millis() - start_ms < blink_interval_ms) return; // not enough time
if (board_millis() - start_ms < blink_interval_ms) return; // not enough time
start_ms += blink_interval_ms;

board_led_write(led_state);
Expand Down
2 changes: 1 addition & 1 deletion examples/device/webusb_serial/src/tusb_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@
#define CFG_TUD_CDC_TX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)

// Vendor FIFO size of TX and RX
// If not configured vendor endpoints will not be buffered
// If zero: vendor endpoints will not be buffered
#define CFG_TUD_VENDOR_RX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
#define CFG_TUD_VENDOR_TX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)

Expand Down
22 changes: 11 additions & 11 deletions src/class/cdc/cdc_host.c
Original file line number Diff line number Diff line change
Expand Up @@ -341,14 +341,14 @@ uint32_t tuh_cdc_write(uint8_t idx, void const* buffer, uint32_t bufsize) {
cdch_interface_t* p_cdc = get_itf(idx);
TU_VERIFY(p_cdc);

return tu_edpt_stream_write(&p_cdc->stream.tx, buffer, bufsize);
return tu_edpt_stream_write(p_cdc->daddr, &p_cdc->stream.tx, buffer, bufsize);
}

uint32_t tuh_cdc_write_flush(uint8_t idx) {
cdch_interface_t* p_cdc = get_itf(idx);
TU_VERIFY(p_cdc);

return tu_edpt_stream_write_xfer(&p_cdc->stream.tx);
return tu_edpt_stream_write_xfer(p_cdc->daddr, &p_cdc->stream.tx);
}

bool tuh_cdc_write_clear(uint8_t idx) {
Expand All @@ -362,7 +362,7 @@ uint32_t tuh_cdc_write_available(uint8_t idx) {
cdch_interface_t* p_cdc = get_itf(idx);
TU_VERIFY(p_cdc);

return tu_edpt_stream_write_available(&p_cdc->stream.tx);
return tu_edpt_stream_write_available(p_cdc->daddr, &p_cdc->stream.tx);
}

//--------------------------------------------------------------------+
Expand All @@ -373,7 +373,7 @@ uint32_t tuh_cdc_read (uint8_t idx, void* buffer, uint32_t bufsize) {
cdch_interface_t* p_cdc = get_itf(idx);
TU_VERIFY(p_cdc);

return tu_edpt_stream_read(&p_cdc->stream.rx, buffer, bufsize);
return tu_edpt_stream_read(p_cdc->daddr, &p_cdc->stream.rx, buffer, bufsize);
}

uint32_t tuh_cdc_read_available(uint8_t idx) {
Expand All @@ -395,7 +395,7 @@ bool tuh_cdc_read_clear (uint8_t idx) {
TU_VERIFY(p_cdc);

bool ret = tu_edpt_stream_clear(&p_cdc->stream.rx);
tu_edpt_stream_read_xfer(&p_cdc->stream.rx);
tu_edpt_stream_read_xfer(p_cdc->daddr, &p_cdc->stream.rx);
return ret;
}

Expand Down Expand Up @@ -677,10 +677,10 @@ bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t
// invoke tx complete callback to possibly refill tx fifo
if (tuh_cdc_tx_complete_cb) tuh_cdc_tx_complete_cb(idx);

if ( 0 == tu_edpt_stream_write_xfer(&p_cdc->stream.tx) ) {
if ( 0 == tu_edpt_stream_write_xfer(daddr, &p_cdc->stream.tx) ) {
// If there is no data left, a ZLP should be sent if:
// - xferred_bytes is multiple of EP Packet size and not zero
tu_edpt_stream_write_zlp_if_needed(&p_cdc->stream.tx, xferred_bytes);
tu_edpt_stream_write_zlp_if_needed(daddr, &p_cdc->stream.tx, xferred_bytes);
}
} else if ( ep_addr == p_cdc->stream.rx.ep_addr ) {
#if CFG_TUH_CDC_FTDI
Expand All @@ -698,7 +698,7 @@ bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t
if (tuh_cdc_rx_cb) tuh_cdc_rx_cb(idx);

// prepare for next transfer if needed
tu_edpt_stream_read_xfer(&p_cdc->stream.rx);
tu_edpt_stream_read_xfer(daddr, &p_cdc->stream.rx);
}else if ( ep_addr == p_cdc->ep_notif ) {
// TODO handle notification endpoint
}else {
Expand All @@ -719,9 +719,9 @@ static bool open_ep_stream_pair(cdch_interface_t* p_cdc, tusb_desc_endpoint_t co
TU_ASSERT(tuh_edpt_open(p_cdc->daddr, desc_ep));

if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) {
tu_edpt_stream_open(&p_cdc->stream.rx, p_cdc->daddr, desc_ep);
tu_edpt_stream_open(&p_cdc->stream.rx, desc_ep);
} else {
tu_edpt_stream_open(&p_cdc->stream.tx, p_cdc->daddr, desc_ep);
tu_edpt_stream_open(&p_cdc->stream.tx, desc_ep);
}

desc_ep = (tusb_desc_endpoint_t const*) tu_desc_next(desc_ep);
Expand Down Expand Up @@ -763,7 +763,7 @@ static void set_config_complete(cdch_interface_t * p_cdc, uint8_t idx, uint8_t i
if (tuh_cdc_mount_cb) tuh_cdc_mount_cb(idx);

// Prepare for incoming data
tu_edpt_stream_read_xfer(&p_cdc->stream.rx);
tu_edpt_stream_read_xfer(p_cdc->daddr, &p_cdc->stream.rx);

// notify usbh that driver enumeration is complete
usbh_driver_set_config_complete(p_cdc->daddr, itf_num);
Expand Down
Loading
Loading