Skip to content

Commit 268c37c

Browse files
authored
Merge pull request #1573 from UltimateHackingKeyboard/adjust_scheduling_simplified2
More jitter adjustments. Rest is peripheral vs central clock drifts :-/.
2 parents 0009fc6 + f49b58c commit 268c37c

8 files changed

Lines changed: 58 additions & 40 deletions

File tree

device/src/bt_conn.c

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,6 @@ struct bt_conn *auth_conn;
5050

5151
uint32_t Bt_LastConnectedTime = 0;
5252

53-
// Last negotiated BLE HID connection interval in milliseconds. Updated by
54-
// infoLatencyParamsUpdated when the active peer is a BLE HID host. Used by the
55-
// report-throttling logic to size the next-window estimate; otherwise on hosts
56-
// that negotiate below our default we would systematically miss send slots.
57-
uint32_t BleHidReportIntervalMs = 11;
58-
5953
/*
6054
* Reason codes are named from the perspective of the party that receives them.
6155
*
@@ -273,6 +267,13 @@ static struct bt_conn_le_data_len_param *data_len;
273267
static void enableDataLengthExtension(struct bt_conn *conn) {
274268
data_len = BT_LE_DATA_LEN_PARAM_MAX;
275269

270+
/**
271+
* This configures actual transmission length.
272+
*
273+
* We don't want it too high in order to prevent scheduling conflicts between multiple links.
274+
* */
275+
data_len->tx_max_time = 2500;
276+
276277
int err = bt_conn_le_data_len_update(conn, data_len);
277278
if (err) {
278279
LOG_INF("LE data length update failed: %d", err);
@@ -314,13 +315,10 @@ static void setLatency(struct bt_conn* conn, const struct bt_le_conn_param* para
314315
static void configureLatency(struct bt_conn *conn, latency_mode_t latencyMode) {
315316
switch (latencyMode) {
316317
case LatencyMode_NUS: {
317-
// https://developer.apple.com/library/archive/qa/qa1931/_index.html
318-
// https://punchthrough.com/manage-ble-connection/
319-
// https://devzone.nordicsemi.com/f/nordic-q-a/28058/what-is-connection-parameters
320318
const struct bt_le_conn_param conn_params = BT_LE_CONN_PARAM_INIT(
321-
6, 6, // keep it low, lowest allowed is 6 (7.5ms), lowest supported widely is 9 (11.25ms)
322-
0, // keeping it higher allows power saving on peripheral when there's nothing to send (keep it under 30 though)
323-
100 // connection timeout (*10ms)
319+
6, 6,
320+
0,
321+
100
324322
);
325323
setLatency(conn, &conn_params);
326324
}
@@ -764,7 +762,7 @@ static void securityChanged(struct bt_conn *conn, bt_security_t level, enum bt_s
764762
struct bt_conn_info info;
765763
int err = bt_conn_get_info(conn, &info);
766764
if (err == 0 && info.state == BT_CONN_STATE_CONNECTED) {
767-
bt_conn_auth_cancel(conn);
765+
// bt_conn_auth_cancel(conn);
768766
// bt_conn_disconnect(conn, BT_REASON_PERMANENT);
769767
} else {
770768
// Sometimes securityChanged gets called twice, resulting in a race and a crash, so check for it \efp.
@@ -791,22 +789,29 @@ __attribute__((unused)) static void infoLatencyParamsUpdated(struct bt_conn* con
791789
{
792790
LOG_DBG("%s conn params: interval=%u ms, latency=%u, timeout=%u ms", GetPeerStringByConn(conn), interval * 5 / 4, latency, timeout * 10);
793791

794-
connection_type_t connectionType = Connections_Type(Peers[GetPeerIdByConn(conn)].connectionId);
792+
int8_t peerId = GetPeerIdByConn(conn);
793+
connection_type_t connectionType = Connections_Type(Peers[peerId].connectionId);
795794
bool isUhkPeer = isUhkDeviceConnection(connectionType);
796795

797-
if (connectionType == ConnectionType_BtHid) {
796+
if (connectionType == ConnectionType_BtHid || connectionType == ConnectionType_NusDongle) {
798797
uint32_t intervalMs = (interval * 5 + 3) / 4;
799798
if (intervalMs < 1) {
800799
intervalMs = 1;
801800
}
802-
BleHidReportIntervalMs = intervalMs;
801+
Peers[peerId].bleReportIntervalMs = intervalMs;
803802
}
804803

805804
if (interval > 10) {
806805
configureLatency(conn, isUhkPeer ? LatencyMode_NUS : LatencyMode_BleHid);
807806
}
808807
}
809808

809+
uint32_t BtConn_GetReportIntervalMs(connection_id_t connectionId) {
810+
uint8_t peerId = Connections[connectionId].peerId;
811+
uint32_t intervalMs = Peers[peerId].bleReportIntervalMs;
812+
return intervalMs != 0 ? intervalMs : 11;
813+
}
814+
810815
BT_CONN_CB_DEFINE(conn_callbacks) = {
811816
.connected = connected,
812817
.disconnected = disconnected,

device/src/bt_conn.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
bt_addr_le_t addr;
4646
struct bt_conn* conn;
4747
uint32_t lastSwitchover;
48+
uint32_t bleReportIntervalMs;
4849
} peer_t;
4950

5051
typedef enum {
@@ -57,11 +58,11 @@ typedef enum {
5758
extern peer_t Peers[];
5859
extern bool Bt_NewPairedDevice;
5960
extern uint32_t Bt_LastConnectedTime;
60-
extern uint32_t BleHidReportIntervalMs;
6161

6262
// Functions:
6363

6464
int8_t GetPeerIdByConn(const struct bt_conn *conn);
65+
uint32_t BtConn_GetReportIntervalMs(connection_id_t connectionId);
6566
char *GetPeerStringByAddr(const bt_addr_le_t *addr);
6667
char *GetPeerStringByConn(const struct bt_conn *conn);
6768
char *GetPeerStringByConnId(uint8_t connectionId);

device/src/shell/shell_commands.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -443,7 +443,11 @@ static int cmd_uhk_jitterTest(const struct shell *shell, size_t argc, char *argv
443443
if (argc == 1) {
444444
shell_fprintf(shell, SHELL_NORMAL, "%i\n", JitterTest_Active ? 1 : 0);
445445
} else {
446-
JitterTest_SetActive(argv[1][0] == '1');
446+
bool active = argv[1][0] == '1';
447+
JitterTest_SetActive(active);
448+
if (active) {
449+
LogU("For jitter test, please make sure that your right half has keystrokeDelay set to 0.\n");
450+
}
447451
}
448452
return 0;
449453
}

doc-dev/other/testing_scenarios.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Following is a list testing suggestions. Not all have to be tested each time.
1212
- Pair two ble hids using `bluetooth pair` while all devices are active.
1313
- Unregistered slot connections: try to add a ble hid without registering it in Agent. Change registered connection count and save the userconfig. Check that the ble hid remaind in the same slot (unless another host connection took that slot - in that case, it should be in the first availalbe slot).
1414
- If moving currently connected device's host connection to another position, check that saving the UserConfig doesn't disconnect it - it should be remapped to the new slot by itself.
15+
- Connect dongle. Switch to it. Then disconnect it. Connect it again. Does it connect? (Repeat a couple of times.)
1516

1617
Todos:
1718
- deduplicate and reorder these scenarios.

right/src/config_manager.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ const config_t DefaultCfg = (config_t){
280280
.Bt_AllowUnsecuredConnections = false,
281281
.Bt_MaxPeripheralConnections = 3,
282282
.Bt_AlwaysAdvertiseHid = true,
283-
.Bt_DirectedAdvertisingAllowed = true,
283+
.Bt_DirectedAdvertisingAllowed = false,
284284
.DevMode = false,
285285
.EmergencyKey = NULL,
286286
.UiStyle = UiStyle_Classic,

right/src/hid/transport.cpp

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
extern "C" {
22
#include "transport.h"
33
#ifdef __ZEPHYR__
4+
#include "bt_conn.h"
45
#include "connections.h"
56
#include "link_protocol.h"
67
#include "messenger.h"
@@ -49,24 +50,19 @@ static uint32_t dispatchTimeMs = 0;
4950
// interval" (worst case: we just missed a window). The send-completion
5051
// callback then reduces the estimate to "now + interval".
5152
static constexpr uint32_t USB_REPORT_INTERVAL_MS = 1;
52-
static constexpr uint32_t DONGLE_REPORT_INTERVAL_MS = 7;
53-
54-
#if DEVICE_IS_UHK80_RIGHT
55-
extern "C" uint32_t BleHidReportIntervalMs;
56-
static inline uint32_t bleHidReportIntervalMs() { return BleHidReportIntervalMs; }
57-
#else
58-
static inline uint32_t bleHidReportIntervalMs() { return 11; }
59-
#endif
6053

6154
static uint32_t reportIntervalForSink(report_sink_t sink)
6255
{
6356
switch (sink) {
6457
case ReportSink_Usb:
6558
return USB_REPORT_INTERVAL_MS;
6659
case ReportSink_BleHid:
67-
return bleHidReportIntervalMs();
6860
case ReportSink_Dongle:
69-
return DONGLE_REPORT_INTERVAL_MS;
61+
#if DEVICE_IS_UHK80_RIGHT
62+
return BtConn_GetReportIntervalMs(ActiveHostConnectionId);
63+
#else
64+
return 11;
65+
#endif
7066
default:
7167
return 0;
7268
}
@@ -79,7 +75,7 @@ static void noteReportDispatched(report_sink_t sink)
7975
dispatchTimeMs = Timer_GetCurrentTime();
8076
}
8177
}
82-
UsbReportWindowEstimate = Timer_GetCurrentTime() + 2 * reportIntervalForSink(sink);
78+
UsbReportWindowEstimate = UsbReportWindowEstimateLast + 2 * reportIntervalForSink(sink);
8379
}
8480

8581
static void noteReportSent(report_sink_t transport)
@@ -91,8 +87,17 @@ static void noteReportSent(report_sink_t transport)
9187
dispatchTimeMs = 0;
9288
}
9389
}
94-
UsbReportWindowEstimate = Timer_GetCurrentTime() + reportIntervalForSink(transport);
95-
EventVector_WakeMain();
90+
uint32_t reportInterval = reportIntervalForSink(transport);
91+
uint32_t currentTime = Timer_GetCurrentTime();
92+
int16_t jitterGuess = (currentTime - UsbReportWindowEstimateLast - reportInterval + 1) / 2;
93+
jitterGuess = MAX(0, jitterGuess);
94+
UsbReportWindowEstimateLast = currentTime - jitterGuess;
95+
UsbReportWindowEstimate = currentTime - jitterGuess + reportInterval;
96+
uint32_t nextIn = UsbReportWindowEstimate - USB_REPORT_WINDOW_LOOKAHEAD_MS;
97+
98+
if (DEVICE_IS_UHK80_RIGHT) {
99+
EventScheduler_Schedule(nextIn, EventSchedulerEvent_Postponer, "Report sent. Recalculate report throttles");
100+
}
96101
}
97102

98103
extern "C" void HidTransport_NoteNusReportSent(void)

right/src/usb_report_updater.c

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -73,16 +73,9 @@ static key_action_cached_t actionCache[SLOT_COUNT][MAX_KEY_COUNT_PER_MODULE];
7373

7474
uint32_t UsbReportUpdater_LastActivityTime;
7575

76+
uint32_t UsbReportWindowEstimateLast = 0;
7677
uint32_t UsbReportWindowEstimate = 0;
7778

78-
// This is how much time we leave for report construction. Most of the time is
79-
// (probably) consumed inside the transport layers.
80-
//
81-
// If too low, we will be missing transports. If too high, we will be introducing
82-
// latency.
83-
#define USB_REPORT_WINDOW_LOOKAHEAD_MS 6
84-
85-
#define USB_RESEND_DELAY_MS MAX(10, Cfg.KeystrokeDelay)
8679

8780
volatile uint8_t UsbReportUpdateSemaphore = 0;
8881

right/src/usb_report_updater.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,14 @@
1616

1717
#define USB_SEMAPHORE_TIMEOUT 100 // ms
1818

19+
// This is how much time we leave for report construction. Most of the time is
20+
// (probably) consumed inside the transport layers.
21+
//
22+
// If too low, we will be missing transports. If too high, we will be introducing
23+
// latency.
24+
#define USB_REPORT_WINDOW_LOOKAHEAD_MS 3
25+
#define USB_RESEND_DELAY_MS MAX(10, Cfg.KeystrokeDelay)
26+
1927
// Typedefs:
2028

2129
typedef struct {
@@ -53,6 +61,7 @@
5361
extern uint32_t LastUsbGetKeyboardStateRequestTimestamp;
5462
extern uint32_t UsbReportUpdater_LastActivityTime;
5563
extern uint32_t UsbReportWindowEstimate;
64+
extern uint32_t UsbReportWindowEstimateLast;
5665

5766
// Functions:
5867

0 commit comments

Comments
 (0)