Initial implementation of XAP protocol.

This commit is contained in:
Nick Brassel 2021-08-11 21:08:32 +10:00
parent f4c447f2df
commit eba91c6e28
34 changed files with 1934 additions and 4 deletions

View file

@ -30,7 +30,8 @@ enum hid_report_ids {
REPORT_ID_SYSTEM,
REPORT_ID_CONSUMER,
REPORT_ID_NKRO,
REPORT_ID_JOYSTICK
REPORT_ID_JOYSTICK,
REPORT_ID_XAP
};
/* Mouse buttons */

View file

@ -85,6 +85,10 @@ extern keymap_config_t keymap_config;
# include "raw_hid.h"
#endif
#ifdef XAP_ENABLE
# include "xap.h"
#endif
#ifdef JOYSTICK_ENABLE
# include "joystick.h"
#endif
@ -249,6 +253,88 @@ static void raw_hid_task(void) {
}
#endif
#ifdef XAP_ENABLE
extern void xap_receive(xap_token_t token, const uint8_t *data, size_t length);
void xap_send_base(uint8_t *data, uint8_t length) {
// TODO: implement variable size packet
if (length != XAP_EPSIZE) {
return;
}
if (USB_DeviceState != DEVICE_STATE_Configured) {
return;
}
// TODO: decide if we allow calls to raw_hid_send() in the middle
// of other endpoint usage.
uint8_t ep = Endpoint_GetCurrentEndpoint();
Endpoint_SelectEndpoint(XAP_IN_EPNUM);
// Check to see if the host is ready to accept another packet
if (Endpoint_IsINReady()) {
// Write data
Endpoint_Write_Stream_LE(data, XAP_EPSIZE, NULL);
// Finalize the stream transfer to send the last packet
Endpoint_ClearIN();
}
Endpoint_SelectEndpoint(ep);
}
void xap_send(xap_token_t token, uint8_t response_flags, const void *data, size_t length) {
uint8_t rdata[XAP_EPSIZE] = {0};
*(xap_token_t *)&rdata[0] = token;
if (length > (XAP_EPSIZE - 4)) response_flags &= ~(XAP_RESPONSE_FLAG_SUCCESS);
rdata[2] = response_flags;
if (response_flags & (XAP_RESPONSE_FLAG_SUCCESS)) {
rdata[3] = (uint8_t)length;
if (data != NULL) {
memcpy(&rdata[4], data, length);
}
}
xap_send_base(rdata, sizeof(rdata));
}
void xap_receive_base(const void *data) {
const uint8_t *u8data = (const uint8_t *)data;
xap_token_t token = *(xap_token_t *)&u8data[0];
uint8_t length = u8data[2];
if (length <= (XAP_EPSIZE - 3)) {
xap_receive(token, &u8data[3], length);
}
}
static void xap_task(void) {
// Create a temporary buffer to hold the read in data from the host
uint8_t data[XAP_EPSIZE];
bool data_read = false;
// Device must be connected and configured for the task to run
if (USB_DeviceState != DEVICE_STATE_Configured) return;
Endpoint_SelectEndpoint(XAP_OUT_EPNUM);
// Check to see if a packet has been sent from the host
if (Endpoint_IsOUTReceived()) {
// Check to see if the packet contains data
if (Endpoint_IsReadWriteAllowed()) {
/* Read data */
Endpoint_Read_Stream_LE(data, sizeof(data), NULL);
data_read = true;
}
// Finalize the stream transfer to receive the last packet
Endpoint_ClearOUT();
if (data_read) {
xap_receive_base(data);
}
}
}
#endif // XAP_ENABLE
/*******************************************************************************
* Console
******************************************************************************/
@ -500,6 +586,12 @@ void EVENT_USB_Device_ConfigurationChanged(void) {
ConfigSuccess &= Endpoint_ConfigureEndpoint((RAW_OUT_EPNUM | ENDPOINT_DIR_OUT), EP_TYPE_INTERRUPT, RAW_EPSIZE, 1);
#endif
#ifdef XAP_ENABLE
/* Setup XAP endpoints */
ConfigSuccess &= Endpoint_ConfigureEndpoint((XAP_IN_EPNUM | ENDPOINT_DIR_IN), EP_TYPE_INTERRUPT, XAP_EPSIZE, 1);
ConfigSuccess &= Endpoint_ConfigureEndpoint((XAP_OUT_EPNUM | ENDPOINT_DIR_OUT), EP_TYPE_INTERRUPT, XAP_EPSIZE, 1);
#endif // XAP_ENABLE
#ifdef CONSOLE_ENABLE
/* Setup console endpoint */
ConfigSuccess &= Endpoint_ConfigureEndpoint((CONSOLE_IN_EPNUM | ENDPOINT_DIR_IN), EP_TYPE_INTERRUPT, CONSOLE_EPSIZE, 1);
@ -1102,6 +1194,10 @@ int main(void) {
raw_hid_task();
#endif
#ifdef XAP_ENABLE
xap_task();
#endif
#if !defined(INTERRUPT_CONTROL_ENDPOINT)
USB_USBTask();
#endif

View file

@ -227,6 +227,7 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = {
HID_RI_OUTPUT(8, HID_IOF_CONSTANT),
HID_RI_END_COLLECTION(0),
#endif
#ifdef SHARED_EP_ENABLE
};
#endif
@ -255,6 +256,30 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM RawReport[] = {
};
#endif
#ifdef XAP_ENABLE
const USB_Descriptor_HIDReport_Datatype_t PROGMEM XapReport[] = {
HID_RI_USAGE_PAGE(16, 0xFF51), // Vendor Defined ('Q')
HID_RI_USAGE(8, 0x58), // Vendor Defined ('X')
HID_RI_COLLECTION(8, 0x01), // Application
// Data to host
HID_RI_USAGE(8, 0x62), // Vendor Defined
HID_RI_LOGICAL_MINIMUM(8, 0x00),
HID_RI_LOGICAL_MAXIMUM(16, 0x00FF),
HID_RI_REPORT_COUNT(8, XAP_EPSIZE),
HID_RI_REPORT_SIZE(8, 0x08),
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
// Data from host
HID_RI_USAGE(8, 0x63), // Vendor Defined
HID_RI_LOGICAL_MINIMUM(8, 0x00),
HID_RI_LOGICAL_MAXIMUM(16, 0x00FF),
HID_RI_REPORT_COUNT(8, XAP_EPSIZE),
HID_RI_REPORT_SIZE(8, 0x08),
HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE),
HID_RI_END_COLLECTION(0),
};
#endif // XAP_ENABLE
#ifdef CONSOLE_ENABLE
const USB_Descriptor_HIDReport_Datatype_t PROGMEM ConsoleReport[] = {
HID_RI_USAGE_PAGE(16, 0xFF31), // Vendor Defined (PJRC Teensy compatible)
@ -492,6 +517,56 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor = {
},
#endif
#ifdef XAP_ENABLE
/*
* QMK XAP
*/
.Xap_Interface = {
.Header = {
.Size = sizeof(USB_Descriptor_Interface_t),
.Type = DTYPE_Interface
},
.InterfaceNumber = XAP_INTERFACE,
.AlternateSetting = 0x00,
.TotalEndpoints = 2,
.Class = HID_CSCP_HIDClass,
.SubClass = HID_CSCP_NonBootSubclass,
.Protocol = HID_CSCP_NonBootProtocol,
.InterfaceStrIndex = NO_DESCRIPTOR
},
.Xap_HID = {
.Header = {
.Size = sizeof(USB_HID_Descriptor_HID_t),
.Type = HID_DTYPE_HID
},
.HIDSpec = VERSION_BCD(1, 1, 1),
.CountryCode = 0x00,
.TotalReportDescriptors = 1,
.HIDReportType = HID_DTYPE_Report,
.HIDReportLength = sizeof(XapReport)
},
.Xap_INEndpoint = {
.Header = {
.Size = sizeof(USB_Descriptor_Endpoint_t),
.Type = DTYPE_Endpoint
},
.EndpointAddress = (ENDPOINT_DIR_IN | XAP_IN_EPNUM),
.Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
.EndpointSize = XAP_EPSIZE,
.PollingIntervalMS = 0x01
},
.Xap_OUTEndpoint = {
.Header = {
.Size = sizeof(USB_Descriptor_Endpoint_t),
.Type = DTYPE_Endpoint
},
.EndpointAddress = (ENDPOINT_DIR_OUT | XAP_OUT_EPNUM),
.Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
.EndpointSize = XAP_EPSIZE,
.PollingIntervalMS = 0x01
},
#endif
#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
/*
* Mouse
@ -1046,6 +1121,14 @@ uint16_t get_usb_descriptor(const uint16_t wValue, const uint16_t wIndex, const
break;
#endif
#ifdef XAP_ENABLE
case XAP_INTERFACE:
Address = &ConfigurationDescriptor.Xap_HID;
Size = sizeof(USB_HID_Descriptor_HID_t);
break;
#endif
#ifdef CONSOLE_ENABLE
case CONSOLE_INTERFACE:
Address = &ConfigurationDescriptor.Console_HID;
@ -1096,6 +1179,14 @@ uint16_t get_usb_descriptor(const uint16_t wValue, const uint16_t wIndex, const
break;
#endif
#ifdef XAP_ENABLE
case XAP_INTERFACE:
Address = &XapReport;
Size = sizeof(XapReport);
break;
#endif
#ifdef CONSOLE_ENABLE
case CONSOLE_INTERFACE:
Address = &ConsoleReport;

View file

@ -75,6 +75,14 @@ typedef struct {
USB_Descriptor_Endpoint_t Raw_OUTEndpoint;
#endif
#ifdef XAP_ENABLE
// Mouse HID Interface
USB_Descriptor_Interface_t Xap_Interface;
USB_HID_Descriptor_HID_t Xap_HID;
USB_Descriptor_Endpoint_t Xap_INEndpoint;
USB_Descriptor_Endpoint_t Xap_OUTEndpoint;
#endif
#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
// Mouse HID Interface
USB_Descriptor_Interface_t Mouse_Interface;
@ -155,6 +163,10 @@ enum usb_interfaces {
RAW_INTERFACE,
#endif
#ifdef XAP_ENABLE
XAP_INTERFACE,
#endif
#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
MOUSE_INTERFACE,
#endif
@ -212,6 +224,15 @@ enum usb_endpoints {
# endif
#endif
#ifdef XAP_ENABLE
XAP_IN_EPNUM = NEXT_EPNUM,
# if STM32_USB_USE_OTG1
# define XAP_OUT_EPNUM XAP_IN_EPNUM
# else
XAP_OUT_EPNUM = NEXT_EPNUM,
# endif
#endif
#ifdef SHARED_EP_ENABLE
SHARED_IN_EPNUM = NEXT_EPNUM,
#endif
@ -272,7 +293,7 @@ enum usb_endpoints {
// TODO - ARM_ATSAM
#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
# 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, XAP
#endif
#define KEYBOARD_EPSIZE 8
@ -284,5 +305,6 @@ enum usb_endpoints {
#define CDC_NOTIFICATION_EPSIZE 8
#define CDC_EPSIZE 16
#define JOYSTICK_EPSIZE 8
#define XAP_EPSIZE 64
uint16_t get_usb_descriptor(const uint16_t wValue, const uint16_t wIndex, const void** const DescriptorAddress);