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