summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorDamien George <damien.p.george@gmail.com>2014-10-31 00:12:02 +0000
committerDamien George <damien.p.george@gmail.com>2014-10-31 00:12:02 +0000
commit9a41b32b3f58246cbe69db237877775b4d2fe920 (patch)
treee77af30b8e341f38cfaf1fd6ca4055384cbc0ebf
parentefc49c5591d23f606a2e6203f9b4e4976aa3e6e3 (diff)
downloadmicropython-9a41b32b3f58246cbe69db237877775b4d2fe920.tar.gz
micropython-9a41b32b3f58246cbe69db237877775b4d2fe920.zip
stmhal: Add ioctl to USB_VCP object, so it works with select.
This patch also enables non-blocking streams on stmhal port. One can now make a USB-UART pass-through function: def pass_through(usb, uart): while True: select.select([usb, uart], [], []) if usb.any(): uart.write(usb.read(256)) if uart.any(): usb.write(uart.read(256)) pass_through(pyb.USB_VCP(), pyb.UART(1, 9600))
-rw-r--r--stmhal/mpconfigport.h1
-rw-r--r--stmhal/usb.c55
-rw-r--r--stmhal/usbd_cdc_interface.c8
-rw-r--r--stmhal/usbd_cdc_interface.h1
4 files changed, 55 insertions, 10 deletions
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 <stdarg.h>
#include <string.h>
+#include <errno.h>
#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);