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