diff options
Diffstat (limited to 'tmk_core')
-rw-r--r-- | tmk_core/common/keyboard.c | 7 | ||||
-rw-r--r-- | tmk_core/common/report.h | 13 | ||||
-rw-r--r-- | tmk_core/protocol/chibios/usb_main.c | 69 | ||||
-rw-r--r-- | tmk_core/protocol/lufa/lufa.c | 67 | ||||
-rw-r--r-- | tmk_core/protocol/usb_descriptor.c | 111 | ||||
-rw-r--r-- | tmk_core/protocol/usb_descriptor.h | 15 |
6 files changed, 280 insertions, 2 deletions
diff --git a/tmk_core/common/keyboard.c b/tmk_core/common/keyboard.c index 714c3d048f..a45af56dfd 100644 --- a/tmk_core/common/keyboard.c +++ b/tmk_core/common/keyboard.c @@ -74,6 +74,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #ifdef MIDI_ENABLE # include "process_midi.h" #endif +#ifdef JOYSTICK_ENABLE +# include "process_joystick.h" +#endif #ifdef HD44780_ENABLE # include "hd44780.h" #endif @@ -420,6 +423,10 @@ MATRIX_LOOP_END: } #endif +#ifdef JOYSTICK_ENABLE + joystick_task(); +#endif + // update LED if (led_status != host_keyboard_leds()) { led_status = host_keyboard_leds(); diff --git a/tmk_core/common/report.h b/tmk_core/common/report.h index 1b2f13bdde..1aa33c998d 100644 --- a/tmk_core/common/report.h +++ b/tmk_core/common/report.h @@ -29,7 +29,8 @@ enum hid_report_ids { REPORT_ID_MOUSE, REPORT_ID_SYSTEM, REPORT_ID_CONSUMER, - REPORT_ID_NKRO + REPORT_ID_NKRO, + REPORT_ID_JOYSTICK }; /* Mouse buttons */ @@ -189,6 +190,16 @@ typedef struct { int8_t h; } __attribute__((packed)) report_mouse_t; +typedef struct { +#if JOYSTICK_AXES_COUNT > 0 + int8_t axes[JOYSTICK_AXES_COUNT]; +#endif + +#if JOYSTICK_BUTTON_COUNT > 0 + uint8_t buttons[(JOYSTICK_BUTTON_COUNT - 1) / 8 + 1]; +#endif +} __attribute__((packed)) joystick_report_t; + /* keycode to system usage */ static inline uint16_t KEYCODE2SYSTEM(uint8_t key) { switch (key) { diff --git a/tmk_core/protocol/chibios/usb_main.c b/tmk_core/protocol/chibios/usb_main.c index 21e9f14e50..68c61cf550 100644 --- a/tmk_core/protocol/chibios/usb_main.c +++ b/tmk_core/protocol/chibios/usb_main.c @@ -47,6 +47,10 @@ extern keymap_config_t keymap_config; #endif +#ifdef JOYSTICK_ENABLE +# include "joystick.h" +#endif + /* --------------------------------------------------------- * Global interface variables and declarations * --------------------------------------------------------- @@ -247,6 +251,9 @@ typedef struct { #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)) @@ -867,3 +882,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 diff --git a/tmk_core/protocol/lufa/lufa.c b/tmk_core/protocol/lufa/lufa.c index 6776a964e9..85603646db 100644 --- a/tmk_core/protocol/lufa/lufa.c +++ b/tmk_core/protocol/lufa/lufa.c @@ -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; @@ -264,6 +268,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 ******************************************************************************/ /* @@ -411,6 +475,9 @@ void EVENT_USB_Device_ConfigurationChanged(void) { ConfigSuccess &= Endpoint_ConfigureEndpoint((CDC_OUT_EPNUM | ENDPOINT_DIR_OUT), EP_TYPE_BULK, CDC_EPSIZE, 1); ConfigSuccess &= Endpoint_ConfigureEndpoint((CDC_IN_EPNUM | ENDPOINT_DIR_IN), EP_TYPE_BULK, CDC_EPSIZE, 1); #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 diff --git a/tmk_core/protocol/usb_descriptor.c b/tmk_core/protocol/usb_descriptor.c index bcca245867..f5d32445de 100644 --- a/tmk_core/protocol/usb_descriptor.c +++ b/tmk_core/protocol/usb_descriptor.c @@ -279,6 +279,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 */ @@ -288,7 +345,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, @@ -813,6 +870,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 }; /* @@ -945,6 +1042,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; @@ -989,6 +1092,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; diff --git a/tmk_core/protocol/usb_descriptor.h b/tmk_core/protocol/usb_descriptor.h index 34a85978a6..79dd87014f 100644 --- a/tmk_core/protocol/usb_descriptor.h +++ b/tmk_core/protocol/usb_descriptor.h @@ -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 }; @@ -219,6 +229,10 @@ enum usb_endpoints { CDC_IN_EPNUM = NEXT_EPNUM, CDC_OUT_EPNUM = NEXT_EPNUM, #endif +#ifdef JOYSTICK_ENABLE + JOYSTICK_IN_EPNUM = NEXT_EPNUM, + JOYSTICK_OUT_EPNUM = NEXT_EPNUM, +#endif }; #ifdef PROTOCOL_LUFA @@ -243,6 +257,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 |