1 /* 2 * Copyright 2008 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com 3 * Copyright 2008 Mika Lindqvist 4 * All rights reserved. Distributed under the terms of the MIT License. 5 */ 6 7 #include "CommandManager.h" 8 9 inline void* buildCommand(uint8 ogf, uint8 ocf, void** param, size_t psize, size_t* outsize) 10 { 11 struct hci_command_header* header; 12 13 #ifdef BT_IOCTLS_PASS_SIZE 14 header = (struct hci_command_header*) malloc(psize + sizeof(struct hci_command_header)); 15 *outsize = psize + sizeof(struct hci_command_header); 16 #else 17 size_t* size = (size_t*)malloc(psize + sizeof(struct hci_command_header) + sizeof(size_t)); 18 *outsize = psize + sizeof(struct hci_command_header) + sizeof(size_t); 19 20 *size = psize + sizeof(struct hci_command_header); 21 header = (struct hci_command_header*) (((uint8*)size)+4); 22 #endif 23 24 25 if (header != NULL) { 26 27 header->opcode = B_HOST_TO_LENDIAN_INT16(PACK_OPCODE(ogf, ocf)); 28 header->clen = psize; 29 30 if (param != NULL && psize != 0) { 31 *param = ((uint8*)header) + sizeof(struct hci_command_header); 32 } 33 } 34 #ifdef BT_IOCTLS_PASS_SIZE 35 return header; 36 #else 37 return (void*)size; 38 #endif 39 } 40 41 42 #if 0 43 #pragma mark - CONTROL BASEBAND - 44 #endif 45 46 47 void* buildReset(size_t* outsize) 48 { 49 return buildCommand(OGF_CONTROL_BASEBAND, OCF_RESET, NULL, 0, outsize); 50 } 51 52 53 void* buildReadLocalName(size_t* outsize) 54 { 55 return buildCommand(OGF_CONTROL_BASEBAND, OCF_READ_LOCAL_NAME, NULL, 0, outsize); 56 } 57 58 59 void* buildReadClassOfDevice(size_t* outsize) 60 { 61 return buildCommand(OGF_CONTROL_BASEBAND, OCF_READ_CLASS_OF_DEV, NULL, 0, outsize); 62 } 63 64 65 void* buildWriteScan(uint8 scanmode, size_t* outsize) 66 { 67 struct hci_write_scan_enable* param; 68 void* command = buildCommand(OGF_CONTROL_BASEBAND, OCF_WRITE_SCAN_ENABLE, (void**) ¶m, sizeof(struct hci_write_scan_enable), outsize); 69 70 71 if (command != NULL) { 72 param->scan = scanmode; 73 } 74 75 return command; 76 77 } 78 79 80 void* buildAuthEnable(uint8 auth, size_t* outsize) 81 { 82 struct hci_write_authentication_enable* param; 83 void* command = buildCommand(OGF_CONTROL_BASEBAND, OCF_WRITE_AUTH_ENABLE, (void**) ¶m, sizeof(struct hci_write_authentication_enable), outsize); 84 85 86 if (command != NULL) { 87 param->authentication = auth; 88 } 89 90 return command; 91 92 } 93 94 95 #if 0 96 #pragma mark - LINK CONTROL - 97 #endif 98 99 100 void* buildCreateConnection(bdaddr_t bdaddr) 101 { 102 /* 103 cm4.size = sizeof(struct hci_command_header)+sizeof(struct hci_cp_create_conn); 104 cm4.header.opcode = B_HOST_TO_LENDIAN_INT16(hci_opcode_pack(OGF_LINK_CONTROL, OCF_CREATE_CONN)); 105 cm4.body.bdaddr.b[0] = 0x92; 106 cm4.body.bdaddr.b[1] = 0xd3; 107 cm4.body.bdaddr.b[2] = 0xaf; 108 cm4.body.bdaddr.b[3] = 0xd9; 109 cm4.body.bdaddr.b[4] = 0x0a; 110 cm4.body.bdaddr.b[5] = 0x00; 111 cm4.body.pkt_type = 0xFFFF; 112 cm4.body.pscan_rep_mode = 1; 113 cm4.body.pscan_mode = 0; 114 cm4.body.clock_offset = 0xc7; 115 cm4.body.role_switch = 1; 116 cm4.header.clen = 13; 117 ioctl(fd1, ISSUE_BT_COMMAND, &cm4, sizeof(cm4)); 118 */ 119 120 return NULL; 121 } 122 123 124 void* buildRemoteNameRequest(bdaddr_t bdaddr,uint8 pscan_rep_mode, uint16 clock_offset, size_t* outsize) 125 { 126 127 struct hci_remote_name_request* param; 128 void* command = buildCommand(OGF_LINK_CONTROL, OCF_REMOTE_NAME_REQUEST, (void**) ¶m, sizeof(struct hci_remote_name_request), outsize); 129 130 if (command != NULL) { 131 param->bdaddr = bdaddr; 132 param->pscan_rep_mode = pscan_rep_mode; 133 param->clock_offset = clock_offset; 134 } 135 136 return command; 137 } 138 139 140 void* buildInquiry(uint32 lap, uint8 length, uint8 num_rsp, size_t* outsize) 141 { 142 143 struct hci_cp_inquiry* param; 144 void* command = buildCommand(OGF_LINK_CONTROL, OCF_INQUIRY, (void**) ¶m, sizeof(struct hci_cp_inquiry), outsize); 145 146 if (command != NULL) { 147 148 param->lap[2] = (lap >> 16) & 0xFF; 149 param->lap[1] = (lap >> 8) & 0xFF; 150 param->lap[0] = (lap >> 0) & 0xFF; 151 param->length = length; 152 param->num_rsp = num_rsp; 153 } 154 155 return command; 156 } 157 158 159 void* buildInquiryCancel(size_t* outsize) 160 { 161 162 return buildCommand(OGF_LINK_CONTROL, OCF_INQUIRY_CANCEL, NULL, 0, outsize); 163 164 } 165 166 167 void* buildPinCodeRequestReply(bdaddr_t bdaddr, uint8 length, char pincode[16], size_t* outsize) 168 { 169 170 struct hci_cp_pin_code_reply* param; 171 172 if (length > HCI_PIN_SIZE) // PinCode cannot be longer than 16 173 return NULL; 174 175 void* command = buildCommand(OGF_LINK_CONTROL, OCF_PIN_CODE_REPLY, (void**) ¶m, sizeof(struct hci_cp_pin_code_reply), outsize); 176 177 if (command != NULL) { 178 179 param->bdaddr = bdaddr; 180 param->pin_len = length; 181 memcpy(¶m->pin_code, pincode, length); 182 183 } 184 185 return command; 186 } 187 188 189 void* buildPinCodeRequestNegativeReply(bdaddr_t bdaddr, size_t* outsize) 190 { 191 192 struct hci_cp_pin_code_neg_reply* param; 193 194 void* command = buildCommand(OGF_LINK_CONTROL, OCF_PIN_CODE_NEG_REPLY, 195 (void**) ¶m, sizeof(struct hci_cp_pin_code_neg_reply), outsize); 196 197 if (command != NULL) { 198 199 param->bdaddr = bdaddr; 200 201 } 202 203 return command; 204 } 205 206 207 void* buildAcceptConnectionRequest(bdaddr_t bdaddr, uint8 role, size_t* outsize) 208 { 209 struct hci_cp_accept_conn_req* param; 210 211 void* command = buildCommand(OGF_LINK_CONTROL, OCF_ACCEPT_CONN_REQ, 212 (void**) ¶m, sizeof(struct hci_cp_accept_conn_req), outsize); 213 214 if (command != NULL) { 215 param->bdaddr = bdaddr; 216 param->role = role; 217 } 218 219 return command; 220 } 221 222 223 void* buildRejectConnectionRequest(bdaddr_t bdaddr, size_t* outsize) 224 { 225 struct hci_cp_reject_conn_req* param; 226 227 void *command = buildCommand(OGF_LINK_CONTROL, OCF_REJECT_CONN_REQ, 228 (void**) ¶m, sizeof(struct hci_cp_reject_conn_req), outsize); 229 230 if (command != NULL) { 231 param->bdaddr = bdaddr; 232 } 233 234 return command; 235 } 236 237 238 #if 0 239 #pragma mark - INFORMATIONAL_PARAM - 240 #endif 241 242 void* buildReadLocalVersionInformation(size_t* outsize) 243 { 244 return buildCommand(OGF_INFORMATIONAL_PARAM, OCF_READ_LOCAL_VERSION, NULL, 0, outsize); 245 } 246 247 248 void* buildReadBufferSize(size_t* outsize) 249 { 250 return buildCommand(OGF_INFORMATIONAL_PARAM, OCF_READ_BUFFER_SIZE, NULL, 0, outsize); 251 } 252 253 254 void* buildReadBdAddr(size_t* outsize) 255 { 256 return buildCommand(OGF_INFORMATIONAL_PARAM, OCF_READ_BD_ADDR, NULL, 0, outsize); 257 } 258 259 260 const char* bluetoothManufacturers[] = { 261 "Ericsson Technology Licensing", 262 "Nokia Mobile Phones", 263 "Intel Corp.", 264 "IBM Corp.", 265 "Toshiba Corp.", 266 "3Com", 267 "Microsoft", 268 "Lucent", 269 "Motorola", 270 "Infineon Technologies AG", 271 "Cambridge Silicon Radio", 272 "Silicon Wave", 273 "Digianswer A/S", 274 "Texas Instruments Inc.", 275 "Parthus Technologies Inc.", 276 "Broadcom Corporation", 277 "Mitel Semiconductor", 278 "Widcomm, Inc.", 279 "Zeevo, Inc.", 280 "Atmel Corporation", 281 "Mitsubishi Electric Corporation", 282 "RTX Telecom A/S", 283 "KC Technology Inc.", 284 "Newlogic", 285 "Transilica, Inc.", 286 "Rohde & Schwartz GmbH & Co. KG", 287 "TTPCom Limited", 288 "Signia Technologies, Inc.", 289 "Conexant Systems Inc.", 290 "Qualcomm", 291 "Inventel", 292 "AVM Berlin", 293 "BandSpeed, Inc.", 294 "Mansella Ltd", 295 "NEC Corporation", 296 "WavePlus Technology Co., Ltd.", 297 "Alcatel", 298 "Philips Semiconductors", 299 "C Technologies", 300 "Open Interface", 301 "R F Micro Devices", 302 "Hitachi Ltd", 303 "Symbol Technologies, Inc.", 304 "Tenovis", 305 "Macronix International Co. Ltd.", 306 "GCT Semiconductor", 307 "Norwood Systems", 308 "MewTel Technology Inc.", 309 "ST Microelectronics", 310 "Synopsys", 311 "Red-M (Communications) Ltd", 312 "Commil Ltd", 313 "Computer Access Technology Corporation (CATC)", 314 "Eclipse (HQ España) S.L.", 315 "Renesas Technology Corp.", 316 "Mobilian Corporation", 317 "Terax", 318 "Integrated System Solution Corp.", 319 "Matsushita Electric Industrial Co., Ltd.", 320 "Gennum Corporation", 321 "Research In Motion", 322 "IPextreme, Inc.", 323 "Systems and Chips, Inc", 324 "Bluetooth SIG, Inc", 325 "Seiko Epson Corporation", 326 "Integrated Silicon Solution Taiwain, Inc.", 327 "CONWISE Technology Corporation Ltd", 328 "PARROT SA", 329 "Socket Communications", 330 "Atheros Communications, Inc.", 331 "MediaTek, Inc.", 332 "Bluegiga", /* (tentative) */ 333 "Marvell Technology Group Ltd.", 334 "3DSP Corporation", 335 "Accel Semiconductor Ltd.", 336 "Continental Automotive Systems", 337 "Apple, Inc.", 338 "Staccato Communications, Inc." 339 }; 340 341 342 const char* linkControlCommands[] = { 343 "Inquiry", 344 "Inquiry cancel", 345 "Periodic inquiry mode", 346 "Exit periodic inquiry mode", 347 "Create connection", 348 "Disconnect", 349 "Add SCO connection", // not on 2.1 350 "Cancel create connection", 351 "Accept connection request", 352 "Reject connection request", 353 "Link key request reply", 354 "Link key request negative reply", 355 "PIN code request reply", 356 "PIN code request negative reply", 357 "Change connection packet type", 358 "Reserved", // not on 2.1", 359 "Authentication requested", 360 "Reserved", // not on 2.1", 361 "Set connection encryption", 362 "Reserved", // not on 2.1", 363 "Change connection link key", 364 "Reserved", // not on 2.1", 365 "Master link key", 366 "Reserved", // not on 2.1", 367 "Remote name request", 368 "Cancel remote name request", 369 "Read remote supported features", 370 "Read remote extended features", 371 "Read remote version information", 372 "Reserved", // not on 2.1", 373 "Read clock offset", 374 "Read LMP handle", 375 "Reserved", 376 "Reserved", 377 "Reserved", 378 "Reserved", 379 "Reserved", 380 "Reserved", 381 "Reserved", 382 "Setup synchronous connection", 383 "Accept synchronous connection", 384 "Reject synchronous connection", 385 "IO capability request reply", 386 "User confirmation request reply", 387 "User confirmation request negative reply", 388 "User passkey request reply", 389 "User passkey request negative reply", 390 "Remote OOB data request reply", 391 "Reserved", 392 "Reserved", 393 "Remote OOB data request negative reply", 394 "IO capabilities response negative reply" 395 }; 396 397 398 const char* linkPolicyCommands[] = { 399 "Hold mode", 400 "Reserved", 401 "Sniff mode", 402 "Exit sniff mode", 403 "Park state", 404 "Exit park state", 405 "QoS setup", 406 "Reserved", 407 "Role discovery", 408 "Reserved", 409 "Switch role", 410 "Read link policy settings", 411 "Write link policy settings", 412 "Read default link policy settings", 413 "Write default link policy settings", 414 "Flow specification", 415 "Sniff subrating" 416 }; 417 418 419 const char* controllerBasebandCommands[] = { 420 "Set event mask", 421 "Reserved", 422 "Reset", 423 "Reserved", 424 "Set event filter", 425 "Reserved", 426 "Reserved", 427 "Flush", 428 "Read PIN type", 429 "Write PIN type", 430 "Create new unit key", 431 "Reserved", 432 "Read stored link key", 433 "Reserved", 434 "Reserved", 435 "Reserved", 436 "Write stored link key", 437 "Delete stored link key", 438 "Write local name", 439 "Read local name", 440 "Read connection accept timeout", 441 "Write connection accept timeout", 442 "Read page timeout", 443 "Write page timeout", 444 "Read scan enable", 445 "Write scan enable", 446 "Read page scan activity", 447 "Write page scan activity", 448 "Read inquiry scan activity", 449 "Write inquiry scan activity", 450 "Read authentication enable", 451 "Write authentication enable", 452 "Read encryption mode", // not 2.1 453 "Write encryption mode",// not 2.1 454 "Read class of device", 455 "Write class of device", 456 "Read voice setting", 457 "Write voice setting", 458 "Read automatic flush timeout", 459 "Write automatic flush timeout", 460 "Read num broadcast retransmissions", 461 "Write num broadcast retransmissions", 462 "Read hold mode activity", 463 "Write hold mode activity", 464 "Read transmit power level", 465 "Read synchronous flow control enable", 466 "Write synchronous flow control enable", 467 "Reserved", 468 "Set host controller to host flow control", 469 "Reserved", 470 "Host buffer size", 471 "Reserved", 472 "Host number of completed packets", 473 "Read link supervision timeout", 474 "Write link supervision timeout", 475 "Read number of supported IAC", 476 "Read current IAC LAP", 477 "Write current IAC LAP", 478 "Read page scan period mode", // not 2.1 479 "Write page scan period mode", // not 2.1 480 "Read page scan mode", // not 2.1 481 "Write page scan mode", // not 2.1 482 "Set AFH channel classification", 483 "Reserved", 484 "Reserved", 485 "Read inquiry scan type", 486 "Write inquiry scan type", 487 "Read inquiry mode", 488 "Write inquiry mode", 489 "Read page scan type", 490 "Write page scan type", 491 "Read AFH channel assessment mode", 492 "Write AFH channel assessment mode", 493 "Reserved", 494 "Reserved", 495 "Reserved", 496 "Reserved", 497 "Reserved", 498 "Reserved", 499 "Reserved", 500 "Read extended inquiry response", 501 "Write extended inquiry response", 502 "Refresh encryption key", 503 "Reserved", 504 "Read simple pairing mode", 505 "Write simple pairing mode", 506 "Read local OOB data", 507 "Read inquiry transmit power level", 508 "Write inquiry transmit power level", 509 "Read default erroneous data reporting", 510 "Write default erroneous data reporting", 511 "Reserved", 512 "Reserved", 513 "Reserved", 514 "Enhanced flush", 515 "Send keypress notification" 516 }; 517 518 519 const char* informationalParametersCommands[] = { 520 "Read local version information", 521 "Read local supported commands", 522 "Read local supported features", 523 "Read local extended features", 524 "Read buffer size", 525 "Reserved", 526 "Read country code", // not 2.1 527 "Reserved", 528 "Read BD ADDR" 529 }; 530 531 532 const char* statusParametersCommands[] = { 533 "Read failed contact counter", 534 "Reset failed contact counter", 535 "Read link quality", 536 "Reserved", 537 "Read RSSI", 538 "Read AFH channel map", 539 "Read clock", 540 }; 541 542 543 const char* testingCommands[] = { 544 "Read loopback mode", 545 "Write loopback mode", 546 "Enable device under test mode", 547 "Write simple pairing debug mode", 548 }; 549 550 551 const char* bluetoothEvents[] = { 552 "Inquiry complete", 553 "Inquiry result", 554 "Conn complete", 555 "Conn request", 556 "Disconnection complete", 557 "Auth complete", 558 "Remote name request complete", 559 "Encrypt change", 560 "Change conn link key complete", 561 "Master link key compl", 562 "Rmt features", 563 "Rmt version", 564 "QoS setup complete", 565 "Command complete", 566 "Command status", 567 "Hardware error", 568 "Flush occur", 569 "Role change", 570 "Num comp Pkts", 571 "Mode change", 572 "Return link keys", 573 "Pin code req", 574 "Link key req", 575 "Link key notify", 576 "Loopback command", 577 "Data buffer overflow", 578 "Max slot change", 579 "Read clock offset compl", 580 "Con Pkt type changed", 581 "QoS violation", 582 "Reserved", 583 "Page scan Rep mode change", 584 "Flow specification", 585 "Inquiry result with RSSI", 586 "Remote extended features", 587 "Reserved", 588 "Reserved", 589 "Reserved", 590 "Reserved", 591 "Reserved", 592 "Reserved", 593 "Reserved", 594 "Reserved", 595 "Synchronous connection completed", 596 "Synchronous connection changed", 597 "Reserved", 598 "Extended inquiry result", 599 "Encryption key refresh complete", 600 "IO capability request", 601 "IO capability response", 602 "User confirmation request", 603 "User passkey request", 604 "OOB data request", 605 "Simple pairing complete", 606 "Reserved", 607 "Link supervision timeout changed", 608 "Enhanced flush complete", 609 "Reserved", 610 "Reserved", 611 "Keypress notification", 612 "Remote host supported features notification" 613 }; 614 615 616 const char* bluetoothErrors[] = { 617 "No error", 618 "Unknown command", 619 "No connection", 620 "Hardware failure", 621 "Page timeout", 622 "Authentication failure", 623 "Pin or key missing", 624 "Memory full", 625 "Connection timeout", 626 "Max number of connections", 627 "Max number of SCO connections", 628 "Acl connection exists", 629 "Command disallowed", 630 "Rejected limited resources", 631 "Rejected security", 632 "Rejected personal", 633 "Host timeout", 634 "Unsupported feature", 635 "Invalid parameters", 636 "Remote user ended connection", 637 "Remote low resources", 638 "Remote power off", 639 "Connection terminated", 640 "Repeated attempts", 641 "Pairing not allowed", 642 "Unknown LMP Pdu", 643 "Unsupported remote feature", 644 "SCO offset rejected", 645 "SCO interval rejected", 646 "Air mode rejected", 647 "Invalid LMP parameters", 648 "Unspecified error", 649 "Unsupported LMP parameter value", 650 "Role change not allowed", 651 "LMP response timeout", 652 "LMP error transaction collision", 653 "LMP Pdu not allowed", 654 "Encryption mode not accepted", 655 "Unit link key used", 656 "QoS not supported", 657 "Instant passed", 658 "Pairing with unit key not supported", 659 "Different transaction collision", 660 "QoS unacceptable parameter", 661 "QoS rejected", 662 "Classification not supported", 663 "Insufficient security", 664 "Parameter out of range", 665 "Reserved", 666 "Role switch pending", 667 "Reserved", 668 "Slot violation", 669 "Role switch failed", 670 "Extended inquiry response too Large", 671 "Simple pairing not supported by host", 672 "Host busy pairing" 673 }; 674 675 676 const char* hciVersion[] = { "1.0B" , "1.1 " , "1.2 " , "2.0 " , "2.1 "}; 677 const char* lmpVersion[] = { "1.0 " , "1.1 " , "1.2 " , "2.0 " , "2.1 "}; 678 679 680 const char* 681 BluetoothHciVersion(uint16 ver) 682 { 683 return hciVersion[ver]; 684 } 685 686 687 const char* 688 BluetoothLmpVersion(uint16 ver) 689 { 690 return lmpVersion[ver]; 691 } 692 693 694 const char* 695 BluetoothCommandOpcode(uint16 opcode) 696 { 697 698 // NOTE: BT implementations beyond 2.1 699 // could specify new commands with OCF numbers 700 // beyond the boundaries of the arrays and crash. 701 // But only our stack could issue them so its under 702 // our control. 703 switch (GET_OPCODE_OGF(opcode)) { 704 case OGF_LINK_CONTROL: 705 return linkControlCommands[GET_OPCODE_OCF(opcode)-1]; 706 break; 707 708 case OGF_LINK_POLICY: 709 return linkPolicyCommands[GET_OPCODE_OCF(opcode)-1]; 710 break; 711 712 case OGF_CONTROL_BASEBAND: 713 return controllerBasebandCommands[GET_OPCODE_OCF(opcode)-1]; 714 break; 715 716 case OGF_INFORMATIONAL_PARAM: 717 return informationalParametersCommands[GET_OPCODE_OCF(opcode)-1]; 718 break; 719 720 case OGF_STATUS_PARAM: 721 return statusParametersCommands[GET_OPCODE_OCF(opcode)-1]; 722 break; 723 724 case OGF_TESTING_CMD: 725 return testingCommands[GET_OPCODE_OCF(opcode)-1]; 726 break; 727 case OGF_VENDOR_CMD: 728 return "Vendor specific command"; 729 break; 730 default: 731 return "Unknown command"; 732 break; 733 } 734 735 } 736 737 738 const char* 739 BluetoothEvent(uint8 event) { 740 741 if (event < sizeof(bluetoothEvents) / sizeof(const char*)) { 742 return bluetoothEvents[event-1]; 743 } else { 744 return "Event out of range!"; 745 } 746 } 747 748 749 const char* 750 BluetoothManufacturer(uint16 manufacturer) { 751 752 if (manufacturer < sizeof(bluetoothManufacturers) / sizeof(const char*)) { 753 return bluetoothManufacturers[manufacturer]; 754 } else if (manufacturer == 0xFFFF) { 755 return "internal use"; 756 } else { 757 return "not assigned"; 758 } 759 } 760 761 762 const char* 763 BluetoothError(uint8 error) { 764 765 if (error < sizeof(bluetoothErrors) / sizeof(const char*)) { 766 return bluetoothErrors[error]; 767 } else { 768 return "not specified"; 769 } 770 } 771 772