245 lines
9.5 KiB
Python
245 lines
9.5 KiB
Python
import subprocess
|
|
|
|
import Descriptor
|
|
import Descriptor as desc
|
|
import StructGenerator
|
|
|
|
|
|
# class for managing string descriptors
|
|
class StringManager:
|
|
def __init__(self):
|
|
self.strings = {}
|
|
self.num_ids = {}
|
|
|
|
# add a string to the manager
|
|
def add_string(self, text_id, text):
|
|
new_id = len(self.strings) + 1
|
|
self.strings[text_id] = {"text": text, "id": new_id}
|
|
self.num_ids[new_id] = text_id
|
|
return new_id
|
|
|
|
# add empty placeholders, reserve indices
|
|
def add_placeholders(self, text_id_array):
|
|
for text_id in text_id_array:
|
|
self.add_string(text_id, "")
|
|
|
|
# retrieve text based on text or numeric id
|
|
def get_text(self, id):
|
|
if isinstance(id, str):
|
|
return self.strings[id]["text"]
|
|
elif isinstance(id, int):
|
|
return self.strings[self.num_ids[id]]["text"]
|
|
else:
|
|
return None
|
|
|
|
# change existing entry
|
|
def change_text(self, text_id, text):
|
|
self.strings[text_id]["text"] = text
|
|
|
|
# get numeric id based on text id
|
|
def get_numeric_id(self, text_id):
|
|
return self.strings[text_id]["id"]
|
|
|
|
# retrieve number of entries
|
|
def get_size(self):
|
|
return len(self.strings)
|
|
|
|
# get text ids
|
|
def get_text_ids(self):
|
|
return self.strings.keys()
|
|
|
|
|
|
class ConfigGenerator:
|
|
def __init__(self, config):
|
|
# declaration and definition file contents
|
|
self.config = config
|
|
self.h = ""
|
|
self.c = ""
|
|
|
|
self.DIVIDER = "\n\n// ---------------------------\n\n"
|
|
|
|
# constants
|
|
self.VAR_FULL_CONF_DESCS = "fullConfDescs"
|
|
self.VAR_LANG_ID_STRDESC = "langid_str_desc"
|
|
# self.VAR_MANUF_STRDESC = "manufacturer_str_desc"
|
|
# self.VAR_PRODUCT_STRDESC = "product_str_desc"
|
|
# self.VAR_SERIAL_STRDESC = "serial_str_desc"
|
|
|
|
# string management
|
|
self.str_mgr = StringManager()
|
|
|
|
string_fields = [
|
|
"vendor_string",
|
|
"product_string",
|
|
"serial_number"
|
|
]
|
|
|
|
self.str_mgr.add_placeholders(string_fields)
|
|
|
|
self.LANG_ID_US_EN = "0x0409"
|
|
|
|
self.max_config_str_desc_size = 0 # maximal size (wLength) of config descriptors
|
|
self.max_endpoint_index = 0 # maximum endpoint index used in at least one of the configurations
|
|
self.max_endpoint_count = 0 # maximum endpoint count across all configurations
|
|
|
|
# add macro to header file
|
|
def add_def_macro(self, key: str, value: str = "", comment=""):
|
|
self.h += "#define " + key
|
|
if value != "":
|
|
self.h += " (" + value + ")"
|
|
|
|
if comment != "":
|
|
self.h += " // " + comment
|
|
|
|
self.h += "\n"
|
|
|
|
# save generated config
|
|
def save(self):
|
|
DECLARATIONS = "usb_desc.h"
|
|
DEFINITIONS = "usb_desc.c"
|
|
|
|
with open(DEFINITIONS, 'w') as f_c:
|
|
f_c.write("#include \"" + DECLARATIONS + "\"\n\n")
|
|
f_c.write(self.c)
|
|
|
|
include_guard_tag = "_" + DECLARATIONS.replace(".", "_").upper()
|
|
|
|
with open(DECLARATIONS, 'w') as f_h:
|
|
f_h.writelines(("#ifndef " + include_guard_tag + "\n", "#define " + include_guard_tag + "\n\n", "#include \"../usb_device_types.h\"\n\n"))
|
|
f_h.write(self.h)
|
|
f_h.writelines(("\n\n#endif // " + include_guard_tag))
|
|
|
|
subprocess.run(["indent", "-linux", "-l120", "-i4", "-nut", DECLARATIONS])
|
|
subprocess.run(["indent", "-linux", "-l120", "-i4", "-nut", DEFINITIONS])
|
|
|
|
# generate Device descriptor
|
|
def generate_device_descriptor(self):
|
|
dev_desc = desc.DeviceDescriptor(self.config, self.str_mgr)
|
|
self.c += dev_desc.gen_c()
|
|
self.h += dev_desc.gen_h()
|
|
|
|
# generate Device Qualifier descriptor
|
|
def generate_device_qualifier_descriptor(self):
|
|
dev_qual_desc = desc.DeviceQualifierDescriptor(self.config)
|
|
self.c += dev_qual_desc.gen_c()
|
|
self.h += dev_qual_desc.gen_h()
|
|
|
|
# generate endpoint descriptor assigned to an interface descriptor
|
|
def generate_endpoint_descriptors(self, intf, full_conf_struct):
|
|
for ep in intf["endpoints"]:
|
|
ep_varname = "ep{:d}{:s}".format(ep["n"], ep["direction"])
|
|
ep_struct = desc.EndpointDescriptor(ep_varname, ep)
|
|
full_conf_struct.add_record(ep_struct)
|
|
|
|
return len(intf["endpoints"])
|
|
|
|
# generate interface descriptor assigned to parent configuration descriptor
|
|
def generate_interface_descriptors(self, conf, full_conf_struct):
|
|
|
|
# fetch number of distinct endpoints
|
|
def get_distinct_endpoint_count(eps):
|
|
eps_found = set()
|
|
for ep in eps:
|
|
eps_found.add(ep["n"])
|
|
return len(eps_found)
|
|
|
|
# -----------------
|
|
|
|
for intf in conf["interfaces"]:
|
|
# generate interface descriptor
|
|
intf_varname = "intf{:d}".format(intf["id"])
|
|
ep_count = get_distinct_endpoint_count(intf["endpoints"])
|
|
intf_struct = desc.InterfaceDescriptor(intf_varname, intf) # endpoint count is unknown
|
|
full_conf_struct.add_record(intf_struct)
|
|
|
|
# generate additional interface descriptors
|
|
# if [intf.keys()].count("additional_interfaces") > 0:
|
|
for addintf in intf["additional_interfaces"]:
|
|
type = addintf["type"]
|
|
addintf_struct = desc.DescriptorFactory.generate(type, intf_varname + type, addintf)
|
|
full_conf_struct.add_record(addintf_struct)
|
|
|
|
self.h += addintf_struct.print_typedef()
|
|
|
|
# generate endpoint descriptors
|
|
self.generate_endpoint_descriptors(intf, full_conf_struct) # generate endpoints
|
|
|
|
# generate configuration descriptors and subordinate descriptor
|
|
def generate_configuration_descriptors(self):
|
|
# array for referencing configuration descriptors
|
|
conf_desc_array_struct = desc.Descriptor("confDescs", "USB_ConfigurationDesc *", [])
|
|
conf_desc_array_struct.typedef = "ConfDescs"
|
|
|
|
# generate full configurations
|
|
index = 0
|
|
for conf in self.config["configurations"]:
|
|
full_conf_typename = "struct _FullConfigurations{:d}".format(index)
|
|
full_conf_struct = Descriptor.Descriptor("fullConfDescs{:d}".format(index), full_conf_typename, [])
|
|
conf_struct = desc.ConfigurationDescriptor("config", conf, "sizeof({:s})".format(full_conf_typename)) # TODO: total length
|
|
full_conf_struct.add_record(conf_struct)
|
|
self.generate_interface_descriptors(conf, full_conf_struct)
|
|
|
|
self.c += full_conf_struct.gen_c()
|
|
self.h += full_conf_struct.gen_h(print_typedef=True)
|
|
|
|
# add descriptor's pointer to the list
|
|
str_desc_ptr = StructGenerator.DummyRecord(full_conf_struct.name, "USB_ConfigurationDesc *", "(USB_ConfigurationDesc *) &" + full_conf_struct.name, StructGenerator.RecordFactory.PLAIN_PRINTER)
|
|
conf_desc_array_struct.add_record(str_desc_ptr)
|
|
|
|
self.h += self.DIVIDER
|
|
|
|
# self.h += conf_desc_array_struct.print_typedef()
|
|
# self.h += conf_desc_array_struct.print_declaration()
|
|
# self.c += conf_desc_array_struct.print_assigment()
|
|
|
|
self.h += conf_desc_array_struct.gen_h(print_typedef=True)
|
|
self.c += conf_desc_array_struct.gen_c()
|
|
|
|
# generate string descriptors
|
|
def generate_string_descriptors(self):
|
|
# array for referencing string descriptors
|
|
str_desc_array_struct = desc.Descriptor("strDescs", "USB_StringDesc *", [])
|
|
str_desc_array_struct.typedef = "StringDescs"
|
|
|
|
# generate lang id descriptor
|
|
lang_id_name = "lang_id"
|
|
lang_id_struct = desc.StringDescriptor(0x0409, lang_id_name) # TODO!
|
|
self.c += lang_id_struct.gen_c()
|
|
self.h += lang_id_struct.gen_h(print_typedef=True)
|
|
|
|
str_desc_ptr = StructGenerator.DummyRecord(lang_id_struct.name, "USB_StringDesc *", "(USB_StringDesc *) &" + lang_id_struct.name, StructGenerator.RecordFactory.PLAIN_PRINTER)
|
|
str_desc_array_struct.add_record(str_desc_ptr)
|
|
|
|
# generate individual string descriptors
|
|
for text_id in self.str_mgr.get_text_ids():
|
|
# create descriptor
|
|
self.str_mgr.change_text(text_id, self.config[text_id])
|
|
str_struct = desc.StringDescriptor(self.str_mgr.get_text(text_id), text_id)
|
|
self.c += str_struct.gen_c()
|
|
self.h += str_struct.gen_h(print_typedef=True)
|
|
|
|
# add descriptor's pointer to the list
|
|
str_desc_ptr = StructGenerator.DummyRecord(text_id, "USB_StringDesc *", "(USB_StringDesc *) &" + str_struct.name, StructGenerator.RecordFactory.PLAIN_PRINTER)
|
|
str_desc_array_struct.add_record(str_desc_ptr)
|
|
self.h += self.DIVIDER
|
|
|
|
# self.h += str_desc_array_struct.print_typedef()
|
|
# self.h += str_desc_array_struct.print_declaration()
|
|
# self.c += str_desc_array_struct.print_assigment()
|
|
self.h += str_desc_array_struct.gen_h(print_typedef=True)
|
|
self.c += str_desc_array_struct.gen_c()
|
|
|
|
def generate_macros(self):
|
|
self.add_def_macro("USBF_NOF_CONFIGURATIONS", str(len(self.config["configurations"])), "Number of configurations")
|
|
self.h += self.DIVIDER
|
|
|
|
def generate(self):
|
|
self.generate_macros() # generate macro definitions
|
|
self.generate_string_descriptors() # generate string descriptors
|
|
self.generate_device_descriptor() # generate device descriptor
|
|
self.generate_device_qualifier_descriptor() # generate device qualifier descriptor
|
|
self.generate_configuration_descriptors() # generate configuration descriptors
|
|
|
|
# save generated files
|
|
self.save()
|