report.c (5734B)
1 /* Copyright 2017 Fred Sundvik 2 * 3 * This program is free software: you can redistribute it and/or modify 4 * it under the terms of the GNU General Public License as published by 5 * the Free Software Foundation, either version 2 of the License, or 6 * (at your option) any later version. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 * You should have received a copy of the GNU General Public License 14 * along with this program. If not, see <http://www.gnu.org/licenses/>. 15 */ 16 17 #include "report.h" 18 #include "action_util.h" 19 #include "host.h" 20 #include "keycode_config.h" 21 #include "debug.h" 22 #include "usb_device_state.h" 23 #include "util.h" 24 #include <string.h> 25 26 /** \brief has_anykey 27 * 28 * FIXME: Needs doc 29 */ 30 uint8_t has_anykey(void) { 31 uint8_t cnt = 0; 32 uint8_t* p = keyboard_report->keys; 33 uint8_t lp = sizeof(keyboard_report->keys); 34 #ifdef NKRO_ENABLE 35 if (host_can_send_nkro() && keymap_config.nkro) { 36 p = nkro_report->bits; 37 lp = sizeof(nkro_report->bits); 38 } 39 #endif 40 while (lp--) { 41 if (*p++) cnt++; 42 } 43 return cnt; 44 } 45 46 /** \brief get_first_key 47 * 48 * FIXME: Needs doc 49 */ 50 uint8_t get_first_key(void) { 51 #ifdef NKRO_ENABLE 52 if (host_can_send_nkro() && keymap_config.nkro) { 53 uint8_t i = 0; 54 for (; i < NKRO_REPORT_BITS && !nkro_report->bits[i]; i++) 55 ; 56 return i << 3 | biton(nkro_report->bits[i]); 57 } 58 #endif 59 return keyboard_report->keys[0]; 60 } 61 62 /** \brief Checks if a key is pressed in the report 63 * 64 * Returns true if the keyboard_report reports that the key is pressed, otherwise false 65 * Note: The function doesn't support modifiers currently, and it returns false for KC_NO 66 */ 67 bool is_key_pressed(uint8_t key) { 68 if (key == KC_NO) { 69 return false; 70 } 71 #ifdef NKRO_ENABLE 72 if (host_can_send_nkro() && keymap_config.nkro) { 73 if ((key >> 3) < NKRO_REPORT_BITS) { 74 return nkro_report->bits[key >> 3] & 1 << (key & 7); 75 } else { 76 return false; 77 } 78 } 79 #endif 80 for (int i = 0; i < KEYBOARD_REPORT_KEYS; i++) { 81 if (keyboard_report->keys[i] == key) { 82 return true; 83 } 84 } 85 return false; 86 } 87 88 /** \brief add key byte 89 * 90 * FIXME: Needs doc 91 */ 92 void add_key_byte(report_keyboard_t* keyboard_report, uint8_t code) { 93 int8_t i = 0; 94 int8_t empty = -1; 95 for (; i < KEYBOARD_REPORT_KEYS; i++) { 96 if (keyboard_report->keys[i] == code) { 97 break; 98 } 99 if (empty == -1 && keyboard_report->keys[i] == 0) { 100 empty = i; 101 } 102 } 103 if (i == KEYBOARD_REPORT_KEYS) { 104 if (empty != -1) { 105 keyboard_report->keys[empty] = code; 106 } 107 } 108 } 109 110 /** \brief del key byte 111 * 112 * FIXME: Needs doc 113 */ 114 void del_key_byte(report_keyboard_t* keyboard_report, uint8_t code) { 115 for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) { 116 if (keyboard_report->keys[i] == code) { 117 keyboard_report->keys[i] = 0; 118 } 119 } 120 } 121 122 #ifdef NKRO_ENABLE 123 /** \brief add key bit 124 * 125 * FIXME: Needs doc 126 */ 127 void add_key_bit(report_nkro_t* nkro_report, uint8_t code) { 128 if ((code >> 3) < NKRO_REPORT_BITS) { 129 nkro_report->bits[code >> 3] |= 1 << (code & 7); 130 } else { 131 dprintf("add_key_bit: can't add: %02X\n", code); 132 } 133 } 134 135 /** \brief del key bit 136 * 137 * FIXME: Needs doc 138 */ 139 void del_key_bit(report_nkro_t* nkro_report, uint8_t code) { 140 if ((code >> 3) < NKRO_REPORT_BITS) { 141 nkro_report->bits[code >> 3] &= ~(1 << (code & 7)); 142 } else { 143 dprintf("del_key_bit: can't del: %02X\n", code); 144 } 145 } 146 #endif 147 148 /** \brief add key to report 149 * 150 * FIXME: Needs doc 151 */ 152 void add_key_to_report(uint8_t key) { 153 #ifdef NKRO_ENABLE 154 if (host_can_send_nkro() && keymap_config.nkro) { 155 add_key_bit(nkro_report, key); 156 return; 157 } 158 #endif 159 add_key_byte(keyboard_report, key); 160 } 161 162 /** \brief del key from report 163 * 164 * FIXME: Needs doc 165 */ 166 void del_key_from_report(uint8_t key) { 167 #ifdef NKRO_ENABLE 168 if (host_can_send_nkro() && keymap_config.nkro) { 169 del_key_bit(nkro_report, key); 170 return; 171 } 172 #endif 173 del_key_byte(keyboard_report, key); 174 } 175 176 /** \brief clear key from report 177 * 178 * FIXME: Needs doc 179 */ 180 void clear_keys_from_report(void) { 181 // not clear mods 182 #ifdef NKRO_ENABLE 183 if (host_can_send_nkro() && keymap_config.nkro) { 184 memset(nkro_report->bits, 0, sizeof(nkro_report->bits)); 185 return; 186 } 187 #endif 188 memset(keyboard_report->keys, 0, sizeof(keyboard_report->keys)); 189 } 190 191 #ifdef MOUSE_ENABLE 192 /** 193 * @brief Compares 2 mouse reports for difference and returns result. Empty 194 * reports always evaluate as unchanged. 195 * 196 * @param[in] new_report report_mouse_t 197 * @param[in] old_report report_mouse_t 198 * @return bool result 199 */ 200 __attribute__((weak)) bool has_mouse_report_changed(report_mouse_t* new_report, report_mouse_t* old_report) { 201 // memcmp doesn't work here because of the `report_id` field when using 202 // shared mouse endpoint 203 bool changed = ((new_report->buttons != old_report->buttons) || 204 # ifdef MOUSE_EXTENDED_REPORT 205 (new_report->boot_x != 0 && new_report->boot_x != old_report->boot_x) || (new_report->boot_y != 0 && new_report->boot_y != old_report->boot_y) || 206 # endif 207 (new_report->x != 0 && new_report->x != old_report->x) || (new_report->y != 0 && new_report->y != old_report->y) || (new_report->h != 0 && new_report->h != old_report->h) || (new_report->v != 0 && new_report->v != old_report->v)); 208 return changed; 209 } 210 #endif