@@ -52,8 +52,8 @@ typedef struct {
52
52
cdc_acm_capability_t acm_capability ;
53
53
uint8_t ep_notif ;
54
54
55
- // Bit 0: DTR (Data Terminal Ready), Bit 1: RTS (Request to Send)
56
- uint8_t line_state ;
55
+ cdc_line_coding_t line_coding ; // Baudrate, stop bits, parity, data width
56
+ uint8_t line_state ; // DTR (bit0), RTS (bit1)
57
57
58
58
tuh_xfer_cb_t user_control_cb ;
59
59
@@ -240,6 +240,13 @@ static void cdch_internal_control_complete(tuh_xfer_t* xfer)
240
240
p_cdc -> line_state = (uint8_t ) tu_le16toh (xfer -> setup -> wValue );
241
241
break ;
242
242
243
+ case CDC_REQUEST_SET_LINE_CODING :
244
+ {
245
+ uint16_t const len = tu_min16 (sizeof (cdc_line_coding_t ), tu_le16toh (xfer -> setup -> wLength ));
246
+ memcpy (& p_cdc -> line_coding , xfer -> buffer , len );
247
+ }
248
+ break ;
249
+
243
250
default : break ;
244
251
}
245
252
}
@@ -265,7 +272,7 @@ bool tuh_cdc_set_control_line_state(uint8_t idx, uint16_t line_state, tuh_xfer_c
265
272
},
266
273
.bRequest = CDC_REQUEST_SET_CONTROL_LINE_STATE ,
267
274
.wValue = tu_htole16 (line_state ),
268
- .wIndex = tu_htole16 (p_cdc -> bInterfaceNumber ),
275
+ .wIndex = tu_htole16 (( uint16_t ) p_cdc -> bInterfaceNumber ),
269
276
.wLength = 0
270
277
};
271
278
@@ -283,6 +290,46 @@ bool tuh_cdc_set_control_line_state(uint8_t idx, uint16_t line_state, tuh_xfer_c
283
290
return tuh_control_xfer (& xfer );
284
291
}
285
292
293
+ bool tuh_cdc_set_line_coding (uint8_t idx , cdc_line_coding_t const * line_coding , tuh_xfer_cb_t complete_cb , uintptr_t user_data )
294
+ {
295
+ cdch_interface_t * p_cdc = get_itf (idx );
296
+ TU_VERIFY (p_cdc && p_cdc -> acm_capability .support_line_request );
297
+
298
+ TU_LOG_CDCH ("CDC Set Line Conding\r\n" );
299
+
300
+ tusb_control_request_t const request =
301
+ {
302
+ .bmRequestType_bit =
303
+ {
304
+ .recipient = TUSB_REQ_RCPT_INTERFACE ,
305
+ .type = TUSB_REQ_TYPE_CLASS ,
306
+ .direction = TUSB_DIR_OUT
307
+ },
308
+ .bRequest = CDC_REQUEST_SET_LINE_CODING ,
309
+ .wValue = 0 ,
310
+ .wIndex = tu_htole16 (p_cdc -> bInterfaceNumber ),
311
+ .wLength = tu_htole16 (sizeof (cdc_line_coding_t ))
312
+ };
313
+
314
+ // use usbh enum buf to hold line coding since user line_coding variable may not live long enough
315
+ // for the transfer to complete
316
+ uint8_t * enum_buf = usbh_get_enum_buf ();
317
+ memcpy (enum_buf , line_coding , sizeof (cdc_line_coding_t ));
318
+
319
+ p_cdc -> user_control_cb = complete_cb ;
320
+ tuh_xfer_t xfer =
321
+ {
322
+ .daddr = p_cdc -> daddr ,
323
+ .ep_addr = 0 ,
324
+ .setup = & request ,
325
+ .buffer = enum_buf ,
326
+ .complete_cb = cdch_internal_control_complete ,
327
+ .user_data = user_data
328
+ };
329
+
330
+ return tuh_control_xfer (& xfer );
331
+ }
332
+
286
333
//--------------------------------------------------------------------+
287
334
// CLASS-USBH API
288
335
//--------------------------------------------------------------------+
@@ -448,46 +495,70 @@ bool cdch_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const *itf_d
448
495
return true;
449
496
}
450
497
451
- static void config_cdc_complete ( uint8_t daddr , uint8_t itf_num )
498
+ enum
452
499
{
453
- uint8_t const idx = tuh_cdc_itf_get_index (daddr , itf_num );
500
+ CONFIG_SET_CONTROL_LINE_STATE ,
501
+ CONFIG_SET_LINE_CODING ,
502
+ CONFIG_COMPLETE
503
+ };
454
504
455
- if (idx != TUSB_INDEX_INVALID )
505
+ static void process_cdc_config (tuh_xfer_t * xfer )
506
+ {
507
+ uintptr_t const state = xfer -> user_data ;
508
+ uint8_t const itf_num = (uint8_t ) tu_le16toh (xfer -> setup -> wIndex );
509
+ uint8_t const idx = tuh_cdc_itf_get_index (xfer -> daddr , itf_num );
510
+ TU_ASSERT (idx != TUSB_INDEX_INVALID , );
511
+
512
+ switch (state )
456
513
{
457
- if (tuh_cdc_mount_cb ) tuh_cdc_mount_cb (idx );
514
+ case CONFIG_SET_CONTROL_LINE_STATE :
515
+ #if CFG_TUH_CDC_LINE_CONTROL_ON_ENUM
516
+ TU_ASSERT ( tuh_cdc_set_control_line_state (idx , CFG_TUH_CDC_LINE_CONTROL_ON_ENUM , process_cdc_config , CONFIG_SET_LINE_CODING ), );
517
+ break ;
518
+ #endif
519
+ TU_ATTR_FALLTHROUGH ;
458
520
459
- // Prepare for incoming data
460
- cdch_interface_t * p_cdc = get_itf (idx );
461
- tu_edpt_stream_read_xfer (& p_cdc -> stream .rx );
462
- }
521
+ case CONFIG_SET_LINE_CODING :
522
+ #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM
523
+ {
524
+ cdc_line_coding_t line_coding = CFG_TUH_CDC_LINE_CODING_ON_ENUM ;
525
+ TU_ASSERT ( tuh_cdc_set_line_coding (idx , & line_coding , process_cdc_config , 0 ), );
526
+ break ;
527
+ }
528
+ #endif
529
+ TU_ATTR_FALLTHROUGH ;
463
530
464
- // notify usbh that driver enumeration is complete
465
- // itf_num+1 to account for data interface as well
466
- usbh_driver_set_config_complete (daddr , itf_num + 1 );
467
- }
531
+ case CONFIG_COMPLETE :
532
+ if (tuh_cdc_mount_cb ) tuh_cdc_mount_cb (idx );
468
533
469
- #if CFG_TUH_CDC_SET_DTRRTS_ON_ENUM
534
+ // Prepare for incoming data
535
+ cdch_interface_t * p_cdc = get_itf (idx );
536
+ tu_edpt_stream_read_xfer (& p_cdc -> stream .rx );
470
537
471
- static void config_set_dtr_rts_complete (tuh_xfer_t * xfer )
472
- {
473
- uint8_t const itf_num = (uint8_t ) tu_le16toh (xfer -> setup -> wIndex );
474
- config_cdc_complete (xfer -> daddr , itf_num );
538
+ // notify usbh that driver enumeration is complete
539
+ // itf_num+1 to account for data interface as well
540
+ usbh_driver_set_config_complete (xfer -> daddr , itf_num + 1 );
541
+ break ;
542
+
543
+ default : break ;
544
+ }
475
545
}
476
546
477
547
bool cdch_set_config (uint8_t daddr , uint8_t itf_num )
478
548
{
479
- uint8_t const idx = tuh_cdc_itf_get_index ( daddr , itf_num );
480
- return tuh_cdc_set_control_line_state ( idx , CFG_TUH_CDC_SET_DTRRTS_ON_ENUM , config_set_dtr_rts_complete , 0 ) ;
481
- }
549
+ // fake transfer to kick-off process
550
+ tusb_control_request_t request ;
551
+ request . wIndex = tu_htole16 (( uint16_t ) itf_num );
482
552
483
- #else
553
+ tuh_xfer_t xfer ;
554
+ xfer .daddr = daddr ;
555
+ xfer .result = XFER_RESULT_SUCCESS ;
556
+ xfer .setup = & request ;
557
+ xfer .user_data = CONFIG_SET_CONTROL_LINE_STATE ;
558
+
559
+ process_cdc_config (& xfer );
484
560
485
- bool cdch_set_config (uint8_t daddr , uint8_t itf_num )
486
- {
487
- config_cdc_complete (daddr , itf_num );
488
561
return true;
489
562
}
490
563
491
564
#endif
492
-
493
- #endif
0 commit comments