|
31 | 31 | #include "tusb.h"
|
32 | 32 |
|
33 | 33 | size_t common_hal_usb_cdc_serial_read(usb_cdc_serial_obj_t *self, uint8_t *data, size_t len, int *errcode) {
|
34 |
| - if (self->timeout < 0.0f) { |
35 |
| - while (tud_cdc_n_available(self->idx) < len) { |
| 34 | + |
| 35 | + const bool wait_forever = self->timeout < 0.0f; |
| 36 | + const bool wait_for_timeout = self->timeout > 0.0f; |
| 37 | + |
| 38 | + // Read up to len bytes immediately. |
| 39 | + // The number of bytes read will not be larger than what is already in the TinyUSB FIFO. |
| 40 | + uint32_t total_num_read = tud_cdc_n_read(self->idx, data, len); |
| 41 | + |
| 42 | + if (wait_forever || wait_for_timeout) { |
| 43 | + // Read more if we have time. |
| 44 | + uint64_t timeout_ms = self->timeout * 1000; // Junk value if timeout < 0. |
| 45 | + uint64_t start_ticks = supervisor_ticks_ms64(); |
| 46 | + |
| 47 | + uint32_t num_read = 0; |
| 48 | + while (total_num_read < len && |
| 49 | + (wait_forever || supervisor_ticks_ms64() - start_ticks <= timeout_ms)) { |
| 50 | + |
| 51 | + // Wait for a bit, and check for ctrl-C. |
36 | 52 | RUN_BACKGROUND_TASKS;
|
37 | 53 | if (mp_hal_is_interrupted()) {
|
38 | 54 | return 0;
|
39 | 55 | }
|
| 56 | + |
| 57 | + // Advance buffer pointer and reduce number of bytes that need to be read. |
| 58 | + len -= num_read; |
| 59 | + data += num_read; |
| 60 | + |
| 61 | + // Try to read another batch of bytes. |
| 62 | + num_read = tud_cdc_n_read(self->idx, data, len); |
| 63 | + total_num_read += num_read; |
40 | 64 | }
|
41 |
| - } else if (self->timeout > 0.0f) { |
42 |
| - uint64_t timeout_ms = self->timeout * 1000; |
| 65 | + } |
| 66 | + |
| 67 | + return total_num_read; |
| 68 | +} |
| 69 | + |
| 70 | +size_t common_hal_usb_cdc_serial_write(usb_cdc_serial_obj_t *self, const uint8_t *data, size_t len, int *errcode) { |
| 71 | + const bool wait_forever = self->write_timeout < 0.0f; |
| 72 | + const bool wait_for_timeout = self->write_timeout > 0.0f; |
| 73 | + |
| 74 | + // Write as many bytes as possible immediately. |
| 75 | + // The number of bytes written at once will not be larger than what can fit in the TinyUSB FIFO. |
| 76 | + uint32_t total_num_written = tud_cdc_n_write(self->idx, data, len); |
| 77 | + tud_cdc_n_write_flush(self->idx); |
| 78 | + |
| 79 | + if (wait_forever || wait_for_timeout) { |
| 80 | + // Write more if we have time. |
| 81 | + uint64_t timeout_ms = self->write_timeout * 1000; // Junk value if write_timeout < 0. |
43 | 82 | uint64_t start_ticks = supervisor_ticks_ms64();
|
44 |
| - while (tud_cdc_n_available(self->idx) < len && |
45 |
| - supervisor_ticks_ms64() - start_ticks <= timeout_ms) { |
| 83 | + |
| 84 | + uint32_t num_written = 0; |
| 85 | + while (total_num_written < len && |
| 86 | + (wait_forever || supervisor_ticks_ms64() - start_ticks <= timeout_ms)) { |
| 87 | + |
| 88 | + // Wait for a bit, and check for ctrl-C. |
46 | 89 | RUN_BACKGROUND_TASKS;
|
47 | 90 | if (mp_hal_is_interrupted()) {
|
48 | 91 | return 0;
|
49 | 92 | }
|
| 93 | + |
| 94 | + // Advance buffer pointer and reduce number of bytes that need to be written. |
| 95 | + len -= num_written; |
| 96 | + data += num_written; |
| 97 | + |
| 98 | + // Try to write another batch of bytes. |
| 99 | + num_written = tud_cdc_n_write(self->idx, data, len); |
| 100 | + tud_cdc_n_write_flush(self->idx); |
| 101 | + total_num_written += num_written; |
50 | 102 | }
|
51 | 103 | }
|
52 |
| - // Timeout of 0.0f falls through to here with no waiting or unnecessary calculation. |
53 |
| - return tud_cdc_n_read(self->idx, data, len); |
54 |
| -} |
55 | 104 |
|
56 |
| -size_t common_hal_usb_cdc_serial_write(usb_cdc_serial_obj_t *self, const uint8_t *data, size_t len, int *errcode) { |
57 |
| - uint32_t num_written = tud_cdc_n_write(self->idx, data, len); |
58 |
| - tud_cdc_n_write_flush(self->idx); |
59 |
| - return num_written; |
| 105 | + return total_num_written; |
60 | 106 | }
|
61 | 107 |
|
62 | 108 | uint32_t common_hal_usb_cdc_serial_get_in_waiting(usb_cdc_serial_obj_t *self) {
|
@@ -91,3 +137,11 @@ mp_float_t common_hal_usb_cdc_serial_get_timeout(usb_cdc_serial_obj_t *self) {
|
91 | 137 | void common_hal_usb_cdc_serial_set_timeout(usb_cdc_serial_obj_t *self, mp_float_t timeout) {
|
92 | 138 | self->timeout = timeout;
|
93 | 139 | }
|
| 140 | + |
| 141 | +mp_float_t common_hal_usb_cdc_serial_get_write_timeout(usb_cdc_serial_obj_t *self) { |
| 142 | + return self->write_timeout; |
| 143 | +} |
| 144 | + |
| 145 | +void common_hal_usb_cdc_serial_set_write_timeout(usb_cdc_serial_obj_t *self, mp_float_t write_timeout) { |
| 146 | + self->write_timeout = write_timeout; |
| 147 | +} |
0 commit comments