1 /* 2 * node.c 3 * 4 * Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 * $Id: node.c,v 1.6 2003/07/22 21:14:02 max Exp $ 29 * $FreeBSD$ 30 */ 31 32 #include <sys/ioctl.h> 33 #define L2CAP_SOCKET_CHECKED 34 #include <bluetooth.h> 35 #include <errno.h> 36 #include <netgraph/ng_message.h> 37 #include <stdio.h> 38 #include <stdlib.h> 39 #include <string.h> 40 #include <unistd.h> 41 #include "hccontrol.h" 42 43 /* Send Read_Node_State command to the node */ 44 static int 45 hci_read_node_state(int s, int argc, char **argv) 46 { 47 struct ng_btsocket_hci_raw_node_state r; 48 49 memset(&r, 0, sizeof(r)); 50 if (ioctl(s, SIOC_HCI_RAW_NODE_GET_STATE, &r, sizeof(r)) < 0) 51 return (ERROR); 52 53 fprintf(stdout, "State: %#x\n", r.state); 54 55 return (OK); 56 } /* hci_read_node_state */ 57 58 /* Send Intitialize command to the node */ 59 static int 60 hci_node_initialize(int s, int argc, char **argv) 61 { 62 if (ioctl(s, SIOC_HCI_RAW_NODE_INIT) < 0) 63 return (ERROR); 64 65 return (OK); 66 } /* hci_node_initialize */ 67 68 /* Send Read_Debug_Level command to the node */ 69 static int 70 hci_read_debug_level(int s, int argc, char **argv) 71 { 72 struct ng_btsocket_hci_raw_node_debug r; 73 74 memset(&r, 0, sizeof(r)); 75 if (ioctl(s, SIOC_HCI_RAW_NODE_GET_DEBUG, &r, sizeof(r)) < 0) 76 return (ERROR); 77 78 fprintf(stdout, "Debug level: %d\n", r.debug); 79 80 return (OK); 81 } /* hci_read_debug_level */ 82 83 /* Send Write_Debug_Level command to the node */ 84 static int 85 hci_write_debug_level(int s, int argc, char **argv) 86 { 87 struct ng_btsocket_hci_raw_node_debug r; 88 89 memset(&r, 0, sizeof(r)); 90 switch (argc) { 91 case 1: 92 r.debug = atoi(argv[0]); 93 break; 94 95 default: 96 return (USAGE); 97 } 98 99 if (ioctl(s, SIOC_HCI_RAW_NODE_SET_DEBUG, &r, sizeof(r)) < 0) 100 return (ERROR); 101 102 return (OK); 103 } /* hci_write_debug_level */ 104 105 /* Send Read_Node_Buffer_Size command to the node */ 106 static int 107 hci_read_node_buffer_size(int s, int argc, char **argv) 108 { 109 struct ng_btsocket_hci_raw_node_buffer r; 110 111 memset(&r, 0, sizeof(r)); 112 if (ioctl(s, SIOC_HCI_RAW_NODE_GET_BUFFER, &r, sizeof(r)) < 0) 113 return (ERROR); 114 115 fprintf(stdout, "Number of free command buffers: %d\n", 116 r.buffer.cmd_free); 117 fprintf(stdout, "Max. ACL packet size: %d\n", 118 r.buffer.acl_size); 119 fprintf(stdout, "Numbef of free ACL buffers: %d\n", 120 r.buffer.acl_free); 121 fprintf(stdout, "Total number of ACL buffers: %d\n", 122 r.buffer.acl_pkts); 123 fprintf(stdout, "Max. SCO packet size: %d\n", 124 r.buffer.sco_size); 125 fprintf(stdout, "Numbef of free SCO buffers: %d\n", 126 r.buffer.sco_free); 127 fprintf(stdout, "Total number of SCO buffers: %d\n", 128 r.buffer.sco_pkts); 129 130 return (OK); 131 } /* hci_read_node_buffer_size */ 132 133 /* Send Read_Node_BD_ADDR command to the node */ 134 static int 135 hci_read_node_bd_addr(int s, int argc, char **argv) 136 { 137 struct ng_btsocket_hci_raw_node_bdaddr r; 138 139 memset(&r, 0, sizeof(r)); 140 if (ioctl(s, SIOC_HCI_RAW_NODE_GET_BDADDR, &r, sizeof(r)) < 0) 141 return (ERROR); 142 143 fprintf(stdout, "BD_ADDR: %s\n", bt_ntoa(&r.bdaddr, NULL)); 144 145 return (OK); 146 } /* hci_read_node_bd_addr */ 147 148 /* Send Read_Node_Features command to the node */ 149 static int 150 hci_read_node_features(int s, int argc, char **argv) 151 { 152 struct ng_btsocket_hci_raw_node_features r; 153 int n; 154 char buffer[1024]; 155 156 memset(&r, 0, sizeof(r)); 157 if (ioctl(s, SIOC_HCI_RAW_NODE_GET_FEATURES, &r, sizeof(r)) < 0) 158 return (ERROR); 159 160 fprintf(stdout, "Features: "); 161 for (n = 0; n < sizeof(r.features)/sizeof(r.features[0]); n++) 162 fprintf(stdout, "%#02x ", r.features[n]); 163 fprintf(stdout, "\n%s\n", hci_features2str(r.features, 164 buffer, sizeof(buffer))); 165 166 return (OK); 167 } /* hci_read_node_features */ 168 169 /* Send Read_Node_Stat command to the node */ 170 static int 171 hci_read_node_stat(int s, int argc, char **argv) 172 { 173 struct ng_btsocket_hci_raw_node_stat r; 174 175 memset(&r, 0, sizeof(r)); 176 if (ioctl(s, SIOC_HCI_RAW_NODE_GET_STAT, &r, sizeof(r)) < 0) 177 return (ERROR); 178 179 fprintf(stdout, "Commands sent: %d\n", r.stat.cmd_sent); 180 fprintf(stdout, "Events received: %d\n", r.stat.evnt_recv); 181 fprintf(stdout, "ACL packets received: %d\n", r.stat.acl_recv); 182 fprintf(stdout, "ACL packets sent: %d\n", r.stat.acl_sent); 183 fprintf(stdout, "SCO packets received: %d\n", r.stat.sco_recv); 184 fprintf(stdout, "SCO packets sent: %d\n", r.stat.sco_sent); 185 fprintf(stdout, "Bytes received: %d\n", r.stat.bytes_recv); 186 fprintf(stdout, "Bytes sent: %d\n", r.stat.bytes_sent); 187 188 return (OK); 189 } /* hci_read_node_stat */ 190 191 /* Send Reset_Node_Stat command to the node */ 192 static int 193 hci_reset_node_stat(int s, int argc, char **argv) 194 { 195 if (ioctl(s, SIOC_HCI_RAW_NODE_RESET_STAT) < 0) 196 return (ERROR); 197 198 return (OK); 199 } /* hci_reset_node_stat */ 200 201 /* Send Flush_Neighbor_Cache command to the node */ 202 static int 203 hci_flush_neighbor_cache(int s, int argc, char **argv) 204 { 205 if (ioctl(s, SIOC_HCI_RAW_NODE_FLUSH_NEIGHBOR_CACHE) < 0) 206 return (ERROR); 207 208 return (OK); 209 } /* hci_flush_neighbor_cache */ 210 211 #define MIN(a,b) (((a)>(b)) ? (b) :(a) ) 212 213 static int hci_dump_adv(uint8_t *data, int length) 214 { 215 int elemlen; 216 int type; 217 int i; 218 219 while(length>0){ 220 elemlen = *data; 221 data++; 222 length --; 223 elemlen--; 224 if(length<=0) 225 break; 226 type = *data; 227 data++; 228 length --; 229 elemlen--; 230 if(length<=0) 231 break; 232 switch(type){ 233 case 0x1: 234 printf("NDflag:%x\n", *data); 235 break; 236 case 0x9: 237 printf("LocalName:"); 238 for(i = 0; i < MIN(length,elemlen); i++){ 239 putchar(data[i]); 240 } 241 printf("\n"); 242 break; 243 default: 244 printf("Type%d:", type); 245 for(i=0; i < MIN(length,elemlen); i++){ 246 printf("%02x ",data[i]); 247 } 248 printf("\n"); 249 break; 250 } 251 data += elemlen; 252 length -= elemlen; 253 } 254 return 0; 255 } 256 #undef MIN 257 /* Send Read_Neighbor_Cache command to the node */ 258 static int 259 hci_read_neighbor_cache(int s, int argc, char **argv) 260 { 261 struct ng_btsocket_hci_raw_node_neighbor_cache r; 262 int n, error = OK; 263 const char *addrtype2str[] = {"B", "P", "R", "E"}; 264 265 memset(&r, 0, sizeof(r)); 266 r.num_entries = NG_HCI_MAX_NEIGHBOR_NUM; 267 r.entries = calloc(NG_HCI_MAX_NEIGHBOR_NUM, 268 sizeof(ng_hci_node_neighbor_cache_entry_ep)); 269 if (r.entries == NULL) { 270 errno = ENOMEM; 271 return (ERROR); 272 } 273 274 if (ioctl(s, SIOC_HCI_RAW_NODE_GET_NEIGHBOR_CACHE, &r, 275 sizeof(r)) < 0) { 276 error = ERROR; 277 goto out; 278 } 279 280 fprintf(stdout, 281 "T " \ 282 "BD_ADDR " \ 283 "Features " \ 284 "Clock offset " \ 285 "Page scan " \ 286 "Rep. scan\n"); 287 288 for (n = 0; n < r.num_entries; n++) { 289 uint8_t addrtype = r.entries[n].addrtype; 290 if(addrtype >= sizeof(addrtype2str)/sizeof(addrtype2str[0])) 291 addrtype = sizeof(addrtype2str)/sizeof(addrtype2str[0]) - 1; 292 fprintf(stdout, 293 "%1s %-17.17s " \ 294 "%02x %02x %02x %02x %02x %02x %02x %02x " \ 295 "%#12x " \ 296 "%#9x " \ 297 "%#9x\n", 298 addrtype2str[addrtype], 299 hci_bdaddr2str(&r.entries[n].bdaddr), 300 r.entries[n].features[0], r.entries[n].features[1], 301 r.entries[n].features[2], r.entries[n].features[3], 302 r.entries[n].features[4], r.entries[n].features[5], 303 r.entries[n].features[6], r.entries[n].features[7], 304 r.entries[n].clock_offset, r.entries[n].page_scan_mode, 305 r.entries[n].page_scan_rep_mode); 306 hci_dump_adv(r.entries[n].extinq_data, 307 r.entries[n].extinq_size); 308 fprintf(stdout,"\n"); 309 } 310 out: 311 free(r.entries); 312 313 return (error); 314 } /* hci_read_neightbor_cache */ 315 316 /* Send Read_Connection_List command to the node */ 317 static int 318 hci_read_connection_list(int s, int argc, char **argv) 319 { 320 struct ng_btsocket_hci_raw_con_list r; 321 int n, error = OK; 322 323 memset(&r, 0, sizeof(r)); 324 r.num_connections = NG_HCI_MAX_CON_NUM; 325 r.connections = calloc(NG_HCI_MAX_CON_NUM, sizeof(ng_hci_node_con_ep)); 326 if (r.connections == NULL) { 327 errno = ENOMEM; 328 return (ERROR); 329 } 330 331 if (ioctl(s, SIOC_HCI_RAW_NODE_GET_CON_LIST, &r, sizeof(r)) < 0) { 332 error = ERROR; 333 goto out; 334 } 335 336 fprintf(stdout, 337 "Remote BD_ADDR " \ 338 "Handle " \ 339 "Type " \ 340 "Mode " \ 341 "Role " \ 342 "Encrypt " \ 343 "Pending " \ 344 "Queue " \ 345 "State\n"); 346 347 for (n = 0; n < r.num_connections; n++) { 348 fprintf(stdout, 349 "%-17.17s " \ 350 "%6d " \ 351 "%4.4s " \ 352 "%4d " \ 353 "%4.4s " \ 354 "%7.7s " \ 355 "%7d " \ 356 "%5d " \ 357 "%s\n", 358 hci_bdaddr2str(&r.connections[n].bdaddr), 359 r.connections[n].con_handle, 360 (r.connections[n].link_type == NG_HCI_LINK_ACL)? 361 "ACL" : "SCO", 362 r.connections[n].mode, 363 (r.connections[n].role == NG_HCI_ROLE_MASTER)? 364 "MAST" : "SLAV", 365 hci_encrypt2str(r.connections[n].encryption_mode, 1), 366 r.connections[n].pending, 367 r.connections[n].queue_len, 368 hci_con_state2str(r.connections[n].state)); 369 } 370 out: 371 free(r.connections); 372 373 return (error); 374 } /* hci_read_connection_list */ 375 376 /* Send Read_Node_Link_Policy_Settings_Mask command to the node */ 377 int 378 hci_read_node_link_policy_settings_mask(int s, int argc, char **argv) 379 { 380 struct ng_btsocket_hci_raw_node_link_policy_mask r; 381 382 memset(&r, 0, sizeof(r)); 383 if (ioctl(s, SIOC_HCI_RAW_NODE_GET_LINK_POLICY_MASK, &r, sizeof(r)) < 0) 384 return (ERROR); 385 386 fprintf(stdout, "Link Policy Settings mask: %#04x\n", r.policy_mask); 387 388 return (OK); 389 } /* hci_read_node_link_policy_settings_mask */ 390 391 /* Send Write_Node_Link_Policy_Settings_Mask command to the node */ 392 int 393 hci_write_node_link_policy_settings_mask(int s, int argc, char **argv) 394 { 395 struct ng_btsocket_hci_raw_node_link_policy_mask r; 396 int m; 397 398 memset(&r, 0, sizeof(r)); 399 400 switch (argc) { 401 case 1: 402 if (sscanf(argv[0], "%x", &m) != 1) 403 return (USAGE); 404 405 r.policy_mask = (m & 0xffff); 406 break; 407 408 default: 409 return (USAGE); 410 } 411 412 if (ioctl(s, SIOC_HCI_RAW_NODE_SET_LINK_POLICY_MASK, &r, sizeof(r)) < 0) 413 return (ERROR); 414 415 return (OK); 416 } /* hci_write_node_link_policy_settings_mask */ 417 418 /* Send Read_Node_Packet_Mask command to the node */ 419 int 420 hci_read_node_packet_mask(int s, int argc, char **argv) 421 { 422 struct ng_btsocket_hci_raw_node_packet_mask r; 423 424 memset(&r, 0, sizeof(r)); 425 if (ioctl(s, SIOC_HCI_RAW_NODE_GET_PACKET_MASK, &r, sizeof(r)) < 0) 426 return (ERROR); 427 428 fprintf(stdout, "Packet mask: %#04x\n", r.packet_mask); 429 430 return (OK); 431 } /* hci_read_node_packet_mask */ 432 433 /* Send Write_Node_Packet_Mask command to the node */ 434 int 435 hci_write_node_packet_mask(int s, int argc, char **argv) 436 { 437 struct ng_btsocket_hci_raw_node_packet_mask r; 438 int m; 439 440 memset(&r, 0, sizeof(r)); 441 442 switch (argc) { 443 case 1: 444 if (sscanf(argv[0], "%x", &m) != 1) 445 return (USAGE); 446 447 r.packet_mask = (m & 0xffff); 448 break; 449 450 default: 451 return (USAGE); 452 } 453 454 if (ioctl(s, SIOC_HCI_RAW_NODE_SET_PACKET_MASK, &r, sizeof(r)) < 0) 455 return (ERROR); 456 457 return (OK); 458 } /* hci_write_node_packet_mask */ 459 460 /* Send Read_Node_Role_Switch command to the node */ 461 int 462 hci_read_node_role_switch(int s, int argc, char **argv) 463 { 464 struct ng_btsocket_hci_raw_node_role_switch r; 465 466 memset(&r, 0, sizeof(r)); 467 if (ioctl(s, SIOC_HCI_RAW_NODE_GET_ROLE_SWITCH, &r, sizeof(r)) < 0) 468 return (ERROR); 469 470 fprintf(stdout, "Role switch: %d\n", r.role_switch); 471 472 return (OK); 473 } /* hci_read_node_role_switch */ 474 475 /* Send Write_Node_Role_Switch command to the node */ 476 int 477 hci_write_node_role_switch(int s, int argc, char **argv) 478 { 479 struct ng_btsocket_hci_raw_node_role_switch r; 480 int m; 481 482 memset(&r, 0, sizeof(r)); 483 484 switch (argc) { 485 case 1: 486 if (sscanf(argv[0], "%d", &m) != 1) 487 return (USAGE); 488 489 r.role_switch = m? 1 : 0; 490 break; 491 492 default: 493 return (USAGE); 494 } 495 496 if (ioctl(s, SIOC_HCI_RAW_NODE_SET_ROLE_SWITCH, &r, sizeof(r)) < 0) 497 return (ERROR); 498 499 return (OK); 500 } /* hci_write_node_role_switch */ 501 502 /* Send Read_Node_List command to the node */ 503 int 504 hci_read_node_list(int s, int argc, char **argv) 505 { 506 struct ng_btsocket_hci_raw_node_list_names r; 507 int i; 508 509 r.num_names = MAX_NODE_NUM; 510 r.names = (struct nodeinfo*)calloc(MAX_NODE_NUM, sizeof(struct nodeinfo)); 511 if (r.names == NULL) 512 return (ERROR); 513 514 if (ioctl(s, SIOC_HCI_RAW_NODE_LIST_NAMES, &r, sizeof(r)) < 0) { 515 free(r.names); 516 return (ERROR); 517 } 518 519 fprintf(stdout, "Name ID Num hooks\n"); 520 for (i = 0; i < r.num_names; ++i) 521 fprintf(stdout, "%-15s %08x %9d\n", 522 r.names[i].name, r.names[i].id, r.names[i].hooks); 523 524 free(r.names); 525 526 return (OK); 527 } /* hci_read_node_list */ 528 529 struct hci_command node_commands[] = { 530 { 531 "read_node_state", 532 "Get the HCI node state", 533 &hci_read_node_state 534 }, 535 { 536 "initialize", 537 "Initialize the HCI node", 538 &hci_node_initialize 539 }, 540 { 541 "read_debug_level", 542 "Read the HCI node debug level", 543 &hci_read_debug_level 544 }, 545 { 546 "write_debug_level <level>", 547 "Write the HCI node debug level", 548 &hci_write_debug_level 549 }, 550 { 551 "read_node_buffer_size", 552 "Read the HCI node buffer information. This will return current state of the\n"\ 553 "HCI buffer for the HCI node", 554 &hci_read_node_buffer_size 555 }, 556 { 557 "read_node_bd_addr", 558 "Read the HCI node BD_ADDR. Returns device BD_ADDR as cached by the HCI node", 559 &hci_read_node_bd_addr 560 }, 561 { 562 "read_node_features", 563 "Read the HCI node features. This will return list of supported features as\n" \ 564 "cached by the HCI node", 565 &hci_read_node_features 566 }, 567 { 568 "read_node_stat", 569 "Read packets and bytes counters for the HCI node", 570 &hci_read_node_stat 571 }, 572 { 573 "reset_node_stat", 574 "Reset packets and bytes counters for the HCI node", 575 &hci_reset_node_stat 576 }, 577 { 578 "flush_neighbor_cache", 579 "Flush content of the HCI node neighbor cache", 580 &hci_flush_neighbor_cache 581 }, 582 { 583 "read_neighbor_cache", 584 "Read content of the HCI node neighbor cache", 585 &hci_read_neighbor_cache 586 }, 587 { 588 "read_connection_list", 589 "Read the baseband connection descriptors list for the HCI node", 590 &hci_read_connection_list 591 }, 592 { 593 "read_node_link_policy_settings_mask", 594 "Read the value of the Link Policy Settinngs mask for the HCI node", 595 &hci_read_node_link_policy_settings_mask 596 }, 597 { 598 "write_node_link_policy_settings_mask <policy_mask>", 599 "Write the value of the Link Policy Settings mask for the HCI node. By default\n" \ 600 "all supported Link Policy modes (as reported by the local device features) are\n"\ 601 "enabled. The particular Link Policy mode is enabled if local device supports\n"\ 602 "it and correspinding bit in the mask was set\n\n" \ 603 "\t<policy_mask> - xxxx; Link Policy mask\n" \ 604 "\t\t0x0000 - Disable All LM Modes\n" \ 605 "\t\t0x0001 - Enable Master Slave Switch\n" \ 606 "\t\t0x0002 - Enable Hold Mode\n" \ 607 "\t\t0x0004 - Enable Sniff Mode\n" \ 608 "\t\t0x0008 - Enable Park Mode\n", 609 &hci_write_node_link_policy_settings_mask 610 }, 611 { 612 "read_node_packet_mask", 613 "Read the value of the Packet mask for the HCI node", 614 &hci_read_node_packet_mask 615 }, 616 { 617 "write_node_packet_mask <packet_mask>", 618 "Write the value of the Packet mask for the HCI node. By default all supported\n" \ 619 "packet types (as reported by the local device features) are enabled. The\n" \ 620 "particular packet type is enabled if local device supports it and corresponding\n" \ 621 "bit in the mask was set\n\n" \ 622 "\t<packet_mask> - xxxx; packet type mask\n" \ 623 "" \ 624 "\t\tACL packets\n" \ 625 "\t\t-----------\n" \ 626 "\t\t0x0008 DM1\n" \ 627 "\t\t0x0010 DH1\n" \ 628 "\t\t0x0400 DM3\n" \ 629 "\t\t0x0800 DH3\n" \ 630 "\t\t0x4000 DM5\n" \ 631 "\t\t0x8000 DH5\n" \ 632 "\n" \ 633 "\t\tSCO packets\n" \ 634 "\t\t-----------\n" \ 635 "\t\t0x0020 HV1\n" \ 636 "\t\t0x0040 HV2\n" \ 637 "\t\t0x0080 HV3\n", 638 &hci_write_node_packet_mask 639 }, 640 { 641 "read_node_role_switch", 642 "Read the value of the Role Switch parameter for the HCI node", 643 &hci_read_node_role_switch 644 }, 645 { 646 "write_node_role_switch {0|1}", 647 "Write the value of the Role Switch parameter for the HCI node. By default,\n" \ 648 "if Role Switch is supported, local device will try to perform Role Switch\n" \ 649 "and become Master on incoming connection. Some devices do not support Role\n" \ 650 "Switch and thus incoming connections from such devices will fail. Setting\n" \ 651 "this parameter to zero will prevent Role Switch and thus accepting device\n" \ 652 "will remain Slave", 653 &hci_write_node_role_switch 654 }, 655 { 656 "read_node_list", 657 "Get a list of HCI nodes, their Netgraph IDs and connected hooks.", 658 &hci_read_node_list 659 }, 660 { 661 NULL, 662 }}; 663 664