mirror of
				https://github.com/mfulz/qmk_firmware.git
				synced 2025-10-31 13:22:31 +01:00 
			
		
		
		
	separated into api files/folder
This commit is contained in:
		
							parent
							
								
									f25596b8dc
								
							
						
					
					
						commit
						7edac212c8
					
				| @ -131,6 +131,14 @@ ifndef CUSTOM_MATRIX | |||||||
| 	SRC += $(QUANTUM_DIR)/matrix.c | 	SRC += $(QUANTUM_DIR)/matrix.c | ||||||
| endif | endif | ||||||
| 
 | 
 | ||||||
|  | ifeq ($(strip $(API_SYSEX_ENABLE)), yes) | ||||||
|  | 	OPT_DEFS += -DAPI_SYSEX_ENABLE | ||||||
|  | 	SRC += $(QUANTUM_DIR)/api/api_sysex.c | ||||||
|  | 	OPT_DEFS += -DAPI_ENABLE | ||||||
|  | 	SRC += $(QUANTUM_DIR)/api.c | ||||||
|  |     MIDI_ENABLE=yes | ||||||
|  | endif | ||||||
|  | 
 | ||||||
| ifeq ($(strip $(MIDI_ENABLE)), yes) | ifeq ($(strip $(MIDI_ENABLE)), yes) | ||||||
|     OPT_DEFS += -DMIDI_ENABLE |     OPT_DEFS += -DMIDI_ENABLE | ||||||
| 	SRC += $(QUANTUM_DIR)/process_keycode/process_midi.c | 	SRC += $(QUANTUM_DIR)/process_keycode/process_midi.c | ||||||
|  | |||||||
| @ -23,4 +23,5 @@ COMMON_VPATH += $(QUANTUM_PATH) | |||||||
| COMMON_VPATH += $(QUANTUM_PATH)/keymap_extras | COMMON_VPATH += $(QUANTUM_PATH)/keymap_extras | ||||||
| COMMON_VPATH += $(QUANTUM_PATH)/audio | COMMON_VPATH += $(QUANTUM_PATH)/audio | ||||||
| COMMON_VPATH += $(QUANTUM_PATH)/process_keycode | COMMON_VPATH += $(QUANTUM_PATH)/process_keycode | ||||||
|  | COMMON_VPATH += $(QUANTUM_PATH)/api | ||||||
| COMMON_VPATH += $(SERIAL_PATH) | COMMON_VPATH += $(SERIAL_PATH) | ||||||
| @ -91,7 +91,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) | |||||||
|         break; |         break; | ||||||
|         case 2: |         case 2: | ||||||
|         if (record->event.pressed) { // For resetting EEPROM
 |         if (record->event.pressed) { // For resetting EEPROM
 | ||||||
|           send_unicode_midi(0x0CA0); |           api_send_unicode(0x0CA0); | ||||||
|         } |         } | ||||||
|         break; |         break; | ||||||
|       } |       } | ||||||
|  | |||||||
| @ -24,6 +24,5 @@ COMMAND_ENABLE   ?= yes # Commands for debug and configuration | |||||||
| CUSTOM_MATRIX    ?= yes # Custom matrix file for the ErgoDox EZ | CUSTOM_MATRIX    ?= yes # Custom matrix file for the ErgoDox EZ | ||||||
| SLEEP_LED_ENABLE ?= yes # Breathing sleep LED during USB suspend | SLEEP_LED_ENABLE ?= yes # Breathing sleep LED during USB suspend | ||||||
| NKRO_ENABLE      ?= yes # USB Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work | NKRO_ENABLE      ?= yes # USB Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work | ||||||
| MIDI_ENABLE      ?= no  # MIDI controls |  | ||||||
| UNICODE_ENABLE   ?= yes # Unicode | UNICODE_ENABLE   ?= yes # Unicode | ||||||
| ONEHAND_ENABLE   ?= yes # Allow swapping hands of keyboard | ONEHAND_ENABLE   ?= yes # Allow swapping hands of keyboard | ||||||
|  | |||||||
| @ -62,6 +62,7 @@ AUDIO_ENABLE ?= no           # Audio output on port C6 | |||||||
| UNICODE_ENABLE ?= no         # Unicode | UNICODE_ENABLE ?= no         # Unicode | ||||||
| BLUETOOTH_ENABLE ?= no       # Enable Bluetooth with the Adafruit EZ-Key HID | BLUETOOTH_ENABLE ?= no       # Enable Bluetooth with the Adafruit EZ-Key HID | ||||||
| RGBLIGHT_ENABLE ?= no        # Enable WS2812 RGB underlight.  Do not enable this with audio at the same time. | RGBLIGHT_ENABLE ?= no        # Enable WS2812 RGB underlight.  Do not enable this with audio at the same time. | ||||||
|  | API_SYSEX_ENABLE = yes | ||||||
| 
 | 
 | ||||||
| # Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
 | # Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
 | ||||||
| SLEEP_LED_ENABLE ?= no    # Breathing sleep LED during USB suspend | SLEEP_LED_ENABLE ?= no    # Breathing sleep LED during USB suspend | ||||||
| @ -1,25 +1,3 @@ | |||||||
| 
 |  | ||||||
| 
 |  | ||||||
| # Build Options
 |  | ||||||
| #   change to "no" to disable the options, or define them in the Makefile in 
 |  | ||||||
| #   the appropriate keymap folder that will get included automatically
 |  | ||||||
| #
 |  | ||||||
| BOOTMAGIC_ENABLE = no       # Virtual DIP switch configuration(+1000) |  | ||||||
| MOUSEKEY_ENABLE = yes       # Mouse keys(+4700) |  | ||||||
| EXTRAKEY_ENABLE = yes       # Audio control and System control(+450) |  | ||||||
| CONSOLE_ENABLE = no         # Console for debug(+400) |  | ||||||
| COMMAND_ENABLE = yes        # Commands for debug and configuration |  | ||||||
| NKRO_ENABLE = yes            # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work |  | ||||||
| BACKLIGHT_ENABLE = yes      # Enable keyboard backlight functionality |  | ||||||
| MIDI_ENABLE = no            # MIDI controls |  | ||||||
| AUDIO_ENABLE = yes           # Audio output on port C6 |  | ||||||
| UNICODE_ENABLE = no         # Unicode |  | ||||||
| BLUETOOTH_ENABLE = no       # Enable Bluetooth with the Adafruit EZ-Key HID |  | ||||||
| RGBLIGHT_ENABLE = no        # Enable WS2812 RGB underlight.  Do not enable this with audio at the same time. |  | ||||||
| 
 |  | ||||||
| # Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
 |  | ||||||
| SLEEP_LED_ENABLE = no    # Breathing sleep LED during USB suspend |  | ||||||
| 
 |  | ||||||
| ifndef QUANTUM_DIR | ifndef QUANTUM_DIR | ||||||
| 	include ../../../../Makefile | 	include ../../../../Makefile | ||||||
| endif | endif | ||||||
| @ -53,7 +53,7 @@ OPT_DEFS += -DBOOTLOADER_SIZE=4096 | |||||||
| #   the appropriate keymap folder that will get included automatically
 | #   the appropriate keymap folder that will get included automatically
 | ||||||
| #
 | #
 | ||||||
| BOOTMAGIC_ENABLE ?= no       # Virtual DIP switch configuration(+1000) | BOOTMAGIC_ENABLE ?= no       # Virtual DIP switch configuration(+1000) | ||||||
| MOUSEKEY_ENABLE ?= yes       # Mouse keys(+4700) | MOUSEKEY_ENABLE ?= no       # Mouse keys(+4700) | ||||||
| EXTRAKEY_ENABLE ?= yes       # Audio control and System control(+450) | EXTRAKEY_ENABLE ?= yes       # Audio control and System control(+450) | ||||||
| CONSOLE_ENABLE ?= no         # Console for debug(+400) | CONSOLE_ENABLE ?= no         # Console for debug(+400) | ||||||
| COMMAND_ENABLE ?= yes        # Commands for debug and configuration | COMMAND_ENABLE ?= yes        # Commands for debug and configuration | ||||||
| @ -64,6 +64,7 @@ AUDIO_ENABLE ?= no           # Audio output on port C6 | |||||||
| UNICODE_ENABLE ?= no         # Unicode | UNICODE_ENABLE ?= no         # Unicode | ||||||
| BLUETOOTH_ENABLE ?= no       # Enable Bluetooth with the Adafruit EZ-Key HID | BLUETOOTH_ENABLE ?= no       # Enable Bluetooth with the Adafruit EZ-Key HID | ||||||
| RGBLIGHT_ENABLE ?= no        # Enable WS2812 RGB underlight.  Do not enable this with audio at the same time. | RGBLIGHT_ENABLE ?= no        # Enable WS2812 RGB underlight.  Do not enable this with audio at the same time. | ||||||
|  | API_SYSEX_ENABLE ?= yes | ||||||
| 
 | 
 | ||||||
| # Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
 | # Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
 | ||||||
| SLEEP_LED_ENABLE ?= no    # Breathing sleep LED during USB suspend | SLEEP_LED_ENABLE ?= no    # Breathing sleep LED during USB suspend | ||||||
							
								
								
									
										178
									
								
								quantum/api.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										178
									
								
								quantum/api.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,178 @@ | |||||||
|  | #include "api.h" | ||||||
|  | #include "quantum.h" | ||||||
|  | 
 | ||||||
|  | void dword_to_bytes(uint32_t dword, uint8_t * bytes) { | ||||||
|  |     bytes[0] = (dword >> 24) & 0xFF; | ||||||
|  |     bytes[1] = (dword >> 16) & 0xFF;  | ||||||
|  |     bytes[2] = (dword >> 8) & 0xFF;  | ||||||
|  |     bytes[3] = (dword >> 0) & 0xFF;  | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | uint32_t bytes_to_dword(uint8_t * bytes, uint8_t index) { | ||||||
|  |     return ((uint32_t)bytes[index + 0] << 24) | ((uint32_t)bytes[index + 1] << 16) | ((uint32_t)bytes[index + 2] << 8) | (uint32_t)bytes[index + 3]; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | __attribute__ ((weak)) | ||||||
|  | bool process_api_quantum(uint8_t length, uint8_t * data) { | ||||||
|  |     return process_api_keyboard(length, data); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | __attribute__ ((weak)) | ||||||
|  | bool process_api_keyboard(uint8_t length, uint8_t * data) { | ||||||
|  |     return process_api_user(length, data); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | __attribute__ ((weak)) | ||||||
|  | bool process_api_user(uint8_t length, uint8_t * data) { | ||||||
|  |     return true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void process_api(uint16_t length, uint8_t * data) { | ||||||
|  |     // SEND_STRING("\nRX: ");
 | ||||||
|  |     // for (uint8_t i = 0; i < length; i++) {
 | ||||||
|  |     //     send_byte(data[i]);
 | ||||||
|  |     //     SEND_STRING(" ");
 | ||||||
|  |     // }
 | ||||||
|  |     if (!process_api_quantum(length, data)) | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|  |     switch (data[0]) { | ||||||
|  |         case MT_SET_DATA: | ||||||
|  |             switch (data[1]) { | ||||||
|  |                 case DT_DEFAULT_LAYER: { | ||||||
|  |                     eeconfig_update_default_layer(data[2]); | ||||||
|  |                     default_layer_set((uint32_t)(data[2])); | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|  |                 case DT_KEYMAP_OPTIONS: { | ||||||
|  |                     eeconfig_update_keymap(data[2]); | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|  |                 case DT_RGBLIGHT: { | ||||||
|  |                     #ifdef RGBLIGHT_ENABLE | ||||||
|  |                         uint32_t rgblight = bytes_to_dword(data, 2); | ||||||
|  |                         rgblight_update_dword(rgblight); | ||||||
|  |                     #endif | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         case MT_GET_DATA: | ||||||
|  |             switch (data[1]) { | ||||||
|  |                 case DT_HANDSHAKE: { | ||||||
|  |                     MT_GET_DATA_ACK(DT_HANDSHAKE, NULL, 0); | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|  |                 case DT_DEBUG: { | ||||||
|  |                     uint8_t debug_bytes[1] = { eeprom_read_byte(EECONFIG_DEBUG) }; | ||||||
|  |                     MT_GET_DATA_ACK(DT_DEBUG, debug_bytes, 1); | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|  |                 case DT_DEFAULT_LAYER: { | ||||||
|  |                     uint8_t default_bytes[1] = { eeprom_read_byte(EECONFIG_DEFAULT_LAYER) }; | ||||||
|  |                     MT_GET_DATA_ACK(DT_DEFAULT_LAYER, default_bytes, 1); | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|  |                 case DT_CURRENT_LAYER: { | ||||||
|  |                     uint8_t layer_state_bytes[4]; | ||||||
|  |                     dword_to_bytes(layer_state, layer_state_bytes); | ||||||
|  |                     MT_GET_DATA_ACK(DT_CURRENT_LAYER, layer_state_bytes, 4); | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|  |                 case DT_AUDIO: { | ||||||
|  |                     #ifdef AUDIO_ENABLE | ||||||
|  |                         uint8_t audio_bytes[1] = { eeprom_read_byte(EECONFIG_AUDIO) }; | ||||||
|  |                         MT_GET_DATA_ACK(DT_AUDIO, audio_bytes, 1); | ||||||
|  |                     #else | ||||||
|  |                         MT_GET_DATA_ACK(DT_AUDIO, NULL, 0); | ||||||
|  |                     #endif | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|  |                 case DT_BACKLIGHT: { | ||||||
|  |                     #ifdef BACKLIGHT_ENABLE | ||||||
|  |                         uint8_t backlight_bytes[1] = { eeprom_read_byte(EECONFIG_BACKLIGHT) }; | ||||||
|  |                         MT_GET_DATA_ACK(DT_BACKLIGHT, backlight_bytes, 1); | ||||||
|  |                     #else | ||||||
|  |                         MT_GET_DATA_ACK(DT_BACKLIGHT, NULL, 0); | ||||||
|  |                     #endif | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|  |                 case DT_RGBLIGHT: { | ||||||
|  |                     #ifdef RGBLIGHT_ENABLE | ||||||
|  |                         uint8_t rgblight_bytes[4]; | ||||||
|  |                         dword_to_bytes(eeconfig_read_rgblight(), rgblight_bytes); | ||||||
|  |                         MT_GET_DATA_ACK(DT_RGBLIGHT, rgblight_bytes, 4); | ||||||
|  |                     #else | ||||||
|  |                         MT_GET_DATA_ACK(DT_RGBLIGHT, NULL, 0); | ||||||
|  |                     #endif | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|  |                 case DT_KEYMAP_OPTIONS: { | ||||||
|  |                     uint8_t keymap_bytes[1] = { eeconfig_read_keymap() }; | ||||||
|  |                     MT_GET_DATA_ACK(DT_KEYMAP_OPTIONS, keymap_bytes, 1); | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|  |                 case DT_KEYMAP_SIZE: { | ||||||
|  |                     uint8_t keymap_size[2] = {MATRIX_ROWS, MATRIX_COLS}; | ||||||
|  |                     MT_GET_DATA_ACK(DT_KEYMAP_SIZE, keymap_size, 2); | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|  |                 case DT_KEYMAP: { | ||||||
|  |                     uint8_t keymap_data[MATRIX_ROWS * MATRIX_COLS * 4 + 3]; | ||||||
|  |                     keymap_data[0] = data[2]; | ||||||
|  |                     keymap_data[1] = MATRIX_ROWS; | ||||||
|  |                     keymap_data[2] = MATRIX_COLS; | ||||||
|  |                     for (int i = 0; i < MATRIX_ROWS; i++) { | ||||||
|  |                         for (int j = 0; j < MATRIX_COLS; j++) { | ||||||
|  |                             keymap_data[3 + (i*MATRIX_COLS*2) + (j*2)] = pgm_read_word(&keymaps[data[2]][i][j]) >> 8; | ||||||
|  |                             keymap_data[3 + (i*MATRIX_COLS*2) + (j*2) + 1] = pgm_read_word(&keymaps[data[2]][i][j]) & 0xFF; | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                     MT_GET_DATA_ACK(DT_KEYMAP, keymap_data, MATRIX_ROWS * MATRIX_COLS * 4 + 3); | ||||||
|  |                     // uint8_t keymap_data[5];
 | ||||||
|  |                     // keymap_data[0] = data[2];
 | ||||||
|  |                     // keymap_data[1] = data[3];
 | ||||||
|  |                     // keymap_data[2] = data[4];
 | ||||||
|  |                     // keymap_data[3] = pgm_read_word(&keymaps[data[2]][data[3]][data[4]]) >> 8;
 | ||||||
|  |                     // keymap_data[4] = pgm_read_word(&keymaps[data[2]][data[3]][data[4]]) & 0xFF;
 | ||||||
|  | 
 | ||||||
|  |                     // MT_GET_DATA_ACK(DT_KEYMAP, keymap_data, 5);
 | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|  |                 default: | ||||||
|  |                     break; | ||||||
|  |             } | ||||||
|  |             break; | ||||||
|  |         case MT_SET_DATA_ACK: | ||||||
|  |         case MT_GET_DATA_ACK: | ||||||
|  |             break; | ||||||
|  |         case MT_SEND_DATA: | ||||||
|  |             break; | ||||||
|  |         case MT_SEND_DATA_ACK: | ||||||
|  |             break; | ||||||
|  |         case MT_EXE_ACTION: | ||||||
|  |             break; | ||||||
|  |         case MT_EXE_ACTION_ACK: | ||||||
|  |             break; | ||||||
|  |         case MT_TYPE_ERROR: | ||||||
|  |             break; | ||||||
|  |         default: ; // command not recognised
 | ||||||
|  |             SEND_BYTES(MT_TYPE_ERROR, DT_NONE, data, length); | ||||||
|  |             break; | ||||||
|  | 
 | ||||||
|  |         // #ifdef RGBLIGHT_ENABLE
 | ||||||
|  |         // case 0x27: ; // RGB LED functions
 | ||||||
|  |         //     switch (*data++) {
 | ||||||
|  |         //         case 0x00: ; // Update HSV
 | ||||||
|  |         //             rgblight_sethsv((data[0] << 8 | data[1]) % 360, data[2], data[3]);
 | ||||||
|  |         //             break;
 | ||||||
|  |         //         case 0x01: ; // Update RGB
 | ||||||
|  |         //             break;
 | ||||||
|  |         //         case 0x02: ; // Update mode
 | ||||||
|  |         //             rgblight_mode(data[0]);
 | ||||||
|  |         //             break;
 | ||||||
|  |         //     }
 | ||||||
|  |         //     break;
 | ||||||
|  |         // #endif
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
							
								
								
									
										59
									
								
								quantum/api.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								quantum/api.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,59 @@ | |||||||
|  | #ifndef _API_H_ | ||||||
|  | #define _API_H_ | ||||||
|  | 
 | ||||||
|  | #include "lufa.h" | ||||||
|  | 
 | ||||||
|  | enum MESSAGE_TYPE { | ||||||
|  |     MT_GET_DATA =      0x10, // Get data from keyboard
 | ||||||
|  |     MT_GET_DATA_ACK =  0x11, // returned data to process (ACK)
 | ||||||
|  |     MT_SET_DATA =      0x20, // Set data on keyboard
 | ||||||
|  |     MT_SET_DATA_ACK =  0x21, // returned data to confirm (ACK)
 | ||||||
|  |     MT_SEND_DATA =     0x30, // Sending data/action from keyboard
 | ||||||
|  |     MT_SEND_DATA_ACK = 0x31, // returned data/action confirmation (ACK)
 | ||||||
|  |     MT_EXE_ACTION =    0x40, // executing actions on keyboard
 | ||||||
|  |     MT_EXE_ACTION_ACK =0x41, // return confirmation/value (ACK)
 | ||||||
|  |     MT_TYPE_ERROR =    0x80 // type not recofgnised (ACK)
 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | enum DATA_TYPE { | ||||||
|  |     DT_NONE = 0x00, | ||||||
|  |     DT_HANDSHAKE, | ||||||
|  |     DT_DEFAULT_LAYER, | ||||||
|  |     DT_CURRENT_LAYER, | ||||||
|  |     DT_KEYMAP_OPTIONS, | ||||||
|  |     DT_BACKLIGHT, | ||||||
|  |     DT_RGBLIGHT, | ||||||
|  |     DT_UNICODE, | ||||||
|  |     DT_DEBUG, | ||||||
|  |     DT_AUDIO, | ||||||
|  |     DT_QUANTUM_ACTION, | ||||||
|  |     DT_KEYBOARD_ACTION, | ||||||
|  |     DT_USER_ACTION, | ||||||
|  |     DT_KEYMAP_SIZE, | ||||||
|  |     DT_KEYMAP | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | void dword_to_bytes(uint32_t dword, uint8_t * bytes); | ||||||
|  | uint32_t bytes_to_dword(uint8_t * bytes, uint8_t index); | ||||||
|  | 
 | ||||||
|  | #define MT_GET_DATA(data_type, data, length) SEND_BYTES(MT_GET_DATA, data_type, data, length) | ||||||
|  | #define MT_GET_DATA_ACK(data_type, data, length) SEND_BYTES(MT_GET_DATA_ACK, data_type, data, length) | ||||||
|  | #define MT_SET_DATA(data_type, data, length) SEND_BYTES(MT_SET_DATA, data_type, data, length) | ||||||
|  | #define MT_SET_DATA_ACK(data_type, data, length) SEND_BYTES(MT_SET_DATA_ACK, data_type, data, length) | ||||||
|  | #define MT_SEND_DATA(data_type, data, length) SEND_BYTES(MT_SEND_DATA, data_type, data, length) | ||||||
|  | #define MT_SEND_DATA_ACK(data_type, data, length) SEND_BYTES(MT_SEND_DATA_ACK, data_type, data, length) | ||||||
|  | #define MT_EXE_ACTION(data_type, data, length) SEND_BYTES(MT_EXE_ACTION, data_type, data, length) | ||||||
|  | #define MT_EXE_ACTION_ACK(data_type, data, length) SEND_BYTES(MT_EXE_ACTION_ACK, data_type, data, length) | ||||||
|  | 
 | ||||||
|  | void process_api(uint16_t length, uint8_t * data); | ||||||
|  | 
 | ||||||
|  | __attribute__ ((weak)) | ||||||
|  | bool process_api_quantum(uint8_t length, uint8_t * data); | ||||||
|  | 
 | ||||||
|  | __attribute__ ((weak)) | ||||||
|  | bool process_api_keyboard(uint8_t length, uint8_t * data); | ||||||
|  | 
 | ||||||
|  | __attribute__ ((weak)) | ||||||
|  | bool process_api_user(uint8_t length, uint8_t * data); | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
							
								
								
									
										29
									
								
								quantum/api/api_sysex.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								quantum/api/api_sysex.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,29 @@ | |||||||
|  | #include "api_sysex.h" | ||||||
|  | 
 | ||||||
|  | void send_bytes_sysex(uint8_t message_type, uint8_t data_type, uint8_t * bytes, uint16_t length) { | ||||||
|  |     // SEND_STRING("\nTX: ");
 | ||||||
|  |     // for (uint8_t i = 0; i < length; i++) {
 | ||||||
|  |     //     send_byte(bytes[i]);
 | ||||||
|  |     //     SEND_STRING(" ");
 | ||||||
|  |     // }
 | ||||||
|  |     uint8_t * precode = malloc(sizeof(uint8_t) * (length + 2)); | ||||||
|  |     precode[0] = message_type; | ||||||
|  |     precode[1] = data_type; | ||||||
|  |     memcpy(precode + 2, bytes, length); | ||||||
|  |     uint8_t * encoded = malloc(sizeof(uint8_t) * (sysex_encoded_length(length + 2))); | ||||||
|  |     uint16_t encoded_length = sysex_encode(encoded, precode, length + 2); | ||||||
|  |     uint8_t * array = malloc(sizeof(uint8_t) * (encoded_length + 5)); | ||||||
|  |     array[0] = 0xF0; | ||||||
|  |     array[1] = 0x00; | ||||||
|  |     array[2] = 0x00; | ||||||
|  |     array[3] = 0x00; | ||||||
|  |     array[encoded_length + 4] = 0xF7; | ||||||
|  |     memcpy(array + 4, encoded, encoded_length); | ||||||
|  |     midi_send_array(&midi_device, encoded_length + 5, array); | ||||||
|  | 
 | ||||||
|  |     // SEND_STRING("\nTD: ");
 | ||||||
|  |     // for (uint8_t i = 0; i < encoded_length + 5; i++) {
 | ||||||
|  |     //     send_byte(array[i]);
 | ||||||
|  |     //     SEND_STRING(" ");
 | ||||||
|  |     // }
 | ||||||
|  | } | ||||||
							
								
								
									
										10
									
								
								quantum/api/api_sysex.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								quantum/api/api_sysex.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,10 @@ | |||||||
|  | #ifndef _API_SYSEX_H_ | ||||||
|  | #define _API_SYSEX_H_ | ||||||
|  | 
 | ||||||
|  | #include "api.h" | ||||||
|  | 
 | ||||||
|  | void send_bytes_sysex(uint8_t message_type, uint8_t data_type, uint8_t * bytes, uint16_t length); | ||||||
|  | 
 | ||||||
|  | #define SEND_BYTES(mt, dt, b, l) send_bytes_sysex(mt, dt, b, l) | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
| @ -847,12 +847,12 @@ void send_nibble(uint8_t number) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void send_unicode_midi(uint32_t unicode) { | void api_send_unicode(uint32_t unicode) { | ||||||
|   #ifdef MIDI_ENABLE | #ifdef API_ENABLE | ||||||
|     uint8_t chunk[4]; |     uint8_t chunk[4]; | ||||||
|     dword_to_bytes(unicode, chunk); |     dword_to_bytes(unicode, chunk); | ||||||
|     MT_SEND_DATA(DT_UNICODE, chunk, 5); |     MT_SEND_DATA(DT_UNICODE, chunk, 5); | ||||||
|   #endif | #endif | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| __attribute__ ((weak)) | __attribute__ ((weak)) | ||||||
|  | |||||||
| @ -119,6 +119,6 @@ void send_nibble(uint8_t number); | |||||||
| void led_set_user(uint8_t usb_led); | void led_set_user(uint8_t usb_led); | ||||||
| void led_set_kb(uint8_t usb_led); | void led_set_kb(uint8_t usb_led); | ||||||
| 
 | 
 | ||||||
| void send_unicode_midi(uint32_t unicode); | void api_send_unicode(uint32_t unicode); | ||||||
| 
 | 
 | ||||||
| #endif | #endif | ||||||
|  | |||||||
| @ -1091,37 +1091,17 @@ void fallthrough_callback(MidiDevice * device, | |||||||
| #endif | #endif | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #ifdef RGB_MIDI |  | ||||||
|     rgblight_config_t rgblight_config; |  | ||||||
| #endif |  | ||||||
| 
 | 
 | ||||||
| void cc_callback(MidiDevice * device, | void cc_callback(MidiDevice * device, | ||||||
|     uint8_t chan, uint8_t num, uint8_t val) { |     uint8_t chan, uint8_t num, uint8_t val) { | ||||||
|   //sending it back on the next channel
 |   //sending it back on the next channel
 | ||||||
|   // midi_send_cc(device, (chan + 1) % 16, num, val);
 |   // midi_send_cc(device, (chan + 1) % 16, num, val);
 | ||||||
|     #ifdef RGB_MIDI |  | ||||||
|         rgblight_config.raw = eeconfig_read_rgblight(); |  | ||||||
|         switch (num) { |  | ||||||
|             case 14: |  | ||||||
|                 rgblight_config.hue = val * 360 / 127; |  | ||||||
|             break; |  | ||||||
|             case 15: |  | ||||||
|                 rgblight_config.sat = val << 1; |  | ||||||
|             break; |  | ||||||
|             case 16: |  | ||||||
|                 rgblight_config.val = val << 1; |  | ||||||
|             break; |  | ||||||
|         } |  | ||||||
|         rgblight_sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val); |  | ||||||
|     #endif |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| uint8_t midi_buffer[MIDI_SYSEX_BUFFER] = {0}; | uint8_t midi_buffer[MIDI_SYSEX_BUFFER] = {0}; | ||||||
| 
 | 
 | ||||||
| void sysex_callback(MidiDevice * device, uint16_t start, uint8_t length, uint8_t * data) { | void sysex_callback(MidiDevice * device, uint16_t start, uint8_t length, uint8_t * data) { | ||||||
|   // for (int i = 0; i < length; i++)
 |     #ifdef API_SYSEX_ENABLE | ||||||
|   //   midi_send_cc(device, 15, 0x7F & data[i], 0x7F & (start + i));
 |  | ||||||
|     // if (start == 0x27) {
 |  | ||||||
|         // SEND_STRING("\n");
 |         // SEND_STRING("\n");
 | ||||||
|         // send_word(start);
 |         // send_word(start);
 | ||||||
|         // SEND_STRING(": ");
 |         // SEND_STRING(": ");
 | ||||||
| @ -1136,190 +1116,13 @@ void sysex_callback(MidiDevice * device, uint16_t start, uint8_t length, uint8_t | |||||||
|                 // }
 |                 // }
 | ||||||
|                 uint8_t * decoded = malloc(sizeof(uint8_t) * (sysex_decoded_length(start + place - 4))); |                 uint8_t * decoded = malloc(sizeof(uint8_t) * (sysex_decoded_length(start + place - 4))); | ||||||
|                 uint16_t decode_length = sysex_decode(decoded, midi_buffer + 4, start + place - 4); |                 uint16_t decode_length = sysex_decode(decoded, midi_buffer + 4, start + place - 4); | ||||||
|                 sysex_buffer_callback(device, decode_length, decoded); |                 process_api(decode_length, decoded); | ||||||
|             } |             } | ||||||
|             // SEND_STRING(" ");
 |             // SEND_STRING(" ");
 | ||||||
|             data++; |             data++; | ||||||
|         } |         } | ||||||
|     // }
 |     #endif | ||||||
| 
 |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void dword_to_bytes(uint32_t dword, uint8_t * bytes) { |  | ||||||
|     bytes[0] = (dword >> 24) & 0xFF; |  | ||||||
|     bytes[1] = (dword >> 16) & 0xFF;  |  | ||||||
|     bytes[2] = (dword >> 8) & 0xFF;  |  | ||||||
|     bytes[3] = (dword >> 0) & 0xFF;  |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| uint32_t bytes_to_dword(uint8_t * bytes, uint8_t index) { |  | ||||||
|     return ((uint32_t)bytes[index + 0] << 24) | ((uint32_t)bytes[index + 1] << 16) | ((uint32_t)bytes[index + 2] << 8) | (uint32_t)bytes[index + 3]; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void send_bytes_sysex(uint8_t message_type, uint8_t data_type, uint8_t * bytes, uint8_t length) { |  | ||||||
|     // SEND_STRING("\nTX: ");
 |  | ||||||
|     // for (uint8_t i = 0; i < length; i++) {
 |  | ||||||
|     //     send_byte(bytes[i]);
 |  | ||||||
|     //     SEND_STRING(" ");
 |  | ||||||
|     // }
 |  | ||||||
|     uint8_t * precode = malloc(sizeof(uint8_t) * (length + 2)); |  | ||||||
|     precode[0] = message_type; |  | ||||||
|     precode[1] = data_type; |  | ||||||
|     memcpy(precode + 2, bytes, length); |  | ||||||
|     uint8_t * encoded = malloc(sizeof(uint8_t) * (sysex_encoded_length(length + 2))); |  | ||||||
|     uint16_t encoded_length = sysex_encode(encoded, precode, length + 2); |  | ||||||
|     uint8_t * array = malloc(sizeof(uint8_t) * (encoded_length + 5)); |  | ||||||
|     array[0] = 0xF0; |  | ||||||
|     array[1] = 0x00; |  | ||||||
|     array[2] = 0x00; |  | ||||||
|     array[3] = 0x00; |  | ||||||
|     array[encoded_length + 4] = 0xF7; |  | ||||||
|     memcpy(array + 4, encoded, encoded_length); |  | ||||||
|     midi_send_array(&midi_device, encoded_length + 5, array); |  | ||||||
| 
 |  | ||||||
|     // SEND_STRING("\nTD: ");
 |  | ||||||
|     // for (uint8_t i = 0; i < encoded_length + 5; i++) {
 |  | ||||||
|     //     send_byte(array[i]);
 |  | ||||||
|     //     SEND_STRING(" ");
 |  | ||||||
|     // }
 |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| __attribute__ ((weak)) |  | ||||||
| bool sysex_process_quantum(uint8_t length, uint8_t * data) { |  | ||||||
|     return sysex_process_keyboard(length, data); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| __attribute__ ((weak)) |  | ||||||
| bool sysex_process_keyboard(uint8_t length, uint8_t * data) { |  | ||||||
|     return sysex_process_user(length, data); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| __attribute__ ((weak)) |  | ||||||
| bool sysex_process_user(uint8_t length, uint8_t * data) { |  | ||||||
|     return true; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void sysex_buffer_callback(MidiDevice * device, uint8_t length, uint8_t * data) { |  | ||||||
|     // SEND_STRING("\nRX: ");
 |  | ||||||
|     // for (uint8_t i = 0; i < length; i++) {
 |  | ||||||
|     //     send_byte(data[i]);
 |  | ||||||
|     //     SEND_STRING(" ");
 |  | ||||||
|     // }
 |  | ||||||
|     if (!sysex_process_quantum(length, data)) |  | ||||||
|         return; |  | ||||||
| 
 |  | ||||||
|     switch (data[0]) { |  | ||||||
|         case MT_SET_DATA: |  | ||||||
|             switch (data[1]) { |  | ||||||
|                 case DT_DEFAULT_LAYER: { |  | ||||||
|                     eeconfig_update_default_layer(data[2]); |  | ||||||
|                     default_layer_set((uint32_t)(data[2])); |  | ||||||
|                     break; |  | ||||||
|                 } |  | ||||||
|                 case DT_KEYMAP_OPTIONS: { |  | ||||||
|                     eeconfig_update_keymap(data[2]); |  | ||||||
|                     break; |  | ||||||
|                 } |  | ||||||
|                 case DT_RGBLIGHT: { |  | ||||||
|                     #ifdef RGBLIGHT_ENABLE |  | ||||||
|                         uint32_t rgblight = bytes_to_dword(data, 2); |  | ||||||
|                         rgblight_update_dword(rgblight); |  | ||||||
|                     #endif |  | ||||||
|                     break; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         case MT_GET_DATA: |  | ||||||
|             switch (data[1]) { |  | ||||||
|                 case DT_HANDSHAKE: { |  | ||||||
|                     MT_GET_DATA_ACK(DT_HANDSHAKE, NULL, 0); |  | ||||||
|                     break; |  | ||||||
|                 } |  | ||||||
|                 case DT_DEBUG: { |  | ||||||
|                     uint8_t debug_bytes[1] = { eeprom_read_byte(EECONFIG_DEBUG) }; |  | ||||||
|                     MT_GET_DATA_ACK(DT_DEBUG, debug_bytes, 1); |  | ||||||
|                     break; |  | ||||||
|                 } |  | ||||||
|                 case DT_DEFAULT_LAYER: { |  | ||||||
|                     uint8_t default_bytes[1] = { eeprom_read_byte(EECONFIG_DEFAULT_LAYER) }; |  | ||||||
|                     MT_GET_DATA_ACK(DT_DEFAULT_LAYER, default_bytes, 1); |  | ||||||
|                     break; |  | ||||||
|                 } |  | ||||||
|                 case DT_CURRENT_LAYER: { |  | ||||||
|                     uint8_t layer_state_bytes[4]; |  | ||||||
|                     dword_to_bytes(layer_state, layer_state_bytes); |  | ||||||
|                     MT_GET_DATA_ACK(DT_CURRENT_LAYER, layer_state_bytes, 4); |  | ||||||
|                     break; |  | ||||||
|                 } |  | ||||||
|                 case DT_AUDIO: { |  | ||||||
|                     #ifdef AUDIO_ENABLE |  | ||||||
|                         uint8_t audio_bytes[1] = { eeprom_read_byte(EECONFIG_AUDIO) }; |  | ||||||
|                         MT_GET_DATA_ACK(DT_AUDIO, audio_bytes, 1); |  | ||||||
|                     #else |  | ||||||
|                         MT_GET_DATA_ACK(DT_AUDIO, NULL, 0); |  | ||||||
|                     #endif |  | ||||||
|                     break; |  | ||||||
|                 } |  | ||||||
|                 case DT_BACKLIGHT: { |  | ||||||
|                     #ifdef BACKLIGHT_ENABLE |  | ||||||
|                         uint8_t backlight_bytes[1] = { eeprom_read_byte(EECONFIG_BACKLIGHT) }; |  | ||||||
|                         MT_GET_DATA_ACK(DT_BACKLIGHT, backlight_bytes, 1); |  | ||||||
|                     #else |  | ||||||
|                         MT_GET_DATA_ACK(DT_BACKLIGHT, NULL, 0); |  | ||||||
|                     #endif |  | ||||||
|                     break; |  | ||||||
|                 } |  | ||||||
|                 case DT_RGBLIGHT: { |  | ||||||
|                     #ifdef RGBLIGHT_ENABLE |  | ||||||
|                         uint8_t rgblight_bytes[4]; |  | ||||||
|                         dword_to_bytes(eeconfig_read_rgblight(), rgblight_bytes); |  | ||||||
|                         MT_GET_DATA_ACK(DT_RGBLIGHT, rgblight_bytes, 4); |  | ||||||
|                     #else |  | ||||||
|                         MT_GET_DATA_ACK(DT_RGBLIGHT, NULL, 0); |  | ||||||
|                     #endif |  | ||||||
|                     break; |  | ||||||
|                 } |  | ||||||
|                 case DT_KEYMAP_OPTIONS: { |  | ||||||
|                     uint8_t keymap_bytes[1] = { eeconfig_read_keymap() }; |  | ||||||
|                     MT_GET_DATA_ACK(DT_KEYMAP_OPTIONS, keymap_bytes, 1); |  | ||||||
|                     break; |  | ||||||
|                 } |  | ||||||
|                 default: |  | ||||||
|                     break; |  | ||||||
|             } |  | ||||||
|             break; |  | ||||||
|         case MT_SET_DATA_ACK: |  | ||||||
|         case MT_GET_DATA_ACK: |  | ||||||
|             break; |  | ||||||
|         case MT_SEND_DATA: |  | ||||||
|             break; |  | ||||||
|         case MT_SEND_DATA_ACK: |  | ||||||
|             break; |  | ||||||
|         case MT_EXE_ACTION: |  | ||||||
|             break; |  | ||||||
|         case MT_EXE_ACTION_ACK: |  | ||||||
|             break; |  | ||||||
|         case MT_TYPE_ERROR: |  | ||||||
|             break; |  | ||||||
|         default: ; // command not recognised
 |  | ||||||
|             send_bytes_sysex(MT_TYPE_ERROR, DT_NONE, data, length); |  | ||||||
|             break; |  | ||||||
| 
 |  | ||||||
|         // #ifdef RGBLIGHT_ENABLE
 |  | ||||||
|         // case 0x27: ; // RGB LED functions
 |  | ||||||
|         //     switch (*data++) {
 |  | ||||||
|         //         case 0x00: ; // Update HSV
 |  | ||||||
|         //             rgblight_sethsv((data[0] << 8 | data[1]) % 360, data[2], data[3]);
 |  | ||||||
|         //             break;
 |  | ||||||
|         //         case 0x01: ; // Update RGB
 |  | ||||||
|         //             break;
 |  | ||||||
|         //         case 0x02: ; // Update mode
 |  | ||||||
|         //             rgblight_mode(data[0]);
 |  | ||||||
|         //             break;
 |  | ||||||
|         //     }
 |  | ||||||
|         //     break;
 |  | ||||||
|         // #endif
 |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| #endif | #endif | ||||||
|  | |||||||
| @ -68,64 +68,17 @@ typedef struct { | |||||||
| } __attribute__ ((packed)) report_extra_t; | } __attribute__ ((packed)) report_extra_t; | ||||||
| 
 | 
 | ||||||
| #ifdef MIDI_ENABLE | #ifdef MIDI_ENABLE | ||||||
|   #define MIDI_SYSEX_BUFFER 16  |  | ||||||
|   void MIDI_Task(void); |   void MIDI_Task(void); | ||||||
|   MidiDevice midi_device; |   MidiDevice midi_device; | ||||||
|  |   #define MIDI_SYSEX_BUFFER 32  | ||||||
|  | #endif | ||||||
| 
 | 
 | ||||||
|   void sysex_callback(MidiDevice * device, uint16_t start, uint8_t length, uint8_t * data); | #ifdef API_ENABLE | ||||||
|   void sysex_buffer_callback(MidiDevice * device, uint8_t length, uint8_t * data); |   #include "api.h" | ||||||
|   void send_bytes_sysex(uint8_t message_type, uint8_t data_type, uint8_t * bytes, uint8_t length); | #endif | ||||||
|   void dword_to_bytes(uint32_t dword, uint8_t * bytes); |  | ||||||
|   uint32_t bytes_to_dword(uint8_t * bytes, uint8_t index); |  | ||||||
| 
 |  | ||||||
|   __attribute__ ((weak)) |  | ||||||
|   bool sysex_process_quantum(uint8_t length, uint8_t * data); |  | ||||||
| 
 |  | ||||||
|   __attribute__ ((weak)) |  | ||||||
|   bool sysex_process_keyboard(uint8_t length, uint8_t * data); |  | ||||||
| 
 |  | ||||||
|   __attribute__ ((weak)) |  | ||||||
|   bool sysex_process_user(uint8_t length, uint8_t * data); |  | ||||||
| 
 |  | ||||||
|   enum MESSAGE_TYPE { |  | ||||||
|       MT_GET_DATA =      0x10, // Get data from keyboard
 |  | ||||||
|       MT_GET_DATA_ACK =  0x11, // returned data to process (ACK)
 |  | ||||||
|       MT_SET_DATA =      0x20, // Set data on keyboard
 |  | ||||||
|       MT_SET_DATA_ACK =  0x21, // returned data to confirm (ACK)
 |  | ||||||
|       MT_SEND_DATA =     0x30, // Sending data/action from keyboard
 |  | ||||||
|       MT_SEND_DATA_ACK = 0x31, // returned data/action confirmation (ACK)
 |  | ||||||
|       MT_EXE_ACTION =    0x40, // executing actions on keyboard
 |  | ||||||
|       MT_EXE_ACTION_ACK =0x41, // return confirmation/value (ACK)
 |  | ||||||
|       MT_TYPE_ERROR =    0x80 // type not recofgnised (ACK)
 |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   enum DATA_TYPE { |  | ||||||
|       DT_NONE = 0x00, |  | ||||||
|       DT_HANDSHAKE, |  | ||||||
|       DT_DEFAULT_LAYER, |  | ||||||
|       DT_CURRENT_LAYER, |  | ||||||
|       DT_KEYMAP_OPTIONS, |  | ||||||
|       DT_BACKLIGHT, |  | ||||||
|       DT_RGBLIGHT, |  | ||||||
|       DT_UNICODE, |  | ||||||
|       DT_DEBUG, |  | ||||||
|       DT_AUDIO, |  | ||||||
|       DT_QUANTUM_ACTION, |  | ||||||
|       DT_KEYBOARD_ACTION, |  | ||||||
|       DT_USER_ACTION, |  | ||||||
| 
 |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|   #define MT_GET_DATA(data_type, data, length) send_bytes_sysex(MT_GET_DATA, data_type, data, length) |  | ||||||
|   #define MT_GET_DATA_ACK(data_type, data, length) send_bytes_sysex(MT_GET_DATA_ACK, data_type, data, length) |  | ||||||
|   #define MT_SET_DATA(data_type, data, length) send_bytes_sysex(MT_SET_DATA, data_type, data, length) |  | ||||||
|   #define MT_SET_DATA_ACK(data_type, data, length) send_bytes_sysex(MT_SET_DATA_ACK, data_type, data, length) |  | ||||||
|   #define MT_SEND_DATA(data_type, data, length) send_bytes_sysex(MT_SEND_DATA, data_type, data, length) |  | ||||||
|   #define MT_SEND_DATA_ACK(data_type, data, length) send_bytes_sysex(MT_SEND_DATA_ACK, data_type, data, length) |  | ||||||
|   #define MT_EXE_ACTION(data_type, data, length) send_bytes_sysex(MT_EXE_ACTION, data_type, data, length) |  | ||||||
|   #define MT_EXE_ACTION_ACK(data_type, data, length) send_bytes_sysex(MT_EXE_ACTION_ACK, data_type, data, length) |  | ||||||
| 
 | 
 | ||||||
|  | #ifdef API_SYSEX_ENABLE | ||||||
|  |   #include "api_sysex.h" | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| // #if LUFA_VERSION_INTEGER < 0x120730
 | // #if LUFA_VERSION_INTEGER < 0x120730
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Jack Humbert
						Jack Humbert