From bdb53e4c043d089279d9891b68bea77614cb97ee Mon Sep 17 00:00:00 2001 From: yiancar Date: Sun, 16 Aug 2020 01:07:21 +0100 Subject: Added 3rd endpoint (#1) * Added 3rd endpoint - Added 3rd endpoint check in asmcommon. This adds 2 extra cycles to the USB routine when enabled. With 16MHz clock (most if not all qmk build use that) the routine is still within spec. - Updated prototype.h file to add additional options. - Simulatanius changes in QMK to follow soon * Update usbdrv/usbdrv.c * Update usbdrv/usbdrv.c * Update usbdrv/usbdrv.c * Update usbdrv/usbdrv.c * Update usbdrv/usbdrvasm.S Accepted to keep changes minimal * Update usbdrv/usbdrvasm.S Accepted to keep changes minimal * Update usbdrv/usbdrvasm.S Accepted to keep changes minimal * Update usbdrv/usbdrvasm.S Accepted to keep changes minimal --- usbdrv/asmcommon.inc | 26 ++++++++++++++++++++++++-- usbdrv/usbconfig-prototype.h | 20 +++++++++++++++----- usbdrv/usbdrv.c | 29 ++++++++++++++++++++++++++++- usbdrv/usbdrv.h | 20 ++++++++++++++++++-- usbdrv/usbdrvasm.S | 4 +++- 5 files changed, 88 insertions(+), 11 deletions(-) diff --git a/usbdrv/asmcommon.inc b/usbdrv/asmcommon.inc index d2a4f7c..906dc14 100644 --- a/usbdrv/asmcommon.inc +++ b/usbdrv/asmcommon.inc @@ -110,11 +110,17 @@ handleData: breq doReturn ;[21] lds x2, usbRxLen ;[22] tst x2 ;[24] - brne sendNakAndReti ;[25] +; 2020-05-04 Following change is used to overcome branch +/- 64 word limit. + breq noBranchSendNakAndReti ; [25] + rjmp sendNakAndReti +noBranchSendNakAndReti: ; 2006-03-11: The following two lines fix a problem where the device was not ; recognized if usbPoll() was called less frequently than once every 4 ms. cpi cnt, 4 ;[26] zero sized data packets are status phase only -- ignore and ack - brmi sendAckAndReti ;[27] keep rx buffer clean -- we must not NAK next SETUP +; 2020-05-04 Following change is used to overcome branch +/- 64 word limit. + brpl noBranchSendAckAndReti ;[27] keep rx buffer clean -- we must not NAK next SETUP + rjmp sendAckAndReti +noBranchSendAckAndReti: #if USB_CFG_CHECK_DATA_TOGGLING sts usbCurrentDataToken, token ; store for checking by C code #endif @@ -165,6 +171,10 @@ handleIn1: ;[38] ; 2006-06-10 as suggested by O.Tamura: support second INTR IN / BULK IN endpoint cpi x3, USB_CFG_EP3_NUMBER;[38] breq handleIn3 ;[39] +#endif +#if USB_CFG_HAVE_INTRIN_ENDPOINT4 + cpi x3, USB_CFG_EP4_NUMBER;[38] + breq handleIn4 ;[39] #endif lds cnt, usbTxLen1 ;[40] sbrc cnt, 4 ;[42] all handshake tokens have bit 4 set @@ -184,4 +194,16 @@ handleIn3: ldi YH, hi8(usbTxBuf3) ;[48] rjmp usbSendAndReti ;[49] 51 + 12 = 63 until SOP #endif + +#if USB_CFG_HAVE_INTRIN_ENDPOINT4 +handleIn4: + lds cnt, usbTxLen4 ;[41] + sbrc cnt, 4 ;[43] + rjmp sendCntAndReti ;[44] 49 + 16 = 65 until SOP + sts usbTxLen4, x1 ;[45] x1 == USBPID_NAK from above + ldi YL, lo8(usbTxBuf4) ;[47] + ldi YH, hi8(usbTxBuf4) ;[48] + rjmp usbSendAndReti ;[49] 51 + 12 = 63 until SOP +#endif + #endif diff --git a/usbdrv/usbconfig-prototype.h b/usbdrv/usbconfig-prototype.h index 22dd9e8..43b9ba7 100644 --- a/usbdrv/usbconfig-prototype.h +++ b/usbdrv/usbconfig-prototype.h @@ -89,9 +89,19 @@ section at the end of this file). /* If the so-called endpoint 3 is used, it can now be configured to any other * endpoint number (except 0) with this macro. Default if undefined is 3. */ +#define USB_CFG_HAVE_INTRIN_ENDPOINT4 0 +/* Define this to 1 if you want to compile a version with three endpoints: The + * default control endpoint 0, an interrupt-in endpoint 4 (or the number + * configured below) and a catch-all default interrupt-in endpoint as above. + * You must also define USB_CFG_HAVE_INTRIN_ENDPOINT to 1 for this feature. + */ +#define USB_CFG_EP4_NUMBER 4 +/* If the so-called endpoint 4 is used, it can now be configured to any other + * endpoint number (except 0) with this macro. Default if undefined is 4. + */ /* #define USB_INITIAL_DATATOKEN USBPID_DATA1 */ /* The above macro defines the startup condition for data toggling on the - * interrupt/bulk endpoints 1 and 3. Defaults to USBPID_DATA1. + * interrupt/bulk endpoints 1, 3 and 4. Defaults to USBPID_DATA1. * Since the token is toggled BEFORE sending any data, the first packet is * sent with the oposite value of this configuration! */ @@ -104,10 +114,10 @@ section at the end of this file). #define USB_CFG_SUPPRESS_INTR_CODE 0 /* Define this to 1 if you want to declare interrupt-in endpoints, but don't * want to send any data over them. If this macro is defined to 1, functions - * usbSetInterrupt() and usbSetInterrupt3() are omitted. This is useful if - * you need the interrupt-in endpoints in order to comply to an interface - * (e.g. HID), but never want to send any data. This option saves a couple - * of bytes in flash memory and the transmit buffers in RAM. + * usbSetInterrupt(), usbSetInterrupt3() and usbSetInterrupt4() are omitted. + * This is useful if you need the interrupt-in endpoints in order to comply + * to an interface (e.g. HID), but never want to send any data. This option + * saves a couple of bytes in flash memory and the transmit buffers in RAM. */ #define USB_CFG_INTR_POLL_INTERVAL 10 /* If you compile a version with endpoint 1 (interrupt-in), this is the poll diff --git a/usbdrv/usbdrv.c b/usbdrv/usbdrv.c index 1d80ac6..b0cb565 100644 --- a/usbdrv/usbdrv.c +++ b/usbdrv/usbdrv.c @@ -37,6 +37,9 @@ usbTxStatus_t usbTxStatus1; # if USB_CFG_HAVE_INTRIN_ENDPOINT3 usbTxStatus_t usbTxStatus3; # endif +# if USB_CFG_HAVE_INTRIN_ENDPOINT4 +usbTxStatus_t usbTxStatus4; +# endif #endif #if USB_CFG_CHECK_DATA_TOGGLING uchar usbCurrentDataToken;/* when we check data toggling to ignore duplicate packets */ @@ -139,7 +142,7 @@ PROGMEM const char usbDescriptorDevice[] = { /* USB device descriptor */ PROGMEM const char usbDescriptorConfiguration[] = { /* USB configuration descriptor */ 9, /* sizeof(usbDescriptorConfiguration): length of descriptor in bytes */ USBDESCR_CONFIG, /* descriptor type */ - 18 + 7 * USB_CFG_HAVE_INTRIN_ENDPOINT + 7 * USB_CFG_HAVE_INTRIN_ENDPOINT3 + + 18 + 7 * USB_CFG_HAVE_INTRIN_ENDPOINT + 7 * USB_CFG_HAVE_INTRIN_ENDPOINT3 + 7 * USB_CFG_HAVE_INTRIN_ENDPOINT4 + (USB_CFG_DESCR_PROPS_HID & 0xff), 0, /* total length of data returned (including inlined descriptors) */ 1, /* number of interfaces in this configuration */ @@ -187,6 +190,14 @@ PROGMEM const char usbDescriptorConfiguration[] = { /* USB configuration desc 8, 0, /* maximum packet size */ USB_CFG_INTR_POLL_INTERVAL, /* in ms */ #endif +#if USB_CFG_HAVE_INTRIN_ENDPOINT4 /* endpoint descriptor for endpoint 4 */ + 7, /* sizeof(usbDescrEndpoint) */ + USBDESCR_ENDPOINT, /* descriptor type = endpoint */ + (char)(0x80 | USB_CFG_EP4_NUMBER), /* IN endpoint number 4 */ + 0x03, /* attrib: Interrupt endpoint */ + 8, 0, /* maximum packet size */ + USB_CFG_INTR_POLL_INTERVAL, /* in ms */ +#endif }; #endif @@ -199,6 +210,9 @@ static inline void usbResetDataToggling(void) # if USB_CFG_HAVE_INTRIN_ENDPOINT3 USB_SET_DATATOKEN3(USB_INITIAL_DATATOKEN); /* reset data toggling for interrupt endpoint */ # endif +# if USB_CFG_HAVE_INTRIN_ENDPOINT4 + USB_SET_DATATOKEN4(USB_INITIAL_DATATOKEN); /* reset data toggling for interrupt endpoint */ +# endif #endif } @@ -209,6 +223,9 @@ static inline void usbResetStall(void) #if USB_CFG_HAVE_INTRIN_ENDPOINT3 usbTxLen3 = USBPID_NAK; #endif +#if USB_CFG_HAVE_INTRIN_ENDPOINT4 + usbTxLen4 = USBPID_NAK; +#endif #endif } @@ -252,6 +269,13 @@ USB_PUBLIC void usbSetInterrupt3(uchar *data, uchar len) usbGenericSetInterrupt(data, len, &usbTxStatus3); } #endif + +#if USB_CFG_HAVE_INTRIN_ENDPOINT4 +USB_PUBLIC void usbSetInterrupt4(uchar *data, uchar len) +{ + usbGenericSetInterrupt(data, len, &usbTxStatus4); +} +#endif #endif /* USB_CFG_SUPPRESS_INTR_CODE */ /* ------------------ utilities for code following below ------------------- */ @@ -628,6 +652,9 @@ USB_PUBLIC void usbInit(void) #if USB_CFG_HAVE_INTRIN_ENDPOINT3 usbTxLen3 = USBPID_NAK; #endif +#if USB_CFG_HAVE_INTRIN_ENDPOINT4 + usbTxLen4 = USBPID_NAK; +#endif #endif } diff --git a/usbdrv/usbdrv.h b/usbdrv/usbdrv.h index f094120..7a44b6d 100644 --- a/usbdrv/usbdrv.h +++ b/usbdrv/usbdrv.h @@ -268,6 +268,11 @@ USB_PUBLIC void usbSetInterrupt3(uchar *data, uchar len); #define usbInterruptIsReady3() (usbTxLen3 & 0x10) /* Same as above for endpoint 3 */ #endif +#if USB_CFG_HAVE_INTRIN_ENDPOINT4 +USB_PUBLIC void usbSetInterrupt4(uchar *data, uchar len); +#define usbInterruptIsReady4() (usbTxLen4 & 0x10) +/* Same as above for endpoint 4 */ +#endif #endif /* USB_CFG_HAVE_INTRIN_ENDPOINT */ #if USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH /* simplified interface for backward compatibility */ #define usbHidReportDescriptor usbDescriptorHidReport @@ -408,8 +413,9 @@ extern volatile schar usbRxLen; #define USB_SET_DATATOKEN1(token) usbTxBuf1[0] = token #define USB_SET_DATATOKEN3(token) usbTxBuf3[0] = token +#define USB_SET_DATATOKEN4(token) usbTxBuf4[0] = token /* These two macros can be used by application software to reset data toggling - * for interrupt-in endpoints 1 and 3. Since the token is toggled BEFORE + * for interrupt-in endpoints 1, 3 and 4. Since the token is toggled BEFORE * sending data, you must set the opposite value of the token which should come * first. */ @@ -592,10 +598,18 @@ int usbDescriptorStringSerialNumber[]; #define USB_CFG_EP3_NUMBER 3 #endif +#ifndef USB_CFG_EP4_NUMBER /* if not defined in usbconfig.h */ +#define USB_CFG_EP4_NUMBER 4 +#endif + #ifndef USB_CFG_HAVE_INTRIN_ENDPOINT3 #define USB_CFG_HAVE_INTRIN_ENDPOINT3 0 #endif +#ifndef USB_CFG_HAVE_INTRIN_ENDPOINT4 +#define USB_CFG_HAVE_INTRIN_ENDPOINT4 0 +#endif + #define USB_BUFSIZE 11 /* PID, 8 bytes data, 2 bytes CRC */ /* ----- Try to find registers and bits responsible for ext interrupt 0 ----- */ @@ -683,11 +697,13 @@ typedef struct usbTxStatus{ uchar buffer[USB_BUFSIZE]; }usbTxStatus_t; -extern usbTxStatus_t usbTxStatus1, usbTxStatus3; +extern usbTxStatus_t usbTxStatus1, usbTxStatus3, usbTxStatus4; #define usbTxLen1 usbTxStatus1.len #define usbTxBuf1 usbTxStatus1.buffer #define usbTxLen3 usbTxStatus3.len #define usbTxBuf3 usbTxStatus3.buffer +#define usbTxLen4 usbTxStatus4.len +#define usbTxBuf4 usbTxStatus4.buffer typedef union usbWord{ diff --git a/usbdrv/usbdrvasm.S b/usbdrv/usbdrvasm.S index 3bda63c..91a7abb 100644 --- a/usbdrv/usbdrvasm.S +++ b/usbdrv/usbdrvasm.S @@ -35,7 +35,7 @@ the file appropriate for the given clock rate. #ifdef __IAR_SYSTEMS_ASM__ extern usbRxBuf, usbDeviceAddr, usbNewDeviceAddr, usbInputBufOffset extern usbCurrentTok, usbRxLen, usbRxToken, usbTxLen - extern usbTxBuf, usbTxStatus1, usbTxStatus3 + extern usbTxBuf, usbTxStatus1, usbTxStatus3, usbTxStatus4 # if USB_COUNT_SOF extern usbSofCount # endif @@ -82,6 +82,8 @@ the file appropriate for the given clock rate. #define usbTxBuf1 (usbTxStatus1 + 1) #define usbTxLen3 usbTxStatus3 #define usbTxBuf3 (usbTxStatus3 + 1) +#define usbTxLen4 usbTxStatus4 +#define usbTxBuf4 (usbTxStatus4 + 1) ;---------------------------------------------------------------------------- -- cgit v1.2.3