import argparse import os import sys # path hacking sys.path.append("../../tools/usb_descriptor") from adafruit_usb_descriptor import cdc, standard, util parser = argparse.ArgumentParser(description='Generate USB descriptors.') parser.add_argument('--manufacturer', type=str, help='manufacturer of the device') parser.add_argument('--product', type=str, help='product name of the device') parser.add_argument('--vid', type=lambda x: int(x, 16), help='vendor id') parser.add_argument('--pid', type=lambda x: int(x, 16), help='product id') parser.add_argument('--serial_number_length', type=int, default=32, help='length needed for the serial number in digits') parser.add_argument('output_file', type=argparse.FileType('w')) args = parser.parse_args() 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 = standard.DeviceDescriptor( idVendor=args.vid, idProduct=args.pid, iManufacturer=strings.index(manufacturer), iProduct=strings.index(product), iSerialNumber=strings.index(serial_number)) # Interface numbers are interface set local and endpoints are interface local # until core.join_interfaces renumbers them. cdc_interfaces = [ standard.InterfaceDescriptor( bInterfaceClass=0x2, # Communications Device Class bInterfaceSubClass=0x02, # Abstract control model bInterfaceProtocol=0x01, # Common AT Commands subdescriptors=[ # Working 2.x # radix: hexadecimal # 05 24 00 10 01 header # 05 24 01 03 01 call manage # 04 24 02 06 acm # 05 24 06 00 01 union cdc.Header(bcdCDC=0x0110), cdc.CallManagement(bmCapabilities=0x03, bDataInterface=0x01), cdc.AbstractControlManagement(bmCapabilities=0x02), cdc.Union(bMasterInterface=0x00, bSlaveInterface=[0x01]), standard.EndpointDescriptor( bEndpointAddress=0x0 | standard.EndpointDescriptor.DIRECTION_IN, bmAttributes=standard.EndpointDescriptor.TYPE_INTERRUPT, wMaxPacketSize=0x8, bInterval=10) ] ), standard.InterfaceDescriptor( bInterfaceClass=0x0a, subdescriptors=[ 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 = [ standard.InterfaceDescriptor( bInterfaceClass=0x08, bInterfaceSubClass=0x06, bInterfaceProtocol=0x50, subdescriptors=[ 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 = util.join_interfaces(cdc_interfaces, msc_interfaces) 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 = standard.ConfigurationDescriptor( wTotalLength=(standard.ConfigurationDescriptor.bLength + cdc_function.bLength + sum([len(bytes(x)) for x in interfaces])), bNumInterfaces=len(interfaces)) descriptor_list = [device, configuration, cdc_function] descriptor_list.extend(interfaces) descriptor_list.extend(strings) output_file = args.output_file output_file.write("#include \n\n") output_file.write("#include \"tools/autogen_usb_descriptor.h\"\n\n") output_file.write("uint8_t usb_descriptors[] = {\n") descriptor_length = 0 serial_number_offset = None for descriptor in descriptor_list: output_file.write("// " + str(descriptor) + "\n") b = bytes(descriptor) i = 0 if descriptor == serial_number: # Add two for the length and descriptor type bytes. serial_number_offset = descriptor_length + 2 # This prints each subdescriptor on a separate line. while i < len(b): length = b[i] for j in range(length): output_file.write("0x{:02x}, ".format(b[i + j])) output_file.write("\n") i += length descriptor_length += length output_file.write("\n") output_file.write("};\n\n") output_file.write("struct usbd_descriptors descriptor_bounds = " + "{usb_descriptors," + " usb_descriptors + sizeof(usb_descriptors)};\n") output_file.write("uint8_t* serial_number = usb_descriptors + " + str(serial_number_offset) + ";\n") output_file.write("uint8_t serial_number_length = " + str(args.serial_number_length) + ";\n") output_file.close()