forked from mfulz_github/qmk_firmware
		
	Compare commits
	
		
			25 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					d2123f3c07 | ||
| 
						 | 
					3996250d81 | ||
| 
						 | 
					09ff4b0c99 | ||
| 
						 | 
					708bb4f55d | ||
| 
						 | 
					a80ea8b7cc | ||
| 
						 | 
					a03d1eb66b | ||
| 
						 | 
					92c6466089 | ||
| 
						 | 
					16fe12e6b6 | ||
| 
						 | 
					1d8102183f | ||
| 
						 | 
					476fce8a32 | ||
| 
						 | 
					0ce015d0c9 | ||
| 
						 | 
					c447c4ffd5 | ||
| 
						 | 
					887e96cbb2 | ||
| 
						 | 
					def06b4976 | ||
| 
						 | 
					34bedc3787 | ||
| 
						 | 
					c6c01f9eff | ||
| 
						 | 
					86853a4110 | ||
| 
						 | 
					a8a2825bd4 | ||
| 
						 | 
					38cd264dd8 | ||
| 
						 | 
					6fd7f9d12f | ||
| 
						 | 
					801be60473 | ||
| 
						 | 
					d88bdc6a1b | ||
| 
						 | 
					b030c45705 | ||
| 
						 | 
					ee43b338ea | ||
| 
						 | 
					3cf7611139 | 
@ -22,6 +22,11 @@ QUANTUM_SRC += \
 | 
				
			|||||||
    $(QUANTUM_DIR)/keymap_common.c \
 | 
					    $(QUANTUM_DIR)/keymap_common.c \
 | 
				
			||||||
    $(QUANTUM_DIR)/keycode_config.c
 | 
					    $(QUANTUM_DIR)/keycode_config.c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					KEYBOARD_ENABLE ?= yes
 | 
				
			||||||
 | 
					ifeq ($(strip $(KEYBOARD_ENABLE)), yes)
 | 
				
			||||||
 | 
					    OPT_DEFS += -DKEYBOARD_ENABLE
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ifeq ($(strip $(DEBUG_MATRIX_SCAN_RATE_ENABLE)), yes)
 | 
					ifeq ($(strip $(DEBUG_MATRIX_SCAN_RATE_ENABLE)), yes)
 | 
				
			||||||
    OPT_DEFS += -DDEBUG_MATRIX_SCAN_RATE
 | 
					    OPT_DEFS += -DDEBUG_MATRIX_SCAN_RATE
 | 
				
			||||||
    CONSOLE_ENABLE = yes
 | 
					    CONSOLE_ENABLE = yes
 | 
				
			||||||
@ -600,3 +605,8 @@ endif
 | 
				
			|||||||
ifeq ($(strip $(JOYSTICK_ENABLE)), digital)
 | 
					ifeq ($(strip $(JOYSTICK_ENABLE)), digital)
 | 
				
			||||||
    OPT_DEFS += -DDIGITAL_JOYSTICK_ENABLE
 | 
					    OPT_DEFS += -DDIGITAL_JOYSTICK_ENABLE
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ifeq ($(strip $(SWITCH_CONTROLLER_ENABLE)), yes)
 | 
				
			||||||
 | 
					    OPT_DEFS += -DSWITCH_CONTROLLER_ENABLE
 | 
				
			||||||
 | 
					    OPT_DEFS += -DGAMEPAD_ENABLE
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
							
								
								
									
										62
									
								
								keyboards/handwired/gc_controller/config.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								keyboards/handwired/gc_controller/config.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,62 @@
 | 
				
			|||||||
 | 
					/* Copyright 2019 Jack Humbert
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation, either version 2 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "config_common.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* USB Device descriptor parameter */
 | 
				
			||||||
 | 
					#define VENDOR_ID       0x0e6f
 | 
				
			||||||
 | 
					#define PRODUCT_ID      0x0185
 | 
				
			||||||
 | 
					#define DEVICE_VER      0x0001
 | 
				
			||||||
 | 
					#define MANUFACTURER    QMK
 | 
				
			||||||
 | 
					#define PRODUCT         Proton C
 | 
				
			||||||
 | 
					#define DESCRIPTION     Handwired Gamepad
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* key matrix size */
 | 
				
			||||||
 | 
					#define MATRIX_ROWS 1
 | 
				
			||||||
 | 
					#define MATRIX_COLS 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define DIODE_DIRECTION COL2ROW
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define MATRIX_COL_PINS { A3 }
 | 
				
			||||||
 | 
					#define MATRIX_ROW_PINS { A1 }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* define if matrix has ghost */
 | 
				
			||||||
 | 
					//#define MATRIX_HAS_GHOST
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Set 0 if debouncing isn't needed */
 | 
				
			||||||
 | 
					#define DEBOUNCE    5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Feature disable options
 | 
				
			||||||
 | 
					 *  These options are also useful to firmware size reduction.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* disable debug print */
 | 
				
			||||||
 | 
					//#define NO_DEBUG
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* disable print */
 | 
				
			||||||
 | 
					//#define NO_PRINT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* disable action features */
 | 
				
			||||||
 | 
					//#define NO_ACTION_LAYER
 | 
				
			||||||
 | 
					//#define NO_ACTION_TAPPING
 | 
				
			||||||
 | 
					//#define NO_ACTION_ONESHOT
 | 
				
			||||||
 | 
					//#define NO_ACTION_MACRO
 | 
				
			||||||
 | 
					//#define NO_ACTION_FUNCTION
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define GAMECUBE_DATA_PIN A2
 | 
				
			||||||
							
								
								
									
										130
									
								
								keyboards/handwired/gc_controller/gc_controller.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										130
									
								
								keyboards/handwired/gc_controller/gc_controller.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,130 @@
 | 
				
			|||||||
 | 
					#include "gc_controller.h"
 | 
				
			||||||
 | 
					#include "gc_read.h"
 | 
				
			||||||
 | 
					#include "gamepad.h"
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint16_t gamecube_buttons = 0;
 | 
				
			||||||
 | 
					uint8_t gamecube_joysticks[6] = {0};
 | 
				
			||||||
 | 
					bool z_button = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					report_gamepad_t report = {
 | 
				
			||||||
 | 
					    .Button = 0,
 | 
				
			||||||
 | 
					    .LX = STICK_CENTER,
 | 
				
			||||||
 | 
					    .LY = STICK_CENTER,
 | 
				
			||||||
 | 
					    .RX = STICK_CENTER,
 | 
				
			||||||
 | 
					    .RY = STICK_CENTER,
 | 
				
			||||||
 | 
					    .HAT = HAT_CENTER
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void board_init(void) {
 | 
				
			||||||
 | 
					    setPinOutput(C13);
 | 
				
			||||||
 | 
					    writePinLow(C13);
 | 
				
			||||||
 | 
					    gamecube_init();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void matrix_init_user(void) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void matrix_scan_user(void) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    gamecube_scan(&gamecube_buttons, gamecube_joysticks);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    z_button = gamecube_buttons & GAMECUBE_Z;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Home & Capture
 | 
				
			||||||
 | 
					    if (gamecube_buttons & GAMECUBE_START) {
 | 
				
			||||||
 | 
					        if (z_button && !(report.Button & SWITCH_HOME))
 | 
				
			||||||
 | 
					            report.Button |= SWITCH_CAPTURE;
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					            report.Button |= SWITCH_HOME;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        report.Button &= ~SWITCH_HOME;
 | 
				
			||||||
 | 
					        report.Button &= ~SWITCH_CAPTURE;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    // Y and L
 | 
				
			||||||
 | 
					    if (gamecube_buttons & GAMECUBE_Y) {
 | 
				
			||||||
 | 
					        if (z_button && !(report.Button & SWITCH_Y))
 | 
				
			||||||
 | 
					            report.Button |= SWITCH_L;
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					            report.Button |= SWITCH_Y;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        report.Button &= ~SWITCH_Y;
 | 
				
			||||||
 | 
					        report.Button &= ~SWITCH_L;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    // X and R
 | 
				
			||||||
 | 
					    if (gamecube_buttons & GAMECUBE_X) {
 | 
				
			||||||
 | 
					        if (z_button && !(report.Button & SWITCH_X))
 | 
				
			||||||
 | 
					            report.Button |= SWITCH_R;
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					            report.Button |= SWITCH_X;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        report.Button &= ~SWITCH_X;
 | 
				
			||||||
 | 
					        report.Button &= ~SWITCH_R;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    // B and -
 | 
				
			||||||
 | 
					    if (gamecube_buttons & GAMECUBE_B) {
 | 
				
			||||||
 | 
					        if (z_button && !(report.Button & SWITCH_B))
 | 
				
			||||||
 | 
					            report.Button |= SWITCH_MINUS;
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					            report.Button |= SWITCH_B;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        report.Button &= ~SWITCH_B;
 | 
				
			||||||
 | 
					        report.Button &= ~SWITCH_MINUS;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    // A and +
 | 
				
			||||||
 | 
					    if (gamecube_buttons & GAMECUBE_A) {
 | 
				
			||||||
 | 
					        if (z_button && !(report.Button & SWITCH_A))
 | 
				
			||||||
 | 
					            report.Button |= SWITCH_PLUS;
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					            report.Button |= SWITCH_A;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        report.Button &= ~SWITCH_A;
 | 
				
			||||||
 | 
					        report.Button &= ~SWITCH_PLUS;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (gamecube_buttons & GAMECUBE_L) {
 | 
				
			||||||
 | 
					        report.Button |= SWITCH_ZL;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        report.Button &= ~SWITCH_ZL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (gamecube_buttons & GAMECUBE_R) {
 | 
				
			||||||
 | 
					        report.Button |= SWITCH_ZR;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        report.Button &= ~SWITCH_ZR;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ((gamecube_buttons & GAMECUBE_UP) && (gamecube_buttons & GAMECUBE_RIGHT))
 | 
				
			||||||
 | 
					        report.HAT = HAT_TOP_RIGHT;
 | 
				
			||||||
 | 
					    else if ((gamecube_buttons & GAMECUBE_UP) && (gamecube_buttons & GAMECUBE_LEFT))
 | 
				
			||||||
 | 
					        report.HAT = HAT_TOP_LEFT;
 | 
				
			||||||
 | 
					    else if ((gamecube_buttons & GAMECUBE_DOWN) && (gamecube_buttons & GAMECUBE_RIGHT))
 | 
				
			||||||
 | 
					        report.HAT = HAT_BOTTOM_RIGHT;
 | 
				
			||||||
 | 
					    else if ((gamecube_buttons & GAMECUBE_DOWN) && (gamecube_buttons & GAMECUBE_LEFT))
 | 
				
			||||||
 | 
					        report.HAT = HAT_BOTTOM_LEFT;
 | 
				
			||||||
 | 
					    else if (gamecube_buttons & GAMECUBE_UP)
 | 
				
			||||||
 | 
					        report.HAT = HAT_TOP;
 | 
				
			||||||
 | 
					    else if (gamecube_buttons & GAMECUBE_DOWN)
 | 
				
			||||||
 | 
					        report.HAT = HAT_BOTTOM;
 | 
				
			||||||
 | 
					    else if (gamecube_buttons & GAMECUBE_RIGHT)
 | 
				
			||||||
 | 
					        report.HAT = HAT_RIGHT;
 | 
				
			||||||
 | 
					    else if (gamecube_buttons & GAMECUBE_LEFT)
 | 
				
			||||||
 | 
					        report.HAT = HAT_LEFT;
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					        report.HAT = HAT_CENTER;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (report.Button || report.HAT != HAT_CENTER)
 | 
				
			||||||
 | 
					        writePinHigh(C13);
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					        writePinLow(C13);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // joystick calculations
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					    report.LX = gamecube_joysticks[0];         
 | 
				
			||||||
 | 
					    report.LY = 255 - gamecube_joysticks[1];    
 | 
				
			||||||
 | 
					    report.RX = gamecube_joysticks[2];          
 | 
				
			||||||
 | 
					    report.RY = 255 - gamecube_joysticks[3];          
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    send_gamepad(&report);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										47
									
								
								keyboards/handwired/gc_controller/gc_controller.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								keyboards/handwired/gc_controller/gc_controller.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,47 @@
 | 
				
			|||||||
 | 
					#include "quantum.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef enum {
 | 
				
			||||||
 | 
					    SWITCH_Y       = 0x01,
 | 
				
			||||||
 | 
					    SWITCH_B       = 0x02,
 | 
				
			||||||
 | 
					    SWITCH_A       = 0x04,
 | 
				
			||||||
 | 
					    SWITCH_X       = 0x08,
 | 
				
			||||||
 | 
					    SWITCH_L       = 0x10,
 | 
				
			||||||
 | 
					    SWITCH_R       = 0x20,
 | 
				
			||||||
 | 
					    SWITCH_ZL      = 0x40,
 | 
				
			||||||
 | 
					    SWITCH_ZR      = 0x80,
 | 
				
			||||||
 | 
					    SWITCH_MINUS   = 0x100,
 | 
				
			||||||
 | 
					    SWITCH_PLUS    = 0x200,
 | 
				
			||||||
 | 
					    SWITCH_LCLICK  = 0x400,
 | 
				
			||||||
 | 
					    SWITCH_RCLICK  = 0x800,
 | 
				
			||||||
 | 
					    SWITCH_HOME    = 0x1000,
 | 
				
			||||||
 | 
					    SWITCH_CAPTURE = 0x2000,
 | 
				
			||||||
 | 
					} SwitchButtons_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef enum {
 | 
				
			||||||
 | 
					    GAMECUBE_A      = 0b0000000000000001,
 | 
				
			||||||
 | 
					    GAMECUBE_B      = 0b0000000000000010,
 | 
				
			||||||
 | 
					    GAMECUBE_X      = 0b0000000000000100,
 | 
				
			||||||
 | 
					    GAMECUBE_Y      = 0b0000000000001000,
 | 
				
			||||||
 | 
					    GAMECUBE_START  = 0b0000000000010000,
 | 
				
			||||||
 | 
					    GAMECUBE_LEFT   = 0b0000000100000000,
 | 
				
			||||||
 | 
					    GAMECUBE_RIGHT  = 0b0000001000000000,
 | 
				
			||||||
 | 
					    GAMECUBE_DOWN   = 0b0000010000000000,
 | 
				
			||||||
 | 
					    GAMECUBE_UP     = 0b0000100000000000,
 | 
				
			||||||
 | 
					    GAMECUBE_Z      = 0b0001000000000000,
 | 
				
			||||||
 | 
					    GAMECUBE_R      = 0b0010000000000000,
 | 
				
			||||||
 | 
					    GAMECUBE_L      = 0b0100000000000000,
 | 
				
			||||||
 | 
					} GamecubeButtons_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define HAT_TOP          0x00
 | 
				
			||||||
 | 
					#define HAT_TOP_RIGHT    0x01
 | 
				
			||||||
 | 
					#define HAT_RIGHT        0x02
 | 
				
			||||||
 | 
					#define HAT_BOTTOM_RIGHT 0x03
 | 
				
			||||||
 | 
					#define HAT_BOTTOM       0x04
 | 
				
			||||||
 | 
					#define HAT_BOTTOM_LEFT  0x05
 | 
				
			||||||
 | 
					#define HAT_LEFT         0x06
 | 
				
			||||||
 | 
					#define HAT_TOP_LEFT     0x07
 | 
				
			||||||
 | 
					#define HAT_CENTER       0x08
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define STICK_MIN      0
 | 
				
			||||||
 | 
					#define STICK_CENTER 128
 | 
				
			||||||
 | 
					#define STICK_MAX    255
 | 
				
			||||||
							
								
								
									
										216
									
								
								keyboards/handwired/gc_controller/gc_read.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										216
									
								
								keyboards/handwired/gc_controller/gc_read.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,216 @@
 | 
				
			|||||||
 | 
					#include "gc_read.h"
 | 
				
			||||||
 | 
					#include "gc_controller.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CONTROLLER_TIMEOUT 60
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool init_message[9] = {0, 0, 0, 0, 0, 0, 0, 0, 1};
 | 
				
			||||||
 | 
					bool request_message[25] = {
 | 
				
			||||||
 | 
					    0, 1, 0, 0, 0, 0, 0, 0, 
 | 
				
			||||||
 | 
					    0, 0, 0, 0, 0, 0, 1, 1, 
 | 
				
			||||||
 | 
					    0, 0, 0, 0, 0, 0, 1, 0, 1};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void start_message(void) {
 | 
				
			||||||
 | 
					    setPinOutput(GAMECUBE_DATA_PIN);
 | 
				
			||||||
 | 
					    writePinLow(GAMECUBE_DATA_PIN);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void send_bit(bool b) {
 | 
				
			||||||
 | 
					    if (b) {
 | 
				
			||||||
 | 
					        writePinLow(GAMECUBE_DATA_PIN);
 | 
				
			||||||
 | 
					        wait_ns(900);
 | 
				
			||||||
 | 
					        writePinHigh(GAMECUBE_DATA_PIN);
 | 
				
			||||||
 | 
					        wait_ns(2900);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        writePinLow(GAMECUBE_DATA_PIN);
 | 
				
			||||||
 | 
					        wait_ns(2900);
 | 
				
			||||||
 | 
					        writePinHigh(GAMECUBE_DATA_PIN);
 | 
				
			||||||
 | 
					        wait_ns(900);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void wait_for_ready(void) {
 | 
				
			||||||
 | 
					    setPinInputHigh(GAMECUBE_DATA_PIN);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // wait for long high
 | 
				
			||||||
 | 
					    uint8_t ready = 0;
 | 
				
			||||||
 | 
					    while (ready < 5) {
 | 
				
			||||||
 | 
					        if (readPin(GAMECUBE_DATA_PIN))
 | 
				
			||||||
 | 
					            ready++;
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					            ready = 0;
 | 
				
			||||||
 | 
					        wait_us(1);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void end_message(void) {
 | 
				
			||||||
 | 
					    setPinInputHigh(GAMECUBE_DATA_PIN);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint8_t buffer[9] = {0};
 | 
				
			||||||
 | 
					uint16_t buttons_debounce = 0;
 | 
				
			||||||
 | 
					bool initialised = false;
 | 
				
			||||||
 | 
					bool calibrated = false;
 | 
				
			||||||
 | 
					uint8_t mid_values[4] = {128, 128, 128, 128};
 | 
				
			||||||
 | 
					uint8_t max_values[4] = {210, 210, 210, 210};
 | 
				
			||||||
 | 
					uint8_t min_values[4] = {35, 35, 35, 35};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void gamecube_init(void) {
 | 
				
			||||||
 | 
					    setPinInputHigh(GAMECUBE_DATA_PIN);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void gamecube_scan(uint16_t * buttons, uint8_t * joysticks) {
 | 
				
			||||||
 | 
					    bool exiting = false;
 | 
				
			||||||
 | 
					    uint16_t timeout_counter = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // somehow we're missing the first bit, which can safely be ignored
 | 
				
			||||||
 | 
					    // i'm not sure if it's something with the timing or what
 | 
				
			||||||
 | 
					    uint8_t buffer_bit = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    chSysLock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!initialised) {
 | 
				
			||||||
 | 
					        wait_for_ready();
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        start_message();
 | 
				
			||||||
 | 
					        for (uint8_t i = 0; i < 9; i++)
 | 
				
			||||||
 | 
					            send_bit(init_message[i]);
 | 
				
			||||||
 | 
					        end_message();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        initialised = true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    wait_for_ready();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    start_message();
 | 
				
			||||||
 | 
					    for (uint8_t i = 0; i < 25; i++)
 | 
				
			||||||
 | 
					        send_bit(request_message[i]);
 | 
				
			||||||
 | 
					    end_message();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    while (!exiting) {
 | 
				
			||||||
 | 
					        timeout_counter = 0;
 | 
				
			||||||
 | 
					        // wait for low or timeout
 | 
				
			||||||
 | 
					        while (readPin(GAMECUBE_DATA_PIN)) {
 | 
				
			||||||
 | 
					            wait_ns(100);
 | 
				
			||||||
 | 
					            timeout_counter++;
 | 
				
			||||||
 | 
					            if (timeout_counter > CONTROLLER_TIMEOUT) {
 | 
				
			||||||
 | 
					                exiting = true;
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!exiting) {
 | 
				
			||||||
 | 
					            // wait for the data part
 | 
				
			||||||
 | 
					            wait_ns(1950);
 | 
				
			||||||
 | 
					            bool b = readPin(GAMECUBE_DATA_PIN);
 | 
				
			||||||
 | 
					            if (b)
 | 
				
			||||||
 | 
					                buffer[buffer_bit / 8] |=  (1 << (7 - (buffer_bit % 8)));
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					                buffer[buffer_bit / 8] &= ~(1 << (7 - (buffer_bit % 8)));
 | 
				
			||||||
 | 
					            buffer_bit++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // wait for high
 | 
				
			||||||
 | 
					            while (!readPin(GAMECUBE_DATA_PIN));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    chSysUnlock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // basic debouncing for buttons
 | 
				
			||||||
 | 
					    uint16_t combined_buttons = buffer[0] | (buffer[1] << 8);
 | 
				
			||||||
 | 
					    *buttons |= buttons_debounce & combined_buttons;
 | 
				
			||||||
 | 
					    *buttons &= buttons_debounce | combined_buttons;
 | 
				
			||||||
 | 
					    buttons_debounce = combined_buttons;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   if (!calibrated && mid_values[0] > 0) {
 | 
				
			||||||
 | 
					        mid_values[0] = buffer[2];
 | 
				
			||||||
 | 
					        mid_values[1] = buffer[3];
 | 
				
			||||||
 | 
					        mid_values[2] = buffer[4];
 | 
				
			||||||
 | 
					        mid_values[3] = buffer[5];
 | 
				
			||||||
 | 
					        calibrated = true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (max_values[0] < buffer[2])
 | 
				
			||||||
 | 
					        max_values[0] = buffer[2];
 | 
				
			||||||
 | 
					    if (max_values[1] < buffer[3])
 | 
				
			||||||
 | 
					        max_values[1] = buffer[3];
 | 
				
			||||||
 | 
					    if (max_values[2] < buffer[4])
 | 
				
			||||||
 | 
					        max_values[2] = buffer[4];
 | 
				
			||||||
 | 
					    if (max_values[3] < buffer[5])
 | 
				
			||||||
 | 
					        max_values[3] = buffer[5];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (min_values[0] > buffer[2])
 | 
				
			||||||
 | 
					        min_values[0] = buffer[2];
 | 
				
			||||||
 | 
					    if (min_values[1] > buffer[3])
 | 
				
			||||||
 | 
					        min_values[1] = buffer[3];
 | 
				
			||||||
 | 
					    if (min_values[2] > buffer[4])
 | 
				
			||||||
 | 
					        min_values[2] = buffer[4];
 | 
				
			||||||
 | 
					    if (min_values[3] > buffer[5])
 | 
				
			||||||
 | 
					        min_values[3] = buffer[5];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // values from my GC controller in Windows
 | 
				
			||||||
 | 
					    // 30 - 138 - 236
 | 
				
			||||||
 | 
					    // 20 - 124 - 225
 | 
				
			||||||
 | 
					    // 37 - 135 - 222
 | 
				
			||||||
 | 
					    // 34 - 126 - 216
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // this should be 127? i don't understand what i'm doing wrong yet
 | 
				
			||||||
 | 
					    #define JOYSTICK_SCALER 180.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int32_t lx_temp = (int16_t)buffer[2] - mid_values[0];
 | 
				
			||||||
 | 
					    if (lx_temp > 0)
 | 
				
			||||||
 | 
					        lx_temp *= JOYSTICK_SCALER / (max_values[0]-mid_values[0]);
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					        lx_temp *= JOYSTICK_SCALER / (mid_values[0]-min_values[0]);
 | 
				
			||||||
 | 
					    lx_temp += STICK_CENTER;
 | 
				
			||||||
 | 
					    if (lx_temp > 255)
 | 
				
			||||||
 | 
					        lx_temp = 255;
 | 
				
			||||||
 | 
					    if (lx_temp < 0)
 | 
				
			||||||
 | 
					        lx_temp = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int32_t ly_temp = (int16_t)buffer[3] - mid_values[1];
 | 
				
			||||||
 | 
					    if (ly_temp > 0)
 | 
				
			||||||
 | 
					        ly_temp *= JOYSTICK_SCALER / (max_values[1]-mid_values[1]);
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					        ly_temp *= JOYSTICK_SCALER / (mid_values[1]-min_values[1]);
 | 
				
			||||||
 | 
					    ly_temp += STICK_CENTER;
 | 
				
			||||||
 | 
					    if (ly_temp > 255)
 | 
				
			||||||
 | 
					        ly_temp = 255;
 | 
				
			||||||
 | 
					    if (ly_temp < 0)
 | 
				
			||||||
 | 
					        ly_temp = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int32_t rx_temp = (int16_t)buffer[4] - mid_values[2];
 | 
				
			||||||
 | 
					    if (rx_temp > 0)
 | 
				
			||||||
 | 
					        rx_temp *= JOYSTICK_SCALER / (max_values[2]-mid_values[2]);
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					        rx_temp *= JOYSTICK_SCALER / (mid_values[2]-min_values[2]);
 | 
				
			||||||
 | 
					    rx_temp += STICK_CENTER;
 | 
				
			||||||
 | 
					    if (rx_temp > 255)
 | 
				
			||||||
 | 
					        rx_temp = 255;
 | 
				
			||||||
 | 
					    if (rx_temp < 0)
 | 
				
			||||||
 | 
					        rx_temp = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int32_t ry_temp = (int16_t)buffer[5] - mid_values[3];
 | 
				
			||||||
 | 
					    if (ry_temp > 0)
 | 
				
			||||||
 | 
					        ry_temp *= JOYSTICK_SCALER / (max_values[3]-mid_values[3]);
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					        ry_temp *= JOYSTICK_SCALER / (mid_values[3]-min_values[3]);
 | 
				
			||||||
 | 
					    ry_temp += STICK_CENTER;
 | 
				
			||||||
 | 
					    if (ry_temp > 255)
 | 
				
			||||||
 | 
					        ry_temp = 255;
 | 
				
			||||||
 | 
					    if (ry_temp < 0)
 | 
				
			||||||
 | 
					        ry_temp = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // checks to avoid a data skip (0 values on input, which aren't possible, i think)
 | 
				
			||||||
 | 
					    if (buffer[2])
 | 
				
			||||||
 | 
					        joysticks[0] = lx_temp;
 | 
				
			||||||
 | 
					    if (buffer[3])
 | 
				
			||||||
 | 
					        joysticks[1] = ly_temp;
 | 
				
			||||||
 | 
					    if (buffer[4])
 | 
				
			||||||
 | 
					        joysticks[2] = rx_temp;
 | 
				
			||||||
 | 
					    if (buffer[5])
 | 
				
			||||||
 | 
					        joysticks[3] = ry_temp;
 | 
				
			||||||
 | 
					    if (buffer[6])
 | 
				
			||||||
 | 
					        joysticks[4] = buffer[6];
 | 
				
			||||||
 | 
					    if (buffer[7])
 | 
				
			||||||
 | 
					        joysticks[5] = buffer[7];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										34
									
								
								keyboards/handwired/gc_controller/gc_read.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								keyboards/handwired/gc_controller/gc_read.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					#include "quantum.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Adapted from https://github.com/bigjosh/SimpleNeoPixelDemo/ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef NOP_FUDGE
 | 
				
			||||||
 | 
					#    if defined(STM32F0XX) || defined(STM32F1XX) || defined(STM32F3XX) || defined(STM32F4XX) || defined(STM32L0XX)
 | 
				
			||||||
 | 
					#        define NOP_FUDGE 0.4
 | 
				
			||||||
 | 
					#    else
 | 
				
			||||||
 | 
					#        error("NOP_FUDGE configuration required")
 | 
				
			||||||
 | 
					#        define NOP_FUDGE 1  // this just pleases the compile so the above error is easier to spot
 | 
				
			||||||
 | 
					#    endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define NUMBER_NOPS 6
 | 
				
			||||||
 | 
					#define CYCLES_PER_SEC (STM32_SYSCLK / NUMBER_NOPS * NOP_FUDGE)
 | 
				
			||||||
 | 
					#define NS_PER_SEC (1000000000L)  // Note that this has to be SIGNED since we want to be able to check for negative values of derivatives
 | 
				
			||||||
 | 
					#define NS_PER_CYCLE (NS_PER_SEC / CYCLES_PER_SEC)
 | 
				
			||||||
 | 
					#define NS_TO_CYCLES(n) ((n) / NS_PER_CYCLE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define wait_ns(x)                                  \
 | 
				
			||||||
 | 
					    do {                                            \
 | 
				
			||||||
 | 
					        for (int i = 0; i < NS_TO_CYCLES(x); i++) { \
 | 
				
			||||||
 | 
					            __asm__ volatile("nop\n\t"              \
 | 
				
			||||||
 | 
					                             "nop\n\t"              \
 | 
				
			||||||
 | 
					                             "nop\n\t"              \
 | 
				
			||||||
 | 
					                             "nop\n\t"              \
 | 
				
			||||||
 | 
					                             "nop\n\t"              \
 | 
				
			||||||
 | 
					                             "nop\n\t");            \
 | 
				
			||||||
 | 
					        }                                           \
 | 
				
			||||||
 | 
					    } while (0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void gamecube_init(void);
 | 
				
			||||||
 | 
					void gamecube_scan(uint16_t * buttons, uint8_t * joysticks);
 | 
				
			||||||
@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					#include QMK_KEYBOARD_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { { { 0 } } };
 | 
				
			||||||
							
								
								
									
										12
									
								
								keyboards/handwired/gc_controller/readme.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								keyboards/handwired/gc_controller/readme.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					J1 header
 | 
				
			||||||
 | 
					---------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					|#|Color  |Proton C|Description|
 | 
				
			||||||
 | 
					|-|-------|----|------------|
 | 
				
			||||||
 | 
					|1|blue   |3.3V|            |
 | 
				
			||||||
 | 
					|2|yellow |5V  |            |
 | 
				
			||||||
 | 
					|3|red    |A2  |Data (3.3V) |
 | 
				
			||||||
 | 
					|4|green  |GND |            |
 | 
				
			||||||
 | 
					|5|white  |GND |            |
 | 
				
			||||||
 | 
					|6|black  |NC  |            |
 | 
				
			||||||
							
								
								
									
										15
									
								
								keyboards/handwired/gc_controller/rules.mk
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								keyboards/handwired/gc_controller/rules.mk
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					# MCU name
 | 
				
			||||||
 | 
					MCU = STM32F303
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BACKLIGHT_ENABLE = no
 | 
				
			||||||
 | 
					MOUSEKEY_ENABLE = no
 | 
				
			||||||
 | 
					EXTRAKEY_ENABLE = no
 | 
				
			||||||
 | 
					CONSOLE_ENABLE = no
 | 
				
			||||||
 | 
					NKRO_ENABLE = no
 | 
				
			||||||
 | 
					RAW_ENABLE = no
 | 
				
			||||||
 | 
					MIDI_ENABLE = no
 | 
				
			||||||
 | 
					VIRTSER_ENABLE = no
 | 
				
			||||||
 | 
					KEYBOARD_ENABLE = no
 | 
				
			||||||
 | 
					SWITCH_CONTROLLER_ENABLE = yes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SRC += gc_read.c
 | 
				
			||||||
@ -29,4 +29,4 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#define RGB_DI_PIN A0
 | 
					#define RGB_DI_PIN A0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define ADC_PIN A0
 | 
					#define ADC_PIN A1
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										4
									
								
								quantum/gamepad.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								quantum/gamepad.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void send_gamepad(report_gamepad_t *report);
 | 
				
			||||||
 | 
					void gamepad_ep_task(void);
 | 
				
			||||||
@ -30,7 +30,8 @@ enum hid_report_ids {
 | 
				
			|||||||
    REPORT_ID_SYSTEM,
 | 
					    REPORT_ID_SYSTEM,
 | 
				
			||||||
    REPORT_ID_CONSUMER,
 | 
					    REPORT_ID_CONSUMER,
 | 
				
			||||||
    REPORT_ID_NKRO,
 | 
					    REPORT_ID_NKRO,
 | 
				
			||||||
    REPORT_ID_JOYSTICK
 | 
					    REPORT_ID_JOYSTICK,
 | 
				
			||||||
 | 
					    REPORT_ID_GAMEPAD
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Mouse buttons */
 | 
					/* Mouse buttons */
 | 
				
			||||||
@ -198,6 +199,29 @@ typedef struct {
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
} __attribute__((packed)) joystick_report_t;
 | 
					} __attribute__((packed)) joystick_report_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef GAMEPAD_ENABLE
 | 
				
			||||||
 | 
					typedef struct {
 | 
				
			||||||
 | 
					#ifdef SWITCH_CONTROLLER_ENABLE
 | 
				
			||||||
 | 
					    uint16_t Button; // 16 buttons; see JoystickButtons_t for bit mapping
 | 
				
			||||||
 | 
					    uint8_t  HAT;    // HAT switch; one nibble w/ unused nibble
 | 
				
			||||||
 | 
					    uint8_t  LX;     // Left  Stick X
 | 
				
			||||||
 | 
					    uint8_t  LY;     // Left  Stick Y
 | 
				
			||||||
 | 
					    uint8_t  RX;     // Right Stick X
 | 
				
			||||||
 | 
					    uint8_t  RY;     // Right Stick Y
 | 
				
			||||||
 | 
					    uint8_t  VendorSpec;
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					    // TODO add generic gamepad report
 | 
				
			||||||
 | 
					    uint16_t Button; // 16 buttons; see JoystickButtons_t for bit mapping
 | 
				
			||||||
 | 
					    uint8_t  HAT;    // HAT switch; one nibble w/ unused nibble
 | 
				
			||||||
 | 
					    uint8_t  LX;     // Left  Stick X
 | 
				
			||||||
 | 
					    uint8_t  LY;     // Left  Stick Y
 | 
				
			||||||
 | 
					    uint8_t  RX;     // Right Stick X
 | 
				
			||||||
 | 
					    uint8_t  RY;     // Right Stick Y
 | 
				
			||||||
 | 
					    uint8_t  VendorSpec;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					} report_gamepad_t;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* keycode to system usage */
 | 
					/* keycode to system usage */
 | 
				
			||||||
static inline uint16_t KEYCODE2SYSTEM(uint8_t key) {
 | 
					static inline uint16_t KEYCODE2SYSTEM(uint8_t key) {
 | 
				
			||||||
    switch (key) {
 | 
					    switch (key) {
 | 
				
			||||||
 | 
				
			|||||||
@ -86,10 +86,15 @@ void raw_hid_task(void);
 | 
				
			|||||||
#ifdef CONSOLE_ENABLE
 | 
					#ifdef CONSOLE_ENABLE
 | 
				
			||||||
void console_task(void);
 | 
					void console_task(void);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef MIDI_ENABLE
 | 
					#ifdef MIDI_ENABLE
 | 
				
			||||||
void midi_ep_task(void);
 | 
					void midi_ep_task(void);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef GAMEPAD_ENABLE
 | 
				
			||||||
 | 
					void gamepad_ep_task(void);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* TESTING
 | 
					/* TESTING
 | 
				
			||||||
 * Amber LED blinker thread, times are in milliseconds.
 | 
					 * Amber LED blinker thread, times are in milliseconds.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@ -258,6 +263,9 @@ int main(void) {
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
#ifdef MIDI_ENABLE
 | 
					#ifdef MIDI_ENABLE
 | 
				
			||||||
        midi_ep_task();
 | 
					        midi_ep_task();
 | 
				
			||||||
 | 
					#endif   
 | 
				
			||||||
 | 
					#ifdef GAMEPAD_ENABLE
 | 
				
			||||||
 | 
					        gamepad_ep_task();
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
#ifdef VIRTSER_ENABLE
 | 
					#ifdef VIRTSER_ENABLE
 | 
				
			||||||
        virtser_task();
 | 
					        virtser_task();
 | 
				
			||||||
 | 
				
			|||||||
@ -51,6 +51,10 @@ extern keymap_config_t keymap_config;
 | 
				
			|||||||
#    include "joystick.h"
 | 
					#    include "joystick.h"
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef GAMEPAD_ENABLE
 | 
				
			||||||
 | 
					#    include "gamepad.h"
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* ---------------------------------------------------------
 | 
					/* ---------------------------------------------------------
 | 
				
			||||||
 *       Global interface variables and declarations
 | 
					 *       Global interface variables and declarations
 | 
				
			||||||
 * ---------------------------------------------------------
 | 
					 * ---------------------------------------------------------
 | 
				
			||||||
@ -109,7 +113,7 @@ static const USBDescriptor *usb_get_descriptor_cb(USBDriver *usbp, uint8_t dtype
 | 
				
			|||||||
        return &desc;
 | 
					        return &desc;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef KEYBOARD_SHARED_EP
 | 
					#if !defined(KEYBOARD_SHARED_EP) && defined(KEYBOARD_ENABLE)
 | 
				
			||||||
/* keyboard endpoint state structure */
 | 
					/* keyboard endpoint state structure */
 | 
				
			||||||
static USBInEndpointState kbd_ep_state;
 | 
					static USBInEndpointState kbd_ep_state;
 | 
				
			||||||
/* keyboard endpoint initialization structure (IN) - see USBEndpointConfig comment at top of file */
 | 
					/* keyboard endpoint initialization structure (IN) - see USBEndpointConfig comment at top of file */
 | 
				
			||||||
@ -314,6 +318,9 @@ typedef struct {
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
#ifdef JOYSTICK_ENABLE
 | 
					#ifdef JOYSTICK_ENABLE
 | 
				
			||||||
            usb_driver_config_t joystick_driver;
 | 
					            usb_driver_config_t joystick_driver;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef GAMEPAD_ENABLE
 | 
				
			||||||
 | 
					            usb_driver_config_t gamepad_driver;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
        usb_driver_config_t array[0];
 | 
					        usb_driver_config_t array[0];
 | 
				
			||||||
@ -359,6 +366,14 @@ static usb_driver_configs_t drivers = {
 | 
				
			|||||||
#    define JOYSTICK_OUT_MODE USB_EP_MODE_TYPE_BULK
 | 
					#    define JOYSTICK_OUT_MODE USB_EP_MODE_TYPE_BULK
 | 
				
			||||||
    .joystick_driver = QMK_USB_DRIVER_CONFIG(JOYSTICK, 0, false),
 | 
					    .joystick_driver = QMK_USB_DRIVER_CONFIG(JOYSTICK, 0, false),
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef GAMEPAD_ENABLE
 | 
				
			||||||
 | 
					#    define GAMEPAD_IN_CAPACITY 4
 | 
				
			||||||
 | 
					#    define GAMEPAD_OUT_CAPACITY 4
 | 
				
			||||||
 | 
					#    define GAMEPAD_IN_MODE USB_EP_MODE_TYPE_BULK
 | 
				
			||||||
 | 
					#    define GAMEPAD_OUT_MODE USB_EP_MODE_TYPE_BULK
 | 
				
			||||||
 | 
					    .gamepad_driver = QMK_USB_DRIVER_CONFIG(GAMEPAD, 0, false),
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define NUM_USB_DRIVERS (sizeof(drivers) / sizeof(usb_driver_config_t))
 | 
					#define NUM_USB_DRIVERS (sizeof(drivers) / sizeof(usb_driver_config_t))
 | 
				
			||||||
@ -378,7 +393,7 @@ static void usb_event_cb(USBDriver *usbp, usbevent_t event) {
 | 
				
			|||||||
        case USB_EVENT_CONFIGURED:
 | 
					        case USB_EVENT_CONFIGURED:
 | 
				
			||||||
            osalSysLockFromISR();
 | 
					            osalSysLockFromISR();
 | 
				
			||||||
            /* Enable the endpoints specified into the configuration. */
 | 
					            /* Enable the endpoints specified into the configuration. */
 | 
				
			||||||
#ifndef KEYBOARD_SHARED_EP
 | 
					#if !defined(KEYBOARD_SHARED_EP) && defined(KEYBOARD_ENABLE)
 | 
				
			||||||
            usbInitEndpointI(usbp, KEYBOARD_IN_EPNUM, &kbd_ep_config);
 | 
					            usbInitEndpointI(usbp, KEYBOARD_IN_EPNUM, &kbd_ep_config);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
 | 
					#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
 | 
				
			||||||
@ -491,11 +506,12 @@ static bool usb_request_hook_cb(USBDriver *usbp) {
 | 
				
			|||||||
                switch (usbp->setup[1]) { /* bRequest */
 | 
					                switch (usbp->setup[1]) { /* bRequest */
 | 
				
			||||||
                    case HID_GET_REPORT:
 | 
					                    case HID_GET_REPORT:
 | 
				
			||||||
                        switch (usbp->setup[4]) { /* LSB(wIndex) (check MSB==0?) */
 | 
					                        switch (usbp->setup[4]) { /* LSB(wIndex) (check MSB==0?) */
 | 
				
			||||||
 | 
					#ifdef KEYBOARD_ENABLE
 | 
				
			||||||
                            case KEYBOARD_INTERFACE:
 | 
					                            case KEYBOARD_INTERFACE:
 | 
				
			||||||
                                usbSetupTransfer(usbp, (uint8_t *)&keyboard_report_sent, sizeof(keyboard_report_sent), NULL);
 | 
					                                usbSetupTransfer(usbp, (uint8_t *)&keyboard_report_sent, sizeof(keyboard_report_sent), NULL);
 | 
				
			||||||
                                return TRUE;
 | 
					                                return TRUE;
 | 
				
			||||||
                                break;
 | 
					                                break;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
 | 
					#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
 | 
				
			||||||
                            case MOUSE_INTERFACE:
 | 
					                            case MOUSE_INTERFACE:
 | 
				
			||||||
                                usbSetupTransfer(usbp, (uint8_t *)&mouse_report_blank, sizeof(mouse_report_blank), NULL);
 | 
					                                usbSetupTransfer(usbp, (uint8_t *)&mouse_report_blank, sizeof(mouse_report_blank), NULL);
 | 
				
			||||||
@ -511,7 +527,7 @@ static bool usb_request_hook_cb(USBDriver *usbp) {
 | 
				
			|||||||
                        break;
 | 
					                        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    case HID_GET_PROTOCOL:
 | 
					                    case HID_GET_PROTOCOL:
 | 
				
			||||||
                        if ((usbp->setup[4] == KEYBOARD_INTERFACE) && (usbp->setup[5] == 0)) { /* wIndex */
 | 
					                        if ((usbp->setup[4] == 0) && (usbp->setup[5] == 0)) { /* wIndex */
 | 
				
			||||||
                            usbSetupTransfer(usbp, &keyboard_protocol, 1, NULL);
 | 
					                            usbSetupTransfer(usbp, &keyboard_protocol, 1, NULL);
 | 
				
			||||||
                            return TRUE;
 | 
					                            return TRUE;
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
@ -528,7 +544,9 @@ static bool usb_request_hook_cb(USBDriver *usbp) {
 | 
				
			|||||||
                switch (usbp->setup[1]) { /* bRequest */
 | 
					                switch (usbp->setup[1]) { /* bRequest */
 | 
				
			||||||
                    case HID_SET_REPORT:
 | 
					                    case HID_SET_REPORT:
 | 
				
			||||||
                        switch (usbp->setup[4]) { /* LSB(wIndex) (check MSB==0?) */
 | 
					                        switch (usbp->setup[4]) { /* LSB(wIndex) (check MSB==0?) */
 | 
				
			||||||
 | 
					#ifdef KEYBOARD_ENABLE
 | 
				
			||||||
                            case KEYBOARD_INTERFACE:
 | 
					                            case KEYBOARD_INTERFACE:
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
#if defined(SHARED_EP_ENABLE) && !defined(KEYBOARD_SHARED_EP)
 | 
					#if defined(SHARED_EP_ENABLE) && !defined(KEYBOARD_SHARED_EP)
 | 
				
			||||||
                            case SHARED_INTERFACE:
 | 
					                            case SHARED_INTERFACE:
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
@ -539,7 +557,7 @@ static bool usb_request_hook_cb(USBDriver *usbp) {
 | 
				
			|||||||
                        break;
 | 
					                        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    case HID_SET_PROTOCOL:
 | 
					                    case HID_SET_PROTOCOL:
 | 
				
			||||||
                        if ((usbp->setup[4] == KEYBOARD_INTERFACE) && (usbp->setup[5] == 0)) { /* wIndex */
 | 
					                        if ((usbp->setup[4] == 0) && (usbp->setup[5] == 0)) { /* wIndex */
 | 
				
			||||||
                            keyboard_protocol = ((usbp->setup[2]) != 0x00);                    /* LSB(wValue) */
 | 
					                            keyboard_protocol = ((usbp->setup[2]) != 0x00);                    /* LSB(wValue) */
 | 
				
			||||||
#ifdef NKRO_ENABLE
 | 
					#ifdef NKRO_ENABLE
 | 
				
			||||||
                            keymap_config.nkro = !!keyboard_protocol;
 | 
					                            keymap_config.nkro = !!keyboard_protocol;
 | 
				
			||||||
@ -660,7 +678,7 @@ void restart_usb_driver(USBDriver *usbp) {
 | 
				
			|||||||
 * ---------------------------------------------------------
 | 
					 * ---------------------------------------------------------
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
/* keyboard IN callback hander (a kbd report has made it IN) */
 | 
					/* keyboard IN callback hander (a kbd report has made it IN) */
 | 
				
			||||||
#ifndef KEYBOARD_SHARED_EP
 | 
					#if !defined(KEYBOARD_SHARED_EP) && defined(KEYBOARD_ENABLE)
 | 
				
			||||||
void kbd_in_cb(USBDriver *usbp, usbep_t ep) {
 | 
					void kbd_in_cb(USBDriver *usbp, usbep_t ep) {
 | 
				
			||||||
    /* STUB */
 | 
					    /* STUB */
 | 
				
			||||||
    (void)usbp;
 | 
					    (void)usbp;
 | 
				
			||||||
@ -693,9 +711,11 @@ static void keyboard_idle_timer_cb(void *arg) {
 | 
				
			|||||||
    if (keyboard_idle && keyboard_protocol) {
 | 
					    if (keyboard_idle && keyboard_protocol) {
 | 
				
			||||||
#endif /* NKRO_ENABLE */
 | 
					#endif /* NKRO_ENABLE */
 | 
				
			||||||
        /* TODO: are we sure we want the KBD_ENDPOINT? */
 | 
					        /* TODO: are we sure we want the KBD_ENDPOINT? */
 | 
				
			||||||
 | 
					#ifdef KEYBOARD_ENABLE
 | 
				
			||||||
        if (!usbGetTransmitStatusI(usbp, KEYBOARD_IN_EPNUM)) {
 | 
					        if (!usbGetTransmitStatusI(usbp, KEYBOARD_IN_EPNUM)) {
 | 
				
			||||||
            usbStartTransmitI(usbp, KEYBOARD_IN_EPNUM, (uint8_t *)&keyboard_report_sent, KEYBOARD_EPSIZE);
 | 
					            usbStartTransmitI(usbp, KEYBOARD_IN_EPNUM, (uint8_t *)&keyboard_report_sent, KEYBOARD_EPSIZE);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
        /* rearm the timer */
 | 
					        /* rearm the timer */
 | 
				
			||||||
        chVTSetI(&keyboard_idle_timer, 4 * TIME_MS2I(keyboard_idle), keyboard_idle_timer_cb, (void *)usbp);
 | 
					        chVTSetI(&keyboard_idle_timer, 4 * TIME_MS2I(keyboard_idle), keyboard_idle_timer_cb, (void *)usbp);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -711,6 +731,7 @@ uint8_t keyboard_leds(void) { return keyboard_led_state; }
 | 
				
			|||||||
/* prepare and start sending a report IN
 | 
					/* prepare and start sending a report IN
 | 
				
			||||||
 * not callable from ISR or locked state */
 | 
					 * not callable from ISR or locked state */
 | 
				
			||||||
void send_keyboard(report_keyboard_t *report) {
 | 
					void send_keyboard(report_keyboard_t *report) {
 | 
				
			||||||
 | 
					#ifdef KEYBOARD_ENABLE
 | 
				
			||||||
    osalSysLock();
 | 
					    osalSysLock();
 | 
				
			||||||
    if (usbGetDriverStateI(&USB_DRIVER) != USB_ACTIVE) {
 | 
					    if (usbGetDriverStateI(&USB_DRIVER) != USB_ACTIVE) {
 | 
				
			||||||
        goto unlock;
 | 
					        goto unlock;
 | 
				
			||||||
@ -767,6 +788,7 @@ void send_keyboard(report_keyboard_t *report) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
unlock:
 | 
					unlock:
 | 
				
			||||||
    osalSysUnlock();
 | 
					    osalSysUnlock();
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* ---------------------------------------------------------
 | 
					/* ---------------------------------------------------------
 | 
				
			||||||
@ -1021,3 +1043,35 @@ void send_joystick_packet(joystick_t *joystick) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef GAMEPAD_ENABLE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void send_gamepad(report_gamepad_t *report) {
 | 
				
			||||||
 | 
					    osalSysLock();
 | 
				
			||||||
 | 
					    if (usbGetDriverStateI(&USB_DRIVER) != USB_ACTIVE) {
 | 
				
			||||||
 | 
					        osalSysUnlock();
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    usbStartTransmitI(&USB_DRIVER, GAMEPAD_IN_EPNUM, (uint8_t *)report, sizeof(report_gamepad_t));
 | 
				
			||||||
 | 
					    osalSysUnlock();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool recv_gamepad_packet(report_gamepad_t *const report) {
 | 
				
			||||||
 | 
					    size_t size = chnReadTimeout(&drivers.gamepad_driver.driver, (uint8_t *)report, sizeof(report_gamepad_t), TIME_IMMEDIATE);
 | 
				
			||||||
 | 
					    return size == sizeof(report_gamepad_t);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void gamepad_ep_task(void) {
 | 
				
			||||||
 | 
					    uint8_t buffer[GAMEPAD_EPSIZE];
 | 
				
			||||||
 | 
					    size_t  size = 0;
 | 
				
			||||||
 | 
					    do {
 | 
				
			||||||
 | 
					        size_t size = chnReadTimeout(&drivers.gamepad_driver.driver, buffer, sizeof(buffer), TIME_IMMEDIATE);
 | 
				
			||||||
 | 
					        if (size > 0) {
 | 
				
			||||||
 | 
					            report_gamepad_t report;
 | 
				
			||||||
 | 
					            recv_gamepad_packet(&report);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    } while (size > 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -524,6 +524,9 @@ void EVENT_USB_Device_ConfigurationChanged(void) {
 | 
				
			|||||||
    /* Setup joystick endpoint */
 | 
					    /* Setup joystick endpoint */
 | 
				
			||||||
    ConfigSuccess &= Endpoint_ConfigureEndpoint((JOYSTICK_IN_EPNUM | ENDPOINT_DIR_IN), EP_TYPE_INTERRUPT, JOYSTICK_EPSIZE, 1);
 | 
					    ConfigSuccess &= Endpoint_ConfigureEndpoint((JOYSTICK_IN_EPNUM | ENDPOINT_DIR_IN), EP_TYPE_INTERRUPT, JOYSTICK_EPSIZE, 1);
 | 
				
			||||||
#endif
 | 
					#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
 | 
					/* FIXME: Expose this table in the docs somehow
 | 
				
			||||||
 | 
				
			|||||||
@ -50,6 +50,7 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * HID report descriptors
 | 
					 * HID report descriptors
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					#ifdef KEYBOARD_ENABLE
 | 
				
			||||||
#ifdef KEYBOARD_SHARED_EP
 | 
					#ifdef KEYBOARD_SHARED_EP
 | 
				
			||||||
const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = {
 | 
					const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = {
 | 
				
			||||||
#    define SHARED_REPORT_STARTED
 | 
					#    define SHARED_REPORT_STARTED
 | 
				
			||||||
@ -100,6 +101,7 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM KeyboardReport[] = {
 | 
				
			|||||||
#ifndef KEYBOARD_SHARED_EP
 | 
					#ifndef KEYBOARD_SHARED_EP
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef MOUSE_ENABLE
 | 
					#ifdef MOUSE_ENABLE
 | 
				
			||||||
#    ifndef MOUSE_SHARED_EP
 | 
					#    ifndef MOUSE_SHARED_EP
 | 
				
			||||||
@ -347,6 +349,64 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM JoystickReport[] = {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef GAMEPAD_ENABLE
 | 
				
			||||||
 | 
					const USB_Descriptor_HIDReport_Datatype_t PROGMEM GamepadReport[] = {
 | 
				
			||||||
 | 
					    HID_RI_USAGE_PAGE(8,1), /* Generic Desktop */
 | 
				
			||||||
 | 
					    HID_RI_USAGE(8,5), /* Joystick */
 | 
				
			||||||
 | 
					    HID_RI_COLLECTION(8,1), /* Application */
 | 
				
			||||||
 | 
					        // Buttons (2 bytes)
 | 
				
			||||||
 | 
					        HID_RI_LOGICAL_MINIMUM(8,0),
 | 
				
			||||||
 | 
					        HID_RI_LOGICAL_MAXIMUM(8,1),
 | 
				
			||||||
 | 
					        HID_RI_PHYSICAL_MINIMUM(8,0),
 | 
				
			||||||
 | 
					        HID_RI_PHYSICAL_MAXIMUM(8,1),
 | 
				
			||||||
 | 
					        // The Switch will allow us to expand the original HORI descriptors to a full 16 buttons.
 | 
				
			||||||
 | 
					        // The Switch will make use of 14 of those buttons.
 | 
				
			||||||
 | 
					        HID_RI_REPORT_SIZE(8,1),
 | 
				
			||||||
 | 
					        HID_RI_REPORT_COUNT(8,16),
 | 
				
			||||||
 | 
					        HID_RI_USAGE_PAGE(8,9),
 | 
				
			||||||
 | 
					        HID_RI_USAGE_MINIMUM(8,1),
 | 
				
			||||||
 | 
					        HID_RI_USAGE_MAXIMUM(8,16),
 | 
				
			||||||
 | 
					        HID_RI_INPUT(8,2),
 | 
				
			||||||
 | 
					        // HAT Switch (1 nibble)
 | 
				
			||||||
 | 
					        HID_RI_USAGE_PAGE(8,1),
 | 
				
			||||||
 | 
					        HID_RI_LOGICAL_MAXIMUM(8,7),
 | 
				
			||||||
 | 
					        HID_RI_PHYSICAL_MAXIMUM(16,315),
 | 
				
			||||||
 | 
					        HID_RI_REPORT_SIZE(8,4),
 | 
				
			||||||
 | 
					        HID_RI_REPORT_COUNT(8,1),
 | 
				
			||||||
 | 
					        HID_RI_UNIT(8,20),
 | 
				
			||||||
 | 
					        HID_RI_USAGE(8,57),
 | 
				
			||||||
 | 
					        HID_RI_INPUT(8,66),
 | 
				
			||||||
 | 
					        // There's an additional nibble here that's utilized as part of the Switch Pro Controller.
 | 
				
			||||||
 | 
					        // I believe this -might- be separate U/D/L/R bits on the Switch Pro Controller, as they're utilized as four button descriptors on the Switch Pro Controller.
 | 
				
			||||||
 | 
					        HID_RI_UNIT(8,0),
 | 
				
			||||||
 | 
					        HID_RI_REPORT_COUNT(8,1),
 | 
				
			||||||
 | 
					        HID_RI_INPUT(8,1),
 | 
				
			||||||
 | 
					        // Joystick (4 bytes)
 | 
				
			||||||
 | 
					        HID_RI_LOGICAL_MAXIMUM(16,255),
 | 
				
			||||||
 | 
					        HID_RI_PHYSICAL_MAXIMUM(16,255),
 | 
				
			||||||
 | 
					        HID_RI_USAGE(8,48),
 | 
				
			||||||
 | 
					        HID_RI_USAGE(8,49),
 | 
				
			||||||
 | 
					        HID_RI_USAGE(8,50),
 | 
				
			||||||
 | 
					        HID_RI_USAGE(8,53),
 | 
				
			||||||
 | 
					        HID_RI_REPORT_SIZE(8,8),
 | 
				
			||||||
 | 
					        HID_RI_REPORT_COUNT(8,4),
 | 
				
			||||||
 | 
					        HID_RI_INPUT(8,2),
 | 
				
			||||||
 | 
					        // ??? Vendor Specific (1 byte)
 | 
				
			||||||
 | 
					        // This byte requires additional investigation.
 | 
				
			||||||
 | 
					        HID_RI_USAGE_PAGE(16,65280),
 | 
				
			||||||
 | 
					        HID_RI_USAGE(8,32),
 | 
				
			||||||
 | 
					        HID_RI_REPORT_COUNT(8,1),
 | 
				
			||||||
 | 
					        HID_RI_INPUT(8,2),
 | 
				
			||||||
 | 
					        // Output (8 bytes)
 | 
				
			||||||
 | 
					        // Original observation of this suggests it to be a mirror of the inputs that we sent.
 | 
				
			||||||
 | 
					        // The Switch requires us to have these descriptors available.
 | 
				
			||||||
 | 
					        HID_RI_USAGE(16,9761),
 | 
				
			||||||
 | 
					        HID_RI_REPORT_COUNT(8,8),
 | 
				
			||||||
 | 
					        HID_RI_OUTPUT(8,2),
 | 
				
			||||||
 | 
					    HID_RI_END_COLLECTION(0),
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Device descriptor
 | 
					 * Device descriptor
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@ -406,7 +466,7 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor = {
 | 
				
			|||||||
        .ConfigAttributes       = (USB_CONFIG_ATTR_RESERVED | USB_CONFIG_ATTR_REMOTEWAKEUP),
 | 
					        .ConfigAttributes       = (USB_CONFIG_ATTR_RESERVED | USB_CONFIG_ATTR_REMOTEWAKEUP),
 | 
				
			||||||
        .MaxPowerConsumption    = USB_CONFIG_POWER_MA(USB_MAX_POWER_CONSUMPTION)
 | 
					        .MaxPowerConsumption    = USB_CONFIG_POWER_MA(USB_MAX_POWER_CONSUMPTION)
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
#ifndef KEYBOARD_SHARED_EP
 | 
					#if !defined(KEYBOARD_SHARED_EP) && defined(KEYBOARD_ENABLE)
 | 
				
			||||||
    /*
 | 
					    /*
 | 
				
			||||||
     * Keyboard
 | 
					     * Keyboard
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
@ -925,6 +985,56 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor = {
 | 
				
			|||||||
        .PollingIntervalMS      = USB_POLLING_INTERVAL_MS
 | 
					        .PollingIntervalMS      = USB_POLLING_INTERVAL_MS
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef GAMEPAD_ENABLE
 | 
				
			||||||
 | 
					    /*
 | 
				
			||||||
 | 
					     * Gamepad
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    .Gamepad_Interface = {
 | 
				
			||||||
 | 
					        .Header = {
 | 
				
			||||||
 | 
					            .Size               = sizeof(USB_Descriptor_Interface_t),
 | 
				
			||||||
 | 
					            .Type               = DTYPE_Interface
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        .InterfaceNumber        = GAMEPAD_INTERFACE,
 | 
				
			||||||
 | 
					        .AlternateSetting       = 0x00,
 | 
				
			||||||
 | 
					        .TotalEndpoints         = 2,
 | 
				
			||||||
 | 
					        .Class                  = HID_CSCP_HIDClass,
 | 
				
			||||||
 | 
					        .SubClass               = HID_CSCP_NonBootSubclass,
 | 
				
			||||||
 | 
					        .Protocol               = HID_CSCP_NonBootProtocol,
 | 
				
			||||||
 | 
					        .InterfaceStrIndex      = NO_DESCRIPTOR
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    .Gamepad_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(GamepadReport)
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    .Gamepad_INEndpoint = {
 | 
				
			||||||
 | 
					        .Header = {
 | 
				
			||||||
 | 
					            .Size               = sizeof(USB_Descriptor_Endpoint_t),
 | 
				
			||||||
 | 
					            .Type               = DTYPE_Endpoint
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        .EndpointAddress        = (ENDPOINT_DIR_IN | GAMEPAD_IN_EPNUM),
 | 
				
			||||||
 | 
					        .Attributes             = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
 | 
				
			||||||
 | 
					        .EndpointSize           = GAMEPAD_EPSIZE,
 | 
				
			||||||
 | 
					        .PollingIntervalMS      = USB_POLLING_INTERVAL_MS
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    .Gamepad_OUTEndpoint = {
 | 
				
			||||||
 | 
					        .Header = {
 | 
				
			||||||
 | 
					            .Size               = sizeof(USB_Descriptor_Endpoint_t),
 | 
				
			||||||
 | 
					            .Type               = DTYPE_Endpoint
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        .EndpointAddress        = (ENDPOINT_DIR_OUT | GAMEPAD_OUT_EPNUM),
 | 
				
			||||||
 | 
					        .Attributes             = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
 | 
				
			||||||
 | 
					        .EndpointSize           = GAMEPAD_EPSIZE,
 | 
				
			||||||
 | 
					        .PollingIntervalMS      = USB_POLLING_INTERVAL_MS
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
@ -1019,7 +1129,7 @@ uint16_t get_usb_descriptor(const uint16_t wValue, const uint16_t wIndex, const
 | 
				
			|||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case HID_DTYPE_HID:
 | 
					        case HID_DTYPE_HID:
 | 
				
			||||||
            switch (wIndex) {
 | 
					            switch (wIndex) {
 | 
				
			||||||
#ifndef KEYBOARD_SHARED_EP
 | 
					#if !defined(KEYBOARD_SHARED_EP) && defined(KEYBOARD_ENABLE)
 | 
				
			||||||
                case KEYBOARD_INTERFACE:
 | 
					                case KEYBOARD_INTERFACE:
 | 
				
			||||||
                    Address = &ConfigurationDescriptor.Keyboard_HID;
 | 
					                    Address = &ConfigurationDescriptor.Keyboard_HID;
 | 
				
			||||||
                    Size    = sizeof(USB_HID_Descriptor_HID_t);
 | 
					                    Size    = sizeof(USB_HID_Descriptor_HID_t);
 | 
				
			||||||
@ -1062,13 +1172,19 @@ uint16_t get_usb_descriptor(const uint16_t wValue, const uint16_t wIndex, const
 | 
				
			|||||||
                    Address = &ConfigurationDescriptor.Joystick_HID;
 | 
					                    Address = &ConfigurationDescriptor.Joystick_HID;
 | 
				
			||||||
                    Size    = sizeof(USB_HID_Descriptor_HID_t);
 | 
					                    Size    = sizeof(USB_HID_Descriptor_HID_t);
 | 
				
			||||||
                    break;
 | 
					                    break;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef GAMEPAD_ENABLE
 | 
				
			||||||
 | 
					                case GAMEPAD_INTERFACE:
 | 
				
			||||||
 | 
					                    Address = &ConfigurationDescriptor.Gamepad_HID;
 | 
				
			||||||
 | 
					                    Size    = sizeof(USB_HID_Descriptor_HID_t);
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case HID_DTYPE_Report:
 | 
					        case HID_DTYPE_Report:
 | 
				
			||||||
            switch (wIndex) {
 | 
					            switch (wIndex) {
 | 
				
			||||||
#ifndef KEYBOARD_SHARED_EP
 | 
					#if !defined(KEYBOARD_SHARED_EP) && defined(KEYBOARD_ENABLE)
 | 
				
			||||||
                case KEYBOARD_INTERFACE:
 | 
					                case KEYBOARD_INTERFACE:
 | 
				
			||||||
                    Address = &KeyboardReport;
 | 
					                    Address = &KeyboardReport;
 | 
				
			||||||
                    Size    = sizeof(KeyboardReport);
 | 
					                    Size    = sizeof(KeyboardReport);
 | 
				
			||||||
@ -1112,6 +1228,12 @@ uint16_t get_usb_descriptor(const uint16_t wValue, const uint16_t wIndex, const
 | 
				
			|||||||
                    Address = &JoystickReport;
 | 
					                    Address = &JoystickReport;
 | 
				
			||||||
                    Size    = sizeof(JoystickReport);
 | 
					                    Size    = sizeof(JoystickReport);
 | 
				
			||||||
                    break;
 | 
					                    break;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef GAMEPAD_ENABLE
 | 
				
			||||||
 | 
					                case GAMEPAD_INTERFACE:
 | 
				
			||||||
 | 
					                    Address = &GamepadReport;
 | 
				
			||||||
 | 
					                    Size    = sizeof(GamepadReport);
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -55,7 +55,7 @@
 | 
				
			|||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
    USB_Descriptor_Configuration_Header_t Config;
 | 
					    USB_Descriptor_Configuration_Header_t Config;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef KEYBOARD_SHARED_EP
 | 
					#if !defined(KEYBOARD_SHARED_EP) && defined(KEYBOARD_ENABLE)
 | 
				
			||||||
    // Keyboard HID Interface
 | 
					    // Keyboard HID Interface
 | 
				
			||||||
    USB_Descriptor_Interface_t Keyboard_Interface;
 | 
					    USB_Descriptor_Interface_t Keyboard_Interface;
 | 
				
			||||||
    USB_HID_Descriptor_HID_t   Keyboard_HID;
 | 
					    USB_HID_Descriptor_HID_t   Keyboard_HID;
 | 
				
			||||||
@ -134,14 +134,26 @@ typedef struct {
 | 
				
			|||||||
    USB_Descriptor_Interface_t Joystick_Interface;
 | 
					    USB_Descriptor_Interface_t Joystick_Interface;
 | 
				
			||||||
    USB_HID_Descriptor_HID_t   Joystick_HID;
 | 
					    USB_HID_Descriptor_HID_t   Joystick_HID;
 | 
				
			||||||
    USB_Descriptor_Endpoint_t  Joystick_INEndpoint;
 | 
					    USB_Descriptor_Endpoint_t  Joystick_INEndpoint;
 | 
				
			||||||
 | 
					    #ifdef SWITCH_CONTROLLER_ENABLE
 | 
				
			||||||
 | 
					    USB_Descriptor_Endpoint_t  Joystick_OUTEndpoint;
 | 
				
			||||||
 | 
					    #endif
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef GAMEPAD_ENABLE
 | 
				
			||||||
 | 
					    // Gamepad HID Interface
 | 
				
			||||||
 | 
					    USB_Descriptor_Interface_t Gamepad_Interface;
 | 
				
			||||||
 | 
					    USB_HID_Descriptor_HID_t   Gamepad_HID;
 | 
				
			||||||
 | 
					    USB_Descriptor_Endpoint_t  Gamepad_INEndpoint;
 | 
				
			||||||
 | 
					    USB_Descriptor_Endpoint_t  Gamepad_OUTEndpoint;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} USB_Descriptor_Configuration_t;
 | 
					} USB_Descriptor_Configuration_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Interface indexes
 | 
					 * Interface indexes
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
enum usb_interfaces {
 | 
					enum usb_interfaces {
 | 
				
			||||||
#ifndef KEYBOARD_SHARED_EP
 | 
					#if !defined(KEYBOARD_SHARED_EP) && defined(KEYBOARD_ENABLE)
 | 
				
			||||||
    KEYBOARD_INTERFACE,
 | 
					    KEYBOARD_INTERFACE,
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
    SHARED_INTERFACE,
 | 
					    SHARED_INTERFACE,
 | 
				
			||||||
@ -177,9 +189,13 @@ enum usb_interfaces {
 | 
				
			|||||||
    CDI_INTERFACE,
 | 
					    CDI_INTERFACE,
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if defined(JOYSTICK_ENABLE)
 | 
					#ifdef JOYSTICK_ENABLE
 | 
				
			||||||
    JOYSTICK_INTERFACE,
 | 
					    JOYSTICK_INTERFACE,
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef GAMEPAD_ENABLE
 | 
				
			||||||
 | 
					    GAMEPAD_INTERFACE,
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
    TOTAL_INTERFACES
 | 
					    TOTAL_INTERFACES
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -191,9 +207,10 @@ enum usb_interfaces {
 | 
				
			|||||||
enum usb_endpoints {
 | 
					enum usb_endpoints {
 | 
				
			||||||
    __unused_epnum__ = NEXT_EPNUM,  // Endpoint numbering starts at 1
 | 
					    __unused_epnum__ = NEXT_EPNUM,  // Endpoint numbering starts at 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef KEYBOARD_SHARED_EP
 | 
					#if !defined(KEYBOARD_SHARED_EP) && defined(KEYBOARD_ENABLE)
 | 
				
			||||||
    KEYBOARD_IN_EPNUM = NEXT_EPNUM,
 | 
					    KEYBOARD_IN_EPNUM = NEXT_EPNUM,
 | 
				
			||||||
#else
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef KEYBOARD_SHARED_EP
 | 
				
			||||||
#    define KEYBOARD_IN_EPNUM SHARED_IN_EPNUM
 | 
					#    define KEYBOARD_IN_EPNUM SHARED_IN_EPNUM
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -259,6 +276,16 @@ enum usb_endpoints {
 | 
				
			|||||||
    JOYSTICK_OUT_EPNUM    = NEXT_EPNUM,
 | 
					    JOYSTICK_OUT_EPNUM    = NEXT_EPNUM,
 | 
				
			||||||
#    endif
 | 
					#    endif
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					#ifdef JOYSTICK_ENABLE
 | 
				
			||||||
 | 
					    JOYSTICK_IN_EPNUM  = NEXT_EPNUM,
 | 
				
			||||||
 | 
					    JOYSTICK_OUT_EPNUM = NEXT_EPNUM,
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef GAMEPAD_ENABLE
 | 
				
			||||||
 | 
					    GAMEPAD_IN_EPNUM  = NEXT_EPNUM,
 | 
				
			||||||
 | 
					    GAMEPAD_OUT_EPNUM = NEXT_EPNUM,
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef PROTOCOL_LUFA
 | 
					#ifdef PROTOCOL_LUFA
 | 
				
			||||||
@ -283,6 +310,7 @@ enum usb_endpoints {
 | 
				
			|||||||
#define MIDI_STREAM_EPSIZE 64
 | 
					#define MIDI_STREAM_EPSIZE 64
 | 
				
			||||||
#define CDC_NOTIFICATION_EPSIZE 8
 | 
					#define CDC_NOTIFICATION_EPSIZE 8
 | 
				
			||||||
#define CDC_EPSIZE 16
 | 
					#define CDC_EPSIZE 16
 | 
				
			||||||
 | 
					#define GAMEPAD_EPSIZE 64
 | 
				
			||||||
#define JOYSTICK_EPSIZE 8
 | 
					#define JOYSTICK_EPSIZE 8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
uint16_t get_usb_descriptor(const uint16_t wValue, const uint16_t wIndex, const void** const DescriptorAddress);
 | 
					uint16_t get_usb_descriptor(const uint16_t wValue, const uint16_t wIndex, const void** const DescriptorAddress);
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user