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
111
112
113
114
115
116
|
use core::mem;
use core::ptr;
use crate::ble::types::*;
use crate::error::Error;
use crate::raw;
use crate::util::*;
use crate::{Connection, ConnectionState, Role};
pub(crate) unsafe fn on_adv_report(_ble_evt: *const raw::ble_evt_t, _gap_evt: &raw::ble_gap_evt_t) {
}
pub(crate) unsafe fn on_qos_channel_survey_report(
_ble_evt: *const raw::ble_evt_t,
_gap_evt: &raw::ble_gap_evt_t,
) {
}
pub(crate) unsafe fn on_conn_param_update_request(
_ble_evt: *const raw::ble_evt_t,
_gap_evt: &raw::ble_gap_evt_t,
) {
}
#[derive(defmt::Format)]
pub enum ConnectError {
Stopped,
Raw(Error),
}
impl From<Error> for ConnectError {
fn from(err: Error) -> Self {
ConnectError::Raw(err)
}
}
pub(crate) static CONNECT_SIGNAL: Signal<Result<Connection, ConnectError>> = Signal::new();
pub async fn connect(whitelist: &[Address]) -> Result<Connection, ConnectError> {
let (addr, fp) = match whitelist.len() {
0 => depanic!("zero-length whitelist"),
1 => (
&whitelist[0] as *const Address as *const raw::ble_gap_addr_t,
raw::BLE_GAP_SCAN_FP_ACCEPT_ALL as u8,
),
_ => depanic!("todo"),
};
// in units of 625us
let scan_interval: u32 = 2732;
let scan_window: u32 = 500;
// TODO make configurable
let mut scan_params: raw::ble_gap_scan_params_t = unsafe { mem::zeroed() };
scan_params.set_extended(1);
scan_params.set_active(1);
scan_params.scan_phys = raw::BLE_GAP_PHY_1MBPS as u8;
scan_params.set_filter_policy(fp);
scan_params.timeout = 123;
// s122 has these in us instead of 625us :shrug:
#[cfg(not(feature="s122"))]
{
scan_params.interval = scan_interval as u16;
scan_params.window = scan_interval as u16;
}
#[cfg(feature="s122")]
{
scan_params.interval_us = scan_interval * 625;
scan_params.window_us = scan_interval * 625;
}
// TODO make configurable
let mut conn_params: raw::ble_gap_conn_params_t = unsafe { mem::zeroed() };
conn_params.min_conn_interval = 50;
conn_params.max_conn_interval = 200;
conn_params.slave_latency = 4;
conn_params.conn_sup_timeout = 400; // 4 s
let ret = unsafe { raw::sd_ble_gap_connect(addr, &mut scan_params, &mut conn_params, 1) };
match Error::convert(ret) {
Ok(()) => {}
Err(err) => {
warn!("sd_ble_gap_connect err {:?}", err);
return Err(ConnectError::Raw(err));
}
}
info!("connect started");
// TODO handle future drop
CONNECT_SIGNAL.wait().await
}
#[derive(defmt::Format)]
pub enum ConnectStopError {
NotRunning,
Raw(Error),
}
impl From<Error> for ConnectStopError {
fn from(err: Error) -> Self {
ConnectStopError::Raw(err)
}
}
pub fn connect_stop() -> Result<(), ConnectStopError> {
let ret = unsafe { raw::sd_ble_gap_connect_cancel() };
match Error::convert(ret).dewarn(intern!("sd_ble_gap_connect_cancel")) {
Ok(()) => Ok(()),
Err(Error::InvalidState) => Err(ConnectStopError::NotRunning),
Err(e) => Err(e.into()),
}
}
|