Skip to content

Commit 3f700dd

Browse files
committed
usbd: Refactor descriptor generation
- Use a single static buffer for descriptor results. - Wrap the descriptor functionality in a Descriptor class. Signed-off-by: Angus Gratton <angus@redyak.com.au>
1 parent 4404ee8 commit 3f700dd

File tree

5 files changed

+266
-235
lines changed

5 files changed

+266
-235
lines changed

micropython/usbd/cdc.py

Lines changed: 37 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@
6262
# Other definitions
6363
_CDC_VERSION = const(0x0120) # release number in binary-coded decimal
6464

65+
_CDC_CONTROL_EP_NUM = const(1)
66+
_CDC_DATA_EP_NUM = const(2)
6567

6668
# CDC data interface definitions
6769
_CDC_ITF_DATA_CLASS = const(0xA)
@@ -216,7 +218,9 @@ class CDCControlInterface(USBInterface):
216218
# Implements the CDC Control Interface
217219

218220
def __init__(self):
219-
super().__init__(_INTERFACE_CLASS_CDC, _INTERFACE_SUBCLASS_CDC, _PROTOCOL_NONE)
221+
super().__init__(
222+
_INTERFACE_CLASS_CDC, _INTERFACE_SUBCLASS_CDC, _PROTOCOL_NONE, _CDC_CONTROL_EP_NUM
223+
)
220224

221225
# Callbacks for particular changes initiated by the host
222226
self.break_cb = None # Host sent a "break" condition
@@ -229,26 +233,27 @@ def __init__(self):
229233

230234
self.ep_in = None # Set when enumeration happens
231235

232-
def get_itf_descriptor(self, num_eps, itf_idx, str_idx):
236+
def descriptor_config_cb(self, desc, itf_num, str_num, ep_num):
233237
# CDC needs a Interface Association Descriptor (IAD)
234238
# two interfaces in total
235-
desc = ustruct.pack(
239+
desc.pack(
236240
"<BBBBBBBB",
237241
8,
238242
_ITF_ASSOCIATION_DESC_TYPE,
239-
itf_idx,
243+
itf_num,
240244
2,
241245
_INTERFACE_CLASS_CDC,
242246
_INTERFACE_SUBCLASS_CDC,
243247
_PROTOCOL_NONE,
244248
0,
245249
)
246250

247-
itf, strs = super().get_itf_descriptor(num_eps, itf_idx, str_idx)
248-
desc += itf
251+
# Now add the standard interface descriptor
252+
strs = super().descriptor_config_cb(desc, itf_num, str_num, ep_num)
253+
249254
# Append the CDC class-specific interface descriptor
250255
# see CDC120-track, p20
251-
desc += ustruct.pack(
256+
desc.pack(
252257
"<BBBH",
253258
5, # bFunctionLength
254259
_CS_DESC_TYPE, # bDescriptorType
@@ -258,7 +263,7 @@ def get_itf_descriptor(self, num_eps, itf_idx, str_idx):
258263

259264
# CDC-PSTN table3 "Call Management"
260265
# set to No
261-
desc += ustruct.pack(
266+
desc.pack(
262267
"<BBBBB",
263268
5, # bFunctionLength
264269
_CS_DESC_TYPE, # bDescriptorType
@@ -269,29 +274,30 @@ def get_itf_descriptor(self, num_eps, itf_idx, str_idx):
269274

270275
# CDC-PSTN table4 "Abstract Control"
271276
# set to support line_coding and send_break
272-
desc += ustruct.pack(
277+
desc.pack(
273278
"<BBBB",
274279
4, # bFunctionLength
275280
_CS_DESC_TYPE, # bDescriptorType
276281
_CDC_FUNC_DESC_ABSTRACT_CONTROL, # bDescriptorSubtype
277282
0x6,
278283
) # bmCapabilities D1, D2
284+
279285
# CDC-PSTN "Union"
280286
# set control interface / data interface number
281-
desc += ustruct.pack(
287+
desc.pack(
282288
"<BBBBB",
283289
5, # bFunctionLength
284290
_CS_DESC_TYPE, # bDescriptorType
285291
_CDC_FUNC_DESC_UNION, # bDescriptorSubtype
286-
itf_idx, # bControlInterface
287-
itf_idx + 1,
292+
itf_num, # bControlInterface
293+
itf_num + 1, # data interface, assume this one will be assigned next
288294
) # bSubordinateInterface0 (data class itf number)
289-
return desc, strs
290295

291-
def get_endpoint_descriptors(self, ep_addr, str_idx):
292-
self.ep_in = ep_addr | EP_IN_FLAG
293-
desc = endpoint_descriptor(self.ep_in, "interrupt", 8, 16)
294-
return (desc, [], (self.ep_in,))
296+
# Descriptor for a single endpoint
297+
self.ep_in = ep_num | EP_IN_FLAG
298+
desc.endpoint(self.ep_in, "interrupt", 8, 16)
299+
300+
return strs
295301

296302
def handle_interface_control_xfer(self, stage, request):
297303
# Handle class-specific interface control transfers
@@ -331,20 +337,26 @@ class CDCDataInterface(USBInterface):
331337
# Implements the CDC Data Interface
332338

333339
def __init__(self):
334-
super().__init__(_CDC_ITF_DATA_CLASS, _CDC_ITF_DATA_SUBCLASS, _CDC_ITF_DATA_PROT)
340+
super().__init__(
341+
_CDC_ITF_DATA_CLASS, _CDC_ITF_DATA_SUBCLASS, _CDC_ITF_DATA_PROT, _CDC_DATA_EP_NUM
342+
)
335343
self._wb = () # Optional write Buffer (IN endpoint), set by CDC.init()
336344
self._rb = () # Optional read Buffer (OUT endpoint), set by CDC.init()
337345
self._timeout = 1000 # set from CDC.init() as well
338346

339347
self.ep_in = self.ep_out = None # Set when enumeration happens
340348

341-
def get_endpoint_descriptors(self, ep_addr, str_idx):
342-
self.ep_in = ep_addr | EP_IN_FLAG
343-
self.ep_out = ep_addr
344-
# one IN / OUT Endpoint
345-
e_out = endpoint_descriptor(self.ep_out, "bulk", _BULK_EP_LEN, 0)
346-
e_in = endpoint_descriptor(self.ep_in, "bulk", _BULK_EP_LEN, 0)
347-
return (e_out + e_in, [], (self.ep_out, self.ep_in))
349+
def descriptor_config_cb(self, pack_fn, itf_num, str_num, ep_num):
350+
# Add the standard interface descriptor
351+
strs = super().descriptor_config_cb(pack_fn, itf_num, str_num, ep_num)
352+
353+
# Two endpoints, bulk IN and OUT
354+
self.ep_in = ep_num | EP_IN_FLAG
355+
self.ep_out = ep_num
356+
endpoint_descriptor(pack_fn, self.ep_out, "bulk", _BULK_EP_LEN, 0)
357+
endpoint_descriptor(pack_fn, self.ep_in, "bulk", _BULK_EP_LEN, 0)
358+
359+
return strs
348360

349361
def write(self, buf):
350362
# use a memoryview to track how much of 'buf' we've written so far

0 commit comments

Comments
 (0)