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