8
8
#include "shared-bindings/usb/core/Device.h"
9
9
10
10
#include "tusb_config.h"
11
+ #include "supervisor/port.h"
12
+ #include "supervisor/port_heap.h"
11
13
12
14
#include "lib/tinyusb/src/host/hcd.h"
13
15
#include "lib/tinyusb/src/host/usbh.h"
@@ -33,6 +35,39 @@ void tuh_umount_cb(uint8_t dev_addr) {
33
35
34
36
static xfer_result_t _xfer_result ;
35
37
static size_t _actual_len ;
38
+
39
+ #if !CIRCUITPY_ALL_MEMORY_DMA_CAPABLE
40
+ // Helper to ensure buffer is DMA-capable for transfer operations
41
+ static uint8_t * _ensure_dma_buffer (usb_core_device_obj_t * self , const uint8_t * buffer , size_t len , bool for_write ) {
42
+ if (port_buffer_is_dma_capable (buffer )) {
43
+ return (uint8_t * )buffer ; // Already DMA-capable, use directly
44
+ }
45
+
46
+ // Need to allocate/reallocate temporary buffer in DMA-capable memory
47
+ if (self -> temp_buffer_size < len ) {
48
+ self -> temp_buffer = port_realloc (self -> temp_buffer , len , true); // true = DMA capable
49
+ if (self -> temp_buffer == NULL ) {
50
+ self -> temp_buffer_size = 0 ;
51
+ return NULL ; // Allocation failed
52
+ }
53
+ self -> temp_buffer_size = len ;
54
+ }
55
+
56
+ // Copy data to DMA buffer if writing
57
+ if (for_write && buffer != NULL ) {
58
+ memcpy (self -> temp_buffer , buffer , len );
59
+ }
60
+
61
+ return self -> temp_buffer ;
62
+ }
63
+
64
+ // Copy data back from DMA buffer to original buffer after read
65
+ static void _copy_from_dma_buffer (usb_core_device_obj_t * self , uint8_t * original_buffer , size_t len ) {
66
+ if (!port_buffer_is_dma_capable (original_buffer ) && self -> temp_buffer != NULL ) {
67
+ memcpy (original_buffer , self -> temp_buffer , len );
68
+ }
69
+ }
70
+ #endif
36
71
bool common_hal_usb_core_device_construct (usb_core_device_obj_t * self , uint8_t device_address ) {
37
72
if (!tuh_inited ()) {
38
73
mp_raise_RuntimeError (MP_ERROR_TEXT ("No usb host port initialized" ));
@@ -46,6 +81,10 @@ bool common_hal_usb_core_device_construct(usb_core_device_obj_t *self, uint8_t d
46
81
}
47
82
self -> device_address = device_address ;
48
83
self -> first_langid = 0 ;
84
+ #if !CIRCUITPY_ALL_MEMORY_DMA_CAPABLE
85
+ self -> temp_buffer = NULL ;
86
+ self -> temp_buffer_size = 0 ;
87
+ #endif
49
88
_xfer_result = XFER_RESULT_INVALID ;
50
89
return true;
51
90
}
@@ -65,6 +104,14 @@ void common_hal_usb_core_device_deinit(usb_core_device_obj_t *self) {
65
104
self -> open_endpoints [i ] = 0 ;
66
105
}
67
106
}
107
+ #if !CIRCUITPY_ALL_MEMORY_DMA_CAPABLE
108
+ // Clean up temporary buffer
109
+ if (self -> temp_buffer != NULL ) {
110
+ port_free (self -> temp_buffer );
111
+ self -> temp_buffer = NULL ;
112
+ self -> temp_buffer_size = 0 ;
113
+ }
114
+ #endif
68
115
self -> device_address = 0 ;
69
116
}
70
117
@@ -399,10 +446,22 @@ mp_int_t common_hal_usb_core_device_write(usb_core_device_obj_t *self, mp_int_t
399
446
mp_raise_usb_core_USBError (NULL );
400
447
return 0 ;
401
448
}
449
+
450
+ #if !CIRCUITPY_ALL_MEMORY_DMA_CAPABLE
451
+ // Ensure buffer is in DMA-capable memory
452
+ uint8_t * dma_buffer = _ensure_dma_buffer (self , buffer , len , true); // true = for write
453
+ if (dma_buffer == NULL ) {
454
+ mp_raise_msg (& mp_type_MemoryError , MP_ERROR_TEXT ("Could not allocate DMA capable buffer" ));
455
+ return 0 ;
456
+ }
457
+ #else
458
+ uint8_t * dma_buffer = (uint8_t * )buffer ; // All memory is DMA-capable
459
+ #endif
460
+
402
461
tuh_xfer_t xfer ;
403
462
xfer .daddr = self -> device_address ;
404
463
xfer .ep_addr = endpoint ;
405
- xfer .buffer = ( uint8_t * ) buffer ;
464
+ xfer .buffer = dma_buffer ;
406
465
xfer .buflen = len ;
407
466
return _xfer (& xfer , timeout );
408
467
}
@@ -412,12 +471,33 @@ mp_int_t common_hal_usb_core_device_read(usb_core_device_obj_t *self, mp_int_t e
412
471
mp_raise_usb_core_USBError (NULL );
413
472
return 0 ;
414
473
}
474
+
475
+ #if !CIRCUITPY_ALL_MEMORY_DMA_CAPABLE
476
+ // Ensure buffer is in DMA-capable memory
477
+ uint8_t * dma_buffer = _ensure_dma_buffer (self , buffer , len , false); // false = for read
478
+ if (dma_buffer == NULL ) {
479
+ mp_raise_msg (& mp_type_MemoryError , MP_ERROR_TEXT ("Could not allocate DMA capable buffer" ));
480
+ return 0 ;
481
+ }
482
+ #else
483
+ uint8_t * dma_buffer = buffer ; // All memory is DMA-capable
484
+ #endif
485
+
415
486
tuh_xfer_t xfer ;
416
487
xfer .daddr = self -> device_address ;
417
488
xfer .ep_addr = endpoint ;
418
- xfer .buffer = buffer ;
489
+ xfer .buffer = dma_buffer ;
419
490
xfer .buflen = len ;
420
- return _xfer (& xfer , timeout );
491
+ mp_int_t result = _xfer (& xfer , timeout );
492
+
493
+ #if !CIRCUITPY_ALL_MEMORY_DMA_CAPABLE
494
+ // Copy data back to original buffer if needed
495
+ if (result > 0 ) {
496
+ _copy_from_dma_buffer (self , buffer , result );
497
+ }
498
+ #endif
499
+
500
+ return result ;
421
501
}
422
502
423
503
mp_int_t common_hal_usb_core_device_ctrl_transfer (usb_core_device_obj_t * self ,
@@ -426,6 +506,23 @@ mp_int_t common_hal_usb_core_device_ctrl_transfer(usb_core_device_obj_t *self,
426
506
uint8_t * buffer , mp_int_t len , mp_int_t timeout ) {
427
507
// Timeout is in ms.
428
508
509
+ #if !CIRCUITPY_ALL_MEMORY_DMA_CAPABLE
510
+ // Determine if this is a write (host-to-device) or read (device-to-host) transfer
511
+ bool is_write = (bmRequestType & 0x80 ) == 0 ; // Bit 7: 0=host-to-device, 1=device-to-host
512
+
513
+ // Ensure buffer is in DMA-capable memory
514
+ uint8_t * dma_buffer = NULL ;
515
+ if (len > 0 && buffer != NULL ) {
516
+ dma_buffer = _ensure_dma_buffer (self , buffer , len , is_write );
517
+ if (dma_buffer == NULL ) {
518
+ mp_raise_msg (& mp_type_MemoryError , MP_ERROR_TEXT ("Could not allocate DMA capable buffer" ));
519
+ return 0 ;
520
+ }
521
+ }
522
+ #else
523
+ uint8_t * dma_buffer = buffer ; // All memory is DMA-capable
524
+ #endif
525
+
429
526
tusb_control_request_t request = {
430
527
.bmRequestType = bmRequestType ,
431
528
.bRequest = bRequest ,
@@ -437,7 +534,7 @@ mp_int_t common_hal_usb_core_device_ctrl_transfer(usb_core_device_obj_t *self,
437
534
.daddr = self -> device_address ,
438
535
.ep_addr = 0 ,
439
536
.setup = & request ,
440
- .buffer = buffer ,
537
+ .buffer = dma_buffer ,
441
538
.complete_cb = _transfer_done_cb ,
442
539
};
443
540
@@ -446,7 +543,16 @@ mp_int_t common_hal_usb_core_device_ctrl_transfer(usb_core_device_obj_t *self,
446
543
mp_raise_usb_core_USBError (NULL );
447
544
return 0 ;
448
545
}
449
- return (mp_int_t )_handle_timed_transfer_callback (& xfer , timeout );
546
+ mp_int_t result = (mp_int_t )_handle_timed_transfer_callback (& xfer , timeout );
547
+
548
+ #if !CIRCUITPY_ALL_MEMORY_DMA_CAPABLE
549
+ // Copy data back to original buffer if this was a read transfer and we got data
550
+ if ((bmRequestType & 0x80 ) != 0 && result > 0 && buffer != NULL ) { // Read transfer (device-to-host)
551
+ _copy_from_dma_buffer (self , buffer , result );
552
+ }
553
+ #endif
554
+
555
+ return result ;
450
556
}
451
557
452
558
bool common_hal_usb_core_device_is_kernel_driver_active (usb_core_device_obj_t * self , mp_int_t interface ) {
0 commit comments