3232#include "usbd_cdc_interface.h"
3333#include "usbd_msc_storage.h"
3434
35- #include "misc.h"
3635#include "mpconfig.h"
36+ #include "misc.h"
3737#include "qstr.h"
3838#include "obj.h"
39+ #include "runtime.h"
40+ #include "stream.h"
41+ #include "bufhelper.h"
3942#include "usb.h"
4043
4144#ifdef USE_DEVICE_MODE
@@ -99,18 +102,14 @@ void usb_vcp_set_interrupt_char(int c) {
99102 }
100103}
101104
102- int usb_vcp_rx_num (void ) {
103- return USBD_CDC_RxNum ();
104- }
105-
106- char usb_vcp_rx_get (void ) {
107- return USBD_CDC_RxGet ();
105+ int usb_vcp_recv_byte (uint8_t * c ) {
106+ return USBD_CDC_Rx (c , 1 , 0 );
108107}
109108
110109void usb_vcp_send_strn (const char * str , int len ) {
111110#ifdef USE_DEVICE_MODE
112111 if (dev_is_enabled ) {
113- USBD_CDC_Tx ( str , len );
112+ USBD_CDC_TxAlways (( const uint8_t * ) str , len );
114113 }
115114#endif
116115}
@@ -120,9 +119,9 @@ void usb_vcp_send_strn_cooked(const char *str, int len) {
120119 if (dev_is_enabled ) {
121120 for (const char * top = str + len ; str < top ; str ++ ) {
122121 if (* str == '\n' ) {
123- USBD_CDC_Tx ( "\r\n" , 2 );
122+ USBD_CDC_TxAlways (( const uint8_t * ) "\r\n" , 2 );
124123 } else {
125- USBD_CDC_Tx ( str , 1 );
124+ USBD_CDC_TxAlways (( const uint8_t * ) str , 1 );
126125 }
127126 }
128127 }
@@ -135,6 +134,145 @@ void usb_hid_send_report(uint8_t *buf) {
135134#endif
136135}
137136
137+ /******************************************************************************/
138+ // Micro Python bindings for USB VCP
139+
140+ typedef struct _pyb_usb_vcp_obj_t {
141+ mp_obj_base_t base ;
142+ } pyb_usb_vcp_obj_t ;
143+
144+ STATIC const pyb_usb_vcp_obj_t pyb_usb_vcp_obj = {{& pyb_usb_vcp_type }};
145+
146+ STATIC void pyb_usb_vcp_print (void (* print )(void * env , const char * fmt , ...), void * env , mp_obj_t self_in , mp_print_kind_t kind ) {
147+ print (env , "USB_VCP()" );
148+ }
149+
150+ STATIC mp_obj_t pyb_usb_vcp_make_new (mp_obj_t type_in , uint n_args , uint n_kw , const mp_obj_t * args ) {
151+ // check arguments
152+ mp_arg_check_num (n_args , n_kw , 0 , 0 , false);
153+
154+ // return the USB VCP object
155+ return (mp_obj_t )& pyb_usb_vcp_obj ;
156+ }
157+
158+ /// \method any()
159+ /// Return `True` if any characters waiting, else `False`.
160+ STATIC mp_obj_t pyb_usb_vcp_any (mp_obj_t self_in ) {
161+ if (USBD_CDC_RxNum () > 0 ) {
162+ return mp_const_true ;
163+ } else {
164+ return mp_const_false ;
165+ }
166+ }
167+ STATIC MP_DEFINE_CONST_FUN_OBJ_1 (pyb_usb_vcp_any_obj , pyb_usb_vcp_any );
168+
169+ /// \method send(data, *, timeout=5000)
170+ /// Send data over the USB VCP:
171+ ///
172+ /// - `data` is the data to send (an integer to send, or a buffer object).
173+ /// - `timeout` is the timeout in milliseconds to wait for the send.
174+ ///
175+ /// Return value: number of bytes sent.
176+ STATIC const mp_arg_t pyb_usb_vcp_send_args [] = {
177+ { MP_QSTR_data , MP_ARG_REQUIRED | MP_ARG_OBJ , {.u_obj = MP_OBJ_NULL } },
178+ { MP_QSTR_timeout , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = 5000 } },
179+ };
180+ #define PYB_USB_VCP_SEND_NUM_ARGS MP_ARRAY_SIZE(pyb_usb_vcp_send_args)
181+
182+ STATIC mp_obj_t pyb_usb_vcp_send (uint n_args , const mp_obj_t * args , mp_map_t * kw_args ) {
183+ // parse args
184+ mp_arg_val_t vals [PYB_USB_VCP_SEND_NUM_ARGS ];
185+ mp_arg_parse_all (n_args - 1 , args + 1 , kw_args , PYB_USB_VCP_SEND_NUM_ARGS , pyb_usb_vcp_send_args , vals );
186+
187+ // get the buffer to send from
188+ mp_buffer_info_t bufinfo ;
189+ uint8_t data [1 ];
190+ pyb_buf_get_for_send (vals [0 ].u_obj , & bufinfo , data );
191+
192+ // send the data
193+ int ret = USBD_CDC_Tx (bufinfo .buf , bufinfo .len , vals [1 ].u_int );
194+
195+ return mp_obj_new_int (ret );
196+ }
197+ STATIC MP_DEFINE_CONST_FUN_OBJ_KW (pyb_usb_vcp_send_obj , 1 , pyb_usb_vcp_send );
198+
199+ /// \method recv(data, *, timeout=5000)
200+ ///
201+ /// Receive data on the bus:
202+ ///
203+ /// - `data` can be an integer, which is the number of bytes to receive,
204+ /// or a mutable buffer, which will be filled with received bytes.
205+ /// - `timeout` is the timeout in milliseconds to wait for the receive.
206+ ///
207+ /// Return value: if `data` is an integer then a new buffer of the bytes received,
208+ /// otherwise the number of bytes read into `data` is returned.
209+ STATIC mp_obj_t pyb_usb_vcp_recv (uint n_args , const mp_obj_t * args , mp_map_t * kw_args ) {
210+ // parse args
211+ mp_arg_val_t vals [PYB_USB_VCP_SEND_NUM_ARGS ];
212+ mp_arg_parse_all (n_args - 1 , args + 1 , kw_args , PYB_USB_VCP_SEND_NUM_ARGS , pyb_usb_vcp_send_args , vals );
213+
214+ // get the buffer to receive into
215+ mp_buffer_info_t bufinfo ;
216+ mp_obj_t o_ret = pyb_buf_get_for_recv (vals [0 ].u_obj , & bufinfo );
217+
218+ // receive the data
219+ int ret = USBD_CDC_Rx (bufinfo .buf , bufinfo .len , vals [1 ].u_int );
220+
221+ // return the received data
222+ if (o_ret == MP_OBJ_NULL ) {
223+ return mp_obj_new_int (ret ); // number of bytes read into given buffer
224+ } else {
225+ return mp_obj_str_builder_end_with_len (o_ret , ret ); // create a new buffer
226+ }
227+ }
228+ STATIC MP_DEFINE_CONST_FUN_OBJ_KW (pyb_usb_vcp_recv_obj , 1 , pyb_usb_vcp_recv );
229+
230+ STATIC mp_uint_t pyb_usb_vcp_read (mp_obj_t self_in , void * buf , mp_uint_t size , int * errcode ) {
231+ int ret = USBD_CDC_Rx ((byte * )buf , size , -1 );
232+ return ret ;
233+ }
234+
235+ STATIC mp_uint_t pyb_usb_vcp_write (mp_obj_t self_in , const void * buf , mp_uint_t size , int * errcode ) {
236+ int ret = USBD_CDC_Tx ((const byte * )buf , size , -1 );
237+ return ret ;
238+ }
239+
240+ mp_obj_t pyb_usb_vcp___exit__ (uint n_args , const mp_obj_t * args ) {
241+ return mp_const_none ;
242+ }
243+ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN (pyb_usb_vcp___exit___obj , 4 , 4 , pyb_usb_vcp___exit__ );
244+
245+ STATIC const mp_map_elem_t pyb_usb_vcp_locals_dict_table [] = {
246+ { MP_OBJ_NEW_QSTR (MP_QSTR_send ), (mp_obj_t )& pyb_usb_vcp_send_obj },
247+ { MP_OBJ_NEW_QSTR (MP_QSTR_recv ), (mp_obj_t )& pyb_usb_vcp_recv_obj },
248+ { MP_OBJ_NEW_QSTR (MP_QSTR_read ), (mp_obj_t )& mp_stream_read_obj },
249+ { MP_OBJ_NEW_QSTR (MP_QSTR_readall ), (mp_obj_t )& mp_stream_readall_obj },
250+ { MP_OBJ_NEW_QSTR (MP_QSTR_readline ), (mp_obj_t )& mp_stream_unbuffered_readline_obj },
251+ { MP_OBJ_NEW_QSTR (MP_QSTR_write ), (mp_obj_t )& mp_stream_write_obj },
252+ { MP_OBJ_NEW_QSTR (MP_QSTR_close ), (mp_obj_t )& mp_identity_obj },
253+ { MP_OBJ_NEW_QSTR (MP_QSTR___del__ ), (mp_obj_t )& mp_identity_obj },
254+ { MP_OBJ_NEW_QSTR (MP_QSTR___enter__ ), (mp_obj_t )& mp_identity_obj },
255+ { MP_OBJ_NEW_QSTR (MP_QSTR___exit__ ), (mp_obj_t )& pyb_usb_vcp___exit___obj },
256+ };
257+
258+ STATIC MP_DEFINE_CONST_DICT (pyb_usb_vcp_locals_dict , pyb_usb_vcp_locals_dict_table );
259+
260+ STATIC const mp_stream_p_t pyb_usb_vcp_stream_p = {
261+ .read = pyb_usb_vcp_read ,
262+ .write = pyb_usb_vcp_write ,
263+ };
264+
265+ const mp_obj_type_t pyb_usb_vcp_type = {
266+ { & mp_type_type },
267+ .name = MP_QSTR_USB_VCP ,
268+ .print = pyb_usb_vcp_print ,
269+ .make_new = pyb_usb_vcp_make_new ,
270+ .getiter = mp_identity ,
271+ .iternext = mp_stream_unbuffered_iter ,
272+ .stream_p = & pyb_usb_vcp_stream_p ,
273+ .locals_dict = (mp_obj_t )& pyb_usb_vcp_locals_dict ,
274+ };
275+
138276/******************************************************************************/
139277// code for experimental USB OTG support
140278
0 commit comments