Direct-BT v3.3.0-1-gc2d430c
Direct-BT - Direct Bluetooth Programming.
MgmtTypes.cpp
Go to the documentation of this file.
1/*
2 * Author: Sven Gothel <sgothel@jausoft.com>
3 * Copyright (c) 2020 Gothel Software e.K.
4 * Copyright (c) 2020 ZAFENA AB
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26#include <cstring>
27#include <string>
28#include <memory>
29#include <cstdint>
30#include <vector>
31#include <cstdio>
32
33#include <algorithm>
34
35// #define PERF_PRINT_ON 1
36#include <jau/debug.hpp>
37
38#include "BTIoctl.hpp"
39
40#include "MgmtTypes.hpp"
41#include "HCIIoctl.hpp"
42#include "HCIComm.hpp"
43#include "BTTypes1.hpp"
44
45extern "C" {
46 #include <inttypes.h>
47 #include <unistd.h>
48}
49
50using namespace direct_bt;
51
52// *************************************************
53// *************************************************
54// *************************************************
55
56#define CASE_TO_STRING(V) case V: return #V;
57#define CASE2_TO_STRING(U,V) case U::V: return #V;
58
59#define MGMT_STATUS_ENUM(X) \
60 X(SUCCESS) \
61 X(UNKNOWN_COMMAND) \
62 X(NOT_CONNECTED) \
63 X(FAILED) \
64 X(CONNECT_FAILED) \
65 X(AUTH_FAILED) \
66 X(NOT_PAIRED) \
67 X(NO_RESOURCES) \
68 X(TIMEOUT) \
69 X(ALREADY_CONNECTED) \
70 X(BUSY) \
71 X(REJECTED) \
72 X(NOT_SUPPORTED) \
73 X(INVALID_PARAMS) \
74 X(DISCONNECTED) \
75 X(NOT_POWERED) \
76 X(CANCELLED) \
77 X(INVALID_INDEX) \
78 X(RFKILLED) \
79 X(ALREADY_PAIRED) \
80 X(PERMISSION_DENIED)
81
82#define MGMT_STATUS_CASE_TO_STRING(V) case MgmtStatus::V: return #V;
83
84std::string direct_bt::to_string(const MgmtStatus opc) noexcept {
85 switch(opc) {
87 default: ; // fall through intended
88 }
89 return "Unknown Status";
90}
91
92#define MGMT_LINKKEYTYPE_ENUM(X) \
93 X(COMBI) \
94 X(LOCAL_UNIT) \
95 X(REMOTE_UNIT) \
96 X(DBG_COMBI) \
97 X(UNAUTH_COMBI_P192) \
98 X(AUTH_COMBI_P192) \
99 X(CHANGED_COMBI) \
100 X(UNAUTH_COMBI_P256) \
101 X(AUTH_COMBI_P256) \
102 X(NONE)
103
104#define MGMT_LINKKEYTYPE_TO_STRING(V) case MgmtLinkKeyType::V: return #V;
105
106std::string direct_bt::to_string(const MgmtLinkKeyType type) noexcept {
107 switch(type) {
109 default: ; // fall through intended
110 }
111 return "Unknown MgmtLinkKeyType";
112}
113
114#define MGMT_LTKTYPE_ENUM(X) \
115 X(UNAUTHENTICATED) \
116 X(AUTHENTICATED) \
117 X(UNAUTHENTICATED_P256) \
118 X(AUTHENTICATED_P256) \
119 X(DEBUG_P256) \
120 X(NONE)
121
122#define MGMT_LTKTYPE_TO_STRING(V) case MgmtLTKType::V: return #V;
123
124std::string direct_bt::to_string(const MgmtLTKType type) noexcept {
125 switch(type) {
127 default: ; // fall through intended
128 }
129 return "Unknown MgmtLTKType";
130}
131
133 if( ( SMPLongTermKey::Property::AUTH & mask ) != SMPLongTermKey::Property::NONE ) {
134 return ( SMPLongTermKey::Property::SC & mask ) != SMPLongTermKey::Property::NONE ?
135 MgmtLTKType::AUTHENTICATED_P256 : MgmtLTKType::AUTHENTICATED;
136 } else {
137 return ( SMPLongTermKey::Property::SC & mask ) != SMPLongTermKey::Property::NONE ?
138 MgmtLTKType::UNAUTHENTICATED_P256 : MgmtLTKType::UNAUTHENTICATED;
139 }
140}
141
142#define MGMT_CSRKTYPE_ENUM(X) \
143 X(UNAUTHENTICATED_LOCAL) \
144 X(UNAUTHENTICATED_REMOTE) \
145 X(AUTHENTICATED_LOCAL) \
146 X(AUTHENTICATED_REMOTE) \
147 X(NONE)
148
149#define MGMT_CSRKTYPE_TO_STRING(V) case MgmtCSRKType::V: return #V;
150
151std::string direct_bt::to_string(const MgmtCSRKType type) noexcept {
152 switch(type) {
154 default: ; // fall through intended
155 }
156 return "Unknown MgmtCSRKType";
157}
158
159
160// *************************************************
161// *************************************************
162// *************************************************
163
164#define MGMT_OPCODE_ENUM(X) \
165 X(READ_VERSION) \
166 X(READ_COMMANDS) \
167 X(READ_INDEX_LIST) \
168 X(READ_INFO) \
169 X(SET_POWERED) \
170 X(SET_DISCOVERABLE) \
171 X(SET_CONNECTABLE) \
172 X(SET_FAST_CONNECTABLE) \
173 X(SET_BONDABLE) \
174 X(SET_LINK_SECURITY) \
175 X(SET_SSP) \
176 X(SET_HS) \
177 X(SET_LE) \
178 X(SET_DEV_CLASS) \
179 X(SET_LOCAL_NAME) \
180 X(ADD_UUID) \
181 X(REMOVE_UUID) \
182 X(LOAD_LINK_KEYS) \
183 X(LOAD_LONG_TERM_KEYS) \
184 X(DISCONNECT) \
185 X(GET_CONNECTIONS) \
186 X(PIN_CODE_REPLY) \
187 X(PIN_CODE_NEG_REPLY) \
188 X(SET_IO_CAPABILITY) \
189 X(PAIR_DEVICE) \
190 X(CANCEL_PAIR_DEVICE) \
191 X(UNPAIR_DEVICE) \
192 X(USER_CONFIRM_REPLY) \
193 X(USER_CONFIRM_NEG_REPLY) \
194 X(USER_PASSKEY_REPLY) \
195 X(USER_PASSKEY_NEG_REPLY) \
196 X(READ_LOCAL_OOB_DATA) \
197 X(ADD_REMOTE_OOB_DATA) \
198 X(REMOVE_REMOTE_OOB_DATA) \
199 X(START_DISCOVERY) \
200 X(STOP_DISCOVERY) \
201 X(CONFIRM_NAME) \
202 X(BLOCK_DEVICE) \
203 X(UNBLOCK_DEVICE) \
204 X(SET_DEVICE_ID) \
205 X(SET_ADVERTISING) \
206 X(SET_BREDR) \
207 X(SET_STATIC_ADDRESS) \
208 X(SET_SCAN_PARAMS) \
209 X(SET_SECURE_CONN) \
210 X(SET_DEBUG_KEYS) \
211 X(SET_PRIVACY) \
212 X(LOAD_IRKS) \
213 X(GET_CONN_INFO) \
214 X(GET_CLOCK_INFO) \
215 X(ADD_DEVICE_WHITELIST) \
216 X(REMOVE_DEVICE_WHITELIST) \
217 X(LOAD_CONN_PARAM) \
218 X(READ_UNCONF_INDEX_LIST) \
219 X(READ_CONFIG_INFO) \
220 X(SET_EXTERNAL_CONFIG) \
221 X(SET_PUBLIC_ADDRESS) \
222 X(START_SERVICE_DISCOVERY) \
223 X(READ_LOCAL_OOB_EXT_DATA) \
224 X(READ_EXT_INDEX_LIST) \
225 X(READ_ADV_FEATURES) \
226 X(ADD_ADVERTISING) \
227 X(REMOVE_ADVERTISING) \
228 X(GET_ADV_SIZE_INFO) \
229 X(START_LIMITED_DISCOVERY) \
230 X(READ_EXT_INFO) \
231 X(SET_APPEARANCE) \
232 X(GET_PHY_CONFIGURATION) \
233 X(SET_PHY_CONFIGURATION) \
234 X(SET_BLOCKED_KEYS) \
235 X(SET_WIDEBAND_SPEECH) \
236 X(READ_SECURITY_INFO) \
237 X(READ_EXP_FEATURES_INFO) \
238 X(SET_EXP_FEATURE) \
239 X(READ_DEF_SYSTEM_CONFIG) \
240 X(SET_DEF_SYSTEM_CONFIG) \
241 X(READ_DEF_RUNTIME_CONFIG) \
242 X(SET_DEF_RUNTIME_CONFIG) \
243 X(GET_DEVICE_FLAGS) \
244 X(SET_DEVICE_FLAGS) \
245 X(READ_ADV_MONITOR_FEATURES) \
246 X(ADD_ADV_PATTERNS_MONITOR) \
247 X(REMOVE_ADV_MONITOR)
248
249#define MGMT_OPCODE_CASE_TO_STRING(V) case MgmtCommand::Opcode::V: return #V;
250
251std::string MgmtCommand::getOpcodeString(const Opcode op) noexcept {
252 switch(op) {
254 default: ; // fall through intended
255 }
256 return "Unknown Operation";
257}
258
259// *************************************************
260// *************************************************
261// *************************************************
262
263#define MGMT_DEFPARAMTYPE_ENUM(X) \
264 X(BREDR_PAGE_SCAN_TYPE) \
265 X(BREDR_PAGE_SCAN_INTERVAL) \
266 X(BREDR_PAGE_SCAN_WINDOW) \
267 X(BREDR_INQUIRY_TYPE) \
268 X(BREDR_INQUIRY_INTERVAL) \
269 X(BREDR_INQUIRY_WINDOW) \
270 X(BREDR_LINK_SUPERVISOR_TIMEOUT) \
271 X(BREDR_PAGE_TIMEOUT) \
272 X(BREDR_MIN_SNIFF_INTERVAL) \
273 X(BREDR_MAX_SNIFF_INTERVAL) \
274 X(LE_ADV_MIN_INTERVAL) \
275 X(LE_ADV_MAX_INTERVAL) \
276 X(LE_MULTI_ADV_ROT_INTERVAL) \
277 X(LE_SCAN_INTERVAL_AUTOCONN) \
278 X(LE_SCAN_WINDOW_AUTOCONN) \
279 X(LE_SCAN_INTERVAL_WAKESCENARIO) \
280 X(LE_SCAN_WINDOW_WAKESCENARIO) \
281 X(LE_SCAN_INTERVAL_DISCOVERY) \
282 X(LE_SCAN_WINDOW_DISCOVERY) \
283 X(LE_SCAN_INTERVAL_ADVMON) \
284 X(LE_SCAN_WINDOW_ADVMON) \
285 X(LE_SCAN_INTERVAL_CONNECT) \
286 X(LE_SCAN_WINDOW_CONNECT) \
287 X(LE_MIN_CONN_INTERVAL) \
288 X(LE_MAX_CONN_INTERVAL) \
289 X(LE_CONN_LATENCY) \
290 X(LE_CONN_SUPERVISOR_TIMEOUT) \
291 X(LE_AUTOCONN_TIMEOUT) \
292 X(NONE)
293
294#define MGMT_DEFPARAMTYPE_CASE_TO_STRING(V) case MgmtDefaultParam::Type::V: return #V;
295
296std::string MgmtDefaultParam::getTypeString(const Type op) noexcept {
297 switch(op) {
299 default: ; // fall through intended
300 }
301 return "Unknown Type";
302}
303
304MgmtDefaultParam MgmtDefaultParam::read(const uint8_t* data, const jau::nsize_t length) noexcept {
305 if( length < 2U ) {
306 return MgmtDefaultParam();
307 }
308 const Type type = static_cast<Type>( jau::get_uint16(data + 0, jau::lb_endian_t::little) );
309 if( length < 2U + 1U ) {
310 return MgmtDefaultParam(type);
311 }
312 const uint8_t value_length = jau::get_uint8(data + 2);
313 if( value_length != to_size(type) ) {
314 return MgmtDefaultParam(type);
315 }
316 if( length < 2U + 1U + value_length ) {
317 return MgmtDefaultParam(type);
318 }
319 switch( value_length ) {
320 case 2:
322 default:
323 return MgmtDefaultParam(type);
324 }
325}
326
327std::vector<MgmtDefaultParam> MgmtReadDefaultSysParamCmd::getParams(const uint8_t *data, const jau::nsize_t length) noexcept {
328 std::vector<MgmtDefaultParam> res;
329 jau::nsize_t consumed = 0;
330 while( consumed < length && ( length - consumed ) > 2U + 1U ) {
331 MgmtDefaultParam p = MgmtDefaultParam::read(data+consumed, length-consumed);
332 if( !p.valid() ) {
333 break;
334 }
335 consumed += p.mgmt_size();
336 res.push_back( std::move(p) );
337 }
338 return res;
339}
340
341// *************************************************
342// *************************************************
343// *************************************************
344
345#define MGMT_EV_OPCODE_ENUM(X) \
346 X(INVALID) \
347 X(CMD_COMPLETE) \
348 X(CMD_STATUS) \
349 X(CONTROLLER_ERROR) \
350 X(INDEX_ADDED) \
351 X(INDEX_REMOVED) \
352 X(NEW_SETTINGS) \
353 X(CLASS_OF_DEV_CHANGED) \
354 X(LOCAL_NAME_CHANGED) \
355 X(NEW_LINK_KEY) \
356 X(NEW_LONG_TERM_KEY) \
357 X(DEVICE_CONNECTED) \
358 X(DEVICE_DISCONNECTED) \
359 X(CONNECT_FAILED) \
360 X(PIN_CODE_REQUEST) \
361 X(USER_CONFIRM_REQUEST) \
362 X(USER_PASSKEY_REQUEST) \
363 X(AUTH_FAILED) \
364 X(DEVICE_FOUND) \
365 X(DISCOVERING) \
366 X(DEVICE_BLOCKED) \
367 X(DEVICE_UNBLOCKED) \
368 X(DEVICE_UNPAIRED) \
369 X(PASSKEY_NOTIFY) \
370 X(NEW_IRK) \
371 X(NEW_CSRK) \
372 X(DEVICE_WHITELIST_ADDED) \
373 X(DEVICE_WHITELIST_REMOVED) \
374 X(NEW_CONN_PARAM) \
375 X(UNCONF_INDEX_ADDED) \
376 X(UNCONF_INDEX_REMOVED) \
377 X(NEW_CONFIG_OPTIONS) \
378 X(EXT_INDEX_ADDED) \
379 X(EXT_INDEX_REMOVED) \
380 X(LOCAL_OOB_DATA_UPDATED) \
381 X(ADVERTISING_ADDED) \
382 X(ADVERTISING_REMOVED) \
383 X(EXT_INFO_CHANGED) \
384 X(PHY_CONFIGURATION_CHANGED) \
385 X(EXP_FEATURE_CHANGED) \
386 X(DEVICE_FLAGS_CHANGED) \
387 X(ADV_MONITOR_ADDED) \
388 X(ADV_MONITOR_REMOVED) \
389 X(PAIR_DEVICE_COMPLETE) \
390 X(HCI_ENC_CHANGED) \
391 X(HCI_ENC_KEY_REFRESH_COMPLETE) \
392 X(HCI_LE_REMOTE_FEATURES) \
393 X(HCI_LE_PHY_UPDATE_COMPLETE) \
394 X(HCI_LE_LTK_REQUEST) \
395 X(HCI_LE_LTK_REPLY_ACK) \
396 X(HCI_LE_LTK_REPLY_REJ) \
397 X(HCI_LE_ENABLE_ENC)
398
399#define MGMT_EV_OPCODE_CASE_TO_STRING(V) case MgmtEvent::Opcode::V: return #V;
400
401std::string MgmtEvent::getOpcodeString(const Opcode opc) noexcept {
402 switch(opc) {
404 default: ; // fall through intended
405 }
406 return "Unknown Opcode";
407}
408
409std::unique_ptr<MgmtEvent> MgmtEvent::getSpecialized(const uint8_t * buffer, jau::nsize_t const buffer_size) noexcept {
410 const MgmtEvent::Opcode opc = MgmtEvent::getOpcode(buffer);
411 switch( opc ) {
412 case MgmtEvent::Opcode::CMD_COMPLETE: {
413 const MgmtCommand::Opcode cmdOpcode = MgmtEvtCmdComplete::getCmdOpcode(buffer);
414
415 if( buffer_size >= MgmtEvtAdapterInfo::getRequiredTotalSize() &&
416 MgmtCommand::Opcode::READ_INFO == cmdOpcode ) {
417 return std::make_unique<MgmtEvtAdapterInfo>(buffer, buffer_size);
418 } else if( buffer_size >= MgmtEvtPairDeviceComplete::getRequiredTotalSize() &&
419 MgmtCommand::Opcode::PAIR_DEVICE == cmdOpcode ) {
420 return std::make_unique<MgmtEvtPairDeviceComplete>(buffer, buffer_size);
421 } else {
422 return std::make_unique<MgmtEvtCmdComplete>(buffer, buffer_size);
423 }
424 }
425 case MgmtEvent::Opcode::CMD_STATUS:
426 return std::make_unique<MgmtEvtCmdStatus>(buffer, buffer_size);
427 case MgmtEvent::Opcode::CONTROLLER_ERROR:
428 return std::make_unique<MgmtEvtControllerError>(buffer, buffer_size);
429 case MgmtEvent::Opcode::INDEX_ADDED:
430 return std::make_unique<MgmtEvent>(buffer, buffer_size, 0);
431 case MgmtEvent::Opcode::INDEX_REMOVED:
432 return std::make_unique<MgmtEvent>(buffer, buffer_size, 0);
433 case MgmtEvent::Opcode::NEW_SETTINGS:
434 return std::make_unique<MgmtEvtNewSettings>(buffer, buffer_size);
435 case MgmtEvent::Opcode::LOCAL_NAME_CHANGED:
436 return std::make_unique<MgmtEvtLocalNameChanged>(buffer, buffer_size);
437 case Opcode::NEW_LINK_KEY:
438 return std::make_unique<MgmtEvtNewLinkKey>(buffer, buffer_size);
439 case Opcode::NEW_LONG_TERM_KEY:
440 return std::make_unique<MgmtEvtNewLongTermKey>(buffer, buffer_size);
441 case MgmtEvent::Opcode::DEVICE_CONNECTED:
442 return std::make_unique<MgmtEvtDeviceConnected>(buffer, buffer_size);
443 case MgmtEvent::Opcode::DEVICE_DISCONNECTED:
444 return std::make_unique<MgmtEvtDeviceDisconnected>(buffer, buffer_size);
445 case MgmtEvent::Opcode::CONNECT_FAILED:
446 return std::make_unique<MgmtEvtDeviceConnectFailed>(buffer, buffer_size);
447 case MgmtEvent::Opcode::PIN_CODE_REQUEST:
448 return std::make_unique<MgmtEvtPinCodeRequest>(buffer, buffer_size);
449 case MgmtEvent::Opcode::USER_CONFIRM_REQUEST:
450 return std::make_unique<MgmtEvtUserConfirmRequest>(buffer, buffer_size);
451 case MgmtEvent::Opcode::USER_PASSKEY_REQUEST:
452 return std::make_unique<MgmtEvtUserPasskeyRequest>(buffer, buffer_size);
453 case MgmtEvent::Opcode::PASSKEY_NOTIFY:
454 return std::make_unique<MgmtEvtPasskeyNotify>(buffer, buffer_size);
455 case Opcode::AUTH_FAILED:
456 return std::make_unique<MgmtEvtAuthFailed>(buffer, buffer_size);
457 case MgmtEvent::Opcode::DEVICE_FOUND:
458 return std::make_unique<MgmtEvtDeviceFound>(buffer, buffer_size);
459 case MgmtEvent::Opcode::DISCOVERING:
460 return std::make_unique<MgmtEvtDiscovering>(buffer, buffer_size);
461 case MgmtEvent::Opcode::DEVICE_UNPAIRED:
462 return std::make_unique<MgmtEvtDeviceUnpaired>(buffer, buffer_size);
463 case Opcode::NEW_IRK:
464 return std::make_unique<MgmtEvtNewIdentityResolvingKey>(buffer, buffer_size);
465 case Opcode::NEW_CSRK:
466 return std::make_unique<MgmtEvtNewSignatureResolvingKey>(buffer, buffer_size);
467 case MgmtEvent::Opcode::DEVICE_WHITELIST_ADDED:
468 return std::make_unique<MgmtEvtDeviceWhitelistAdded>(buffer, buffer_size);
469 case MgmtEvent::Opcode::DEVICE_WHITELIST_REMOVED:
470 return std::make_unique<MgmtEvtDeviceWhitelistRemoved>(buffer, buffer_size);
471 case MgmtEvent::Opcode::NEW_CONN_PARAM:
472 return std::make_unique<MgmtEvtNewConnectionParam>(buffer, buffer_size);
473 default:
474 return std::make_unique<MgmtEvent>(buffer, buffer_size, 0);
475 }
476}
477
478// *************************************************
479// *************************************************
480// *************************************************
481
482bool MgmtEvtCmdComplete::getCurrentSettings(AdapterSetting& current_settings) const noexcept {
483 if( 4 != getDataSize() ) {
484 return false;
485 }
486 MgmtCommand::Opcode cmd = getCmdOpcode();
487 switch(cmd) {
488 case MgmtCommand::Opcode::SET_POWERED:
489 [[fallthrough]];
490 case MgmtCommand::Opcode::SET_DISCOVERABLE:
491 [[fallthrough]];
492 case MgmtCommand::Opcode::SET_CONNECTABLE:
493 [[fallthrough]];
494 case MgmtCommand::Opcode::SET_FAST_CONNECTABLE:
495 [[fallthrough]];
496 case MgmtCommand::Opcode::SET_BONDABLE:
497 [[fallthrough]];
498 case MgmtCommand::Opcode::SET_LINK_SECURITY:
499 [[fallthrough]];
500 case MgmtCommand::Opcode::SET_SSP:
501 [[fallthrough]];
502 case MgmtCommand::Opcode::SET_HS:
503 [[fallthrough]];
504 case MgmtCommand::Opcode::SET_LE:
505 [[fallthrough]];
506 case MgmtCommand::Opcode::SET_ADVERTISING:
507 [[fallthrough]];
508 case MgmtCommand::Opcode::SET_BREDR:
509 [[fallthrough]];
510 case MgmtCommand::Opcode::SET_STATIC_ADDRESS:
511 [[fallthrough]];
512 case MgmtCommand::Opcode::SET_SECURE_CONN:
513 [[fallthrough]];
514 case MgmtCommand::Opcode::SET_DEBUG_KEYS:
515 [[fallthrough]];
516 case MgmtCommand::Opcode::SET_PRIVACY:
517 current_settings = static_cast<AdapterSetting>( pdu.get_uint32_nc(getDataOffset()) );
518 return true;
519 default:
520 return false;
521 }
522}
523
524std::shared_ptr<ConnectionInfo> MgmtEvtCmdComplete::toConnectionInfo() const noexcept {
526 ERR_PRINT("Not a GET_CONN_INFO reply: %s", toString().c_str());
527 return nullptr;
528 }
529 if( MgmtStatus::SUCCESS != getStatus() ) {
530 ERR_PRINT("No Success: %s", toString().c_str());
531 return nullptr;
532 }
534 if( getDataSize() < min_size ) {
535 ERR_PRINT("Data size < %d: %s", min_size, toString().c_str());
536 return nullptr;
537 }
538
539 const uint8_t *data = getData();
540 if( nullptr == data ) {
541 // Prelim checking to avoid g++ [8 - 10] giving a warning: '-Wnull-dereference' (impossible here!)
542 ERR_PRINT("Data nullptr: %s", toString().c_str());
543 return nullptr;
544 }
545 EUI48 address = EUI48( data, jau::lb_endian_t::native );
546 BDAddressType addressType = static_cast<BDAddressType>( jau::get_uint8(data + 6) );
547 int8_t rssi = jau::get_int8(data + 7);
548 int8_t tx_power = jau::get_int8(data + 8);
549 int8_t max_tx_power = jau::get_int8(data + 9);
550 return std::make_shared<ConnectionInfo>(address, addressType, rssi, tx_power, max_tx_power);
551}
552
553std::shared_ptr<NameAndShortName> MgmtEvtCmdComplete::toNameAndShortName() const noexcept {
555 ERR_PRINT("Not a SET_LOCAL_NAME reply: %s", toString().c_str());
556 return nullptr;
557 }
558 if( MgmtStatus::SUCCESS != getStatus() ) {
559 ERR_PRINT("No Success: %s", toString().c_str());
560 return nullptr;
561 }
563 if( getDataSize() < min_size ) {
564 ERR_PRINT("Data size < %d: %s", min_size, toString().c_str());
565 return nullptr;
566 }
567
568
569 const uint8_t *data = getData();
570 std::string name = std::string( (const char*) ( data ) );
571 std::string short_name = std::string( (const char*) ( data + MGMT_MAX_NAME_LENGTH ) );
572
573 return std::make_shared<NameAndShortName>(name, short_name);
574}
575
576std::shared_ptr<NameAndShortName> MgmtEvtLocalNameChanged::toNameAndShortName() const noexcept {
577 return std::make_shared<NameAndShortName>(getName(), getShortName());
578}
579
580std::unique_ptr<AdapterInfo> MgmtEvtAdapterInfo::toAdapterInfo() const noexcept {
581 return std::make_unique<AdapterInfo>(
582 getDevID(),
584 getVersion(),
587 getName(), getShortName());
588}
589
591 if( info.dev_id != getDevID() || info.addressAndType.address != getAddress() ) {
592 return false;
593 }
594 info.setSettingMasks(getSupportedSetting(), getCurrentSetting());
595 info.setDevClass(getDevClass());
596 info.setName(getName());
597 info.setShortName(getShortName());
598 return true;
599}
600
602 switch(mgmtReason) {
603 case DisconnectReason::TIMEOUT: return "TIMEOUT";
604 case DisconnectReason::LOCAL_HOST: return "LOCAL_HOST";
605 case DisconnectReason::REMOTE: return "REMOTE";
606 case DisconnectReason::AUTH_FAILURE: return "AUTH_FAILURE";
607
608 case DisconnectReason::UNKNOWN:
609 default:
610 return "UNKNOWN";
611 }
612 return "Unknown DisconnectReason";
613}
614
616 switch (hciReason) {
618 return DisconnectReason::TIMEOUT;
622 return DisconnectReason::REMOTE;
624 return DisconnectReason::LOCAL_HOST;
626 return DisconnectReason::AUTH_FAILURE;
627
630 default:
631 return DisconnectReason::UNKNOWN;
632
633 }
634}
636 switch(mgmtReason) {
637 case DisconnectReason::TIMEOUT: return HCIStatusCode::CONNECTION_TIMEOUT;
638 case DisconnectReason::LOCAL_HOST: return HCIStatusCode::CONNECTION_TERMINATED_BY_LOCAL_HOST;
639 case DisconnectReason::REMOTE: return HCIStatusCode::REMOTE_USER_TERMINATED_CONNECTION;
640 case DisconnectReason::AUTH_FAILURE: return HCIStatusCode::AUTHENTICATION_FAILURE;
641
642 case DisconnectReason::UNKNOWN:
643 default:
645 }
646}
647
649 switch(mstatus) {
671 default:
673 }
674}
#define MGMT_CSRKTYPE_TO_STRING(V)
Definition: MgmtTypes.cpp:149
#define MGMT_EV_OPCODE_CASE_TO_STRING(V)
Definition: MgmtTypes.cpp:399
#define MGMT_LTKTYPE_TO_STRING(V)
Definition: MgmtTypes.cpp:122
#define MGMT_LINKKEYTYPE_ENUM(X)
Definition: MgmtTypes.cpp:92
#define MGMT_DEFPARAMTYPE_ENUM(X)
Definition: MgmtTypes.cpp:263
#define MGMT_STATUS_ENUM(X)
Definition: MgmtTypes.cpp:59
#define MGMT_LTKTYPE_ENUM(X)
Definition: MgmtTypes.cpp:114
#define MGMT_LINKKEYTYPE_TO_STRING(V)
Definition: MgmtTypes.cpp:104
#define MGMT_OPCODE_ENUM(X)
Definition: MgmtTypes.cpp:164
#define MGMT_STATUS_CASE_TO_STRING(V)
Definition: MgmtTypes.cpp:82
#define MGMT_EV_OPCODE_ENUM(X)
Definition: MgmtTypes.cpp:345
#define MGMT_CSRKTYPE_ENUM(X)
Definition: MgmtTypes.cpp:142
#define MGMT_DEFPARAMTYPE_CASE_TO_STRING(V)
Definition: MgmtTypes.cpp:294
#define MGMT_OPCODE_CASE_TO_STRING(V)
Definition: MgmtTypes.cpp:249
Unique Bluetooth EUI48 address and BDAddressType tuple.
Definition: BTAddress.hpp:175
static jau::nsize_t minimumDataSize() noexcept
Definition: BTTypes1.hpp:92
std::string toString() const noexcept override
Definition: MgmtTypes.hpp:1543
AdapterSetting getSupportedSetting() const noexcept
Definition: MgmtTypes.hpp:2906
bool updateAdapterInfo(AdapterInfo &info) const noexcept
Definition: MgmtTypes.cpp:590
AdapterSetting getCurrentSetting() const noexcept
Definition: MgmtTypes.hpp:2907
std::unique_ptr< AdapterInfo > toAdapterInfo() const noexcept
Definition: MgmtTypes.cpp:580
uint32_t getDevClass() const noexcept
Definition: MgmtTypes.hpp:2908
const EUI48 & getAddress() const noexcept
The adapter address reported is always the public address, i.e.
Definition: MgmtTypes.hpp:2903
std::string getShortName() const noexcept
Definition: MgmtTypes.hpp:2912
uint16_t getManufacturer() const noexcept
Definition: MgmtTypes.hpp:2905
uint8_t getVersion() const noexcept
Definition: MgmtTypes.hpp:2904
std::string getName() const noexcept
Definition: MgmtTypes.hpp:2911
std::shared_ptr< NameAndShortName > toNameAndShortName() const noexcept
Convert this instance into ConnectionInfo if getCmdOpcode() == SET_LOCAL_NAME, getStatus() == SUCCESS...
Definition: MgmtTypes.cpp:553
MgmtStatus getStatus() const noexcept
Definition: MgmtTypes.hpp:1608
const uint8_t * getData() const noexcept override
Definition: MgmtTypes.hpp:1612
jau::nsize_t getDataSize() const noexcept override
Definition: MgmtTypes.hpp:1611
MgmtCommand::Opcode getCmdOpcode() const noexcept
Definition: MgmtTypes.hpp:1607
static std::string getDisconnectReasonString(DisconnectReason mgmtReason) noexcept
Definition: MgmtTypes.cpp:601
static DisconnectReason getDisconnectReason(HCIStatusCode hciReason) noexcept
BlueZ Kernel Mgmt mapping of HCI disconnect reason, which reduces some information.
Definition: MgmtTypes.cpp:615
HCIStatusCode getHCIReason() const noexcept
Returns either the HCI reason if given, or the translated DisconnectReason.
Definition: MgmtTypes.hpp:1922
std::shared_ptr< NameAndShortName > toNameAndShortName() const noexcept
Definition: MgmtTypes.cpp:576
const std::string getName() const noexcept
Definition: MgmtTypes.hpp:1740
const std::string getShortName() const noexcept
Definition: MgmtTypes.hpp:1741
static jau::nsize_t namesDataSize() noexcept
Definition: MgmtTypes.hpp:1725
uint16_t getDevID() const noexcept
Definition: MgmtTypes.hpp:409
#define ERR_PRINT(...)
Use for unconditional error messages, prefix '[elapsed_time] Error @ FILE:LINE FUNC: '.
Definition: debug.hpp:109
constexpr uint16_t get_uint16(uint8_t const *buffer) noexcept
Returns a uint16_t value from the given byte address using packed_t to resolve a potential memory ali...
Definition: byte_util.hpp:661
constexpr int8_t get_int8(uint8_t const *buffer) noexcept
Definition: byte_util.hpp:615
constexpr uint8_t get_uint8(uint8_t const *buffer) noexcept
Definition: byte_util.hpp:611
@ native
Identifier for native platform type, one of the above.
@ little
Identifier for little endian, equivalent to endian::little.
HCIStatusCode to_HCIStatusCode(const MgmtStatus mstatus) noexcept
Definition: MgmtTypes.cpp:648
MgmtCSRKType
Signature Resolving Key Types compatible with Mgmt's MgmtSignatureResolvingKey.
Definition: MgmtTypes.hpp:165
MgmtLinkKeyType
Link Key Types compatible with Mgmt's MgmtLinkKeyInfo.
Definition: MgmtTypes.hpp:118
MgmtLTKType
Long Term Key Types compatible with Mgmt's MgmtLongTermKey.
Definition: MgmtTypes.hpp:145
MgmtLTKType to_MgmtLTKType(const SMPLongTermKey::Property ltk_prop_mask) noexcept
Definition: MgmtTypes.cpp:132
@ MGMT_MAX_NAME_LENGTH
Definition: MgmtTypes.hpp:80
std::string to_string(const DiscoveryPolicy v) noexcept
Definition: BTAdapter.cpp:58
AdapterSetting
Adapter Setting Bits.
Definition: BTTypes1.hpp:144
BDAddressType
BT Core Spec v5.2: Vol 3, Part C Generic Access Profile (GAP): 15.1.1.1 Public Bluetooth address.
Definition: BTAddress.hpp:60
HCIStatusCode
BT Core Spec v5.2: Vol 1, Part F Controller Error Codes: 1.3 List of Error Codes.
Definition: HCITypes.hpp:138
@ BDADDR_LE_PUBLIC
Bluetooth LE public address.
@ REMOTE_DEVICE_TERMINATED_CONNECTION_LOW_RESOURCES
uint_fast32_t nsize_t
Natural 'size_t' alternative using uint_fast32_t as its natural sized type.
Definition: int_types.hpp:53
Used in MgmtReadDefaultSysParamCmd and MgmtSetDefaultConnParamCmd.
Definition: MgmtTypes.hpp:1237
jau::nsize_t mgmt_size() const
Mgmt size, i.e.
Definition: MgmtTypes.hpp:1317
A packed 48 bit EUI-48 identifier, formerly known as MAC-48 or simply network device MAC address (Med...
Definition: eui48.hpp:324