diff options
Diffstat (limited to 'tmk_core/protocol/chibios')
| -rw-r--r-- | tmk_core/protocol/chibios/usb_driver.c | 14 | ||||
| -rw-r--r-- | tmk_core/protocol/chibios/usb_main.c | 29 |
2 files changed, 27 insertions, 16 deletions
diff --git a/tmk_core/protocol/chibios/usb_driver.c b/tmk_core/protocol/chibios/usb_driver.c index 40bfb8eb2..cc0ce7600 100644 --- a/tmk_core/protocol/chibios/usb_driver.c +++ b/tmk_core/protocol/chibios/usb_driver.c | |||
| @@ -80,19 +80,7 @@ static bool qmkusb_start_receive(QMKUSBDriver *qmkusbp) { | |||
| 80 | * Interface implementation. | 80 | * Interface implementation. |
| 81 | */ | 81 | */ |
| 82 | 82 | ||
| 83 | static size_t _write(void *ip, const uint8_t *bp, size_t n) { | 83 | static size_t _write(void *ip, const uint8_t *bp, size_t n) { return obqWriteTimeout(&((QMKUSBDriver *)ip)->obqueue, bp, n, TIME_INFINITE); } |
| 84 | output_buffers_queue_t *obqueue = &((QMKUSBDriver *)ip)->obqueue; | ||
| 85 | chSysLock(); | ||
| 86 | const bool full = obqIsFullI(obqueue); | ||
| 87 | chSysUnlock(); | ||
| 88 | if (full || bqIsSuspendedX(obqueue)) { | ||
| 89 | /* Discard any writes while the queue is suspended or full, i.e. the hidraw | ||
| 90 | interface is not open. If we tried to send with an infinite timeout, we | ||
| 91 | would deadlock the keyboard otherwise. */ | ||
| 92 | return -1; | ||
| 93 | } | ||
| 94 | return obqWriteTimeout(obqueue, bp, n, TIME_INFINITE); | ||
| 95 | } | ||
| 96 | 84 | ||
| 97 | static size_t _read(void *ip, uint8_t *bp, size_t n) { return ibqReadTimeout(&((QMKUSBDriver *)ip)->ibqueue, bp, n, TIME_INFINITE); } | 85 | static size_t _read(void *ip, uint8_t *bp, size_t n) { return ibqReadTimeout(&((QMKUSBDriver *)ip)->ibqueue, bp, n, TIME_INFINITE); } |
| 98 | 86 | ||
diff --git a/tmk_core/protocol/chibios/usb_main.c b/tmk_core/protocol/chibios/usb_main.c index 8adecfa71..0703cdc71 100644 --- a/tmk_core/protocol/chibios/usb_main.c +++ b/tmk_core/protocol/chibios/usb_main.c | |||
| @@ -930,9 +930,32 @@ void send_consumer(uint16_t data) { | |||
| 930 | #ifdef CONSOLE_ENABLE | 930 | #ifdef CONSOLE_ENABLE |
| 931 | 931 | ||
| 932 | int8_t sendchar(uint8_t c) { | 932 | int8_t sendchar(uint8_t c) { |
| 933 | // The previous implmentation had timeouts, but I think it's better to just slow down | 933 | static bool timed_out = false; |
| 934 | // and make sure that everything is transferred, rather than dropping stuff | 934 | /* The `timed_out` state is an approximation of the ideal `is_listener_disconnected?` state. |
| 935 | return chnWrite(&drivers.console_driver.driver, &c, 1); | 935 | * |
| 936 | * When a 5ms timeout write has timed out, hid_listen is most likely not running, or not | ||
| 937 | * listening to this keyboard, so we go into the timed_out state. In this state we assume | ||
| 938 | * that hid_listen is most likely not gonna be connected to us any time soon, so it would | ||
| 939 | * be wasteful to write follow-up characters with a 5ms timeout, it would all add up and | ||
| 940 | * unncecessarily slow down the firmware. However instead of just dropping the characters, | ||
| 941 | * we write them with a TIME_IMMEDIATE timeout, which is a zero timeout, | ||
| 942 | * and this will succeed only if hid_listen gets connected again. When a write with | ||
| 943 | * TIME_IMMEDIATE timeout succeeds, we know that hid_listen is listening to us again, and | ||
| 944 | * we can go back to the timed_out = false state, and following writes will be executed | ||
| 945 | * with a 5ms timeout. The reason we don't just send all characters with the TIME_IMMEDIATE | ||
| 946 | * timeout is that this could cause bytes to be lost even if hid_listen is running, if there | ||
| 947 | * is a lot of data being sent over the console. | ||
| 948 | * | ||
| 949 | * This logic will work correctly as long as hid_listen is able to receive at least 200 | ||
| 950 | * bytes per second. On a heavily overloaded machine that's so overloaded that it's | ||
| 951 | * unusable, and constantly swapping, hid_listen might have trouble receiving 200 bytes per | ||
| 952 | * second, so some bytes might be lost on the console. | ||
| 953 | */ | ||
| 954 | |||
| 955 | const sysinterval_t timeout = timed_out ? TIME_IMMEDIATE : TIME_MS2I(5); | ||
| 956 | const size_t result = chnWriteTimeout(&drivers.console_driver.driver, &c, 1, timeout); | ||
| 957 | timed_out = (result == 0); | ||
| 958 | return result; | ||
| 936 | } | 959 | } |
| 937 | 960 | ||
| 938 | // Just a dummy function for now, this could be exposed as a weak function | 961 | // Just a dummy function for now, this could be exposed as a weak function |
