diff --git a/stmhal/mpconfigport.h b/stmhal/mpconfigport.h index 7e57755c7c..c85f5fba78 100644 --- a/stmhal/mpconfigport.h +++ b/stmhal/mpconfigport.h @@ -48,6 +48,7 @@ */ #define MICROPY_ENABLE_LFN (1) #define MICROPY_LFN_CODE_PAGE (437) /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */ +#define MICROPY_STREAMS_NON_BLOCK (1) #define MICROPY_MODULE_WEAK_LINKS (1) #define MICROPY_PY_BUILTINS_STR_UNICODE (1) #define MICROPY_PY_BUILTINS_MEMORYVIEW (1) diff --git a/stmhal/usb.c b/stmhal/usb.c index 4211c88296..ea2bd1c449 100644 --- a/stmhal/usb.c +++ b/stmhal/usb.c @@ -24,7 +24,9 @@ * THE SOFTWARE. */ +#include #include +#include #include "usbd_core.h" #include "usbd_desc.h" @@ -40,6 +42,7 @@ #include "stream.h" #include "bufhelper.h" #include "usb.h" +#include "pybioctl.h" #ifdef USE_DEVICE_MODE USBD_HandleTypeDef hUSBDDevice; @@ -243,16 +246,6 @@ STATIC mp_obj_t pyb_usb_vcp_recv(mp_uint_t n_args, const mp_obj_t *args, mp_map_ } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_usb_vcp_recv_obj, 1, pyb_usb_vcp_recv); -STATIC mp_uint_t pyb_usb_vcp_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) { - int ret = USBD_CDC_Rx((byte*)buf, size, -1); - return ret; -} - -STATIC mp_uint_t pyb_usb_vcp_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) { - int ret = USBD_CDC_Tx((const byte*)buf, size, -1); - return ret; -} - mp_obj_t pyb_usb_vcp___exit__(mp_uint_t n_args, const mp_obj_t *args) { return mp_const_none; } @@ -279,9 +272,51 @@ STATIC const mp_map_elem_t pyb_usb_vcp_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(pyb_usb_vcp_locals_dict, pyb_usb_vcp_locals_dict_table); +STATIC mp_uint_t pyb_usb_vcp_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) { + int ret = USBD_CDC_Rx((byte*)buf, size, 0); + if (ret == 0) { + // return EAGAIN error to indicate non-blocking + *errcode = EAGAIN; + return MP_STREAM_ERROR; + } + return ret; +} + +STATIC mp_uint_t pyb_usb_vcp_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) { + int ret = USBD_CDC_Tx((const byte*)buf, size, 0); + if (ret == 0) { + // return EAGAIN error to indicate non-blocking + *errcode = EAGAIN; + return MP_STREAM_ERROR; + } + return ret; +} + +STATIC mp_uint_t pyb_usb_vcp_ioctl(mp_obj_t self_in, mp_uint_t request, int *errcode, ...) { + va_list vargs; + va_start(vargs, errcode); + mp_uint_t ret; + if (request == MP_IOCTL_POLL) { + mp_uint_t flags = va_arg(vargs, mp_uint_t); + ret = 0; + if ((flags & MP_IOCTL_POLL_RD) && USBD_CDC_RxNum() > 0) { + ret |= MP_IOCTL_POLL_RD; + } + if ((flags & MP_IOCTL_POLL_WR) && USBD_CDC_TxHalfEmpty()) { + ret |= MP_IOCTL_POLL_WR; + } + } else { + *errcode = EINVAL; + ret = MP_STREAM_ERROR; + } + va_end(vargs); + return ret; +} + STATIC const mp_stream_p_t pyb_usb_vcp_stream_p = { .read = pyb_usb_vcp_read, .write = pyb_usb_vcp_write, + .ioctl = pyb_usb_vcp_ioctl, }; const mp_obj_type_t pyb_usb_vcp_type = { diff --git a/stmhal/usbd_cdc_interface.c b/stmhal/usbd_cdc_interface.c index e9b4863f6b..7f1eef5b3e 100644 --- a/stmhal/usbd_cdc_interface.c +++ b/stmhal/usbd_cdc_interface.c @@ -402,6 +402,14 @@ void USBD_CDC_SetInterrupt(int chr, void *data) { user_interrupt_data = data; } +int USBD_CDC_TxHalfEmpty(void) { + int32_t tx_waiting = (int32_t)UserTxBufPtrIn - (int32_t)UserTxBufPtrOut; + if (tx_waiting < 0) { + tx_waiting += APP_TX_DATA_SIZE; + } + return tx_waiting <= APP_TX_DATA_SIZE / 2; +} + // timout in milliseconds. // Returns number of bytes written to the device. int USBD_CDC_Tx(const uint8_t *buf, uint32_t len, uint32_t timeout) { diff --git a/stmhal/usbd_cdc_interface.h b/stmhal/usbd_cdc_interface.h index f312682fbf..5a5d4cf004 100644 --- a/stmhal/usbd_cdc_interface.h +++ b/stmhal/usbd_cdc_interface.h @@ -37,6 +37,7 @@ void USBD_CDC_HAL_TIM_PeriodElapsedCallback(void); int USBD_CDC_IsConnected(void); void USBD_CDC_SetInterrupt(int chr, void *data); +int USBD_CDC_TxHalfEmpty(void); int USBD_CDC_Tx(const uint8_t *buf, uint32_t len, uint32_t timeout); void USBD_CDC_TxAlways(const uint8_t *buf, uint32_t len);