Initial implementation of XAP protocol.
This commit is contained in:
		
							parent
							
								
									f4c447f2df
								
							
						
					
					
						commit
						eba91c6e28
					
				
					 34 changed files with 1934 additions and 4 deletions
				
			
		| 
						 | 
				
			
			@ -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 */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue