@@ -58,9 +58,8 @@ STATIC const mp_obj_str_t pyb_usb_hid_mouse_desc_obj = {
58
58
};
59
59
const mp_obj_tuple_t pyb_usb_hid_mouse_obj = {
60
60
{& mp_type_tuple },
61
- 5 ,
61
+ 4 ,
62
62
{
63
- MP_OBJ_NEW_SMALL_INT (USBD_PID_CDC_HID ),
64
63
MP_OBJ_NEW_SMALL_INT (1 ), // subclass: boot
65
64
MP_OBJ_NEW_SMALL_INT (2 ), // protocol: mouse
66
65
MP_OBJ_NEW_SMALL_INT (USBD_HID_MOUSE_MAX_PACKET ),
@@ -77,9 +76,8 @@ STATIC const mp_obj_str_t pyb_usb_hid_keyboard_desc_obj = {
77
76
};
78
77
const mp_obj_tuple_t pyb_usb_hid_keyboard_obj = {
79
78
{& mp_type_tuple },
80
- 5 ,
79
+ 4 ,
81
80
{
82
- MP_OBJ_NEW_SMALL_INT (USBD_PID_CDC_HID ),
83
81
MP_OBJ_NEW_SMALL_INT (1 ), // subclass: boot
84
82
MP_OBJ_NEW_SMALL_INT (1 ), // protocol: keyboard
85
83
MP_OBJ_NEW_SMALL_INT (USBD_HID_KEYBOARD_MAX_PACKET ),
@@ -94,12 +92,14 @@ void pyb_usb_init0(void) {
94
92
MP_STATE_PORT (pyb_hid_report_desc ) = MP_OBJ_NULL ;
95
93
}
96
94
97
- void pyb_usb_dev_init (uint16_t pid , usb_device_mode_t mode , USBD_HID_ModeInfoTypeDef * hid_info ) {
95
+ bool pyb_usb_dev_init (uint16_t vid , uint16_t pid , usb_device_mode_t mode , USBD_HID_ModeInfoTypeDef * hid_info ) {
98
96
#ifdef USE_DEVICE_MODE
99
97
if (!(pyb_usb_flags & PYB_USB_FLAG_DEV_ENABLED )) {
100
98
// only init USB once in the device's power-lifetime
101
- USBD_SetPID (pid );
102
- USBD_SelectMode (mode , hid_info );
99
+ USBD_SetVIDPIDRelease (vid , pid , 0x0200 );
100
+ if (USBD_SelectMode (mode , hid_info ) != 0 ) {
101
+ return false;
102
+ }
103
103
USBD_Init (& hUSBDDevice , (USBD_DescriptorsTypeDef * )& USBD_Descriptors , 0 );
104
104
USBD_RegisterClass (& hUSBDDevice , & USBD_CDC_MSC_HID );
105
105
USBD_CDC_RegisterInterface (& hUSBDDevice , (USBD_CDC_ItfTypeDef * )& USBD_CDC_fops );
@@ -117,6 +117,8 @@ void pyb_usb_dev_init(uint16_t pid, usb_device_mode_t mode, USBD_HID_ModeInfoTyp
117
117
}
118
118
pyb_usb_flags |= PYB_USB_FLAG_DEV_ENABLED ;
119
119
#endif
120
+
121
+ return true;
120
122
}
121
123
122
124
void pyb_usb_dev_deinit (void ) {
@@ -169,75 +171,120 @@ void usb_vcp_send_strn_cooked(const char *str, int len) {
169
171
// Micro Python bindings for USB
170
172
171
173
/*
172
- TODO think about how to expose the USB device. Currently we have:
173
- pyb.usb_mode(None) # disable USB
174
- pyb.usb_mode('CDC+MSC')
175
- pyb.usb_mode('CDC+HID') # defaults to mouse
176
- pyb.usb_mode('CDC+HID', pyb.hid_mouse)
177
- pyb.usb_mode('CDC+HID', pyb.hid_keyboard)
178
- pyb.usb_mode('CDC+HID', (pid, subclass, protocol, max_packet_len, report_desc))
179
- pyb.usb_mode('host', ...)
174
+ Philosophy of USB driver and Python API: pyb.usb_mode(...) configures the USB
175
+ on the board. The USB itself is not an entity, rather the interfaces are, and
176
+ can be accessed by creating objects, such as pyb.USB_VCP() and pyb.USB_HID().
177
+
178
+ We have:
179
+
180
+ pyb.usb_mode(None) # disable USB
181
+ pyb.usb_mode('VCP') # enable with VCP interface
182
+ pyb.usb_mode('VCP+MSC') # enable with VCP and MSC interfaces
183
+ pyb.usb_mode('VCP+HID') # enable with VCP and HID, defaulting to mouse protocol
184
+ pyb.usb_mode('VCP+HID', vid=0xf055, pid=0x9800) # specify VID and PID
185
+ pyb.usb_mode('VCP+HID', hid=pyb.hid_mouse)
186
+ pyb.usb_mode('VCP+HID', hid=pyb.hid_keyboard)
187
+ pyb.usb_mode('VCP+HID', pid=0x1234, hid=(subclass, protocol, max_packet_len, report_desc))
188
+
180
189
vcp = pyb.USB_VCP() # get the VCP device for read/write
181
190
hid = pyb.USB_HID() # get the HID device for write/poll
182
191
183
- We could use a more class based approach, like UART and others:
184
- usb = pyb.USB('CDC+MSC')
185
- usb = pyb.USB('CDC+HID', pyb.USB.hid_mouse)
186
- usb = pyb.USB('CDC+HID', pyb.USB.hid_keyboard)
187
- usb = pyb.USB('CDC+HID', (pid, subclass, protocol, max_packet_len, report_desc))
188
- usb = pyb.USB('host', ...)
189
- usb = pyb.USB() # get currently configured object
190
- vcp = usb.VCP() # get VCP device
191
- hid = usb.HID() # get HID device
192
+ Possible extensions:
193
+ pyb.usb_mode('host', ...)
194
+ pyb.usb_mode('OTG', ...)
195
+ pyb.usb_mode(..., port=2) # for second USB port
192
196
*/
193
197
194
- STATIC mp_obj_t pyb_usb_mode (mp_uint_t n_args , const mp_obj_t * args ) {
198
+ STATIC mp_obj_t pyb_usb_mode (mp_uint_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args ) {
199
+ static const mp_arg_t allowed_args [] = {
200
+ { MP_QSTR_mode , MP_ARG_REQUIRED | MP_ARG_OBJ , {.u_obj = mp_const_none } },
201
+ { MP_QSTR_vid , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = USBD_VID } },
202
+ { MP_QSTR_pid , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = -1 } },
203
+ { MP_QSTR_hid , MP_ARG_KW_ONLY | MP_ARG_OBJ , {.u_obj = (mp_obj_t )& pyb_usb_hid_mouse_obj } },
204
+ };
205
+
206
+ // parse args
207
+ mp_arg_val_t args [MP_ARRAY_SIZE (allowed_args )];
208
+ mp_arg_parse_all (n_args , pos_args , kw_args , MP_ARRAY_SIZE (allowed_args ), allowed_args , args );
209
+
210
+ // record the fact that the usb has been explicitly configured
195
211
pyb_usb_flags |= PYB_USB_FLAG_USB_MODE_CALLED ;
196
212
197
- if (args [0 ] == mp_const_none ) {
213
+ // check if user wants to disable the USB
214
+ if (args [0 ].u_obj == mp_const_none ) {
198
215
// disable usb
199
216
#if defined(USE_DEVICE_MODE )
200
217
pyb_usb_dev_deinit ();
201
218
#endif
202
219
return mp_const_none ;
203
220
}
204
221
205
- const char * mode_str = mp_obj_str_get_str (args [0 ]);
222
+ // get mode string
223
+ const char * mode_str = mp_obj_str_get_str (args [0 ].u_obj );
224
+
206
225
#if defined(USE_HOST_MODE )
207
- // USB host
226
+
227
+ // hardware configured for USB host mode
228
+
208
229
if (strcmp (mode_str , "host" ) == 0 ) {
209
230
pyb_usb_host_init ();
210
231
} else {
211
232
goto bad_mode ;
212
233
}
234
+
213
235
#elif defined(USE_DEVICE_MODE )
214
- // USB device
215
- if (strcmp (mode_str , "CDC+MSC" ) == 0 ) {
216
- pyb_usb_dev_init (USBD_PID_CDC_MSC , USBD_MODE_CDC_MSC , NULL );
217
- } else if (strcmp (mode_str , "CDC+HID" ) == 0 ) {
218
- mp_obj_t hid_info_obj = (mp_obj_t )& pyb_usb_hid_mouse_obj ; // default is mouse mode
219
- if (n_args == 2 ) {
220
- hid_info_obj = args [1 ];
236
+
237
+ // hardware configured for USB device mode
238
+
239
+ // get the VID, PID and USB mode
240
+ // note: PID=-1 means select PID based on mode
241
+ // note: we support CDC as a synonym for VCP for backward compatibility
242
+ uint16_t vid = args [1 ].u_int ;
243
+ uint16_t pid = args [2 ].u_int ;
244
+ usb_device_mode_t mode ;
245
+ if (strcmp (mode_str , "CDC+MSC" ) == 0 || strcmp (mode_str , "VCP+MSC" ) == 0 ) {
246
+ if (args [2 ].u_int == -1 ) {
247
+ pid = USBD_PID_CDC_MSC ;
248
+ }
249
+ mode = USBD_MODE_CDC_MSC ;
250
+ } else if (strcmp (mode_str , "CDC+HID" ) == 0 || strcmp (mode_str , "VCP+HID" ) == 0 ) {
251
+ if (args [2 ].u_int == -1 ) {
252
+ pid = USBD_PID_CDC_HID ;
221
253
}
254
+ mode = USBD_MODE_CDC_HID ;
255
+ } else if (strcmp (mode_str , "CDC" ) == 0 || strcmp (mode_str , "VCP" ) == 0 ) {
256
+ if (args [2 ].u_int == -1 ) {
257
+ pid = USBD_PID_CDC ;
258
+ }
259
+ mode = USBD_MODE_CDC ;
260
+ } else {
261
+ goto bad_mode ;
262
+ }
263
+
264
+ // get hid info if user selected such a mode
265
+ USBD_HID_ModeInfoTypeDef hid_info ;
266
+ if (mode & USBD_MODE_HID ) {
222
267
mp_obj_t * items ;
223
- mp_obj_get_array_fixed_n (hid_info_obj , 5 , & items );
224
- USBD_HID_ModeInfoTypeDef hid_info ;
225
- mp_int_t pid = mp_obj_get_int (items [0 ]);
226
- hid_info .subclass = mp_obj_get_int (items [1 ]);
227
- hid_info .protocol = mp_obj_get_int (items [2 ]);
228
- hid_info .max_packet_len = mp_obj_get_int (items [3 ]);
229
- MP_STATE_PORT (pyb_hid_report_desc ) = items [4 ]; // need to keep a copy of this so report_desc does not get GC'd
268
+ mp_obj_get_array_fixed_n (args [3 ].u_obj , 4 , & items );
269
+ hid_info .subclass = mp_obj_get_int (items [0 ]);
270
+ hid_info .protocol = mp_obj_get_int (items [1 ]);
271
+ hid_info .max_packet_len = mp_obj_get_int (items [2 ]);
230
272
mp_buffer_info_t bufinfo ;
231
- mp_get_buffer_raise (items [4 ], & bufinfo , MP_BUFFER_READ );
273
+ mp_get_buffer_raise (items [3 ], & bufinfo , MP_BUFFER_READ );
232
274
hid_info .report_desc = bufinfo .buf ;
233
275
hid_info .report_desc_len = bufinfo .len ;
234
- pyb_usb_dev_init (pid , USBD_MODE_CDC_HID , & hid_info );
235
- } else if (strcmp (mode_str , "CDC" ) == 0 ) {
236
- pyb_usb_dev_init (USBD_PID_CDC , USBD_MODE_CDC , NULL );
237
- } else {
276
+
277
+ // need to keep a copy of this so report_desc does not get GC'd
278
+ MP_STATE_PORT (pyb_hid_report_desc ) = items [3 ];
279
+ }
280
+
281
+ // init the USB device
282
+ if (!pyb_usb_dev_init (vid , pid , mode , & hid_info )) {
238
283
goto bad_mode ;
239
284
}
285
+
240
286
#else
287
+ // hardware not configured for USB
241
288
goto bad_mode ;
242
289
#endif
243
290
@@ -246,7 +293,7 @@ STATIC mp_obj_t pyb_usb_mode(mp_uint_t n_args, const mp_obj_t *args) {
246
293
bad_mode :
247
294
nlr_raise (mp_obj_new_exception_msg (& mp_type_ValueError , "bad USB mode" ));
248
295
}
249
- MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN (pyb_usb_mode_obj , 1 , 2 , pyb_usb_mode );
296
+ MP_DEFINE_CONST_FUN_OBJ_KW (pyb_usb_mode_obj , 1 , pyb_usb_mode );
250
297
251
298
/******************************************************************************/
252
299
// Micro Python bindings for USB VCP
@@ -274,6 +321,8 @@ STATIC mp_obj_t pyb_usb_vcp_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint
274
321
// check arguments
275
322
mp_arg_check_num (n_args , n_kw , 0 , 0 , false);
276
323
324
+ // TODO raise exception if USB is not configured for VCP
325
+
277
326
// return the USB VCP object
278
327
return (mp_obj_t )& pyb_usb_vcp_obj ;
279
328
}
@@ -463,6 +512,8 @@ STATIC mp_obj_t pyb_usb_hid_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint
463
512
// check arguments
464
513
mp_arg_check_num (n_args , n_kw , 0 , 0 , false);
465
514
515
+ // TODO raise exception if USB is not configured for HID
516
+
466
517
// return the USB HID object
467
518
return (mp_obj_t )& pyb_usb_hid_obj ;
468
519
}
0 commit comments