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