Merge branch 'hid_joystick' of git://github.com/a-chol/qmk_firmware into a-chol-hid_joystick

This commit is contained in:
Jack Humbert 2020-05-04 13:19:48 -04:00
commit 708bb4f55d
23 changed files with 1556 additions and 5 deletions

View file

@ -47,6 +47,10 @@
extern keymap_config_t keymap_config;
#endif
#ifdef JOYSTICK_ENABLE
# include "joystick.h"
#endif
/* ---------------------------------------------------------
* Global interface variables and declarations
* ---------------------------------------------------------
@ -246,6 +250,9 @@ typedef struct {
#endif
#ifdef VIRTSER_ENABLE
usb_driver_config_t serial_driver;
#endif
#ifdef JOYSTICK_ENABLE
usb_driver_config_t joystick_driver;
#endif
};
usb_driver_config_t array[0];
@ -283,6 +290,14 @@ static usb_driver_configs_t drivers = {
# define CDC_OUT_MODE USB_EP_MODE_TYPE_BULK
.serial_driver = QMK_USB_DRIVER_CONFIG(CDC, CDC_NOTIFICATION_EPNUM, false),
#endif
#ifdef JOYSTICK_ENABLE
# define JOYSTICK_IN_CAPACITY 4
# define JOYSTICK_OUT_CAPACITY 4
# define JOYSTICK_IN_MODE USB_EP_MODE_TYPE_BULK
# define JOYSTICK_OUT_MODE USB_EP_MODE_TYPE_BULK
.joystick_driver = QMK_USB_DRIVER_CONFIG(JOYSTICK, 0, false),
#endif
};
#define NUM_USB_DRIVERS (sizeof(drivers) / sizeof(usb_driver_config_t))
@ -870,3 +885,57 @@ void virtser_task(void) {
}
#endif
#ifdef JOYSTICK_ENABLE
void send_joystick_packet(joystick_t *joystick) {
joystick_report_t rep = {
# if JOYSTICK_AXES_COUNT > 0
.axes = {joystick->axes[0],
# if JOYSTICK_AXES_COUNT >= 2
joystick->axes[1],
# endif
# if JOYSTICK_AXES_COUNT >= 3
joystick->axes[2],
# endif
# if JOYSTICK_AXES_COUNT >= 4
joystick->axes[3],
# endif
# if JOYSTICK_AXES_COUNT >= 5
joystick->axes[4],
# endif
# if JOYSTICK_AXES_COUNT >= 6
joystick->axes[5],
# endif
},
# endif // JOYSTICK_AXES_COUNT>0
# if JOYSTICK_BUTTON_COUNT > 0
.buttons = {joystick->buttons[0],
# if JOYSTICK_BUTTON_COUNT > 8
joystick->buttons[1],
# endif
# if JOYSTICK_BUTTON_COUNT > 16
joystick->buttons[2],
# endif
# if JOYSTICK_BUTTON_COUNT > 24
joystick->buttons[3],
# endif
}
# endif // JOYSTICK_BUTTON_COUNT>0
};
// chnWrite(&drivers.joystick_driver.driver, (uint8_t *)&rep, sizeof(rep));
osalSysLock();
if (usbGetDriverStateI(&USB_DRIVER) != USB_ACTIVE) {
osalSysUnlock();
return;
}
usbStartTransmitI(&USB_DRIVER, JOYSTICK_IN_EPNUM, (uint8_t *)&rep, sizeof(joystick_report_t));
osalSysUnlock();
}
#endif

View file

@ -85,6 +85,10 @@ extern keymap_config_t keymap_config;
# include "raw_hid.h"
#endif
#ifdef JOYSTICK_ENABLE
# include "joystick.h"
#endif
uint8_t keyboard_idle = 0;
/* 0: Boot Protocol, 1: Report Protocol(default) */
uint8_t keyboard_protocol = 1;
@ -263,6 +267,66 @@ static void Console_Task(void) {
}
#endif
/*******************************************************************************
* Joystick
******************************************************************************/
#ifdef JOYSTICK_ENABLE
void send_joystick_packet(joystick_t *joystick) {
uint8_t timeout = 255;
joystick_report_t r = {
# if JOYSTICK_AXES_COUNT > 0
.axes = {joystick->axes[0],
# if JOYSTICK_AXES_COUNT >= 2
joystick->axes[1],
# endif
# if JOYSTICK_AXES_COUNT >= 3
joystick->axes[2],
# endif
# if JOYSTICK_AXES_COUNT >= 4
joystick->axes[3],
# endif
# if JOYSTICK_AXES_COUNT >= 5
joystick->axes[4],
# endif
# if JOYSTICK_AXES_COUNT >= 6
joystick->axes[5],
# endif
},
# endif // JOYSTICK_AXES_COUNT>0
# if JOYSTICK_BUTTON_COUNT > 0
.buttons = {joystick->buttons[0],
# if JOYSTICK_BUTTON_COUNT > 8
joystick->buttons[1],
# endif
# if JOYSTICK_BUTTON_COUNT > 16
joystick->buttons[2],
# endif
# if JOYSTICK_BUTTON_COUNT > 24
joystick->buttons[3],
# endif
}
# endif // JOYSTICK_BUTTON_COUNT>0
};
/* Select the Joystick Report Endpoint */
Endpoint_SelectEndpoint(JOYSTICK_IN_EPNUM);
/* Check if write ready for a polling interval around 10ms */
while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
if (!Endpoint_IsReadWriteAllowed()) return;
/* Write Joystick Report Data */
Endpoint_Write_Stream_LE(&r, sizeof(joystick_report_t), NULL);
/* Finalize the stream transfer to send the last packet */
Endpoint_ClearIN();
}
#endif
/*******************************************************************************
* USB Events
******************************************************************************/
@ -410,6 +474,9 @@ void EVENT_USB_Device_ConfigurationChanged(void) {
ConfigSuccess &= Endpoint_ConfigureEndpoint(CDC_OUT_EPADDR, EP_TYPE_BULK, CDC_EPSIZE, ENDPOINT_BANK_SINGLE);
ConfigSuccess &= Endpoint_ConfigureEndpoint(CDC_IN_EPADDR, EP_TYPE_BULK, CDC_EPSIZE, ENDPOINT_BANK_SINGLE);
#endif
#ifdef JOYSTICK_ENABLE
ConfigSuccess &= ENDPOINT_CONFIG(JOYSTICK_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN, JOYSTICK_EPSIZE, ENDPOINT_BANK_SINGLE);
#endif
}
/* FIXME: Expose this table in the docs somehow

View file

@ -278,6 +278,63 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM ConsoleReport[] = {
};
#endif
#ifdef JOYSTICK_ENABLE
# if JOYSTICK_AXES_COUNT == 0 && JOYSTICK_BUTTON_COUNT == 0
# error Need at least one axis or button for joystick
# endif
const USB_Descriptor_HIDReport_Datatype_t PROGMEM JoystickReport[] = {
HID_RI_USAGE_PAGE(8, 0x01), // Generic Desktop
HID_RI_USAGE(8, 0x04), // Joystick
HID_RI_COLLECTION(8, 0x01), // Application
HID_RI_COLLECTION(8, 0x00), // Physical
HID_RI_USAGE_PAGE(8, 0x01), // Generic Desktop
# if JOYSTICK_AXES_COUNT >= 1
HID_RI_USAGE(8, 0x30), // X
# endif
# if JOYSTICK_AXES_COUNT >= 2
HID_RI_USAGE(8, 0x31), // Y
# endif
# if JOYSTICK_AXES_COUNT >= 3
HID_RI_USAGE(8, 0x32), // Z
# endif
# if JOYSTICK_AXES_COUNT >= 4
HID_RI_USAGE(8, 0x33), // Rx
# endif
# if JOYSTICK_AXES_COUNT >= 5
HID_RI_USAGE(8, 0x34), // Ry
# endif
# if JOYSTICK_AXES_COUNT >= 6
HID_RI_USAGE(8, 0x35), // Rz
# endif
# if JOYSTICK_AXES_COUNT >= 1
HID_RI_LOGICAL_MINIMUM(8, -127),
HID_RI_LOGICAL_MAXIMUM(8, 127),
HID_RI_REPORT_COUNT(8, JOYSTICK_AXES_COUNT),
HID_RI_REPORT_SIZE(8, 0x08),
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
# endif
# if JOYSTICK_BUTTON_COUNT >= 1
HID_RI_USAGE_PAGE(8, 0x09), // Button
HID_RI_USAGE_MINIMUM(8, 0x01),
HID_RI_USAGE_MAXIMUM(8, JOYSTICK_BUTTON_COUNT),
HID_RI_LOGICAL_MINIMUM(8, 0x00),
HID_RI_LOGICAL_MAXIMUM(8, 0x01),
HID_RI_REPORT_COUNT(8, JOYSTICK_BUTTON_COUNT),
HID_RI_REPORT_SIZE(8, 0x01),
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
# if (JOYSTICK_BUTTON_COUNT % 8) != 0
HID_RI_REPORT_COUNT(8, 8 - (JOYSTICK_BUTTON_COUNT % 8)),
HID_RI_REPORT_SIZE(8, 0x01),
HID_RI_INPUT(8, HID_IOF_CONSTANT),
# endif
# endif
HID_RI_END_COLLECTION(0),
HID_RI_END_COLLECTION(0)
};
#endif
/*
* Device descriptor
*/
@ -287,7 +344,7 @@ const USB_Descriptor_Device_t PROGMEM DeviceDescriptor = {
.Type = DTYPE_Device
},
.USBSpecification = VERSION_BCD(1, 1, 0),
#if VIRTSER_ENABLE
.Class = USB_CSCP_IADDeviceClass,
.SubClass = USB_CSCP_IADDeviceSubclass,
@ -812,6 +869,46 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor = {
.PollingIntervalMS = 0x05
},
#endif
/*
* Joystick
*/
#ifdef JOYSTICK_ENABLE
.Joystick_Interface = {
.Header = {
.Size = sizeof(USB_Descriptor_Interface_t),
.Type = DTYPE_Interface
},
.InterfaceNumber = JOYSTICK_INTERFACE,
.AlternateSetting = 0x00,
.TotalEndpoints = 1,
.Class = HID_CSCP_HIDClass,
.SubClass = HID_CSCP_NonBootSubclass,
.Protocol = HID_CSCP_NonBootProtocol,
.InterfaceStrIndex = NO_DESCRIPTOR
},
.Joystick_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(JoystickReport)
},
.Joystick_INEndpoint = {
.Header = {
.Size = sizeof(USB_Descriptor_Endpoint_t),
.Type = DTYPE_Endpoint
},
.EndpointAddress = (ENDPOINT_DIR_IN | JOYSTICK_IN_EPNUM),
.Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
.EndpointSize = JOYSTICK_EPSIZE,
.PollingIntervalMS = USB_POLLING_INTERVAL_MS
}
#endif
};
/*
@ -944,6 +1041,12 @@ uint16_t get_usb_descriptor(const uint16_t wValue, const uint16_t wIndex, const
break;
#endif
#ifdef JOYSTICK_ENABLE
case JOYSTICK_INTERFACE:
Address = &ConfigurationDescriptor.Joystick_HID;
Size = sizeof(USB_HID_Descriptor_HID_t);
break;
#endif
}
break;
@ -988,6 +1091,12 @@ uint16_t get_usb_descriptor(const uint16_t wValue, const uint16_t wIndex, const
break;
#endif
#ifdef JOYSTICK_ENABLE
case JOYSTICK_INTERFACE:
Address = &JoystickReport;
Size = sizeof(JoystickReport);
break;
#endif
}
break;

View file

@ -123,6 +123,13 @@ typedef struct {
USB_Descriptor_Endpoint_t CDC_DataOutEndpoint;
USB_Descriptor_Endpoint_t CDC_DataInEndpoint;
#endif
#ifdef JOYSTICK_ENABLE
// Joystick HID Interface
USB_Descriptor_Interface_t Joystick_Interface;
USB_HID_Descriptor_HID_t Joystick_HID;
USB_Descriptor_Endpoint_t Joystick_INEndpoint;
#endif
} USB_Descriptor_Configuration_t;
/*
@ -164,6 +171,9 @@ enum usb_interfaces {
CDI_INTERFACE,
#endif
#if defined(JOYSTICK_ENABLE)
JOYSTICK_INTERFACE,
#endif
TOTAL_INTERFACES
};
@ -224,6 +234,10 @@ enum usb_endpoints {
# define CDC_IN_EPADDR (ENDPOINT_DIR_IN | CDC_IN_EPNUM)
# define CDC_OUT_EPADDR (ENDPOINT_DIR_OUT | CDC_OUT_EPNUM)
#endif
#ifdef JOYSTICK_ENABLE
JOYSTICK_IN_EPNUM = NEXT_EPNUM,
JOYSTICK_OUT_EPNUM = NEXT_EPNUM,
#endif
};
#ifdef PROTOCOL_LUFA
@ -248,6 +262,7 @@ enum usb_endpoints {
#define MIDI_STREAM_EPSIZE 64
#define CDC_NOTIFICATION_EPSIZE 8
#define CDC_EPSIZE 16
#define JOYSTICK_EPSIZE 8
uint16_t get_usb_descriptor(const uint16_t wValue, const uint16_t wIndex, const void** const DescriptorAddress);
#endif