]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - usr.sbin/bluetooth/hccontrol/node.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / usr.sbin / bluetooth / hccontrol / node.c
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