@@ -150,6 +150,17 @@ class HidService : public espp::BaseComponent {
150
150
// / is related to the characteristic.
151
151
// / @return The input report characteristic.
152
152
NimBLECharacteristic *input_report (uint8_t report_id) {
153
+ std::lock_guard<std::mutex> lock (input_report_characteristics_mutex_);
154
+
155
+ // look up the report ID in the list of input report characteristics
156
+ for (const auto &report_char : input_report_characteristics_) {
157
+ // cppcheck-suppress useStlAlgorithm
158
+ if (report_char.first == report_id) {
159
+ return report_char.second ;
160
+ }
161
+ }
162
+
163
+ // we got here, so the report ID was not found
153
164
auto input_report_char = service_->createCharacteristic (
154
165
NimBLEUUID (REPORT_UUID),
155
166
NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::NOTIFY | NIMBLE_PROPERTY::READ_ENC);
@@ -160,15 +171,49 @@ class HidService : public espp::BaseComponent {
160
171
uint8_t desc_value[] = {report_id, 0x01 };
161
172
desc->setValue (desc_value, sizeof (desc_value));
162
173
174
+ // now add the report ID to the list of input report characteristics
175
+ input_report_characteristics_.emplace_back (report_id, input_report_char);
176
+
163
177
return input_report_char;
164
178
}
165
179
180
+ // / @brief Remove an input report characteristic.
181
+ // / @param report_id The report ID of the input report characteristic to
182
+ // / remove.
183
+ // / @note This will delete the characteristic, and remove it from the list.
184
+ // / Any stored pointers to the characteristic will be invalid after this
185
+ // / call.
186
+ void remove_input_report (uint8_t report_id) {
187
+ std::lock_guard<std::mutex> lock (input_report_characteristics_mutex_);
188
+ auto it =
189
+ std::find_if (input_report_characteristics_.begin (), input_report_characteristics_.end (),
190
+ [report_id](const ReportCharacteristic &report_char) {
191
+ return report_char.first == report_id;
192
+ });
193
+ if (it != input_report_characteristics_.end ()) {
194
+ static constexpr bool delete_char = true ;
195
+ service_->removeCharacteristic (it->second , delete_char);
196
+ input_report_characteristics_.erase (it);
197
+ }
198
+ }
199
+
166
200
// / @brief Create an output report characteristic.
167
201
// / @param report_id The report ID. This should be the same as the report
168
202
// / ID in the report descriptor for the output object that
169
203
// / is related to the characteristic.
170
204
// / @return The output report characteristic.
171
205
NimBLECharacteristic *output_report (uint8_t report_id) {
206
+ std::lock_guard<std::mutex> lock (output_report_characteristics_mutex_);
207
+
208
+ // look up the report ID in the list of output report characteristics
209
+ for (const auto &report_char : output_report_characteristics_) {
210
+ // cppcheck-suppress useStlAlgorithm
211
+ if (report_char.first == report_id) {
212
+ return report_char.second ;
213
+ }
214
+ }
215
+
216
+ // we got here, so the report ID was not found
172
217
auto output_report_char = service_->createCharacteristic (
173
218
NimBLEUUID (REPORT_UUID), NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE |
174
219
NIMBLE_PROPERTY::WRITE_NR | NIMBLE_PROPERTY::READ_ENC |
@@ -182,15 +227,49 @@ class HidService : public espp::BaseComponent {
182
227
uint8_t desc_value[] = {report_id, 0x02 };
183
228
desc->setValue (desc_value, sizeof (desc_value));
184
229
230
+ // now add the report ID to the list of output report characteristics
231
+ output_report_characteristics_.emplace_back (report_id, output_report_char);
232
+
185
233
return output_report_char;
186
234
}
187
235
236
+ // / @brief Remove an output report characteristic.
237
+ // / @param report_id The report ID of the output report characteristic to
238
+ // / remove.
239
+ // / @note This will delete the characteristic, and remove it from the list.
240
+ // / Any stored pointers to the characteristic will be invalid after this
241
+ // / call.
242
+ void remove_output_report (uint8_t report_id) {
243
+ std::lock_guard<std::mutex> lock (output_report_characteristics_mutex_);
244
+ auto it =
245
+ std::find_if (output_report_characteristics_.begin (), output_report_characteristics_.end (),
246
+ [report_id](const ReportCharacteristic &report_char) {
247
+ return report_char.first == report_id;
248
+ });
249
+ if (it != output_report_characteristics_.end ()) {
250
+ static constexpr bool delete_char = true ;
251
+ service_->removeCharacteristic (it->second , delete_char);
252
+ output_report_characteristics_.erase (it);
253
+ }
254
+ }
255
+
188
256
// / @brief Create a feature report characteristic.
189
257
// / @param report_id The report ID. This should be the same as the report
190
258
// / ID in the report descriptor for the feature object that
191
259
// / is related to the characteristic.
192
260
// / @return The feature report characteristic.
193
261
NimBLECharacteristic *feature_report (uint8_t report_id) {
262
+ std::lock_guard<std::mutex> lock (feature_report_characteristics_mutex_);
263
+
264
+ // look up the report ID in the list of feature report characteristics
265
+ for (const auto &report_char : feature_report_characteristics_) {
266
+ // cppcheck-suppress useStlAlgorithm
267
+ if (report_char.first == report_id) {
268
+ return report_char.second ;
269
+ }
270
+ }
271
+
272
+ // we got here, so the report ID was not found
194
273
auto feature_report_char = service_->createCharacteristic (
195
274
NimBLEUUID (REPORT_UUID), NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE |
196
275
NIMBLE_PROPERTY::READ_ENC | NIMBLE_PROPERTY::WRITE_ENC);
@@ -203,9 +282,32 @@ class HidService : public espp::BaseComponent {
203
282
uint8_t desc_value[] = {report_id, 0x03 };
204
283
desc->setValue (desc_value, sizeof (desc_value));
205
284
285
+ // now add the report ID to the list of feature report characteristics
286
+ feature_report_characteristics_.emplace_back (report_id, feature_report_char);
287
+
206
288
return feature_report_char;
207
289
}
208
290
291
+ // / @brief Remove a feature report characteristic.
292
+ // / @param report_id The report ID of the feature report characteristic to
293
+ // / remove.
294
+ // / @note This will delete the characteristic, and remove it from the list.
295
+ // / Any stored pointers to the characteristic will be invalid after this
296
+ // / call.
297
+ void remove_feature_report (uint8_t report_id) {
298
+ std::lock_guard<std::mutex> lock (feature_report_characteristics_mutex_);
299
+ auto it =
300
+ std::find_if (feature_report_characteristics_.begin (), feature_report_characteristics_.end (),
301
+ [report_id](const ReportCharacteristic &report_char) {
302
+ return report_char.first == report_id;
303
+ });
304
+ if (it != feature_report_characteristics_.end ()) {
305
+ static constexpr bool delete_char = true ;
306
+ service_->removeCharacteristic (it->second , delete_char);
307
+ feature_report_characteristics_.erase (it);
308
+ }
309
+ }
310
+
209
311
protected:
210
312
static constexpr uint16_t SERVICE_UUID = 0x1812 ;
211
313
static constexpr uint16_t HID_INFORMATION_UUID = 0x2a4a ;
@@ -238,6 +340,15 @@ class HidService : public espp::BaseComponent {
238
340
protocol_mode_->setValue (pMode, 1 );
239
341
}
240
342
343
+ typedef std::pair<uint8_t , NimBLECharacteristic *> ReportCharacteristic;
344
+
345
+ std::mutex input_report_characteristics_mutex_;
346
+ std::vector<ReportCharacteristic> input_report_characteristics_;
347
+ std::mutex output_report_characteristics_mutex_;
348
+ std::vector<ReportCharacteristic> output_report_characteristics_;
349
+ std::mutex feature_report_characteristics_mutex_;
350
+ std::vector<ReportCharacteristic> feature_report_characteristics_;
351
+
241
352
NimBLEService *service_{nullptr };
242
353
NimBLECharacteristic *hid_info_{nullptr }; // 0x2a4a
243
354
NimBLECharacteristic *report_map_{nullptr }; // 0x2a4b
0 commit comments