diff options
| -rw-r--r-- | .gitmodules | 3 | ||||
| -rw-r--r-- | ports/atmel-samd/tools/gen_usb_descriptor.py | 59 | ||||
| m--------- | tools/usb_descriptor | 0 | ||||
| -rw-r--r-- | tools/usb_descriptor/cdc.py | 53 | ||||
| -rw-r--r-- | tools/usb_descriptor/core.py | 187 |
5 files changed, 32 insertions, 270 deletions
diff --git a/.gitmodules b/.gitmodules index adf0c871a..4861053fe 100644 --- a/.gitmodules +++ b/.gitmodules @@ -37,3 +37,6 @@ path = ports/atmel-samd/asf4 url = https://github.com/adafruit/asf4.git branch = circuitpython +[submodule "tools/usb_descriptor"] + path = tools/usb_descriptor + url = https://github.com/adafruit/usb_descriptor.git diff --git a/ports/atmel-samd/tools/gen_usb_descriptor.py b/ports/atmel-samd/tools/gen_usb_descriptor.py index 2a2b217fd..545600523 100644 --- a/ports/atmel-samd/tools/gen_usb_descriptor.py +++ b/ports/atmel-samd/tools/gen_usb_descriptor.py @@ -4,10 +4,9 @@ import os import sys # path hacking -sys.path.append("../../tools") +sys.path.append("../../tools/usb_descriptor") -from usb_descriptor import core -from usb_descriptor import cdc +from adafruit_usb_descriptor import cdc, standard, util parser = argparse.ArgumentParser(description='Generate USB descriptors.') parser.add_argument('--manufacturer', type=str, @@ -24,16 +23,16 @@ parser.add_argument('output_file', type=argparse.FileType('w')) args = parser.parse_args() -langid = core.StringDescriptor("\u0409") -manufacturer = core.StringDescriptor(args.manufacturer) -product = core.StringDescriptor(args.product) -serial_number = core.StringDescriptor("serial number. you should fill in a unique serial number here."[:args.serial_number_length]) +langid = standard.StringDescriptor("\u0409") +manufacturer = standard.StringDescriptor(args.manufacturer) +product = standard.StringDescriptor(args.product) +serial_number = standard.StringDescriptor("serial number. you should fill in a unique serial number here."[:args.serial_number_length]) strings = [langid, manufacturer, product, serial_number] # vid = 0x239A # pid = 0x8021 -device = core.DeviceDescriptor( +device = standard.DeviceDescriptor( idVendor=args.vid, idProduct=args.pid, iManufacturer=strings.index(manufacturer), @@ -43,7 +42,7 @@ device = core.DeviceDescriptor( # Interface numbers are interface set local and endpoints are interface local # until core.join_interfaces renumbers them. cdc_interfaces = [ - core.InterfaceDescriptor( + standard.InterfaceDescriptor( bInterfaceClass=0x2, # Communications Device Class bInterfaceSubClass=0x02, # Abstract control model bInterfaceProtocol=0x01, # Common AT Commands @@ -59,53 +58,53 @@ cdc_interfaces = [ cdc.AbstractControlManagement(bmCapabilities=0x02), cdc.Union(bMasterInterface=0x00, bSlaveInterface=[0x01]), - core.EndpointDescriptor( - bEndpointAddress=0x0 | core.EndpointDescriptor.DIRECTION_IN, - bmAttributes=core.EndpointDescriptor.TYPE_INTERRUPT, + standard.EndpointDescriptor( + bEndpointAddress=0x0 | standard.EndpointDescriptor.DIRECTION_IN, + bmAttributes=standard.EndpointDescriptor.TYPE_INTERRUPT, wMaxPacketSize=0x8, bInterval=10) ] ), - core.InterfaceDescriptor( + standard.InterfaceDescriptor( bInterfaceClass=0x0a, subdescriptors=[ - core.EndpointDescriptor( - bEndpointAddress=0x0 | core.EndpointDescriptor.DIRECTION_IN, - bmAttributes=core.EndpointDescriptor.TYPE_BULK), - core.EndpointDescriptor( - bEndpointAddress=0x0 | core.EndpointDescriptor.DIRECTION_OUT, - bmAttributes=core.EndpointDescriptor.TYPE_BULK) + standard.EndpointDescriptor( + bEndpointAddress=0x0 | standard.EndpointDescriptor.DIRECTION_IN, + bmAttributes=standard.EndpointDescriptor.TYPE_BULK), + standard.EndpointDescriptor( + bEndpointAddress=0x0 | standard.EndpointDescriptor.DIRECTION_OUT, + bmAttributes=standard.EndpointDescriptor.TYPE_BULK) ] ) ] msc_interfaces = [ - core.InterfaceDescriptor( + standard.InterfaceDescriptor( bInterfaceClass=0x08, bInterfaceSubClass=0x06, bInterfaceProtocol=0x50, subdescriptors=[ - core.EndpointDescriptor( - bEndpointAddress=0x0 | core.EndpointDescriptor.DIRECTION_IN, - bmAttributes=core.EndpointDescriptor.TYPE_BULK), - core.EndpointDescriptor( - bEndpointAddress=0x1 | core.EndpointDescriptor.DIRECTION_OUT, - bmAttributes=core.EndpointDescriptor.TYPE_BULK) + standard.EndpointDescriptor( + bEndpointAddress=0x0 | standard.EndpointDescriptor.DIRECTION_IN, + bmAttributes=standard.EndpointDescriptor.TYPE_BULK), + standard.EndpointDescriptor( + bEndpointAddress=0x1 | standard.EndpointDescriptor.DIRECTION_OUT, + bmAttributes=standard.EndpointDescriptor.TYPE_BULK) ] ) ] -interfaces = core.join_interfaces(cdc_interfaces, msc_interfaces) +interfaces = util.join_interfaces(cdc_interfaces, msc_interfaces) -cdc_function = core.InterfaceAssociationDescriptor( +cdc_function = standard.InterfaceAssociationDescriptor( bFirstInterface=interfaces.index(cdc_interfaces[0]), bInterfaceCount=len(cdc_interfaces), bFunctionClass=0x2, # Communications Device Class bFunctionSubClass=0x2, # Abstract control model bFunctionProtocol=0x1) # Common AT Commands -configuration = core.ConfigurationDescriptor( - wTotalLength=(core.ConfigurationDescriptor.bLength + +configuration = standard.ConfigurationDescriptor( + wTotalLength=(standard.ConfigurationDescriptor.bLength + cdc_function.bLength + sum([len(bytes(x)) for x in interfaces])), bNumInterfaces=len(interfaces)) diff --git a/tools/usb_descriptor b/tools/usb_descriptor new file mode 160000 +Subproject a04341153b41b4728f9b42a77cbd51c49536228 diff --git a/tools/usb_descriptor/cdc.py b/tools/usb_descriptor/cdc.py deleted file mode 100644 index 4042e7673..000000000 --- a/tools/usb_descriptor/cdc.py +++ /dev/null @@ -1,53 +0,0 @@ -from . import core -import struct - -class FunctionalDescriptor(core.Descriptor): - bDescriptorType = 0x24 - - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - self.fmt = "<BBB" + self.fmt[3:] - - def __bytes__(self): - return struct.pack(self.fmt, self.bLength, self.bDescriptorType, self.bDescriptorSubtype, *self.data) - - -class Header(FunctionalDescriptor): - fields = [('bcdCDC', "H", None)] - bLength = 0x05 - bDescriptorSubtype = 0x0 - - -class CallManagement(FunctionalDescriptor): - fields = [('bmCapabilities', "b", None), - ('bDataInterface', "b", None)] - bLength = 0x05 - bDescriptorSubtype = 0x01 - - -class AbstractControlManagement(FunctionalDescriptor): - fields = [('bmCapabilities', "b", None)] - bLength = 0x04 - bDescriptorSubtype = 0x02 - - -class DirectLineManagement(FunctionalDescriptor): - fields = [('bmCapabilities', "b", None)] - bLength = 0x04 - bDescriptorSubtype = 0x03 - - -class Union(FunctionalDescriptor): - fields = [('bMasterInterface', "b", None)] - bDescriptorSubtype = 0x06 - - def __init__(self, *args, **kwargs): - self.bSlaveInterface = kwargs["bSlaveInterface"] - super().__init__(*args, **kwargs) - - def __bytes__(self): - return super().__bytes__() + bytes(self.bSlaveInterface) - - @property - def bLength(self): - return 0x4 + len(self.bSlaveInterface) diff --git a/tools/usb_descriptor/core.py b/tools/usb_descriptor/core.py deleted file mode 100644 index 03d9c3e63..000000000 --- a/tools/usb_descriptor/core.py +++ /dev/null @@ -1,187 +0,0 @@ -import struct - - -def join_interfaces(*args): - interfaces = [] - base_endpoint_number = 1 - for interface_set in args: - base_interface_number = len(interfaces) - for i, interface in enumerate(interface_set): - interfaces.append(interface) - interface.bInterfaceNumber = interfaces.index(interface) - max_endpoint_address = base_endpoint_number - for subdescriptor in interface.subdescriptors: - if subdescriptor.bDescriptorType == EndpointDescriptor.bDescriptorType: - subdescriptor.bEndpointAddress += base_endpoint_number - max_endpoint_address = max(max_endpoint_address, subdescriptor.bEndpointAddress & 0xf) - base_endpoint_number = max_endpoint_address + 1 - return interfaces - - -class Descriptor: - def __init__(self, *args, **kwargs): - self.fmt = ["<B", "B"] - for field in self.fields: - self.fmt.append(field[1]) - self.fmt = "".join(self.fmt) - if len(args) == 1: - self.data = struct.unpack(self.fmt, args[0]) - if self.data[1] != self.bDescriptorType: - raise RuntimeError("Descriptor type doesn't match.") - return - elif len(args) > 1: - raise TypeError("Only one arg or keyword args expected.") - elif len(kwargs) == 0: - raise TypeError("Only one arg or keyword args expected.") - - self.data = [] - for field, _, default in self.fields: - if field in kwargs: - self.data.append(kwargs[field]) - elif default is not None: - self.data.append(default) - else: - raise ValueError("Missing {} argument.".format(field)) - - def __bytes__(self): - return struct.pack(self.fmt, self.bLength, self.bDescriptorType, *self.data) - - @property - def bDescriptorType(self): - return self._bDescriptorType - -class EndpointDescriptor(Descriptor): - fields = [('bEndpointAddress', "B", None), - ('bmAttributes', "B", None), - ('wMaxPacketSize', "H", 0x40), - ('bInterval', "B", 0)] - - bLength = 0x07 - bDescriptorType = 0x5 - - TYPE_CONTROL = 0b00 - TYPE_ISOCHRONOUS = 0b01 - TYPE_BULK = 0b10 - TYPE_INTERRUPT = 0b11 - - DIRECTION_IN = 0x80 - DIRECTION_OUT = 0x00 - - @property - def bEndpointAddress(self): - return self.data[0] - - @bEndpointAddress.setter - def bEndpointAddress(self, value): - self.data[0] = value - - -class InterfaceDescriptor(Descriptor): - fields = [('bInterfaceNumber', "B", 0), - ('bAlternateSetting', "B", 0), - ('bNumEndpoints', "B", 0), - ('bInterfaceClass', "B", None), - ('bInterfaceSubClass', "B", 0), - ('bInterfaceProtocol', "B", 0), - ('iInterface', "B", 0)] - - bLength = 0x09 - bDescriptorType = 0x4 - - def __init__(self, *args, **kwargs): - self.subdescriptors = [] - if "subdescriptors" in kwargs: - self.subdescriptors = kwargs["subdescriptors"] - super().__init__(*args, **kwargs) - - def __bytes__(self): - endpoint_count = 0 - subdescriptor_bytes = [] - for desc in self.subdescriptors: - subdescriptor_bytes.append(bytes(desc)) - if desc.bDescriptorType == EndpointDescriptor.bDescriptorType: - endpoint_count += 1 - subdescriptor_bytes = b"".join(subdescriptor_bytes) - self.data[2] = endpoint_count - return super().__bytes__() + subdescriptor_bytes - - @property - def bInterfaceNumber(self): - return self.data[0] - - @bInterfaceNumber.setter - def bInterfaceNumber(self, value): - self.data[0] = value - -class InterfaceAssociationDescriptor(Descriptor): - fields = [('bFirstInterface', "B", None), - ('bInterfaceCount', "B", None), - ('bFunctionClass', "B", None), - ('bFunctionSubClass', "B", None), - ('bFunctionProtocol', "B", None), - ('iFunction', "B", 0)] - - bLength = 0x08 - bDescriptorType = 0xB - - -class ConfigurationDescriptor(Descriptor): - fields = [('wTotalLength', "H", None), - ('bNumInterfaces', "B", None), - ('bConfigurationValue', "B", 0x1), - ('iConfiguration', "B", 0), - # bus powered (bit 6), no remote wakeup (bit 5), bit 7 is always 1 and 0-4 are always 0 - ('bmAttributes', "B", 0x80), - # 100 mA by default - ('bMaxPower', "B", 50)] - - bLength = 0x09 - bDescriptorType = 0x2 - -class DeviceDescriptor(Descriptor): - fields = [('bcdUSB', "H", 0x200), - ('bDeviceClass', "B", 0xef), - ('bDeviceSubClass', "B", 0x02), - ('bDeviceProtocol', "B", 0x01), - ('bMaxPacketSize0', "B", 0x40), - ('idVendor', "H", None), - ('idProduct', "H", None), - ('bcdDevice', "H", 0x100), - ('iManufacturer', "B", None), - ('iProduct', "B", None), - ('iSerialNumber', "B", None), - ('bNumConfigurations', "B", 1)] - - bLength = 0x12 - bDescriptorType = 0x1 - -class StringDescriptor: - def __init__(self, value): - if type(value) == str: - self._bString = value.encode("utf-16-le") - self._bLength = len(self._bString) + 2 - elif len(value) > 1: - self._bLength = value[0] - if value[1] != 3: - raise ValueError("Sequence not a StringDescriptor") - self._bString = value[2:2+self.bLength] - - def __bytes__(self): - return struct.pack("BB{}s".format(len(self._bString)), self.bLength, self.bDescriptorType, self._bString) - - @property - def bString(self): - return self._bString.decode("utf-16-le") - - @bString.setter - def bString(self, value): - self._bString = value.encode("utf-16-le") - self._bLength = len(self.encoded) + 2 - - @property - def bDescriptorType(self): - return 3 - - @property - def bLength(self): - return self._bLength |
