1 /*-
2  * status.c
3  *
4  * SPDX-License-Identifier: BSD-2-Clause
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: status.c,v 1.2 2003/05/21 22:40:30 max Exp $
31  */
32 
33 #include <sys/types.h>
34 #include <sys/endian.h>
35 #include <errno.h>
36 #include <netgraph/bluetooth/include/ng_hci.h>
37 #include <stdio.h>
38 #include "hccontrol.h"
39 
40 /* Send Read_Failed_Contact_Counter command to the unit */
41 static int
42 hci_read_failed_contact_counter(int s, int argc, char **argv)
43 {
44 	ng_hci_read_failed_contact_cntr_cp	cp;
45 	ng_hci_read_failed_contact_cntr_rp	rp;
46 	int					n;
47 
48 	switch (argc) {
49 	case 1:
50 		/* connection handle */
51 		if (sscanf(argv[0], "%d", &n) != 1 || n <= 0 || n > 0x0eff)
52 			return (USAGE);
53 
54 		cp.con_handle = (uint16_t) (n & 0x0fff);
55 		cp.con_handle = htole16(cp.con_handle);
56 		break;
57 
58 	default:
59 		return (USAGE);
60 	}
61 
62 	/* send command */
63 	n = sizeof(rp);
64 	if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_STATUS,
65 			NG_HCI_OCF_READ_FAILED_CONTACT_CNTR),
66 			(char const *) &cp, sizeof(cp),
67 			(char *) &rp, &n) == ERROR)
68 		return (ERROR);
69 
70 	if (rp.status != 0x00) {
71 		fprintf(stdout, "Status: %s [%#02x]\n",
72 			hci_status2str(rp.status), rp.status);
73 		return (FAILED);
74 	}
75 
76 	fprintf(stdout, "Connection handle: %d\n", le16toh(rp.con_handle));
77 	fprintf(stdout, "Failed contact counter: %d\n", le16toh(rp.counter));
78 
79 	return (OK);
80 } /* hci_read_failed_contact_counter */
81 
82 /* Send Reset_Failed_Contact_Counter command to the unit */
83 static int
84 hci_reset_failed_contact_counter(int s, int argc, char **argv)
85 {
86 	ng_hci_reset_failed_contact_cntr_cp	cp;
87 	ng_hci_reset_failed_contact_cntr_rp	rp;
88 	int					n;
89 
90 	switch (argc) {
91 	case 1:
92 		/* connection handle */
93 		if (sscanf(argv[0], "%d", &n) != 1 || n <= 0 || n > 0x0eff)
94 			return (USAGE);
95 
96 		cp.con_handle = (uint16_t) (n & 0x0fff);
97 		cp.con_handle = htole16(cp.con_handle);
98 		break;
99 
100 	default:
101 		return (USAGE);
102 	}
103 
104 	/* send command */
105 	n = sizeof(rp);
106 	if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_STATUS,
107 			NG_HCI_OCF_RESET_FAILED_CONTACT_CNTR),
108 			(char const *) &cp, sizeof(cp),
109 			(char *) &rp, &n) == ERROR)
110 		return (ERROR);
111 
112 	if (rp.status != 0x00) {
113 		fprintf(stdout, "Status: %s [%#02x]\n",
114 			hci_status2str(rp.status), rp.status);
115 		return (FAILED);
116 	}
117 
118 	return (OK);
119 } /* hci_reset_failed_contact_counter */
120 
121 /* Sent Get_Link_Quality command to the unit */
122 static int
123 hci_get_link_quality(int s, int argc, char **argv)
124 {
125 	ng_hci_get_link_quality_cp	cp;
126 	ng_hci_get_link_quality_rp	rp;
127 	int				n;
128 
129 	switch (argc) {
130 	case 1:
131 		/* connection handle */
132 		if (sscanf(argv[0], "%d", &n) != 1 || n <= 0 || n > 0x0eff)
133 			return (USAGE);
134 
135 		cp.con_handle = (uint16_t) (n & 0x0fff);
136 		cp.con_handle = htole16(cp.con_handle);
137 		break;
138 
139 	default:
140 		return (USAGE);
141 	}
142 
143 	/* send command */
144 	n = sizeof(rp);
145 	if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_STATUS,
146 			NG_HCI_OCF_GET_LINK_QUALITY),
147 			(char const *) &cp, sizeof(cp),
148 			(char *) &rp, &n) == ERROR)
149 		return (ERROR);
150 
151 	if (rp.status != 0x00) {
152 		fprintf(stdout, "Status: %s [%#02x]\n",
153 			hci_status2str(rp.status), rp.status);
154 		return (FAILED);
155 	}
156 
157 	fprintf(stdout, "Connection handle: %d\n", le16toh(rp.con_handle));
158 	fprintf(stdout, "Link quality: %d\n", le16toh(rp.quality));
159 
160 	return (OK);
161 } /* hci_get_link_quality */
162 
163 /* Send Read_RSSI command to the unit */
164 static int
165 hci_read_rssi(int s, int argc, char **argv)
166 {
167 	ng_hci_read_rssi_cp	cp;
168 	ng_hci_read_rssi_rp	rp;
169 	int			n;
170 
171 	switch (argc) {
172 	case 1:
173 		/* connection handle */
174 		if (sscanf(argv[0], "%d", &n) != 1 || n <= 0 || n > 0x0eff)
175 			return (USAGE);
176 
177 		cp.con_handle = (uint16_t) (n & 0x0fff);
178 		cp.con_handle = htole16(cp.con_handle);
179 		break;
180 
181 	default:
182 		return (USAGE);
183 	}
184 
185 	/* send command */
186 	n = sizeof(rp);
187 	if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_STATUS,
188 			NG_HCI_OCF_READ_RSSI),
189 			(char const *) &cp, sizeof(cp),
190 			(char *) &rp, &n) == ERROR)
191 		return (ERROR);
192 
193 	if (rp.status != 0x00) {
194 		fprintf(stdout, "Status: %s [%#02x]\n",
195 			hci_status2str(rp.status), rp.status);
196 		return (FAILED);
197 	}
198 
199 	fprintf(stdout, "Connection handle: %d\n", le16toh(rp.con_handle));
200 	fprintf(stdout, "RSSI: %d dB\n", (int) rp.rssi);
201 
202 	return (OK);
203 } /* hci_read_rssi */
204 
205 struct hci_command	status_commands[] = {
206 {
207 "read_failed_contact_counter <connection_handle>",
208 "\nThis command will read the value for the Failed_Contact_Counter\n" \
209 "parameter for a particular ACL connection to another device.\n\n" \
210 "\t<connection_handle> - dddd; ACL connection handle\n",
211 &hci_read_failed_contact_counter
212 },
213 {
214 "reset_failed_contact_counter <connection_handle>",
215 "\nThis command will reset the value for the Failed_Contact_Counter\n" \
216 "parameter for a particular ACL connection to another device.\n\n" \
217 "\t<connection_handle> - dddd; ACL connection handle\n",
218 &hci_reset_failed_contact_counter
219 },
220 {
221 "get_link_quality <connection_handle>",
222 "\nThis command will return the value for the Link_Quality for the\n" \
223 "specified ACL connection handle. This command will return a Link_Quality\n" \
224 "value from 0-255, which represents the quality of the link between two\n" \
225 "Bluetooth devices. The higher the value, the better the link quality is.\n" \
226 "Each Bluetooth module vendor will determine how to measure the link quality." \
227 "\n\n" \
228 "\t<connection_handle> - dddd; ACL connection handle\n",
229 &hci_get_link_quality
230 },
231 {
232 "read_rssi <connection_handle>",
233 "\nThis command will read the value for the difference between the\n" \
234 "measured Received Signal Strength Indication (RSSI) and the limits of\n" \
235 "the Golden Receive Power Range for a ACL connection handle to another\n" \
236 "Bluetooth device. Any positive RSSI value returned by the Host Controller\n" \
237 "indicates how many dB the RSSI is above the upper limit, any negative\n" \
238 "value indicates how many dB the RSSI is below the lower limit. The value\n" \
239 "zero indicates that the RSSI is inside the Golden Receive Power Range.\n\n" \
240 "\t<connection_handle> - dddd; ACL connection handle\n",
241 &hci_read_rssi
242 },
243 {
244 NULL,
245 }};
246 
247