forked from mirrors/qmk_userspace
		
	add hid_raw feature to VUSB (#8380)
* rewrite usbhid feature on vusb * Apply suggestions from code review Co-Authored-By: Ryan <fauxpark@gmail.com> * fix typo * fix typo again * Update tmk_core/protocol/vusb/vusb.c Co-Authored-By: Ryan <fauxpark@gmail.com> * clean up defines Co-authored-by: Ryan <fauxpark@gmail.com>
This commit is contained in:
		
					parent
					
						
							
								b892a1429d
							
						
					
				
			
			
				commit
				
					
						89a675d57c
					
				
			
		
					 3 changed files with 174 additions and 1 deletions
				
			
		| 
						 | 
					@ -108,6 +108,13 @@ int main(void) {
 | 
				
			||||||
                keyboard_task();
 | 
					                keyboard_task();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            vusb_transfer_keyboard();
 | 
					            vusb_transfer_keyboard();
 | 
				
			||||||
 | 
					#ifdef RAW_ENABLE
 | 
				
			||||||
 | 
					            usbPoll();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (usbConfiguration && usbInterruptIsReady3()) {
 | 
				
			||||||
 | 
					                raw_hid_task();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -28,6 +28,14 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
#include "vusb.h"
 | 
					#include "vusb.h"
 | 
				
			||||||
#include <util/delay.h>
 | 
					#include <util/delay.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(RAW_ENABLE)
 | 
				
			||||||
 | 
					#    include "raw_hid.h"
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if (defined(MOUSE_ENABLE) || defined(EXTRAKEY_ENABLE)) && defined(RAW_ENABLE)
 | 
				
			||||||
 | 
					#    error "Enabling Mousekeys/Extrakeys and Raw HID at the same time is not currently supported on V-USB."
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static uint8_t vusb_keyboard_leds = 0;
 | 
					static uint8_t vusb_keyboard_leds = 0;
 | 
				
			||||||
static uint8_t vusb_idle_rate     = 0;
 | 
					static uint8_t vusb_idle_rate     = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -71,6 +79,52 @@ void vusb_transfer_keyboard(void) {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*------------------------------------------------------------------*
 | 
				
			||||||
 | 
					 * RAW HID
 | 
				
			||||||
 | 
					 *------------------------------------------------------------------*/
 | 
				
			||||||
 | 
					#ifdef RAW_ENABLE
 | 
				
			||||||
 | 
					#    define RAW_BUFFER_SIZE 32
 | 
				
			||||||
 | 
					#    define RAW_EPSIZE 8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static uint8_t raw_output_buffer[RAW_BUFFER_SIZE];
 | 
				
			||||||
 | 
					static uint8_t raw_output_received_bytes = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void raw_hid_send(uint8_t *data, uint8_t length) {
 | 
				
			||||||
 | 
					    if (length != RAW_BUFFER_SIZE) {
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uint8_t *temp = data;
 | 
				
			||||||
 | 
					    for (uint8_t i = 0; i < 4; i++) {
 | 
				
			||||||
 | 
					        while (!usbInterruptIsReady3()) {
 | 
				
			||||||
 | 
					            usbPoll();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        usbSetInterrupt3(temp, 8);
 | 
				
			||||||
 | 
					        temp += 8;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    while (!usbInterruptIsReady3()) {
 | 
				
			||||||
 | 
					        usbPoll();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    usbSetInterrupt3(0, 0);
 | 
				
			||||||
 | 
					    usbPoll();
 | 
				
			||||||
 | 
					    _delay_ms(1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					__attribute__((weak)) void raw_hid_receive(uint8_t *data, uint8_t length) {
 | 
				
			||||||
 | 
					    // Users should #include "raw_hid.h" in their own code
 | 
				
			||||||
 | 
					    // and implement this function there. Leave this as weak linkage
 | 
				
			||||||
 | 
					    // so users can opt to not handle data coming in.
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void raw_hid_task(void) {
 | 
				
			||||||
 | 
					    if (raw_output_received_bytes == RAW_BUFFER_SIZE) {
 | 
				
			||||||
 | 
					        raw_hid_receive(raw_output_buffer, RAW_BUFFER_SIZE);
 | 
				
			||||||
 | 
					        raw_output_received_bytes = 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*------------------------------------------------------------------*
 | 
					/*------------------------------------------------------------------*
 | 
				
			||||||
 * Host driver
 | 
					 * Host driver
 | 
				
			||||||
 *------------------------------------------------------------------*/
 | 
					 *------------------------------------------------------------------*/
 | 
				
			||||||
| 
						 | 
					@ -206,6 +260,27 @@ uchar usbFunctionWrite(uchar *data, uchar len) {
 | 
				
			||||||
    return 1;
 | 
					    return 1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void usbFunctionWriteOut(uchar *data, uchar len) {
 | 
				
			||||||
 | 
					#ifdef RAW_ENABLE
 | 
				
			||||||
 | 
					    // Data from host must be divided every 8bytes
 | 
				
			||||||
 | 
					    if (len != 8) {
 | 
				
			||||||
 | 
					        debug("RAW: invalid length");
 | 
				
			||||||
 | 
					        raw_output_received_bytes = 0;
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (raw_output_received_bytes + len > RAW_BUFFER_SIZE) {
 | 
				
			||||||
 | 
					        debug("RAW: buffer full");
 | 
				
			||||||
 | 
					        raw_output_received_bytes = 0;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        for (uint8_t i = 0; i < 8; i++) {
 | 
				
			||||||
 | 
					            raw_output_buffer[raw_output_received_bytes + i] = data[i];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        raw_output_received_bytes += len;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*------------------------------------------------------------------*
 | 
					/*------------------------------------------------------------------*
 | 
				
			||||||
 * Descriptors                                                      *
 | 
					 * Descriptors                                                      *
 | 
				
			||||||
 *------------------------------------------------------------------*/
 | 
					 *------------------------------------------------------------------*/
 | 
				
			||||||
| 
						 | 
					@ -335,6 +410,29 @@ const PROGMEM uchar mouse_extra_hid_report[] = {
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(RAW_ENABLE)
 | 
				
			||||||
 | 
					const PROGMEM uchar raw_hid_report[] = {
 | 
				
			||||||
 | 
					    0x06, 0x60, 0xFF,  // Usage Page (Vendor Defined)
 | 
				
			||||||
 | 
					    0x09, 0x61,        // Usage (Vendor Defined)
 | 
				
			||||||
 | 
					    0xA1, 0x01,        // Collection (Application)
 | 
				
			||||||
 | 
					    // Data to host
 | 
				
			||||||
 | 
					    0x09, 0x62,             //   Usage (Vendor Defined)
 | 
				
			||||||
 | 
					    0x15, 0x00,             //   Logical Minimum (0)
 | 
				
			||||||
 | 
					    0x26, 0xFF, 0x00,       //   Logical Maximum (255)
 | 
				
			||||||
 | 
					    0x95, RAW_BUFFER_SIZE,  //   Report Count
 | 
				
			||||||
 | 
					    0x75, 0x08,             //   Report Size (8)
 | 
				
			||||||
 | 
					    0x81, 0x02,             //   Input (Data, Variable, Absolute)
 | 
				
			||||||
 | 
					    // Data from host
 | 
				
			||||||
 | 
					    0x09, 0x63,             //   Usage (Vendor Defined)
 | 
				
			||||||
 | 
					    0x15, 0x00,             //   Logical Minimum (0)
 | 
				
			||||||
 | 
					    0x26, 0xFF, 0x00,       //   Logical Maximum (255)
 | 
				
			||||||
 | 
					    0x95, RAW_BUFFER_SIZE,  //   Report Count
 | 
				
			||||||
 | 
					    0x75, 0x08,             //   Report Size (8)
 | 
				
			||||||
 | 
					    0x91, 0x02,             //   Output (Data, Variable, Absolute)
 | 
				
			||||||
 | 
					    0xC0,                   // End Collection
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef SERIAL_NUMBER
 | 
					#ifndef SERIAL_NUMBER
 | 
				
			||||||
#    define SERIAL_NUMBER 0
 | 
					#    define SERIAL_NUMBER 0
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					@ -416,7 +514,7 @@ const PROGMEM usbConfigurationDescriptor_t usbConfigurationDescriptor = {
 | 
				
			||||||
            .bDescriptorType = USBDESCR_CONFIG
 | 
					            .bDescriptorType = USBDESCR_CONFIG
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        .wTotalLength        = sizeof(usbConfigurationDescriptor_t),
 | 
					        .wTotalLength        = sizeof(usbConfigurationDescriptor_t),
 | 
				
			||||||
#    if defined(MOUSE_ENABLE) || defined(EXTRAKEY_ENABLE)
 | 
					#    if defined(MOUSE_ENABLE) || defined(EXTRAKEY_ENABLE) || defined(RAW_ENABLE)
 | 
				
			||||||
        .bNumInterfaces      = 2,
 | 
					        .bNumInterfaces      = 2,
 | 
				
			||||||
#    else
 | 
					#    else
 | 
				
			||||||
        .bNumInterfaces      = 1,
 | 
					        .bNumInterfaces      = 1,
 | 
				
			||||||
| 
						 | 
					@ -511,6 +609,53 @@ const PROGMEM usbConfigurationDescriptor_t usbConfigurationDescriptor = {
 | 
				
			||||||
        .bInterval           = USB_POLLING_INTERVAL_MS
 | 
					        .bInterval           = USB_POLLING_INTERVAL_MS
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
#        endif
 | 
					#        endif
 | 
				
			||||||
 | 
					#    elif defined(RAW_ENABLE)
 | 
				
			||||||
 | 
					    .rawInterface = {
 | 
				
			||||||
 | 
					        .header = {
 | 
				
			||||||
 | 
					            .bLength         = sizeof(usbInterfaceDescriptor_t),
 | 
				
			||||||
 | 
					            .bDescriptorType = USBDESCR_INTERFACE
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        .bInterfaceNumber    = 1,
 | 
				
			||||||
 | 
					        .bAlternateSetting   = 0x00,
 | 
				
			||||||
 | 
					        .bNumEndpoints       = 2,
 | 
				
			||||||
 | 
					        .bInterfaceClass     = 0x03,
 | 
				
			||||||
 | 
					        .bInterfaceSubClass  = 0x00,
 | 
				
			||||||
 | 
					        .bInterfaceProtocol  = 0x00,
 | 
				
			||||||
 | 
					        .iInterface          = 0x00
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    .rawHID = {
 | 
				
			||||||
 | 
					        .header = {
 | 
				
			||||||
 | 
					            .bLength         = sizeof(usbHIDDescriptor_t),
 | 
				
			||||||
 | 
					            .bDescriptorType = USBDESCR_HID
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        .bcdHID              = 0x0101,
 | 
				
			||||||
 | 
					        .bCountryCode        = 0x00,
 | 
				
			||||||
 | 
					        .bNumDescriptors     = 2,
 | 
				
			||||||
 | 
					        .bDescriptorType     = USBDESCR_HID_REPORT,
 | 
				
			||||||
 | 
					        .wDescriptorLength   = sizeof(raw_hid_report)
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					#        if USB_CFG_HAVE_INTRIN_ENDPOINT3
 | 
				
			||||||
 | 
					    .rawINEndpoint = {
 | 
				
			||||||
 | 
					        .header = {
 | 
				
			||||||
 | 
					            .bLength         = sizeof(usbEndpointDescriptor_t),
 | 
				
			||||||
 | 
					            .bDescriptorType = USBDESCR_ENDPOINT
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        .bEndpointAddress    = (USBRQ_DIR_DEVICE_TO_HOST | USB_CFG_EP3_NUMBER),
 | 
				
			||||||
 | 
					        .bmAttributes        = 0x03,
 | 
				
			||||||
 | 
					        .wMaxPacketSize      = RAW_EPSIZE,
 | 
				
			||||||
 | 
					        .bInterval           = USB_POLLING_INTERVAL_MS
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    .rawOUTEndpoint = {
 | 
				
			||||||
 | 
					        .header = {
 | 
				
			||||||
 | 
					            .bLength         = sizeof(usbEndpointDescriptor_t),
 | 
				
			||||||
 | 
					            .bDescriptorType = USBDESCR_ENDPOINT
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        .bEndpointAddress    = (USBRQ_DIR_HOST_TO_DEVICE | USB_CFG_EP3_NUMBER),
 | 
				
			||||||
 | 
					        .bmAttributes        = 0x03,
 | 
				
			||||||
 | 
					        .wMaxPacketSize      = RAW_EPSIZE,
 | 
				
			||||||
 | 
					        .bInterval           = USB_POLLING_INTERVAL_MS
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#        endif
 | 
				
			||||||
#    endif
 | 
					#    endif
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					@ -572,6 +717,11 @@ USB_PUBLIC usbMsgLen_t usbFunctionDescriptor(struct usbRequest *rq) {
 | 
				
			||||||
                    usbMsgPtr = (unsigned char *)&usbConfigurationDescriptor.mouseExtraHID;
 | 
					                    usbMsgPtr = (unsigned char *)&usbConfigurationDescriptor.mouseExtraHID;
 | 
				
			||||||
                    len       = sizeof(usbHIDDescriptor_t);
 | 
					                    len       = sizeof(usbHIDDescriptor_t);
 | 
				
			||||||
                    break;
 | 
					                    break;
 | 
				
			||||||
 | 
					#elif defined(RAW_ENABLE)
 | 
				
			||||||
 | 
					                case 1:
 | 
				
			||||||
 | 
					                    usbMsgPtr = (unsigned char *)&usbConfigurationDescriptor.rawHID;
 | 
				
			||||||
 | 
					                    len       = sizeof(usbHIDDescriptor_t);
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
| 
						 | 
					@ -587,6 +737,11 @@ USB_PUBLIC usbMsgLen_t usbFunctionDescriptor(struct usbRequest *rq) {
 | 
				
			||||||
                    usbMsgPtr = (unsigned char *)mouse_extra_hid_report;
 | 
					                    usbMsgPtr = (unsigned char *)mouse_extra_hid_report;
 | 
				
			||||||
                    len       = sizeof(mouse_extra_hid_report);
 | 
					                    len       = sizeof(mouse_extra_hid_report);
 | 
				
			||||||
                    break;
 | 
					                    break;
 | 
				
			||||||
 | 
					#elif defined(RAW_ENABLE)
 | 
				
			||||||
 | 
					                case 1:
 | 
				
			||||||
 | 
					                    usbMsgPtr = (unsigned char *)raw_hid_report;
 | 
				
			||||||
 | 
					                    len       = sizeof(raw_hid_report);
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -97,6 +97,13 @@ typedef struct usbConfigurationDescriptor {
 | 
				
			||||||
#    ifdef USB_CFG_HAVE_INTRIN_ENDPOINT3
 | 
					#    ifdef USB_CFG_HAVE_INTRIN_ENDPOINT3
 | 
				
			||||||
    usbEndpointDescriptor_t mouseExtraINEndpoint;
 | 
					    usbEndpointDescriptor_t mouseExtraINEndpoint;
 | 
				
			||||||
#    endif
 | 
					#    endif
 | 
				
			||||||
 | 
					#elif defined(RAW_ENABLE)
 | 
				
			||||||
 | 
					    usbInterfaceDescriptor_t rawInterface;
 | 
				
			||||||
 | 
					    usbHIDDescriptor_t       rawHID;
 | 
				
			||||||
 | 
					#    ifdef USB_CFG_HAVE_INTRIN_ENDPOINT3
 | 
				
			||||||
 | 
					    usbEndpointDescriptor_t rawINEndpoint;
 | 
				
			||||||
 | 
					    usbEndpointDescriptor_t rawOUTEndpoint;
 | 
				
			||||||
 | 
					#    endif
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
} __attribute__((packed)) usbConfigurationDescriptor_t;
 | 
					} __attribute__((packed)) usbConfigurationDescriptor_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -104,3 +111,7 @@ typedef struct usbConfigurationDescriptor {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
host_driver_t *vusb_driver(void);
 | 
					host_driver_t *vusb_driver(void);
 | 
				
			||||||
void           vusb_transfer_keyboard(void);
 | 
					void           vusb_transfer_keyboard(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(RAW_ENABLE)
 | 
				
			||||||
 | 
					void raw_hid_task(void);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue