From ff19706059a6414681177f021767ba4dda92db6b Mon Sep 17 00:00:00 2001 From: "hemera@nephelae.eu" Date: Wed, 1 Mar 2023 10:33:43 +0200 Subject: [PATCH] Add support for descriptors been stored / loaded in EEPROM. --- usbdrv/usbdrv.c | 48 ++++++++++++++++++++++++++++----------- usbdrv/usbdrv.h | 50 +++++++++++++++++++++++++++++++++++++++-- usbdrv/usbportability.h | 3 +++ 3 files changed, 86 insertions(+), 15 deletions(-) diff --git a/usbdrv/usbdrv.c b/usbdrv/usbdrv.c index 1d80ac6..9ab96e1 100644 --- a/usbdrv/usbdrv.c +++ b/usbdrv/usbdrv.c @@ -291,17 +291,23 @@ USB_PUBLIC void usbSetInterrupt3(uchar *data, uchar len) * This may cause problems with undefined symbols if compiled without * optimizing! */ -#define GET_DESCRIPTOR(cfgProp, staticName) \ - if(cfgProp){ \ - if((cfgProp) & USB_PROP_IS_RAM) \ - flags = 0; \ - if((cfgProp) & USB_PROP_IS_DYNAMIC){ \ - len = usbFunctionDescriptor(rq); \ - }else{ \ - len = USB_PROP_LENGTH(cfgProp); \ - usbMsgPtr = (usbMsgPtr_t)(staticName); \ - } \ - } +#define GET_DESCRIPTOR(cfgProp, staticName) \ + if(cfgProp){ \ + if((cfgProp) & USB_PROP_IS_RAM){ \ + flags = 0; \ + } \ + if((cfgProp) & USB_PROP_IS_DYNAMIC){ \ + len = usbFunctionDescriptor(rq); \ + }else{ \ + if((cfgProp) & USB_PROP_IS_EEPROM){ \ + flags = USB_FLG_MSGPTR_IS_EEPROM; \ + len = USB_PROP_EEPROM_LENGTH(cfgProp); \ + } else { \ + len = USB_PROP_LENGTH(cfgProp); \ + } \ + usbMsgPtr = (usbMsgPtr_t)(staticName); \ + } \ + } \ /* usbDriverDescriptor() is similar to usbFunctionDescriptor(), but used * internally for all types of descriptors. @@ -318,8 +324,12 @@ uchar flags = USB_FLG_MSGPTR_IS_ROM; GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_CONFIGURATION, usbDescriptorConfiguration) SWITCH_CASE(USBDESCR_STRING) /* 3 */ #if USB_CFG_DESCR_PROPS_STRINGS & USB_PROP_IS_DYNAMIC - if(USB_CFG_DESCR_PROPS_STRINGS & USB_PROP_IS_RAM) + if(USB_CFG_DESCR_PROPS_STRINGS & USB_PROP_IS_RAM){ flags = 0; + } else + if(USB_CFG_DESCR_PROPS_UNKNOWN & USB_PROP_IS_EEPROM){ + flags = USB_FLG_MSGPTR_IS_EEPROM; + } len = usbFunctionDescriptor(rq); #else /* USB_CFG_DESCR_PROPS_STRINGS & USB_PROP_IS_DYNAMIC */ SWITCH_START(rq->wValue.bytes[0]) @@ -335,6 +345,9 @@ uchar flags = USB_FLG_MSGPTR_IS_ROM; if(USB_CFG_DESCR_PROPS_UNKNOWN & USB_PROP_IS_DYNAMIC){ if(USB_CFG_DESCR_PROPS_UNKNOWN & USB_PROP_IS_RAM){ flags = 0; + } else + if(USB_CFG_DESCR_PROPS_UNKNOWN & USB_PROP_IS_EEPROM){ + flags = USB_FLG_MSGPTR_IS_EEPROM; } len = usbFunctionDescriptor(rq); } @@ -350,6 +363,9 @@ uchar flags = USB_FLG_MSGPTR_IS_ROM; if(USB_CFG_DESCR_PROPS_UNKNOWN & USB_PROP_IS_DYNAMIC){ if(USB_CFG_DESCR_PROPS_UNKNOWN & USB_PROP_IS_RAM){ flags = 0; + } else + if(USB_CFG_DESCR_PROPS_UNKNOWN & USB_PROP_IS_EEPROM){ + flags = USB_FLG_MSGPTR_IS_EEPROM; } len = usbFunctionDescriptor(rq); } @@ -505,7 +521,13 @@ static uchar usbDeviceRead(uchar *data, uchar len) { uchar i = len; usbMsgPtr_t r = usbMsgPtr; - if(usbMsgFlags & USB_FLG_MSGPTR_IS_ROM){ /* ROM data */ + if(usbMsgFlags & USB_FLG_MSGPTR_IS_EEPROM){ /* EEPROM data */ + do{ + uchar c = USB_READ_EEPROM(r); /* assign to char size variable to enforce byte ops */ + *data++ = c; + r++; + }while(--i); + }else if(usbMsgFlags & USB_FLG_MSGPTR_IS_ROM){ /* ROM data */ do{ uchar c = USB_READ_FLASH(r); /* assign to char size variable to enforce byte ops */ *data++ = c; diff --git a/usbdrv/usbdrv.h b/usbdrv/usbdrv.h index f094120..0484db5 100644 --- a/usbdrv/usbdrv.h +++ b/usbdrv/usbdrv.h @@ -215,7 +215,8 @@ extern uchar usbMsgFlags; /* flag values see USB_FLG_* */ * address. */ -#define USB_FLG_MSGPTR_IS_ROM (1<<6) +#define USB_FLG_MSGPTR_IS_ROM (1<<6) +#define USB_FLG_MSGPTR_IS_EEPROM (1<<5) USB_PUBLIC usbMsgLen_t usbFunctionSetup(uchar data[8]); /* This function is called when the driver receives a SETUP transaction from @@ -424,6 +425,11 @@ extern volatile schar usbRxLen; * about the various methods to define USB descriptors. If you do nothing, * the default descriptors will be used. */ +#define USB_PROP_IS_EEPROM (1u << 13) +/* If this property is set for a descriptor, the data is read from EEPROM +* memory. Use it combined (OR) with with USB_PROP_EEPROM_STRING_LENGTH +* if its a string descriptor. + */ #define USB_PROP_IS_DYNAMIC (1u << 14) /* If this property is set for a descriptor, usbFunctionDescriptor() will be * used to obtain the particular descriptor. Data directly returned via @@ -439,6 +445,15 @@ extern volatile schar usbRxLen; /* If a static external descriptor is used, this is the total length of the * descriptor in bytes. */ + #define USB_PROP_EEPROM_LENGTH(len) ((len) & 0x1fff) +/* If a static external descriptor stored in EEPROM is used, this is the total length of the + * descriptor in bytes. + */ + #define USB_PROP_EEPROM_STRING_LENGTH(eepromStringLength) (USB_PROP_EEPROM_LENGTH((2*(eepromStringLength)+2))) +/* This macro computes the EEPROM length for a string descriptor given the + * string's length. See usbdrv.c for an example how to use it. + */ + /* all descriptors which may have properties: */ #ifndef USB_CFG_DESCR_PROPS_DEVICE @@ -483,46 +498,77 @@ extern volatile schar usbRxLen; */ #ifndef __ASSEMBLER__ extern +#if !(USB_CFG_DESCR_PROPS_DEVICE & USB_PROP_IS_EEPROM) #if !(USB_CFG_DESCR_PROPS_DEVICE & USB_PROP_IS_RAM) PROGMEM const #endif char usbDescriptorDevice[]; +#else +const char EEMEM usbDescriptorDevice[]; +#endif + extern +#if !(USB_CFG_DESCR_PROPS_CONFIGURATION & USB_PROP_IS_EEPROM) #if !(USB_CFG_DESCR_PROPS_CONFIGURATION & USB_PROP_IS_RAM) PROGMEM const #endif char usbDescriptorConfiguration[]; +#else +const char EEMEM usbDescriptorConfiguration[]; +#endif extern +#if !(USB_CFG_DESCR_PROPS_CONFIGURATION & USB_PROP_IS_EEPROM) #if !(USB_CFG_DESCR_PROPS_HID_REPORT & USB_PROP_IS_RAM) PROGMEM const #endif char usbDescriptorHidReport[]; +#else +const char EEMEM usbDescriptorHidReport[]; +#endif extern +#if !(USB_CFG_DESCR_PROPS_CONFIGURATION & USB_PROP_IS_EEPROM) #if !(USB_CFG_DESCR_PROPS_STRING_0 & USB_PROP_IS_RAM) PROGMEM const #endif char usbDescriptorString0[]; +#else +const char EEMEM usbDescriptorString0[]; +#endif extern +#if !(USB_CFG_DESCR_PROPS_STRING_VENDOR & USB_PROP_IS_EEPROM) #if !(USB_CFG_DESCR_PROPS_STRING_VENDOR & USB_PROP_IS_RAM) PROGMEM const #endif int usbDescriptorStringVendor[]; +#else +const int EEMEM usbDescriptorStringVendor[]; +#endif + extern +#if !(USB_CFG_DESCR_PROPS_STRING_PRODUCT & USB_PROP_IS_EEPROM) #if !(USB_CFG_DESCR_PROPS_STRING_PRODUCT & USB_PROP_IS_RAM) PROGMEM const #endif int usbDescriptorStringDevice[]; +#else +const int EEMEM usbDescriptorStringDevice[]; +#endif extern -#if !(USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER & USB_PROP_IS_RAM) +#if !(USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER & USB_PROP_IS_EEPROM) +#if !(USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER & USB_PROP_IS_RAM) PROGMEM const #endif int usbDescriptorStringSerialNumber[]; +#else +const int EEMEM usbDescriptorStringSerialNumber[]; +#endif + #endif /* __ASSEMBLER__ */ diff --git a/usbdrv/usbportability.h b/usbdrv/usbportability.h index 0a861d0..3b3d0ba 100644 --- a/usbdrv/usbportability.h +++ b/usbdrv/usbportability.h @@ -118,6 +118,7 @@ static inline void sei(void) /* ------------------------------------------------------------------------- */ #include +#include #ifdef __ASSEMBLER__ # define _VECTOR(N) __vector_ ## N /* io.h does not define this for asm */ #else @@ -130,6 +131,8 @@ static inline void sei(void) # define USB_READ_FLASH(addr) pgm_read_byte(addr) #endif +#define USB_READ_EEPROM(addr) eeprom_read_byte(addr) + #define macro .macro #define endm .endm #define nop2 rjmp .+0 /* jump to next instruction */