esp32_nimble/server/
ble_hid_device.rs1use alloc::sync::Arc;
2
3use crate::{
4 BLECharacteristic, BLEServer, BLEService, DescriptorProperties, NimbleProperties,
5 cpfd::*,
6 utilities::{BleUuid, mutex::Mutex},
7};
8
9const BLE_SVC_DIS_CHR_UUID16_MANUFACTURER_NAME: BleUuid = BleUuid::from_uuid16(0x2A29);
10const BLE_SVC_BAS_UUID16: BleUuid = BleUuid::from_uuid16(0x180F);
11const BLE_SVC_BAS_CHR_UUID16_BATTERY_LEVEL: BleUuid = BleUuid::from_uuid16(0x2A19);
12
13#[allow(dead_code)]
14pub struct BLEHIDDevice {
15 device_info_service: Arc<Mutex<BLEService>>,
16 pnp_characteristic: Arc<Mutex<BLECharacteristic>>,
17 manufacturer_characteristic: Option<Arc<Mutex<BLECharacteristic>>>,
18
19 hid_service: Arc<Mutex<BLEService>>,
20 hid_info_characteristic: Arc<Mutex<BLECharacteristic>>,
21 report_map_characteristic: Arc<Mutex<BLECharacteristic>>,
22 hid_control_characteristic: Arc<Mutex<BLECharacteristic>>,
23 protocol_mode_characteristic: Arc<Mutex<BLECharacteristic>>,
24
25 battery_service: Arc<Mutex<BLEService>>,
26 battery_level_characteristic: Arc<Mutex<BLECharacteristic>>,
27}
28
29impl BLEHIDDevice {
30 pub fn new(server: &mut BLEServer) -> Self {
31 let device_info_service = server.create_service(BleUuid::from_uuid16(0x180a));
32
33 let pnp_characteristic = device_info_service
34 .lock()
35 .create_characteristic(BleUuid::from_uuid16(0x2a50), NimbleProperties::READ);
36
37 let hid_service = server.create_service(BleUuid::from_uuid16(0x1812));
38
39 let hid_info_characteristic = hid_service
40 .lock()
41 .create_characteristic(BleUuid::Uuid16(0x2a4a), NimbleProperties::READ);
42 let report_map_characteristic = hid_service
43 .lock()
44 .create_characteristic(BleUuid::Uuid16(0x2a4b), NimbleProperties::READ);
45 let hid_control_characteristic = hid_service
46 .lock()
47 .create_characteristic(BleUuid::Uuid16(0x2a4c), NimbleProperties::WRITE_NO_RSP);
48 let protocol_mode_characteristic = hid_service.lock().create_characteristic(
49 BleUuid::Uuid16(0x2a4e),
50 NimbleProperties::WRITE_NO_RSP | NimbleProperties::READ,
51 );
52
53 let battery_service = server.create_service(BLE_SVC_BAS_UUID16);
54 let battery_level_characteristic = battery_service.lock().create_characteristic(
55 BLE_SVC_BAS_CHR_UUID16_BATTERY_LEVEL,
56 NimbleProperties::READ | NimbleProperties::NOTIFY,
57 );
58 battery_level_characteristic.lock().cpfd(Cpfd {
59 format: ChrFormat::Uint8,
60 exponent: 0,
61 unit: ChrUnit::Percentage,
62 name_space: 1,
63 description: 0,
64 });
65
66 Self {
67 device_info_service,
68 pnp_characteristic,
69 manufacturer_characteristic: None,
70 hid_service,
71 hid_info_characteristic,
72 report_map_characteristic,
73 hid_control_characteristic,
74 protocol_mode_characteristic,
75 battery_service,
76 battery_level_characteristic,
77 }
78 }
79
80 pub fn report_map(&mut self, map: &[u8]) {
82 self.report_map_characteristic.lock().set_value(map);
83 }
84
85 pub fn manufacturer(&mut self, name: &str) {
86 let chr = self.manufacturer_characteristic.get_or_insert_with(|| {
87 self.device_info_service.lock().create_characteristic(
88 BLE_SVC_DIS_CHR_UUID16_MANUFACTURER_NAME,
89 NimbleProperties::READ,
90 )
91 });
92 chr.lock().set_value(name.as_bytes());
93 }
94
95 pub fn pnp(&mut self, sig: u8, vid: u16, pid: u16, version: u16) {
96 let mut pnp_characteristic = self.pnp_characteristic.lock();
97 let value = pnp_characteristic.value_mut();
98 value.clear();
99 value.extend(&[sig]);
100 value.extend(&vid.to_be_bytes());
101 value.extend(&pid.to_be_bytes());
102 value.extend(&version.to_be_bytes());
103 }
104
105 pub fn hid_info(&mut self, country: u8, flags: u8) {
107 let info = [0x11, 0x1, country, flags];
108 self.hid_info_characteristic.lock().set_value(&info);
109 }
110
111 pub fn input_report(&mut self, report_id: u8) -> Arc<Mutex<BLECharacteristic>> {
113 let input_report_characteristic = self.hid_service.lock().create_characteristic(
114 BleUuid::from_uuid16(0x2a4d),
115 NimbleProperties::READ | NimbleProperties::NOTIFY | NimbleProperties::READ_ENC,
116 );
117 let input_report_descriptor = input_report_characteristic.lock().create_descriptor(
118 BleUuid::Uuid16(0x2908),
119 DescriptorProperties::READ | DescriptorProperties::READ_ENC,
120 );
121
122 let desc1_val = [report_id, 0x01];
123 input_report_descriptor.lock().set_value(&desc1_val);
124
125 input_report_characteristic
126 }
127
128 pub fn output_report(&mut self, report_id: u8) -> Arc<Mutex<BLECharacteristic>> {
129 let output_report_characteristic = self.hid_service.lock().create_characteristic(
130 BleUuid::from_uuid16(0x2a4d),
131 NimbleProperties::READ
132 | NimbleProperties::WRITE
133 | NimbleProperties::WRITE_NO_RSP
134 | NimbleProperties::READ_ENC
135 | NimbleProperties::WRITE_ENC,
136 );
137 let output_report_descriptor = output_report_characteristic.lock().create_descriptor(
138 BleUuid::Uuid16(0x2908),
139 DescriptorProperties::READ
140 | DescriptorProperties::WRITE
141 | DescriptorProperties::READ_ENC
142 | DescriptorProperties::WRITE_ENC,
143 );
144
145 let desc1_val = [report_id, 0x02];
146 output_report_descriptor.lock().set_value(&desc1_val);
147
148 output_report_characteristic
149 }
150
151 pub fn feature_report(&mut self, report_id: u8) -> Arc<Mutex<BLECharacteristic>> {
152 let feature_report_characteristic = self.hid_service.lock().create_characteristic(
153 BleUuid::from_uuid16(0x2a4d),
154 NimbleProperties::READ
155 | NimbleProperties::WRITE
156 | NimbleProperties::READ_ENC
157 | NimbleProperties::WRITE_ENC,
158 );
159 let feature_report_descriptor = feature_report_characteristic.lock().create_descriptor(
160 BleUuid::Uuid16(0x2908),
161 DescriptorProperties::READ
162 | DescriptorProperties::WRITE
163 | DescriptorProperties::READ_ENC
164 | DescriptorProperties::WRITE_ENC,
165 );
166
167 let desc1_val = [report_id, 0x03];
168 feature_report_descriptor.lock().set_value(&desc1_val);
169
170 feature_report_characteristic
171 }
172
173 pub fn boot_input(&self) -> Arc<Mutex<BLECharacteristic>> {
175 self.hid_service
176 .lock()
177 .create_characteristic(BleUuid::from_uuid16(0x2a22), NimbleProperties::NOTIFY)
178 }
179
180 pub fn boot_output(&self) -> Arc<Mutex<BLECharacteristic>> {
182 self.hid_service.lock().create_characteristic(
183 BleUuid::from_uuid16(0x2a32),
184 NimbleProperties::READ | NimbleProperties::WRITE | NimbleProperties::WRITE_NO_RSP,
185 )
186 }
187
188 pub fn hid_control(&self) -> &Arc<Mutex<BLECharacteristic>> {
190 &self.hid_control_characteristic
191 }
192
193 pub fn protocol_mode(&self) -> &Arc<Mutex<BLECharacteristic>> {
195 &self.protocol_mode_characteristic
196 }
197
198 pub fn set_battery_level(&mut self, level: u8) {
200 self.battery_level_characteristic.lock().set_value(&[level]);
201 }
202
203 pub fn hid_service(&self) -> &Arc<Mutex<BLEService>> {
205 &self.hid_service
206 }
207}