import codecs import construct import importlib import sys from usb_protocol.types.descriptors.standard import ConfigurationDescriptor, DescriptorFormat, EndpointDescriptor, InterfaceDescriptor, StandardDescriptorNumbers from string import Template # Note this file is under the following copyright: copyright = '''/*- * Copyright 2022 John-Mark Gurney. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. If you are STMicroelectronics N.V., one of it's subsidiaries, a * subsidiary of an owner of STMicroelectronics N.V., or an employee, * contractor, or agent of any of the preceeding entities, you are not * allowed to use this code, in either source or binary forms. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ ''' UniDesc = DescriptorFormat( "bLength" / construct.Int8ul, "bDescriptorType" / construct.Int8ul, ) descparsers = { StandardDescriptorNumbers.INTERFACE: InterfaceDescriptor.parse, StandardDescriptorNumbers.ENDPOINT: EndpointDescriptor.parse, } def getepdescs(confdesc): ret = [] lastdesc = ConfigurationDescriptor.parse(confdesc) pos = lastdesc.bLength while pos < len(confdesc): descparser = descparsers.get(confdesc[pos + 1], UniDesc.parse) desc = descparser(confdesc[pos:]) if confdesc[pos + 1] == StandardDescriptorNumbers.ENDPOINT: ret.append(desc) lastdesc = desc pos += lastdesc.bLength return ret if __name__ == '__main__': usbname = sys.argv[1] mod = importlib.import_module(usbname) collection = mod.collection sorteddesc = sorted(collection) descs = { (x, y): z for x, y, z in collection } for value, index, raw in sorteddesc: print(int(value), repr(index), codecs.encode(raw, 'hex')) p = lambda *args, **kwargs: print(*args, **kwargs, file=fp) with open('%s_base.h' % usbname, 'w') as fp: p(Template('''${copyright} #include extern USBD_ClassTypeDef ${usbname}_def; void USBD_GetDescriptor(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); void ${usbname}_init(void); void ${usbname}_epopen(USBD_HandleTypeDef *pdev); void ${usbname}_epclose(USBD_HandleTypeDef *pdev); ''').substitute(locals())) with open('%s_base.c' % usbname, 'w') as fp: descstrings = '\n'.join('const uint8_t desc_%d_%d[] = { %s };' % (x, y, ', '.join(hex(w) for w in z)) for x, y, z in sorteddesc) descstructs = '\n'.join('\t{ .type = %d, .subnumb = %d, .datalen = %d, .data = desc_%d_%d },' % (x, y, len(z), x, y) for x, y, z in sorteddesc) epdescs = getepdescs(descs[(2, 0)]) print(repr(epdescs)) epopencode = '\n\t'.join(sum(([ 'USBD_LL_OpenEP(pdev, %#x, %d, %d);' % (ep.bEndpointAddress, ep.bmAttributes & 0x3, ep.wMaxPacketSize), 'pdev->%s[%#x & 0xFU].is_used = 1;' % ('ep_in' if ep.bEndpointAddress & 0x80 else 'ep_out', ep.bEndpointAddress) ] for ep in epdescs), [])) epclosecode = '\n\t'.join(sum(([ 'USBD_LL_CloseEP(pdev, %#x);' % (ep.bEndpointAddress), 'pdev->%s[%#x & 0xFU].is_used = 0;' % ('ep_in' if ep.bEndpointAddress & 0x80 else 'ep_out', ep.bEndpointAddress) ] for ep in epdescs), [])) print(repr(epopencode)) p(Template('''${copyright} #include "${usbname}_base.h" #include #include /* #include */ /* #include */ static USBD_HandleTypeDef usbd_inst; void USBD_GetDescriptor(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); ${descstrings} static const struct { uint8_t type; uint8_t subnumb; uint8_t datalen; const uint8_t *data; } descriptors[] = { ${descstructs} }; void USBD_GetDescriptor(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) { uint8_t const *buf; uint8_t buflen; uint8_t type, subnumb; int i; type = req->wValue >> 8; subnumb = req->wValue & 0xff; for (i = 0; i < sizeof descriptors / sizeof *descriptors; i++) { if (descriptors[i].type == type && descriptors[i].subnumb == subnumb) { buf = descriptors[i].data; buflen = descriptors[i].datalen; if ((buflen != 0U) && (req->wLength != 0U)) { buflen = MIN(buflen, req->wLength); USBD_CtlSendData(pdev, (uint8_t *)(uintptr_t)buf, buflen); } if(req->wLength == 0U) { USBD_CtlSendStatus(pdev); } return; } } USBD_CtlError(pdev , req); } void ${usbname}_init(void) { if (USBD_Init(&usbd_inst, NULL/*Desc, not used*/, DEVICE_FS) != USBD_OK) Error_Handler(); if (USBD_RegisterClass(&usbd_inst, &${usbname}_def) != USBD_OK) Error_Handler(); if (USBD_Start(&usbd_inst) != USBD_OK) Error_Handler(); } SYSINIT_VF(${usbname}_init, SI_SUB_USB, SI_ORDER_MIDDLE, ${usbname}_init); void ${usbname}_epopen(USBD_HandleTypeDef *pdev) { ${epopencode} } void ${usbname}_epclose(USBD_HandleTypeDef *pdev) { ${epclosecode} } extern PCD_HandleTypeDef hpcd_USB_FS; void USB_LP_IRQHandler(void) { HAL_PCD_IRQHandler(&hpcd_USB_FS); } static volatile uint32_t holding; void Error_Handler(void) { #if 0 debug_printf("error_handler\\n"); #endif for (;;) holding++; }''').substitute(locals())) print('enda')