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.8 2002/11/12 22:33: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, "Node: %s\nState: %#x\n", r.hci_node, 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 struct ng_btsocket_hci_raw_node_init r; 65 66 memset(&r, 0, sizeof(r)); 67 if (ioctl(s, SIOC_HCI_RAW_NODE_INIT, &r, sizeof(r)) < 0) 68 return (ERROR); 69 70 return (OK); 71 } /* hci_node_initialize */ 72 73 /* Send Read_Debug_Level command to the node */ 74 static int 75 hci_read_debug_level(int s, int argc, char **argv) 76 { 77 struct ng_btsocket_hci_raw_node_debug r; 78 79 memset(&r, 0, sizeof(r)); 80 if (ioctl(s, SIOC_HCI_RAW_NODE_GET_DEBUG, &r, sizeof(r)) < 0) 81 return (ERROR); 82 83 fprintf(stdout, "Node: %s\nDebug level: %d\n", r.hci_node, r.debug); 84 85 return (OK); 86 } /* hci_read_debug_level */ 87 88 /* Send Write_Debug_Level command to the node */ 89 static int 90 hci_write_debug_level(int s, int argc, char **argv) 91 { 92 struct ng_btsocket_hci_raw_node_debug r; 93 94 memset(&r, 0, sizeof(r)); 95 switch (argc) { 96 case 1: 97 r.debug = atoi(argv[0]); 98 break; 99 100 default: 101 return (USAGE); 102 } 103 104 if (ioctl(s, SIOC_HCI_RAW_NODE_SET_DEBUG, &r, sizeof(r)) < 0) 105 return (ERROR); 106 107 return (OK); 108 } /* hci_write_debug_level */ 109 110 /* Send Read_Node_Buffer_Size command to the node */ 111 static int 112 hci_read_node_buffer_size(int s, int argc, char **argv) 113 { 114 struct ng_btsocket_hci_raw_node_buffer r; 115 116 memset(&r, 0, sizeof(r)); 117 if (ioctl(s, SIOC_HCI_RAW_NODE_GET_BUFFER, &r, sizeof(r)) < 0) 118 return (ERROR); 119 120 fprintf(stdout, "Node: %s\n", 121 r.hci_node); 122 fprintf(stdout, "Number of free command buffers: %d\n", 123 r.buffer.cmd_free); 124 fprintf(stdout, "Max. ACL packet size: %d\n", 125 r.buffer.acl_size); 126 fprintf(stdout, "Numbef of free ACL buffers: %d\n", 127 r.buffer.acl_free); 128 fprintf(stdout, "Total number of ACL buffers: %d\n", 129 r.buffer.acl_pkts); 130 fprintf(stdout, "Max. SCO packet size: %d\n", 131 r.buffer.sco_size); 132 fprintf(stdout, "Numbef of free SCO buffers: %d\n", 133 r.buffer.sco_free); 134 fprintf(stdout, "Total number of SCO buffers: %d\n", 135 r.buffer.sco_pkts); 136 137 return (OK); 138 } /* hci_read_node_buffer_size */ 139 140 /* Send Read_Node_BD_ADDR command to the node */ 141 static int 142 hci_read_node_bd_addr(int s, int argc, char **argv) 143 { 144 struct ng_btsocket_hci_raw_node_bdaddr r; 145 146 memset(&r, 0, sizeof(r)); 147 if (ioctl(s, SIOC_HCI_RAW_NODE_GET_BDADDR, &r, sizeof(r)) < 0) 148 return (ERROR); 149 150 fprintf(stdout, "Node: %s\n", r.hci_node); 151 fprintf(stdout, "BD_ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n", 152 r.bdaddr.b[5], r.bdaddr.b[4], r.bdaddr.b[3], 153 r.bdaddr.b[2], r.bdaddr.b[1], r.bdaddr.b[0]); 154 155 return (OK); 156 } /* hci_read_node_bd_addr */ 157 158 /* Send Read_Node_Features command to the node */ 159 static int 160 hci_read_node_features(int s, int argc, char **argv) 161 { 162 struct ng_btsocket_hci_raw_node_features r; 163 int n; 164 char buffer[1024]; 165 166 memset(&r, 0, sizeof(r)); 167 if (ioctl(s, SIOC_HCI_RAW_NODE_GET_FEATURES, &r, sizeof(r)) < 0) 168 return (ERROR); 169 170 fprintf(stdout, "Node: %s\nFeatures: ", r.hci_node); 171 for (n = 0; n < sizeof(r.features)/sizeof(r.features[0]); n++) 172 fprintf(stdout, "%#02x ", r.features[n]); 173 fprintf(stdout, "\n%s\n", hci_features2str(r.features, 174 buffer, sizeof(buffer))); 175 176 return (OK); 177 } /* hci_read_node_features */ 178 179 /* Send Read_Node_Stat command to the node */ 180 static int 181 hci_read_node_stat(int s, int argc, char **argv) 182 { 183 struct ng_btsocket_hci_raw_node_stat r; 184 185 memset(&r, 0, sizeof(r)); 186 if (ioctl(s, SIOC_HCI_RAW_NODE_GET_STAT, &r, sizeof(r)) < 0) 187 return (ERROR); 188 189 fprintf(stdout, "Node: %s\n", r.hci_node); 190 fprintf(stdout, "Commands sent: %d\n", r.stat.cmd_sent); 191 fprintf(stdout, "Events received: %d\n", r.stat.evnt_recv); 192 fprintf(stdout, "ACL packets received: %d\n", r.stat.acl_recv); 193 fprintf(stdout, "ACL packets sent: %d\n", r.stat.acl_sent); 194 fprintf(stdout, "SCO packets received: %d\n", r.stat.sco_recv); 195 fprintf(stdout, "SCO packets sent: %d\n", r.stat.sco_sent); 196 fprintf(stdout, "Bytes received: %d\n", r.stat.bytes_recv); 197 fprintf(stdout, "Bytes sent: %d\n", r.stat.bytes_sent); 198 199 return (OK); 200 } /* hci_read_node_stat */ 201 202 /* Send Reset_Node_Stat command to the node */ 203 static int 204 hci_reset_node_stat(int s, int argc, char **argv) 205 { 206 struct ng_btsocket_hci_raw_node_reset_stat r; 207 208 memset(&r, 0, sizeof(r)); 209 if (ioctl(s, SIOC_HCI_RAW_NODE_RESET_STAT, &r, sizeof(r)) < 0) 210 return (ERROR); 211 212 return (OK); 213 } /* hci_reset_node_stat */ 214 215 /* Send Flush_Neighbor_Cache command to the node */ 216 static int 217 hci_flush_neighbor_cache(int s, int argc, char **argv) 218 { 219 struct ng_btsocket_hci_raw_node_flush_neighbor_cache r; 220 221 memset(&r, 0, sizeof(r)); 222 if (ioctl(s, SIOC_HCI_RAW_NODE_FLUSH_NEIGHBOR_CACHE, 223 &r, sizeof(r)) < 0) 224 return (ERROR); 225 226 return (OK); 227 } /* hci_flush_neighbor_cache */ 228 229 /* Send Read_Neighbor_Cache command to the node */ 230 static int 231 hci_read_neighbor_cache(int s, int argc, char **argv) 232 { 233 struct ng_btsocket_hci_raw_node_neighbor_cache r; 234 int n, error = OK; 235 236 memset(&r, 0, sizeof(r)); 237 r.num_entries = NG_HCI_MAX_NEIGHBOR_NUM; 238 r.entries = calloc(NG_HCI_MAX_NEIGHBOR_NUM, 239 sizeof(ng_hci_node_neighbor_cache_entry_ep)); 240 if (r.entries == NULL) { 241 errno = ENOMEM; 242 return (ERROR); 243 } 244 245 if (ioctl(s, SIOC_HCI_RAW_NODE_GET_NEIGHBOR_CACHE, &r, 246 sizeof(r)) < 0) { 247 error = ERROR; 248 goto out; 249 } 250 251 fprintf(stdout, "Neighbor cache for the node: %s\n", r.hci_node); 252 fprintf(stdout, 253 "BD_ADDR " \ 254 "Features " \ 255 "Clock offset " \ 256 "Page scan " \ 257 "Rep. scan\n"); 258 259 for (n = 0; n < r.num_entries; n++) { 260 fprintf(stdout, 261 "%02x:%02x:%02x:%02x:%02x:%02x " \ 262 "%02x %02x %02x %02x %02x %02x %02x %02x " \ 263 "%#12x " \ 264 "%#9x " \ 265 "%#9x\n", 266 r.entries[n].bdaddr.b[5], r.entries[n].bdaddr.b[4], 267 r.entries[n].bdaddr.b[3], r.entries[n].bdaddr.b[2], 268 r.entries[n].bdaddr.b[1], r.entries[n].bdaddr.b[0], 269 r.entries[n].features[0], r.entries[n].features[1], 270 r.entries[n].features[2], r.entries[n].features[3], 271 r.entries[n].features[4], r.entries[n].features[5], 272 r.entries[n].features[6], r.entries[n].features[7], 273 r.entries[n].clock_offset, r.entries[n].page_scan_mode, 274 r.entries[n].page_scan_rep_mode); 275 } 276 out: 277 free(r.entries); 278 279 return (error); 280 } /* hci_read_neightbor_cache */ 281 282 /* Send Read_Connection_List command to the node */ 283 static int 284 hci_read_connection_list(int s, int argc, char **argv) 285 { 286 struct ng_btsocket_hci_raw_con_list r; 287 int n, error = OK; 288 289 memset(&r, 0, sizeof(r)); 290 r.num_connections = NG_HCI_MAX_CON_NUM; 291 r.connections = calloc(NG_HCI_MAX_CON_NUM, sizeof(ng_hci_node_con_ep)); 292 if (r.connections == NULL) { 293 errno = ENOMEM; 294 return (ERROR); 295 } 296 297 if (ioctl(s, SIOC_HCI_RAW_NODE_GET_CON_LIST, &r, sizeof(r)) < 0) { 298 error = ERROR; 299 goto out; 300 } 301 302 fprintf(stdout, "Connections list for the node: %s\n", r.hci_node); 303 fprintf(stdout, 304 "Remote BD_ADDR " \ 305 "Handle " \ 306 "Type " \ 307 "Mode " \ 308 "Role " \ 309 "Encrypt " \ 310 "Pending " \ 311 "Queue " \ 312 "State\n"); 313 314 for (n = 0; n < r.num_connections; n++) { 315 fprintf(stdout, 316 "%02x:%02x:%02x:%02x:%02x:%02x " \ 317 "%6d " \ 318 "%4.4s " \ 319 "%4d " \ 320 "%4.4s " \ 321 "%7.7s " \ 322 "%7d " \ 323 "%5d " \ 324 "%s\n", 325 r.connections[n].bdaddr.b[5], 326 r.connections[n].bdaddr.b[4], 327 r.connections[n].bdaddr.b[3], 328 r.connections[n].bdaddr.b[2], 329 r.connections[n].bdaddr.b[1], 330 r.connections[n].bdaddr.b[0], 331 r.connections[n].con_handle, 332 (r.connections[n].link_type == NG_HCI_LINK_ACL)? 333 "ACL" : "SCO", 334 r.connections[n].mode, 335 (r.connections[n].role == NG_HCI_ROLE_MASTER)? 336 "MAST" : "SLAV", 337 hci_encrypt2str(r.connections[n].encryption_mode, 1), 338 r.connections[n].pending, 339 r.connections[n].queue_len, 340 hci_con_state2str(r.connections[n].state)); 341 } 342 out: 343 free(r.connections); 344 345 return (error); 346 } /* hci_read_connection_list */ 347 348 /* Send Read_Link_Policy_Settings_Mask command to the node */ 349 int 350 hci_read_link_policy_settings_mask(int s, int argc, char **argv) 351 { 352 struct ng_btsocket_hci_raw_node_link_policy_mask r; 353 354 memset(&r, 0, sizeof(r)); 355 if (ioctl(s, SIOC_HCI_RAW_NODE_GET_LINK_POLICY_MASK, &r, sizeof(r)) < 0) 356 return (ERROR); 357 358 fprintf(stdout, "Node: %s\nLink Policy Settings mask: %#04x\n", 359 r.hci_node, r.policy_mask); 360 361 return (OK); 362 } /* hci_read_link_policy_settings_mask */ 363 364 /* Send Write_Link_Policy_Settings_Mask command to the node */ 365 int 366 hci_write_link_policy_settings_mask(int s, int argc, char **argv) 367 { 368 struct ng_btsocket_hci_raw_node_link_policy_mask r; 369 int m; 370 371 memset(&r, 0, sizeof(r)); 372 373 switch (argc) { 374 case 1: 375 if (sscanf(argv[0], "%x", &m) != 1) 376 return (USAGE); 377 378 r.policy_mask = (m & 0xffff); 379 break; 380 381 default: 382 return (USAGE); 383 } 384 385 if (ioctl(s, SIOC_HCI_RAW_NODE_SET_LINK_POLICY_MASK, &r, sizeof(r)) < 0) 386 return (ERROR); 387 388 return (OK); 389 } /* hci_write_link_policy_settings_mask */ 390 391 /* Send Read_Packet_Mask command to the node */ 392 int 393 hci_read_packet_mask(int s, int argc, char **argv) 394 { 395 struct ng_btsocket_hci_raw_node_packet_mask r; 396 397 memset(&r, 0, sizeof(r)); 398 if (ioctl(s, SIOC_HCI_RAW_NODE_GET_PACKET_MASK, &r, sizeof(r)) < 0) 399 return (ERROR); 400 401 fprintf(stdout, "Node: %s\nPacket mask: %#04x\n", 402 r.hci_node, r.packet_mask); 403 404 return (OK); 405 } /* hci_read_packet_mask */ 406 407 /* Send Write_Packet_Mask command to the node */ 408 int 409 hci_write_packet_mask(int s, int argc, char **argv) 410 { 411 struct ng_btsocket_hci_raw_node_packet_mask r; 412 int m; 413 414 memset(&r, 0, sizeof(r)); 415 416 switch (argc) { 417 case 1: 418 if (sscanf(argv[0], "%x", &m) != 1) 419 return (USAGE); 420 421 r.packet_mask = (m & 0xffff); 422 break; 423 424 default: 425 return (USAGE); 426 } 427 428 if (ioctl(s, SIOC_HCI_RAW_NODE_SET_PACKET_MASK, &r, sizeof(r)) < 0) 429 return (ERROR); 430 431 return (OK); 432 } /* hci_write_packet_mask */ 433 434 struct hci_command node_commands[] = { 435 { 436 "read_node_state", 437 "Get HCI node state", 438 &hci_read_node_state 439 }, 440 { 441 "initialize", 442 "Initialize HCI node", 443 &hci_node_initialize 444 }, 445 { 446 "read_debug_level", 447 "Read HCI node debug level", 448 &hci_read_debug_level 449 }, 450 { 451 "write_debug_level <level>", 452 "Write HCI node debug level", 453 &hci_write_debug_level 454 }, 455 { 456 "read_node_buffer_size", 457 "Read HCI node buffer information", 458 &hci_read_node_buffer_size 459 }, 460 { 461 "read_node_bd_addr", 462 "Read HCI node BD_ADDR", 463 &hci_read_node_bd_addr 464 }, 465 { 466 "read_node_features", 467 "Read HCI node features", 468 &hci_read_node_features 469 }, 470 { 471 "read_node_stat", 472 "Read HCI node statistic information", 473 &hci_read_node_stat 474 }, 475 { 476 "reset_node_stat", 477 "Reset HCI node statistic information", 478 &hci_reset_node_stat 479 }, 480 { 481 "flush_neighbor_cache", 482 "Flush HCI node neighbor cache", 483 &hci_flush_neighbor_cache 484 }, 485 { 486 "read_neighbor_cache", 487 "Read HCI node neighbor cache", 488 &hci_read_neighbor_cache 489 }, 490 { 491 "read_connection_list", 492 "Read connection list", 493 &hci_read_connection_list 494 }, 495 { 496 "read_node_link_policy_settings_mask", 497 "Read Link Policy Settinngs mask for the node", 498 &hci_read_link_policy_settings_mask 499 }, 500 { 501 "write_node_link_policy_settings_mask <policy_mask>", 502 "Write Link Policy Settinngs mask for the node. Policy mask - xxxx", 503 &hci_write_link_policy_settings_mask 504 }, 505 { 506 "read_node_packet_mask", 507 "Read Packet mask for the node", 508 &hci_read_packet_mask 509 }, 510 { 511 "write_node_packet_mask <packet_mask>", 512 "Write Packet mask for the node. Packet mask - xxxx", 513 &hci_write_packet_mask 514 }, 515 { 516 NULL, 517 }}; 518 519