qmk_firmware

QMK firmware for my keyboards (Corne, Sweep Ferris) and trackball (Ploopy Adept)
Log | Files | Refs | Submodules | LICENSE

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