Relocate protocol files within tmk_core/common/ (#14972)
* Relocate non platform files within tmk_core/common/ * clang
This commit is contained in:
		
							
								
								
									
										138
									
								
								tmk_core/protocol/host.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										138
									
								
								tmk_core/protocol/host.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,138 @@ | ||||
| /* | ||||
| Copyright 2011,2012 Jun Wako <wakojun@gmail.com> | ||||
|  | ||||
| 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/>. | ||||
| */ | ||||
|  | ||||
| #include <stdint.h> | ||||
| //#include <avr/interrupt.h> | ||||
| #include "keyboard.h" | ||||
| #include "keycode.h" | ||||
| #include "host.h" | ||||
| #include "util.h" | ||||
| #include "debug.h" | ||||
| #include "digitizer.h" | ||||
|  | ||||
| #ifdef NKRO_ENABLE | ||||
| #    include "keycode_config.h" | ||||
| extern keymap_config_t keymap_config; | ||||
| #endif | ||||
|  | ||||
| static host_driver_t *driver; | ||||
| static uint16_t       last_system_report              = 0; | ||||
| static uint16_t       last_consumer_report            = 0; | ||||
| static uint32_t       last_programmable_button_report = 0; | ||||
|  | ||||
| void host_set_driver(host_driver_t *d) { driver = d; } | ||||
|  | ||||
| host_driver_t *host_get_driver(void) { return driver; } | ||||
|  | ||||
| #ifdef SPLIT_KEYBOARD | ||||
| uint8_t split_led_state = 0; | ||||
| void    set_split_host_keyboard_leds(uint8_t led_state) { split_led_state = led_state; } | ||||
| #endif | ||||
|  | ||||
| uint8_t host_keyboard_leds(void) { | ||||
| #ifdef SPLIT_KEYBOARD | ||||
|     if (!is_keyboard_master()) return split_led_state; | ||||
| #endif | ||||
|     if (!driver) return 0; | ||||
|     return (*driver->keyboard_leds)(); | ||||
| } | ||||
|  | ||||
| led_t host_keyboard_led_state(void) { return (led_t)host_keyboard_leds(); } | ||||
|  | ||||
| /* send report */ | ||||
| void host_keyboard_send(report_keyboard_t *report) { | ||||
|     if (!driver) return; | ||||
| #if defined(NKRO_ENABLE) && defined(NKRO_SHARED_EP) | ||||
|     if (keyboard_protocol && keymap_config.nkro) { | ||||
|         /* The callers of this function assume that report->mods is where mods go in. | ||||
|          * But report->nkro.mods can be at a different offset if core keyboard does not have a report ID. | ||||
|          */ | ||||
|         report->nkro.mods      = report->mods; | ||||
|         report->nkro.report_id = REPORT_ID_NKRO; | ||||
|     } else | ||||
| #endif | ||||
|     { | ||||
| #ifdef KEYBOARD_SHARED_EP | ||||
|         report->report_id = REPORT_ID_KEYBOARD; | ||||
| #endif | ||||
|     } | ||||
|     (*driver->send_keyboard)(report); | ||||
|  | ||||
|     if (debug_keyboard) { | ||||
|         dprint("keyboard_report: "); | ||||
|         for (uint8_t i = 0; i < KEYBOARD_REPORT_SIZE; i++) { | ||||
|             dprintf("%02X ", report->raw[i]); | ||||
|         } | ||||
|         dprint("\n"); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void host_mouse_send(report_mouse_t *report) { | ||||
|     if (!driver) return; | ||||
| #ifdef MOUSE_SHARED_EP | ||||
|     report->report_id = REPORT_ID_MOUSE; | ||||
| #endif | ||||
|     (*driver->send_mouse)(report); | ||||
| } | ||||
|  | ||||
| void host_system_send(uint16_t report) { | ||||
|     if (report == last_system_report) return; | ||||
|     last_system_report = report; | ||||
|  | ||||
|     if (!driver) return; | ||||
|     (*driver->send_system)(report); | ||||
| } | ||||
|  | ||||
| void host_consumer_send(uint16_t report) { | ||||
|     if (report == last_consumer_report) return; | ||||
|     last_consumer_report = report; | ||||
|  | ||||
|     if (!driver) return; | ||||
|     (*driver->send_consumer)(report); | ||||
| } | ||||
|  | ||||
| void host_digitizer_send(digitizer_t *digitizer) { | ||||
|     if (!driver) return; | ||||
|  | ||||
|     report_digitizer_t report = { | ||||
| #ifdef DIGITIZER_SHARED_EP | ||||
|         .report_id = REPORT_ID_DIGITIZER, | ||||
| #endif | ||||
|         .tip     = digitizer->tipswitch & 0x1, | ||||
|         .inrange = digitizer->inrange & 0x1, | ||||
|         .x       = (uint16_t)(digitizer->x * 0x7FFF), | ||||
|         .y       = (uint16_t)(digitizer->y * 0x7FFF), | ||||
|     }; | ||||
|  | ||||
|     send_digitizer(&report); | ||||
| } | ||||
|  | ||||
| __attribute__((weak)) void send_digitizer(report_digitizer_t *report) {} | ||||
|  | ||||
| void host_programmable_button_send(uint32_t report) { | ||||
|     if (report == last_programmable_button_report) return; | ||||
|     last_programmable_button_report = report; | ||||
|  | ||||
|     if (!driver) return; | ||||
|     (*driver->send_programmable_button)(report); | ||||
| } | ||||
|  | ||||
| uint16_t host_last_system_report(void) { return last_system_report; } | ||||
|  | ||||
| uint16_t host_last_consumer_report(void) { return last_consumer_report; } | ||||
|  | ||||
| uint32_t host_last_programmable_button_report(void) { return last_programmable_button_report; } | ||||
							
								
								
									
										58
									
								
								tmk_core/protocol/host.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								tmk_core/protocol/host.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,58 @@ | ||||
| /* | ||||
| Copyright 2011 Jun Wako <wakojun@gmail.com> | ||||
|  | ||||
| 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 <stdint.h> | ||||
| #include <stdbool.h> | ||||
| #include "report.h" | ||||
| #include "host_driver.h" | ||||
| #include "led.h" | ||||
|  | ||||
| #define IS_LED_ON(leds, led_name) ((leds) & (1 << (led_name))) | ||||
| #define IS_LED_OFF(leds, led_name) (~(leds) & (1 << (led_name))) | ||||
|  | ||||
| #define IS_HOST_LED_ON(led_name) IS_LED_ON(host_keyboard_leds(), led_name) | ||||
| #define IS_HOST_LED_OFF(led_name) IS_LED_OFF(host_keyboard_leds(), led_name) | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
|  | ||||
| extern uint8_t keyboard_idle; | ||||
| extern uint8_t keyboard_protocol; | ||||
|  | ||||
| /* host driver */ | ||||
| void           host_set_driver(host_driver_t *driver); | ||||
| host_driver_t *host_get_driver(void); | ||||
|  | ||||
| /* host driver interface */ | ||||
| uint8_t host_keyboard_leds(void); | ||||
| led_t   host_keyboard_led_state(void); | ||||
| void    host_keyboard_send(report_keyboard_t *report); | ||||
| void    host_mouse_send(report_mouse_t *report); | ||||
| void    host_system_send(uint16_t data); | ||||
| void    host_consumer_send(uint16_t data); | ||||
| void    host_programmable_button_send(uint32_t data); | ||||
|  | ||||
| uint16_t host_last_system_report(void); | ||||
| uint16_t host_last_consumer_report(void); | ||||
| uint32_t host_last_programmable_button_report(void); | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
							
								
								
									
										35
									
								
								tmk_core/protocol/host_driver.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								tmk_core/protocol/host_driver.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | ||||
| /* | ||||
| Copyright 2011 Jun Wako <wakojun@gmail.com> | ||||
|  | ||||
| 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 <stdint.h> | ||||
| #include "report.h" | ||||
| #ifdef MIDI_ENABLE | ||||
| #    include "midi.h" | ||||
| #endif | ||||
|  | ||||
| typedef struct { | ||||
|     uint8_t (*keyboard_leds)(void); | ||||
|     void (*send_keyboard)(report_keyboard_t *); | ||||
|     void (*send_mouse)(report_mouse_t *); | ||||
|     void (*send_system)(uint16_t); | ||||
|     void (*send_consumer)(uint16_t); | ||||
|     void (*send_programmable_button)(uint32_t); | ||||
| } host_driver_t; | ||||
|  | ||||
| void send_digitizer(report_digitizer_t *report); | ||||
							
								
								
									
										280
									
								
								tmk_core/protocol/report.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										280
									
								
								tmk_core/protocol/report.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,280 @@ | ||||
| /* Copyright 2017 Fred Sundvik | ||||
|  * | ||||
|  * 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/>. | ||||
|  */ | ||||
|  | ||||
| #include "report.h" | ||||
| #include "host.h" | ||||
| #include "keycode_config.h" | ||||
| #include "debug.h" | ||||
| #include "util.h" | ||||
| #include <string.h> | ||||
|  | ||||
| #ifdef RING_BUFFERED_6KRO_REPORT_ENABLE | ||||
| #    define RO_ADD(a, b) ((a + b) % KEYBOARD_REPORT_KEYS) | ||||
| #    define RO_SUB(a, b) ((a - b + KEYBOARD_REPORT_KEYS) % KEYBOARD_REPORT_KEYS) | ||||
| #    define RO_INC(a) RO_ADD(a, 1) | ||||
| #    define RO_DEC(a) RO_SUB(a, 1) | ||||
| static int8_t cb_head  = 0; | ||||
| static int8_t cb_tail  = 0; | ||||
| static int8_t cb_count = 0; | ||||
| #endif | ||||
|  | ||||
| /** \brief has_anykey | ||||
|  * | ||||
|  * FIXME: Needs doc | ||||
|  */ | ||||
| uint8_t has_anykey(report_keyboard_t* keyboard_report) { | ||||
|     uint8_t  cnt = 0; | ||||
|     uint8_t* p   = keyboard_report->keys; | ||||
|     uint8_t  lp  = sizeof(keyboard_report->keys); | ||||
| #ifdef NKRO_ENABLE | ||||
|     if (keyboard_protocol && keymap_config.nkro) { | ||||
|         p  = keyboard_report->nkro.bits; | ||||
|         lp = sizeof(keyboard_report->nkro.bits); | ||||
|     } | ||||
| #endif | ||||
|     while (lp--) { | ||||
|         if (*p++) cnt++; | ||||
|     } | ||||
|     return cnt; | ||||
| } | ||||
|  | ||||
| /** \brief get_first_key | ||||
|  * | ||||
|  * FIXME: Needs doc | ||||
|  */ | ||||
| uint8_t get_first_key(report_keyboard_t* keyboard_report) { | ||||
| #ifdef NKRO_ENABLE | ||||
|     if (keyboard_protocol && keymap_config.nkro) { | ||||
|         uint8_t i = 0; | ||||
|         for (; i < KEYBOARD_REPORT_BITS && !keyboard_report->nkro.bits[i]; i++) | ||||
|             ; | ||||
|         return i << 3 | biton(keyboard_report->nkro.bits[i]); | ||||
|     } | ||||
| #endif | ||||
| #ifdef RING_BUFFERED_6KRO_REPORT_ENABLE | ||||
|     uint8_t i = cb_head; | ||||
|     do { | ||||
|         if (keyboard_report->keys[i] != 0) { | ||||
|             break; | ||||
|         } | ||||
|         i = RO_INC(i); | ||||
|     } while (i != cb_tail); | ||||
|     return keyboard_report->keys[i]; | ||||
| #else | ||||
|     return keyboard_report->keys[0]; | ||||
| #endif | ||||
| } | ||||
|  | ||||
| /** \brief Checks if a key is pressed in the report | ||||
|  * | ||||
|  * Returns true if the keyboard_report reports that the key is pressed, otherwise false | ||||
|  * Note: The function doesn't support modifers currently, and it returns false for KC_NO | ||||
|  */ | ||||
| bool is_key_pressed(report_keyboard_t* keyboard_report, uint8_t key) { | ||||
|     if (key == KC_NO) { | ||||
|         return false; | ||||
|     } | ||||
| #ifdef NKRO_ENABLE | ||||
|     if (keyboard_protocol && keymap_config.nkro) { | ||||
|         if ((key >> 3) < KEYBOARD_REPORT_BITS) { | ||||
|             return keyboard_report->nkro.bits[key >> 3] & 1 << (key & 7); | ||||
|         } else { | ||||
|             return false; | ||||
|         } | ||||
|     } | ||||
| #endif | ||||
|     for (int i = 0; i < KEYBOARD_REPORT_KEYS; i++) { | ||||
|         if (keyboard_report->keys[i] == key) { | ||||
|             return true; | ||||
|         } | ||||
|     } | ||||
|     return false; | ||||
| } | ||||
|  | ||||
| /** \brief add key byte | ||||
|  * | ||||
|  * FIXME: Needs doc | ||||
|  */ | ||||
| void add_key_byte(report_keyboard_t* keyboard_report, uint8_t code) { | ||||
| #ifdef RING_BUFFERED_6KRO_REPORT_ENABLE | ||||
|     int8_t i     = cb_head; | ||||
|     int8_t empty = -1; | ||||
|     if (cb_count) { | ||||
|         do { | ||||
|             if (keyboard_report->keys[i] == code) { | ||||
|                 return; | ||||
|             } | ||||
|             if (empty == -1 && keyboard_report->keys[i] == 0) { | ||||
|                 empty = i; | ||||
|             } | ||||
|             i = RO_INC(i); | ||||
|         } while (i != cb_tail); | ||||
|         if (i == cb_tail) { | ||||
|             if (cb_tail == cb_head) { | ||||
|                 // buffer is full | ||||
|                 if (empty == -1) { | ||||
|                     // pop head when has no empty space | ||||
|                     cb_head = RO_INC(cb_head); | ||||
|                     cb_count--; | ||||
|                 } else { | ||||
|                     // left shift when has empty space | ||||
|                     uint8_t offset = 1; | ||||
|                     i              = RO_INC(empty); | ||||
|                     do { | ||||
|                         if (keyboard_report->keys[i] != 0) { | ||||
|                             keyboard_report->keys[empty] = keyboard_report->keys[i]; | ||||
|                             keyboard_report->keys[i]     = 0; | ||||
|                             empty                        = RO_INC(empty); | ||||
|                         } else { | ||||
|                             offset++; | ||||
|                         } | ||||
|                         i = RO_INC(i); | ||||
|                     } while (i != cb_tail); | ||||
|                     cb_tail = RO_SUB(cb_tail, offset); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     // add to tail | ||||
|     keyboard_report->keys[cb_tail] = code; | ||||
|     cb_tail                        = RO_INC(cb_tail); | ||||
|     cb_count++; | ||||
| #else | ||||
|     int8_t i     = 0; | ||||
|     int8_t empty = -1; | ||||
|     for (; i < KEYBOARD_REPORT_KEYS; i++) { | ||||
|         if (keyboard_report->keys[i] == code) { | ||||
|             break; | ||||
|         } | ||||
|         if (empty == -1 && keyboard_report->keys[i] == 0) { | ||||
|             empty = i; | ||||
|         } | ||||
|     } | ||||
|     if (i == KEYBOARD_REPORT_KEYS) { | ||||
|         if (empty != -1) { | ||||
|             keyboard_report->keys[empty] = code; | ||||
|         } | ||||
|     } | ||||
| #endif | ||||
| } | ||||
|  | ||||
| /** \brief del key byte | ||||
|  * | ||||
|  * FIXME: Needs doc | ||||
|  */ | ||||
| void del_key_byte(report_keyboard_t* keyboard_report, uint8_t code) { | ||||
| #ifdef RING_BUFFERED_6KRO_REPORT_ENABLE | ||||
|     uint8_t i = cb_head; | ||||
|     if (cb_count) { | ||||
|         do { | ||||
|             if (keyboard_report->keys[i] == code) { | ||||
|                 keyboard_report->keys[i] = 0; | ||||
|                 cb_count--; | ||||
|                 if (cb_count == 0) { | ||||
|                     // reset head and tail | ||||
|                     cb_tail = cb_head = 0; | ||||
|                 } | ||||
|                 if (i == RO_DEC(cb_tail)) { | ||||
|                     // left shift when next to tail | ||||
|                     do { | ||||
|                         cb_tail = RO_DEC(cb_tail); | ||||
|                         if (keyboard_report->keys[RO_DEC(cb_tail)] != 0) { | ||||
|                             break; | ||||
|                         } | ||||
|                     } while (cb_tail != cb_head); | ||||
|                 } | ||||
|                 break; | ||||
|             } | ||||
|             i = RO_INC(i); | ||||
|         } while (i != cb_tail); | ||||
|     } | ||||
| #else | ||||
|     for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) { | ||||
|         if (keyboard_report->keys[i] == code) { | ||||
|             keyboard_report->keys[i] = 0; | ||||
|         } | ||||
|     } | ||||
| #endif | ||||
| } | ||||
|  | ||||
| #ifdef NKRO_ENABLE | ||||
| /** \brief add key bit | ||||
|  * | ||||
|  * FIXME: Needs doc | ||||
|  */ | ||||
| void add_key_bit(report_keyboard_t* keyboard_report, uint8_t code) { | ||||
|     if ((code >> 3) < KEYBOARD_REPORT_BITS) { | ||||
|         keyboard_report->nkro.bits[code >> 3] |= 1 << (code & 7); | ||||
|     } else { | ||||
|         dprintf("add_key_bit: can't add: %02X\n", code); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** \brief del key bit | ||||
|  * | ||||
|  * FIXME: Needs doc | ||||
|  */ | ||||
| void del_key_bit(report_keyboard_t* keyboard_report, uint8_t code) { | ||||
|     if ((code >> 3) < KEYBOARD_REPORT_BITS) { | ||||
|         keyboard_report->nkro.bits[code >> 3] &= ~(1 << (code & 7)); | ||||
|     } else { | ||||
|         dprintf("del_key_bit: can't del: %02X\n", code); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
|  | ||||
| /** \brief add key to report | ||||
|  * | ||||
|  * FIXME: Needs doc | ||||
|  */ | ||||
| void add_key_to_report(report_keyboard_t* keyboard_report, uint8_t key) { | ||||
| #ifdef NKRO_ENABLE | ||||
|     if (keyboard_protocol && keymap_config.nkro) { | ||||
|         add_key_bit(keyboard_report, key); | ||||
|         return; | ||||
|     } | ||||
| #endif | ||||
|     add_key_byte(keyboard_report, key); | ||||
| } | ||||
|  | ||||
| /** \brief del key from report | ||||
|  * | ||||
|  * FIXME: Needs doc | ||||
|  */ | ||||
| void del_key_from_report(report_keyboard_t* keyboard_report, uint8_t key) { | ||||
| #ifdef NKRO_ENABLE | ||||
|     if (keyboard_protocol && keymap_config.nkro) { | ||||
|         del_key_bit(keyboard_report, key); | ||||
|         return; | ||||
|     } | ||||
| #endif | ||||
|     del_key_byte(keyboard_report, key); | ||||
| } | ||||
|  | ||||
| /** \brief clear key from report | ||||
|  * | ||||
|  * FIXME: Needs doc | ||||
|  */ | ||||
| void clear_keys_from_report(report_keyboard_t* keyboard_report) { | ||||
|     // not clear mods | ||||
| #ifdef NKRO_ENABLE | ||||
|     if (keyboard_protocol && keymap_config.nkro) { | ||||
|         memset(keyboard_report->nkro.bits, 0, sizeof(keyboard_report->nkro.bits)); | ||||
|         return; | ||||
|     } | ||||
| #endif | ||||
|     memset(keyboard_report->keys, 0, sizeof(keyboard_report->keys)); | ||||
| } | ||||
							
								
								
									
										325
									
								
								tmk_core/protocol/report.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										325
									
								
								tmk_core/protocol/report.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,325 @@ | ||||
| /* | ||||
| Copyright 2011,2012 Jun Wako <wakojun@gmail.com> | ||||
|  | ||||
| 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 <stdint.h> | ||||
| #include <stdbool.h> | ||||
| #include "keycode.h" | ||||
|  | ||||
| // clang-format off | ||||
|  | ||||
| /* HID report IDs */ | ||||
| enum hid_report_ids { | ||||
|     REPORT_ID_KEYBOARD = 1, | ||||
|     REPORT_ID_MOUSE, | ||||
|     REPORT_ID_SYSTEM, | ||||
|     REPORT_ID_CONSUMER, | ||||
|     REPORT_ID_PROGRAMMABLE_BUTTON, | ||||
|     REPORT_ID_NKRO, | ||||
|     REPORT_ID_JOYSTICK, | ||||
|     REPORT_ID_DIGITIZER | ||||
| }; | ||||
|  | ||||
| /* Mouse buttons */ | ||||
| #define MOUSE_BTN_MASK(n) (1 << (n)) | ||||
| enum mouse_buttons { | ||||
|     MOUSE_BTN1 = MOUSE_BTN_MASK(0), | ||||
|     MOUSE_BTN2 = MOUSE_BTN_MASK(1), | ||||
|     MOUSE_BTN3 = MOUSE_BTN_MASK(2), | ||||
|     MOUSE_BTN4 = MOUSE_BTN_MASK(3), | ||||
|     MOUSE_BTN5 = MOUSE_BTN_MASK(4), | ||||
|     MOUSE_BTN6 = MOUSE_BTN_MASK(5), | ||||
|     MOUSE_BTN7 = MOUSE_BTN_MASK(6), | ||||
|     MOUSE_BTN8 = MOUSE_BTN_MASK(7) | ||||
| }; | ||||
|  | ||||
| /* Consumer Page (0x0C) | ||||
|  * | ||||
|  * See https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf#page=75 | ||||
|  */ | ||||
| enum consumer_usages { | ||||
|     // 15.5 Display Controls | ||||
|     SNAPSHOT               = 0x065, | ||||
|     BRIGHTNESS_UP          = 0x06F, // https://www.usb.org/sites/default/files/hutrr41_0.pdf | ||||
|     BRIGHTNESS_DOWN        = 0x070, | ||||
|     // 15.7 Transport Controls | ||||
|     TRANSPORT_RECORD       = 0x0B2, | ||||
|     TRANSPORT_FAST_FORWARD = 0x0B3, | ||||
|     TRANSPORT_REWIND       = 0x0B4, | ||||
|     TRANSPORT_NEXT_TRACK   = 0x0B5, | ||||
|     TRANSPORT_PREV_TRACK   = 0x0B6, | ||||
|     TRANSPORT_STOP         = 0x0B7, | ||||
|     TRANSPORT_EJECT        = 0x0B8, | ||||
|     TRANSPORT_RANDOM_PLAY  = 0x0B9, | ||||
|     TRANSPORT_STOP_EJECT   = 0x0CC, | ||||
|     TRANSPORT_PLAY_PAUSE   = 0x0CD, | ||||
|     // 15.9.1 Audio Controls - Volume | ||||
|     AUDIO_MUTE             = 0x0E2, | ||||
|     AUDIO_VOL_UP           = 0x0E9, | ||||
|     AUDIO_VOL_DOWN         = 0x0EA, | ||||
|     // 15.15 Application Launch Buttons | ||||
|     AL_CC_CONFIG           = 0x183, | ||||
|     AL_EMAIL               = 0x18A, | ||||
|     AL_CALCULATOR          = 0x192, | ||||
|     AL_LOCAL_BROWSER       = 0x194, | ||||
|     AL_LOCK                = 0x19E, | ||||
|     AL_CONTROL_PANEL       = 0x19F, | ||||
|     AL_ASSISTANT           = 0x1CB, | ||||
|     AL_KEYBOARD_LAYOUT     = 0x1AE, | ||||
|     // 15.16 Generic GUI Application Controls | ||||
|     AC_NEW                 = 0x201, | ||||
|     AC_OPEN                = 0x202, | ||||
|     AC_CLOSE               = 0x203, | ||||
|     AC_EXIT                = 0x204, | ||||
|     AC_MAXIMIZE            = 0x205, | ||||
|     AC_MINIMIZE            = 0x206, | ||||
|     AC_SAVE                = 0x207, | ||||
|     AC_PRINT               = 0x208, | ||||
|     AC_PROPERTIES          = 0x209, | ||||
|     AC_UNDO                = 0x21A, | ||||
|     AC_COPY                = 0x21B, | ||||
|     AC_CUT                 = 0x21C, | ||||
|     AC_PASTE               = 0x21D, | ||||
|     AC_SELECT_ALL          = 0x21E, | ||||
|     AC_FIND                = 0x21F, | ||||
|     AC_SEARCH              = 0x221, | ||||
|     AC_HOME                = 0x223, | ||||
|     AC_BACK                = 0x224, | ||||
|     AC_FORWARD             = 0x225, | ||||
|     AC_STOP                = 0x226, | ||||
|     AC_REFRESH             = 0x227, | ||||
|     AC_BOOKMARKS           = 0x22A | ||||
| }; | ||||
|  | ||||
| /* Generic Desktop Page (0x01) | ||||
|  * | ||||
|  * See https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf#page=26 | ||||
|  */ | ||||
| enum desktop_usages { | ||||
|     // 4.5.1 System Controls - Power Controls | ||||
|     SYSTEM_POWER_DOWN             = 0x81, | ||||
|     SYSTEM_SLEEP                  = 0x82, | ||||
|     SYSTEM_WAKE_UP                = 0x83, | ||||
|     SYSTEM_RESTART                = 0x8F, | ||||
|     // 4.10 System Display Controls | ||||
|     SYSTEM_DISPLAY_TOGGLE_INT_EXT = 0xB5 | ||||
| }; | ||||
|  | ||||
| // clang-format on | ||||
|  | ||||
| #define NKRO_SHARED_EP | ||||
| /* key report size(NKRO or boot mode) */ | ||||
| #if defined(NKRO_ENABLE) | ||||
| #    if defined(PROTOCOL_LUFA) || defined(PROTOCOL_CHIBIOS) | ||||
| #        include "protocol/usb_descriptor.h" | ||||
| #        define KEYBOARD_REPORT_BITS (SHARED_EPSIZE - 2) | ||||
| #    elif defined(PROTOCOL_ARM_ATSAM) | ||||
| #        include "protocol/arm_atsam/usb/udi_device_epsize.h" | ||||
| #        define KEYBOARD_REPORT_BITS (NKRO_EPSIZE - 1) | ||||
| #        undef NKRO_SHARED_EP | ||||
| #        undef MOUSE_SHARED_EP | ||||
| #    else | ||||
| #        error "NKRO not supported with this protocol" | ||||
| #    endif | ||||
| #endif | ||||
|  | ||||
| #ifdef KEYBOARD_SHARED_EP | ||||
| #    define KEYBOARD_REPORT_SIZE 9 | ||||
| #else | ||||
| #    define KEYBOARD_REPORT_SIZE 8 | ||||
| #endif | ||||
|  | ||||
| #define KEYBOARD_REPORT_KEYS 6 | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
|  | ||||
| /* | ||||
|  * keyboard report is 8-byte array retains state of 8 modifiers and 6 keys. | ||||
|  * | ||||
|  * byte |0       |1       |2       |3       |4       |5       |6       |7 | ||||
|  * -----+--------+--------+--------+--------+--------+--------+--------+-------- | ||||
|  * desc |mods    |reserved|keys[0] |keys[1] |keys[2] |keys[3] |keys[4] |keys[5] | ||||
|  * | ||||
|  * It is exended to 16 bytes to retain 120keys+8mods when NKRO mode. | ||||
|  * | ||||
|  * byte |0       |1       |2       |3       |4       |5       |6       |7        ... |15 | ||||
|  * -----+--------+--------+--------+--------+--------+--------+--------+--------     +-------- | ||||
|  * desc |mods    |bits[0] |bits[1] |bits[2] |bits[3] |bits[4] |bits[5] |bits[6]  ... |bit[14] | ||||
|  * | ||||
|  * mods retains state of 8 modifiers. | ||||
|  * | ||||
|  *  bit |0       |1       |2       |3       |4       |5       |6       |7 | ||||
|  * -----+--------+--------+--------+--------+--------+--------+--------+-------- | ||||
|  * desc |Lcontrol|Lshift  |Lalt    |Lgui    |Rcontrol|Rshift  |Ralt    |Rgui | ||||
|  * | ||||
|  */ | ||||
| typedef union { | ||||
|     uint8_t raw[KEYBOARD_REPORT_SIZE]; | ||||
|     struct { | ||||
| #ifdef KEYBOARD_SHARED_EP | ||||
|         uint8_t report_id; | ||||
| #endif | ||||
|         uint8_t mods; | ||||
|         uint8_t reserved; | ||||
|         uint8_t keys[KEYBOARD_REPORT_KEYS]; | ||||
|     }; | ||||
| #ifdef NKRO_ENABLE | ||||
|     struct nkro_report { | ||||
| #    ifdef NKRO_SHARED_EP | ||||
|         uint8_t report_id; | ||||
| #    endif | ||||
|         uint8_t mods; | ||||
|         uint8_t bits[KEYBOARD_REPORT_BITS]; | ||||
|     } nkro; | ||||
| #endif | ||||
| } __attribute__((packed)) report_keyboard_t; | ||||
|  | ||||
| typedef struct { | ||||
|     uint8_t  report_id; | ||||
|     uint16_t usage; | ||||
| } __attribute__((packed)) report_extra_t; | ||||
|  | ||||
| typedef struct { | ||||
|     uint8_t  report_id; | ||||
|     uint32_t usage; | ||||
| } __attribute__((packed)) report_programmable_button_t; | ||||
|  | ||||
| typedef struct { | ||||
| #ifdef MOUSE_SHARED_EP | ||||
|     uint8_t report_id; | ||||
| #endif | ||||
|     uint8_t buttons; | ||||
|     int8_t  x; | ||||
|     int8_t  y; | ||||
|     int8_t  v; | ||||
|     int8_t  h; | ||||
| } __attribute__((packed)) report_mouse_t; | ||||
|  | ||||
| typedef struct { | ||||
| #ifdef DIGITIZER_SHARED_EP | ||||
|     uint8_t report_id; | ||||
| #endif | ||||
|     uint8_t  tip : 1; | ||||
|     uint8_t  inrange : 1; | ||||
|     uint8_t  pad2 : 6; | ||||
|     uint16_t x; | ||||
|     uint16_t y; | ||||
| } __attribute__((packed)) report_digitizer_t; | ||||
|  | ||||
| typedef struct { | ||||
| #if JOYSTICK_AXES_COUNT > 0 | ||||
| #    if JOYSTICK_AXES_RESOLUTION > 8 | ||||
|     int16_t axes[JOYSTICK_AXES_COUNT]; | ||||
| #    else | ||||
|     int8_t axes[JOYSTICK_AXES_COUNT]; | ||||
| #    endif | ||||
| #endif | ||||
|  | ||||
| #if JOYSTICK_BUTTON_COUNT > 0 | ||||
|     uint8_t buttons[(JOYSTICK_BUTTON_COUNT - 1) / 8 + 1]; | ||||
| #endif | ||||
| } __attribute__((packed)) joystick_report_t; | ||||
|  | ||||
| /* keycode to system usage */ | ||||
| static inline uint16_t KEYCODE2SYSTEM(uint8_t key) { | ||||
|     switch (key) { | ||||
|         case KC_SYSTEM_POWER: | ||||
|             return SYSTEM_POWER_DOWN; | ||||
|         case KC_SYSTEM_SLEEP: | ||||
|             return SYSTEM_SLEEP; | ||||
|         case KC_SYSTEM_WAKE: | ||||
|             return SYSTEM_WAKE_UP; | ||||
|         default: | ||||
|             return 0; | ||||
|     } | ||||
| } | ||||
|  | ||||
| /* keycode to consumer usage */ | ||||
| static inline uint16_t KEYCODE2CONSUMER(uint8_t key) { | ||||
|     switch (key) { | ||||
|         case KC_AUDIO_MUTE: | ||||
|             return AUDIO_MUTE; | ||||
|         case KC_AUDIO_VOL_UP: | ||||
|             return AUDIO_VOL_UP; | ||||
|         case KC_AUDIO_VOL_DOWN: | ||||
|             return AUDIO_VOL_DOWN; | ||||
|         case KC_MEDIA_NEXT_TRACK: | ||||
|             return TRANSPORT_NEXT_TRACK; | ||||
|         case KC_MEDIA_PREV_TRACK: | ||||
|             return TRANSPORT_PREV_TRACK; | ||||
|         case KC_MEDIA_FAST_FORWARD: | ||||
|             return TRANSPORT_FAST_FORWARD; | ||||
|         case KC_MEDIA_REWIND: | ||||
|             return TRANSPORT_REWIND; | ||||
|         case KC_MEDIA_STOP: | ||||
|             return TRANSPORT_STOP; | ||||
|         case KC_MEDIA_EJECT: | ||||
|             return TRANSPORT_STOP_EJECT; | ||||
|         case KC_MEDIA_PLAY_PAUSE: | ||||
|             return TRANSPORT_PLAY_PAUSE; | ||||
|         case KC_MEDIA_SELECT: | ||||
|             return AL_CC_CONFIG; | ||||
|         case KC_MAIL: | ||||
|             return AL_EMAIL; | ||||
|         case KC_CALCULATOR: | ||||
|             return AL_CALCULATOR; | ||||
|         case KC_MY_COMPUTER: | ||||
|             return AL_LOCAL_BROWSER; | ||||
|         case KC_WWW_SEARCH: | ||||
|             return AC_SEARCH; | ||||
|         case KC_WWW_HOME: | ||||
|             return AC_HOME; | ||||
|         case KC_WWW_BACK: | ||||
|             return AC_BACK; | ||||
|         case KC_WWW_FORWARD: | ||||
|             return AC_FORWARD; | ||||
|         case KC_WWW_STOP: | ||||
|             return AC_STOP; | ||||
|         case KC_WWW_REFRESH: | ||||
|             return AC_REFRESH; | ||||
|         case KC_BRIGHTNESS_UP: | ||||
|             return BRIGHTNESS_UP; | ||||
|         case KC_BRIGHTNESS_DOWN: | ||||
|             return BRIGHTNESS_DOWN; | ||||
|         case KC_WWW_FAVORITES: | ||||
|             return AC_BOOKMARKS; | ||||
|         default: | ||||
|             return 0; | ||||
|     } | ||||
| } | ||||
|  | ||||
| uint8_t has_anykey(report_keyboard_t* keyboard_report); | ||||
| uint8_t get_first_key(report_keyboard_t* keyboard_report); | ||||
| bool    is_key_pressed(report_keyboard_t* keyboard_report, uint8_t key); | ||||
|  | ||||
| void add_key_byte(report_keyboard_t* keyboard_report, uint8_t code); | ||||
| void del_key_byte(report_keyboard_t* keyboard_report, uint8_t code); | ||||
| #ifdef NKRO_ENABLE | ||||
| void add_key_bit(report_keyboard_t* keyboard_report, uint8_t code); | ||||
| void del_key_bit(report_keyboard_t* keyboard_report, uint8_t code); | ||||
| #endif | ||||
|  | ||||
| void add_key_to_report(report_keyboard_t* keyboard_report, uint8_t key); | ||||
| void del_key_from_report(report_keyboard_t* keyboard_report, uint8_t key); | ||||
| void clear_keys_from_report(report_keyboard_t* keyboard_report); | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
							
								
								
									
										51
									
								
								tmk_core/protocol/usb_device_state.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								tmk_core/protocol/usb_device_state.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | ||||
| /* | ||||
|  * Copyright 2021 Andrei Purdea <andrei@purdea.ro> | ||||
|  * | ||||
|  * 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/>. | ||||
|  */ | ||||
|  | ||||
| #include "usb_device_state.h" | ||||
|  | ||||
| enum usb_device_state usb_device_state = USB_DEVICE_STATE_NO_INIT; | ||||
|  | ||||
| __attribute__((weak)) void notify_usb_device_state_change_kb(enum usb_device_state usb_device_state) { notify_usb_device_state_change_user(usb_device_state); } | ||||
|  | ||||
| __attribute__((weak)) void notify_usb_device_state_change_user(enum usb_device_state usb_device_state) {} | ||||
|  | ||||
| static void notify_usb_device_state_change(enum usb_device_state usb_device_state) { notify_usb_device_state_change_kb(usb_device_state); } | ||||
|  | ||||
| void usb_device_state_set_configuration(bool isConfigured, uint8_t configurationNumber) { | ||||
|     usb_device_state = isConfigured ? USB_DEVICE_STATE_CONFIGURED : USB_DEVICE_STATE_INIT; | ||||
|     notify_usb_device_state_change(usb_device_state); | ||||
| } | ||||
|  | ||||
| void usb_device_state_set_suspend(bool isConfigured, uint8_t configurationNumber) { | ||||
|     usb_device_state = USB_DEVICE_STATE_SUSPEND; | ||||
|     notify_usb_device_state_change(usb_device_state); | ||||
| } | ||||
|  | ||||
| void usb_device_state_set_resume(bool isConfigured, uint8_t configurationNumber) { | ||||
|     usb_device_state = isConfigured ? USB_DEVICE_STATE_CONFIGURED : USB_DEVICE_STATE_INIT; | ||||
|     notify_usb_device_state_change(usb_device_state); | ||||
| } | ||||
|  | ||||
| void usb_device_state_set_reset(void) { | ||||
|     usb_device_state = USB_DEVICE_STATE_INIT; | ||||
|     notify_usb_device_state_change(usb_device_state); | ||||
| } | ||||
|  | ||||
| void usb_device_state_init(void) { | ||||
|     usb_device_state = USB_DEVICE_STATE_INIT; | ||||
|     notify_usb_device_state_change(usb_device_state); | ||||
| } | ||||
							
								
								
									
										39
									
								
								tmk_core/protocol/usb_device_state.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								tmk_core/protocol/usb_device_state.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| /* | ||||
|  * Copyright 2021 Andrei Purdea <andrei@purdea.ro> | ||||
|  * | ||||
|  * 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 <stdbool.h> | ||||
| #include <stdint.h> | ||||
|  | ||||
| void usb_device_state_set_configuration(bool isConfigured, uint8_t configurationNumber); | ||||
| void usb_device_state_set_suspend(bool isConfigured, uint8_t configurationNumber); | ||||
| void usb_device_state_set_resume(bool isConfigured, uint8_t configurationNumber); | ||||
| void usb_device_state_set_reset(void); | ||||
| void usb_device_state_init(void); | ||||
|  | ||||
| enum usb_device_state { | ||||
|     USB_DEVICE_STATE_NO_INIT    = 0,  // We're in this state before calling usb_device_state_init() | ||||
|     USB_DEVICE_STATE_INIT       = 1,  // Can consume up to 100mA | ||||
|     USB_DEVICE_STATE_CONFIGURED = 2,  // Can consume up to what is specified in configuration descriptor, typically 500mA | ||||
|     USB_DEVICE_STATE_SUSPEND    = 3   // Can consume only suspend current | ||||
| }; | ||||
|  | ||||
| extern enum usb_device_state usb_device_state; | ||||
|  | ||||
| void notify_usb_device_state_change_kb(enum usb_device_state usb_device_state); | ||||
| void notify_usb_device_state_change_user(enum usb_device_state usb_device_state); | ||||
							
								
								
									
										29
									
								
								tmk_core/protocol/usb_util.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								tmk_core/protocol/usb_util.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| /* Copyright 2021 QMK | ||||
|  * | ||||
|  * 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 3 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/>. | ||||
|  */ | ||||
| #include "quantum.h" | ||||
| #include "usb_util.h" | ||||
|  | ||||
| __attribute__((weak)) void usb_disconnect(void) {} | ||||
| __attribute__((weak)) bool usb_connected_state(void) { return true; } | ||||
| __attribute__((weak)) bool usb_vbus_state(void) { | ||||
| #ifdef USB_VBUS_PIN | ||||
|     setPinInput(USB_VBUS_PIN); | ||||
|     wait_us(5); | ||||
|     return readPin(USB_VBUS_PIN); | ||||
| #else | ||||
|     return true; | ||||
| #endif | ||||
| } | ||||
							
								
								
									
										22
									
								
								tmk_core/protocol/usb_util.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								tmk_core/protocol/usb_util.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| /* Copyright 2021 QMK | ||||
|  * | ||||
|  * 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 3 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 <stdbool.h> | ||||
|  | ||||
| void usb_disconnect(void); | ||||
| bool usb_connected_state(void); | ||||
| bool usb_vbus_state(void); | ||||
		Reference in New Issue
	
	Block a user