Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add hid_raw feature to VUSB #8380

Merged
merged 6 commits into from
Mar 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions tmk_core/protocol/vusb/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,13 @@ int main(void) {
keyboard_task();
}
vusb_transfer_keyboard();
#ifdef RAW_ENABLE
usbPoll();

if (usbConfiguration && usbInterruptIsReady3()) {
raw_hid_task();
}
#endif
}
}
}
157 changes: 156 additions & 1 deletion tmk_core/protocol/vusb/vusb.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "vusb.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_idle_rate = 0;

Expand Down Expand Up @@ -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
*------------------------------------------------------------------*/
Expand Down Expand Up @@ -206,6 +260,27 @@ uchar usbFunctionWrite(uchar *data, uchar len) {
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 *
*------------------------------------------------------------------*/
Expand Down Expand Up @@ -335,6 +410,29 @@ const PROGMEM uchar mouse_extra_hid_report[] = {
};
#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
# define SERIAL_NUMBER 0
#endif
Expand Down Expand Up @@ -416,7 +514,7 @@ const PROGMEM usbConfigurationDescriptor_t usbConfigurationDescriptor = {
.bDescriptorType = USBDESCR_CONFIG
},
.wTotalLength = sizeof(usbConfigurationDescriptor_t),
# if defined(MOUSE_ENABLE) || defined(EXTRAKEY_ENABLE)
# if defined(MOUSE_ENABLE) || defined(EXTRAKEY_ENABLE) || defined(RAW_ENABLE)
.bNumInterfaces = 2,
# else
.bNumInterfaces = 1,
Expand Down Expand Up @@ -511,6 +609,53 @@ const PROGMEM usbConfigurationDescriptor_t usbConfigurationDescriptor = {
.bInterval = USB_POLLING_INTERVAL_MS
}
# 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
Expand Down Expand Up @@ -572,6 +717,11 @@ USB_PUBLIC usbMsgLen_t usbFunctionDescriptor(struct usbRequest *rq) {
usbMsgPtr = (unsigned char *)&usbConfigurationDescriptor.mouseExtraHID;
len = sizeof(usbHIDDescriptor_t);
break;
#elif defined(RAW_ENABLE)
case 1:
usbMsgPtr = (unsigned char *)&usbConfigurationDescriptor.rawHID;
len = sizeof(usbHIDDescriptor_t);
break;
#endif
}
break;
Expand All @@ -587,6 +737,11 @@ USB_PUBLIC usbMsgLen_t usbFunctionDescriptor(struct usbRequest *rq) {
usbMsgPtr = (unsigned char *)mouse_extra_hid_report;
len = sizeof(mouse_extra_hid_report);
break;
#elif defined(RAW_ENABLE)
case 1:
usbMsgPtr = (unsigned char *)raw_hid_report;
len = sizeof(raw_hid_report);
break;
#endif
}
break;
Expand Down
11 changes: 11 additions & 0 deletions tmk_core/protocol/vusb/vusb.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,21 @@ typedef struct usbConfigurationDescriptor {
# ifdef USB_CFG_HAVE_INTRIN_ENDPOINT3
usbEndpointDescriptor_t mouseExtraINEndpoint;
# 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
} __attribute__((packed)) usbConfigurationDescriptor_t;

#define USB_STRING_LEN(s) (sizeof(usbDescriptorHeader_t) + ((s) << 1))

host_driver_t *vusb_driver(void);
void vusb_transfer_keyboard(void);

#if defined(RAW_ENABLE)
void raw_hid_task(void);
#endif