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 4 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 "can't use mouse/extra key and hid raw at same time on VUSB"
hsgw marked this conversation as resolved.
Show resolved Hide resolved
#endif
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC, this is handled automatically, and should error out anyways, if there are too many endpoints enabled.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be handled in makefile? Now this is not implemented in makefile.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test is good as it is now, as it's explicit about the mutual exclusivity and conditional compilation requirement of this code.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, Leave this as it is.

Copy link
Member

@drashna drashna Mar 14, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, okay, LUFA and ChibiOS has a check for the number of endpoints, but V-USB doesn't.

This is fine, for now, but is something that we would want to change in the near future, @fauxpark?

For reference:

#if (NEXT_EPNUM - 1) > MAX_ENDPOINTS
# error There are not enough available endpoints to support all functions. Please disable one or more of the following: Mouse Keys, Extra Keys, Console, NKRO, MIDI, Serial, Steno
#endif

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@zvecr 's console PR #8559 includes something like that - perhaps we should pull that out and merge it first to simplify both these PRs.


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_INPUT_SIZE (32)
# define RAW_OUTPUT_SIZE (32)
fauxpark marked this conversation as resolved.
Show resolved Hide resolved

static uint8_t raw_output_buffer[RAW_OUTPUT_SIZE];
hsgw marked this conversation as resolved.
Show resolved Hide resolved
static uint8_t raw_output_received_bytes = 0;

void raw_hid_send(uint8_t *data, uint8_t length) {
if (length != RAW_INPUT_SIZE) {
hsgw marked this conversation as resolved.
Show resolved Hide resolved
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_OUTPUT_SIZE) {
raw_hid_receive(raw_output_buffer, RAW_OUTPUT_SIZE);
hsgw marked this conversation as resolved.
Show resolved Hide resolved
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_OUTPUT_SIZE) {
hsgw marked this conversation as resolved.
Show resolved Hide resolved
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_INPUT_SIZE, // Report Count
hsgw marked this conversation as resolved.
Show resolved Hide resolved
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_OUTPUT_SIZE, // Report Count
hsgw marked this conversation as resolved.
Show resolved Hide resolved
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 = 8,
hsgw marked this conversation as resolved.
Show resolved Hide resolved
.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 = 8,
hsgw marked this conversation as resolved.
Show resolved Hide resolved
.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