-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathhid_report_buffer.cc
110 lines (87 loc) · 3.14 KB
/
hid_report_buffer.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
//---------------------------------------------------------------------------
#include "hid_report_buffer.h"
#include "javelin/clock.h"
#include "javelin/console.h"
#include "split_hid_report_buffer.h"
#include "usb_descriptors.h"
#include <string.h>
#include <tusb.h>
//---------------------------------------------------------------------------
constexpr uint32_t FULL_BUFFER_RESET_TIMEOUT = 50;
//---------------------------------------------------------------------------
uint32_t HidReportBufferBase::reportsSentCount[ITF_NUM_TOTAL] = {};
//---------------------------------------------------------------------------
void HidReportBufferBase::SendReport(uint8_t reportId, const uint8_t *data,
size_t length) {
PumpUntilNotFull();
const bool triggerSend = startIndex == endIndex;
if (triggerSend) {
if (!tud_hid_n_ready(instanceNumber)) {
#if JAVELIN_SPLIT
if (Split::IsMaster() &&
Connection::IsPairConnected(PairConnectionId::ACTIVE)) {
reportsSentCount[instanceNumber]++;
SplitHidReportBuffer::Add(instanceNumber, reportId, data, length);
}
#endif
return;
}
if (tud_hid_n_report(instanceNumber, reportId, data, length)) {
++endIndex;
reportsSentCount[instanceNumber]++;
}
return;
}
const size_t entryIndex = endIndex++ & (NUMBER_OF_ENTRIES - 1);
Entry *entry = GetEntry(entryIndex);
entry->length = length;
entry->reportId = reportId;
memcpy(entry->data, data, length);
}
//---------------------------------------------------------------------------
void HidReportBufferBase::SendNextReport() {
// This should never happen!
if (startIndex == endIndex) {
return;
}
for (;;) {
++startIndex;
if (startIndex == endIndex) {
return;
}
const size_t entryIndex = startIndex & (NUMBER_OF_ENTRIES - 1);
const Entry *entry = GetEntry(entryIndex);
reportsSentCount[instanceNumber]++;
if (tud_hid_n_report(instanceNumber, entry->reportId, entry->data,
entry->length)) {
return;
}
}
}
//---------------------------------------------------------------------------
void HidReportBufferBase::PumpUntilNotFull() {
// Android and Linux do not read 'un-attached' usb endpoints, leading the
// console to end up in an infinite waiting loop to have a free entry.
//
// To protect against this, check if there's no progress for a period of time
// and reset the buffer if so.
const size_t startTime = Clock::GetMilliseconds();
for (;;) {
tud_task();
if (!IsFull()) {
return;
}
if (Clock::GetMilliseconds() - startTime > FULL_BUFFER_RESET_TIMEOUT) {
Reset();
return;
}
}
}
//---------------------------------------------------------------------------
void HidReportBufferBase::PrintInfo() {
Console::Printf("HID reports sent\n");
Console::Printf(" Keyboard: %u\n", reportsSentCount[ITF_NUM_KEYBOARD]);
Console::Printf(" Plover HID: %u\n", reportsSentCount[ITF_NUM_PLOVER_HID]);
Console::Printf(" Console: %u\n", reportsSentCount[ITF_NUM_CONSOLE]);
}
//---------------------------------------------------------------------------