1107120Sjulian/*
2107120Sjulian * link_control.c
3107120Sjulian *
4107120Sjulian * Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com>
5107120Sjulian * All rights reserved.
6107120Sjulian *
7107120Sjulian * Redistribution and use in source and binary forms, with or without
8107120Sjulian * modification, are permitted provided that the following conditions
9107120Sjulian * are met:
10107120Sjulian * 1. Redistributions of source code must retain the above copyright
11107120Sjulian *    notice, this list of conditions and the following disclaimer.
12107120Sjulian * 2. Redistributions in binary form must reproduce the above copyright
13107120Sjulian *    notice, this list of conditions and the following disclaimer in the
14107120Sjulian *    documentation and/or other materials provided with the distribution.
15107120Sjulian *
16107120Sjulian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17107120Sjulian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18107120Sjulian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19107120Sjulian * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20107120Sjulian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21107120Sjulian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22107120Sjulian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23107120Sjulian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24107120Sjulian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25107120Sjulian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26107120Sjulian * SUCH DAMAGE.
27107120Sjulian *
28121054Semax * $Id: link_control.c,v 1.4 2003/08/18 19:19:54 max Exp $
29107120Sjulian * $FreeBSD$
30107120Sjulian */
31107120Sjulian
32121054Semax#include <bluetooth.h>
33107120Sjulian#include <errno.h>
34107120Sjulian#include <stdio.h>
35107120Sjulian#include <string.h>
36107120Sjulian#include "hccontrol.h"
37107120Sjulian
38128079Semaxstatic void hci_inquiry_response (int n, uint8_t **b);
39107120Sjulian
40107120Sjulian/* Send Inquiry command to the unit */
41107120Sjulianstatic int
42107120Sjulianhci_inquiry(int s, int argc, char **argv)
43107120Sjulian{
44107120Sjulian	int			 n0, n1, n2, timo;
45162529Semax	char			 b[512];
46107120Sjulian	ng_hci_inquiry_cp	 cp;
47107120Sjulian	ng_hci_event_pkt_t	*e = (ng_hci_event_pkt_t *) b;
48107120Sjulian
49107120Sjulian	/* set defaults */
50107120Sjulian	cp.lap[2] = 0x9e;
51107120Sjulian	cp.lap[1] = 0x8b;
52107120Sjulian	cp.lap[0] = 0x33;
53107120Sjulian	cp.inquiry_length = 5;
54107120Sjulian	cp.num_responses = 8;
55107120Sjulian
56107120Sjulian	/* parse command parameters */
57107120Sjulian	switch (argc) {
58107120Sjulian	case 3:
59131216Semax		/* number of responses, range 0x00 - 0xff */
60131216Semax		if (sscanf(argv[2], "%d", &n0) != 1 || n0 < 0 || n0 > 0xff)
61107120Sjulian			return (USAGE);
62107120Sjulian
63131216Semax		cp.num_responses = (n0 & 0xff);
64107120Sjulian
65107120Sjulian	case 2:
66131216Semax		/* inquiry length (N * 1.28) sec, range 0x01 - 0x30 */
67107120Sjulian		if (sscanf(argv[1], "%d", &n0) != 1 || n0 < 0x1 || n0 > 0x30)
68107120Sjulian			return (USAGE);
69107120Sjulian
70107120Sjulian		cp.inquiry_length = (n0 & 0xff);
71107120Sjulian
72107120Sjulian	case 1:
73131216Semax		/* LAP */
74131216Semax		if (sscanf(argv[0], "%x:%x:%x", &n2, &n1, &n0) != 3)
75107120Sjulian			return (USAGE);
76107120Sjulian
77131216Semax		cp.lap[0] = (n0 & 0xff);
78131216Semax		cp.lap[1] = (n1 & 0xff);
79131216Semax		cp.lap[2] = (n2 & 0xff);
80107120Sjulian
81107120Sjulian	case 0:
82131216Semax		/* use defaults */
83107120Sjulian		break;
84107120Sjulian
85107120Sjulian	default:
86107120Sjulian		return (USAGE);
87107120Sjulian	}
88107120Sjulian
89107120Sjulian	/* send request and expect status back */
90107120Sjulian	n0 = sizeof(b);
91107120Sjulian	if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL,
92107120Sjulian			NG_HCI_OCF_INQUIRY), (char const *) &cp, sizeof(cp),
93107120Sjulian			b, &n0) == ERROR)
94107120Sjulian		return (ERROR);
95107120Sjulian
96107120Sjulian	if (*b != 0x00)
97107120Sjulian		return (FAILED);
98107120Sjulian
99107120Sjulian	timo = timeout;
100107120Sjulian	timeout = cp.inquiry_length * 1.28 + 1;
101107120Sjulian
102107120Sjulianwait_for_more:
103107120Sjulian	/* wait for inquiry events */
104107120Sjulian	n0 = sizeof(b);
105107120Sjulian	if (hci_recv(s, b, &n0) == ERROR) {
106107120Sjulian		timeout = timo;
107107120Sjulian		return (ERROR);
108107120Sjulian	}
109107120Sjulian
110107120Sjulian	if (n0 < sizeof(*e)) {
111107120Sjulian		timeout = timo;
112107120Sjulian		errno = EIO;
113107120Sjulian		return (ERROR);
114107120Sjulian	}
115107120Sjulian
116107120Sjulian	switch (e->event) {
117107120Sjulian	case NG_HCI_EVENT_INQUIRY_RESULT: {
118107120Sjulian		ng_hci_inquiry_result_ep	*ir =
119107120Sjulian				(ng_hci_inquiry_result_ep *)(e + 1);
120128079Semax		uint8_t				*r = (uint8_t *)(ir + 1);
121107120Sjulian
122107120Sjulian		fprintf(stdout, "Inquiry result, num_responses=%d\n",
123107120Sjulian			ir->num_responses);
124107120Sjulian
125107120Sjulian		for (n0 = 0; n0 < ir->num_responses; n0++)
126107120Sjulian			hci_inquiry_response(n0, &r);
127107120Sjulian
128107120Sjulian		goto wait_for_more;
129107120Sjulian		}
130107120Sjulian
131107120Sjulian	case NG_HCI_EVENT_INQUIRY_COMPL:
132107120Sjulian		fprintf(stdout, "Inquiry complete. Status: %s [%#02x]\n",
133107120Sjulian			hci_status2str(*(b + sizeof(*e))), *(b + sizeof(*e)));
134107120Sjulian		break;
135107120Sjulian
136107120Sjulian	default:
137107120Sjulian		goto wait_for_more;
138107120Sjulian	}
139107120Sjulian
140107120Sjulian	timeout = timo;
141107120Sjulian
142107120Sjulian	return (OK);
143107120Sjulian} /* hci_inquiry */
144107120Sjulian
145107120Sjulian/* Print Inquiry_Result event */
146107120Sjulianstatic void
147128079Semaxhci_inquiry_response(int n, uint8_t **b)
148107120Sjulian{
149133415Semax	ng_hci_inquiry_response	*ir = (ng_hci_inquiry_response *)(*b);
150107120Sjulian
151107120Sjulian	fprintf(stdout, "Inquiry result #%d\n", n);
152121054Semax	fprintf(stdout, "\tBD_ADDR: %s\n", hci_bdaddr2str(&ir->bdaddr));
153107120Sjulian	fprintf(stdout, "\tPage Scan Rep. Mode: %#02x\n",
154107120Sjulian		ir->page_scan_rep_mode);
155107120Sjulian	fprintf(stdout, "\tPage Scan Period Mode: %#02x\n",
156107120Sjulian		ir->page_scan_period_mode);
157107120Sjulian	fprintf(stdout, "\tPage Scan Mode: %#02x\n",
158107120Sjulian		ir->page_scan_mode);
159107120Sjulian	fprintf(stdout, "\tClass: %02x:%02x:%02x\n",
160139686Semax		ir->uclass[2], ir->uclass[1], ir->uclass[0]);
161107120Sjulian	fprintf(stdout, "\tClock offset: %#04x\n",
162107120Sjulian		le16toh(ir->clock_offset));
163107120Sjulian
164107120Sjulian	*b += sizeof(*ir);
165107120Sjulian} /* hci_inquiry_response */
166107120Sjulian
167107120Sjulian/* Send Create_Connection command to the unit */
168107120Sjulianstatic int
169107120Sjulianhci_create_connection(int s, int argc, char **argv)
170107120Sjulian{
171121054Semax	int			 n0;
172107120Sjulian	char			 b[512];
173107120Sjulian	ng_hci_create_con_cp	 cp;
174107120Sjulian	ng_hci_event_pkt_t	*e = (ng_hci_event_pkt_t *) b;
175107120Sjulian
176107120Sjulian	/* Set defaults */
177107120Sjulian	memset(&cp, 0, sizeof(cp));
178107120Sjulian	cp.pkt_type = htole16(	NG_HCI_PKT_DM1 | NG_HCI_PKT_DH1 |
179107120Sjulian				NG_HCI_PKT_DM3 | NG_HCI_PKT_DH3 |
180107120Sjulian				NG_HCI_PKT_DM5);
181107120Sjulian	cp.page_scan_rep_mode = NG_HCI_SCAN_REP_MODE0;
182107120Sjulian	cp.page_scan_mode = NG_HCI_MANDATORY_PAGE_SCAN_MODE;
183107120Sjulian	cp.clock_offset = 0;
184107120Sjulian	cp.accept_role_switch = 1;
185107120Sjulian
186107120Sjulian	/* parse command parameters */
187107120Sjulian	switch (argc) {
188107120Sjulian	case 6:
189107120Sjulian		/* accept role switch */
190131216Semax		if (sscanf(argv[5], "%d", &n0) != 1)
191107120Sjulian			return (USAGE);
192107120Sjulian
193107120Sjulian		cp.accept_role_switch = n0 ? 1 : 0;
194107120Sjulian
195107120Sjulian	case 5:
196107120Sjulian		/* clock offset */
197131216Semax		if (sscanf(argv[4], "%d", &n0) != 1)
198107120Sjulian			return (USAGE);
199107120Sjulian
200107120Sjulian		cp.clock_offset = (n0 & 0xffff);
201107120Sjulian		cp.clock_offset = htole16(cp.clock_offset);
202107120Sjulian
203107120Sjulian	case 4:
204107120Sjulian		/* page scan mode */
205131216Semax		if (sscanf(argv[3], "%d", &n0) != 1 || n0 < 0 || n0 > 3)
206107120Sjulian			return (USAGE);
207107120Sjulian
208107120Sjulian		cp.page_scan_mode = (n0 & 0xff);
209107120Sjulian
210107120Sjulian	case 3:
211107120Sjulian		/* page scan rep mode */
212107120Sjulian		if (sscanf(argv[2], "%d", &n0) != 1 || n0 < 0 || n0 > 2)
213107120Sjulian			return (USAGE);
214107120Sjulian
215107120Sjulian		cp.page_scan_rep_mode = (n0 & 0xff);
216107120Sjulian
217107120Sjulian	case 2:
218107120Sjulian		/* packet type */
219107120Sjulian		if (sscanf(argv[1], "%x", &n0) != 1)
220107120Sjulian			return (USAGE);
221107120Sjulian
222107120Sjulian		n0 &= (	NG_HCI_PKT_DM1 | NG_HCI_PKT_DH1 |
223107120Sjulian			NG_HCI_PKT_DM3 | NG_HCI_PKT_DH3 |
224107120Sjulian			NG_HCI_PKT_DM5);
225107120Sjulian		if (n0 == 0)
226107120Sjulian			return (USAGE);
227107120Sjulian
228107120Sjulian		cp.pkt_type = (n0 & 0xffff);
229107120Sjulian		cp.pkt_type = htole16(cp.pkt_type);
230107120Sjulian
231107120Sjulian	case 1:
232107120Sjulian		/* BD_ADDR */
233121054Semax		if (!bt_aton(argv[0], &cp.bdaddr)) {
234121054Semax			struct hostent	*he = NULL;
235107120Sjulian
236121054Semax			if ((he = bt_gethostbyname(argv[0])) == NULL)
237121054Semax				return (USAGE);
238121054Semax
239121054Semax			memcpy(&cp.bdaddr, he->h_addr, sizeof(cp.bdaddr));
240121054Semax		}
241107120Sjulian		break;
242107120Sjulian
243107120Sjulian	default:
244107120Sjulian		return (USAGE);
245107120Sjulian	}
246107120Sjulian
247107120Sjulian	/* send request and expect status response */
248107120Sjulian	n0 = sizeof(b);
249107120Sjulian	if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL,
250107120Sjulian			NG_HCI_OCF_CREATE_CON),
251107120Sjulian			(char const *) &cp, sizeof(cp), b, &n0) == ERROR)
252107120Sjulian		return (ERROR);
253107120Sjulian
254107120Sjulian	if (*b != 0x00)
255107120Sjulian		return (FAILED);
256107120Sjulian
257107120Sjulian	/* wait for event */
258107120Sjulianagain:
259107120Sjulian	n0 = sizeof(b);
260107120Sjulian	if (hci_recv(s, b, &n0) == ERROR)
261107120Sjulian		return (ERROR);
262107120Sjulian	if (n0 < sizeof(*e)) {
263107120Sjulian		errno = EIO;
264107120Sjulian		return (ERROR);
265107120Sjulian	}
266107120Sjulian
267107120Sjulian	if (e->event == NG_HCI_EVENT_CON_COMPL) {
268107120Sjulian		ng_hci_con_compl_ep	*ep = (ng_hci_con_compl_ep *)(e + 1);
269107120Sjulian
270107120Sjulian		if (ep->status != 0x00) {
271107120Sjulian			fprintf(stdout, "Status: %s [%#02x]\n",
272107120Sjulian				hci_status2str(ep->status), ep->status);
273107120Sjulian			return (FAILED);
274107120Sjulian		}
275107120Sjulian
276121054Semax		fprintf(stdout, "BD_ADDR: %s\n", hci_bdaddr2str(&ep->bdaddr));
277107120Sjulian		fprintf(stdout, "Connection handle: %d\n",
278107120Sjulian			le16toh(ep->con_handle));
279107120Sjulian		fprintf(stdout, "Encryption mode: %s [%d]\n",
280107120Sjulian			hci_encrypt2str(ep->encryption_mode, 0),
281107120Sjulian			ep->encryption_mode);
282107120Sjulian	} else
283107120Sjulian		goto again;
284107120Sjulian
285107120Sjulian	return (OK);
286107120Sjulian} /* hci_create_connection */
287107120Sjulian
288107120Sjulian/* Send Disconnect command to the unit */
289107120Sjulianstatic int
290107120Sjulianhci_disconnect(int s, int argc, char **argv)
291107120Sjulian{
292107120Sjulian	int			 n;
293107120Sjulian	char			 b[512];
294107120Sjulian	ng_hci_discon_cp	 cp;
295107120Sjulian	ng_hci_event_pkt_t	*e = (ng_hci_event_pkt_t *) b;
296107120Sjulian
297107120Sjulian	/* Set defaults */
298107120Sjulian	memset(&cp, 0, sizeof(cp));
299107120Sjulian	cp.reason = 0x13;
300107120Sjulian
301107120Sjulian	/* parse command parameters */
302107120Sjulian	switch (argc) {
303107120Sjulian	case 2:
304107120Sjulian		/* reason */
305107120Sjulian		if (sscanf(argv[1], "%d", &n) != 1 || n <= 0x00 || n > 0xff)
306107120Sjulian			return (USAGE);
307107120Sjulian
308128079Semax		cp.reason = (uint8_t) (n & 0xff);
309107120Sjulian
310107120Sjulian	case 1:
311107120Sjulian		/* connection handle */
312107120Sjulian		if (sscanf(argv[0], "%d", &n) != 1 || n <= 0 || n > 0x0eff)
313107120Sjulian			return (USAGE);
314107120Sjulian
315128079Semax		cp.con_handle = (uint16_t) (n & 0x0fff);
316107120Sjulian		cp.con_handle = htole16(cp.con_handle);
317107120Sjulian		break;
318107120Sjulian
319107120Sjulian	default:
320107120Sjulian		return (USAGE);
321107120Sjulian	}
322107120Sjulian
323107120Sjulian	/* send request and expect status response */
324107120Sjulian	n = sizeof(b);
325107120Sjulian	if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL,
326107120Sjulian			NG_HCI_OCF_DISCON),
327107120Sjulian			(char const *) &cp, sizeof(cp), b, &n) == ERROR)
328107120Sjulian		return (ERROR);
329107120Sjulian
330107120Sjulian	if (*b != 0x00)
331107120Sjulian		return (FAILED);
332107120Sjulian
333107120Sjulian	/* wait for event */
334107120Sjulianagain:
335107120Sjulian	n = sizeof(b);
336107120Sjulian	if (hci_recv(s, b, &n) == ERROR)
337107120Sjulian		return (ERROR);
338107120Sjulian	if (n < sizeof(*e)) {
339107120Sjulian		errno = EIO;
340107120Sjulian		return (ERROR);
341107120Sjulian	}
342107120Sjulian
343107120Sjulian	if (e->event == NG_HCI_EVENT_DISCON_COMPL) {
344107120Sjulian		ng_hci_discon_compl_ep	*ep = (ng_hci_discon_compl_ep *)(e + 1);
345107120Sjulian
346107120Sjulian		if (ep->status != 0x00) {
347107120Sjulian			fprintf(stdout, "Status: %s [%#02x]\n",
348107120Sjulian				hci_status2str(ep->status), ep->status);
349107120Sjulian			return (FAILED);
350107120Sjulian		}
351107120Sjulian
352107120Sjulian		fprintf(stdout, "Connection handle: %d\n",
353107120Sjulian			le16toh(ep->con_handle));
354107120Sjulian		fprintf(stdout, "Reason: %s [%#02x]\n",
355107120Sjulian			hci_status2str(ep->reason), ep->reason);
356107120Sjulian	} else
357107120Sjulian		goto again;
358107120Sjulian
359107120Sjulian	return (OK);
360250460Seadler} /* hci_disconnect */
361107120Sjulian
362107120Sjulian/* Send Add_SCO_Connection command to the unit */
363107120Sjulianstatic int
364107120Sjulianhci_add_sco_connection(int s, int argc, char **argv)
365107120Sjulian{
366107120Sjulian	int			 n;
367107120Sjulian	char			 b[512];
368107120Sjulian	ng_hci_add_sco_con_cp	 cp;
369107120Sjulian	ng_hci_event_pkt_t	*e = (ng_hci_event_pkt_t *) b;
370107120Sjulian
371107120Sjulian	/* Set defaults */
372107120Sjulian	memset(&cp, 0, sizeof(cp));
373107120Sjulian	cp.pkt_type = htole16(NG_HCI_PKT_HV1 | NG_HCI_PKT_HV2 | NG_HCI_PKT_HV3);
374107120Sjulian
375107120Sjulian	/* parse command parameters */
376107120Sjulian	switch (argc) {
377107120Sjulian	case 2:
378107120Sjulian		/* packet type */
379131216Semax		if (sscanf(argv[1], "%x", &n) != 1)
380107120Sjulian			return (USAGE);
381107120Sjulian
382107120Sjulian		n &= (NG_HCI_PKT_HV1 | NG_HCI_PKT_HV2 | NG_HCI_PKT_HV3);
383107120Sjulian		if (n == 0)
384107120Sjulian			return (USAGE);
385107120Sjulian
386128079Semax		cp.pkt_type = (uint16_t) (n & 0x0fff);
387107120Sjulian		cp.pkt_type = htole16(cp.pkt_type);
388107120Sjulian
389107120Sjulian	case 1:
390107120Sjulian		/* acl connection handle */
391107120Sjulian		if (sscanf(argv[0], "%d", &n) != 1 || n <= 0 || n > 0x0eff)
392107120Sjulian			return (USAGE);
393107120Sjulian
394128079Semax		cp.con_handle = (uint16_t) (n & 0x0fff);
395107120Sjulian		cp.con_handle = htole16(cp.con_handle);
396107120Sjulian		break;
397107120Sjulian
398107120Sjulian	default:
399107120Sjulian		return (USAGE);
400107120Sjulian	}
401107120Sjulian
402107120Sjulian	/* send request and expect status response */
403107120Sjulian	n = sizeof(b);
404107120Sjulian	if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL,
405107120Sjulian			NG_HCI_OCF_ADD_SCO_CON),
406107120Sjulian			(char const *) &cp, sizeof(cp), b, &n) == ERROR)
407107120Sjulian		return (ERROR);
408107120Sjulian
409107120Sjulian	if (*b != 0x00)
410107120Sjulian		return (FAILED);
411107120Sjulian
412107120Sjulian	/* wait for event */
413107120Sjulianagain:
414107120Sjulian	n = sizeof(b);
415107120Sjulian	if (hci_recv(s, b, &n) == ERROR)
416107120Sjulian		return (ERROR);
417107120Sjulian	if (n < sizeof(*e)) {
418107120Sjulian		errno = EIO;
419107120Sjulian		return (ERROR);
420107120Sjulian	}
421107120Sjulian
422107120Sjulian	if (e->event == NG_HCI_EVENT_CON_COMPL) {
423107120Sjulian		ng_hci_con_compl_ep	*ep = (ng_hci_con_compl_ep *)(e + 1);
424107120Sjulian
425107120Sjulian		if (ep->status != 0x00) {
426107120Sjulian			fprintf(stdout, "Status: %s [%#02x]\n",
427107120Sjulian				hci_status2str(ep->status), ep->status);
428107120Sjulian			return (FAILED);
429107120Sjulian		}
430107120Sjulian
431121054Semax		fprintf(stdout, "BD_ADDR: %s\n", hci_bdaddr2str(&ep->bdaddr));
432107120Sjulian		fprintf(stdout, "Connection handle: %d\n",
433107120Sjulian			le16toh(ep->con_handle));
434107120Sjulian		fprintf(stdout, "Encryption mode: %s [%d]\n",
435107120Sjulian			hci_encrypt2str(ep->encryption_mode, 0),
436107120Sjulian			ep->encryption_mode);
437107120Sjulian	} else
438107120Sjulian		goto again;
439107120Sjulian
440107120Sjulian	return (OK);
441107120Sjulian} /* Add_SCO_Connection */
442107120Sjulian
443107120Sjulian/* Send Change_Connection_Packet_Type command to the unit */
444107120Sjulianstatic int
445107120Sjulianhci_change_connection_packet_type(int s, int argc, char **argv)
446107120Sjulian{
447107120Sjulian	int				 n;
448107120Sjulian	char				 b[512];
449107120Sjulian	ng_hci_change_con_pkt_type_cp	 cp;
450107120Sjulian	ng_hci_event_pkt_t		*e = (ng_hci_event_pkt_t *) b;
451107120Sjulian
452107120Sjulian	switch (argc) {
453107120Sjulian	case 2:
454107120Sjulian		/* connection handle */
455107120Sjulian		if (sscanf(argv[0], "%d", &n) != 1 || n <= 0 || n > 0x0eff)
456107120Sjulian			return (USAGE);
457107120Sjulian
458128079Semax		cp.con_handle = (uint16_t) (n & 0x0fff);
459107120Sjulian		cp.con_handle = htole16(cp.con_handle);
460107120Sjulian
461107120Sjulian		/* packet type */
462107120Sjulian		if (sscanf(argv[1], "%x", &n) != 1)
463107120Sjulian			return (USAGE);
464107120Sjulian
465128079Semax		cp.pkt_type = (uint16_t) (n & 0xffff);
466107120Sjulian		cp.pkt_type = htole16(cp.pkt_type);
467107120Sjulian		break;
468107120Sjulian
469107120Sjulian	default:
470107120Sjulian		return (USAGE);
471107120Sjulian	}
472107120Sjulian
473107120Sjulian	/* send request and expect status response */
474107120Sjulian	n = sizeof(b);
475107120Sjulian	if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL,
476107120Sjulian			NG_HCI_OCF_CHANGE_CON_PKT_TYPE),
477107120Sjulian			(char const *) &cp, sizeof(cp), b, &n) == ERROR)
478107120Sjulian		return (ERROR);
479107120Sjulian
480107120Sjulian	if (*b != 0x00)
481107120Sjulian		return (FAILED);
482107120Sjulian
483107120Sjulian	/* wait for event */
484107120Sjulianagain:
485107120Sjulian	n = sizeof(b);
486107120Sjulian	if (hci_recv(s, b, &n) == ERROR)
487107120Sjulian		return (ERROR);
488107120Sjulian	if (n < sizeof(*e)) {
489107120Sjulian		errno = EIO;
490107120Sjulian		return (ERROR);
491107120Sjulian	}
492107120Sjulian
493107120Sjulian	if (e->event == NG_HCI_EVENT_CON_PKT_TYPE_CHANGED) {
494107120Sjulian		ng_hci_con_pkt_type_changed_ep	*ep =
495107120Sjulian				(ng_hci_con_pkt_type_changed_ep *)(e + 1);
496107120Sjulian
497107120Sjulian		if (ep->status != 0x00) {
498107120Sjulian			fprintf(stdout, "Status: %s [%#02x]\n",
499107120Sjulian				hci_status2str(ep->status), ep->status);
500107120Sjulian			return (FAILED);
501107120Sjulian		}
502107120Sjulian
503107120Sjulian		fprintf(stdout, "Connection handle: %d\n",
504107120Sjulian			le16toh(ep->con_handle));
505107120Sjulian		fprintf(stdout, "Packet type: %#04x\n",
506107120Sjulian			le16toh(ep->pkt_type));
507107120Sjulian	} else
508107120Sjulian		goto again;
509107120Sjulian
510107120Sjulian	return (OK);
511107120Sjulian} /* hci_change_connection_packet_type */
512107120Sjulian
513107120Sjulian/* Send Remote_Name_Request command to the unit */
514107120Sjulianstatic int
515107120Sjulianhci_remote_name_request(int s, int argc, char **argv)
516107120Sjulian{
517121054Semax	int				 n0;
518107120Sjulian	char				 b[512];
519107120Sjulian	ng_hci_remote_name_req_cp	 cp;
520107120Sjulian	ng_hci_event_pkt_t		*e = (ng_hci_event_pkt_t *) b;
521107120Sjulian
522114879Sjulian	memset(&cp, 0, sizeof(cp));
523114879Sjulian	cp.page_scan_rep_mode = NG_HCI_SCAN_REP_MODE0;
524114879Sjulian	cp.page_scan_mode = NG_HCI_MANDATORY_PAGE_SCAN_MODE;
525114879Sjulian
526107120Sjulian	/* parse command parameters */
527107120Sjulian	switch (argc) {
528107120Sjulian	case 4:
529114879Sjulian		/* clock_offset */
530114879Sjulian		if (sscanf(argv[3], "%x", &n0) != 1)
531114879Sjulian			return (USAGE);
532114879Sjulian
533114879Sjulian		cp.clock_offset = (n0 & 0xffff);
534114879Sjulian		cp.clock_offset = htole16(cp.clock_offset);
535114879Sjulian
536114879Sjulian	case 3:
537114879Sjulian		/* page_scan_mode */
538114879Sjulian		if (sscanf(argv[2], "%d", &n0) != 1 || n0 < 0x00 || n0 > 0x03)
539114879Sjulian			return (USAGE);
540114879Sjulian
541114879Sjulian		cp.page_scan_mode = (n0 & 0xff);
542114879Sjulian
543114879Sjulian	case 2:
544114879Sjulian		/* page_scan_rep_mode */
545114879Sjulian		if (sscanf(argv[1], "%d", &n0) != 1 || n0 < 0x00 || n0 > 0x02)
546114879Sjulian			return (USAGE);
547114879Sjulian
548114879Sjulian		cp.page_scan_rep_mode = (n0 & 0xff);
549114879Sjulian
550114879Sjulian	case 1:
551107120Sjulian		/* BD_ADDR */
552121054Semax		if (!bt_aton(argv[0], &cp.bdaddr)) {
553121054Semax			struct hostent	*he = NULL;
554107120Sjulian
555121054Semax			if ((he = bt_gethostbyname(argv[0])) == NULL)
556121054Semax				return (USAGE);
557121054Semax
558121054Semax			memcpy(&cp.bdaddr, he->h_addr, sizeof(cp.bdaddr));
559121054Semax		}
560107120Sjulian		break;
561107120Sjulian
562107120Sjulian	default:
563107120Sjulian		return (USAGE);
564107120Sjulian	}
565107120Sjulian
566107120Sjulian	/* send request and expect status response */
567107120Sjulian	n0 = sizeof(b);
568107120Sjulian	if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL,
569107120Sjulian			NG_HCI_OCF_REMOTE_NAME_REQ),
570107120Sjulian			(char const *) &cp, sizeof(cp), b, &n0) == ERROR)
571107120Sjulian		return (ERROR);
572107120Sjulian
573107120Sjulian	if (*b != 0x00)
574107120Sjulian		return (FAILED);
575107120Sjulian
576107120Sjulian	/* wait for event */
577107120Sjulianagain:
578107120Sjulian	n0 = sizeof(b);
579107120Sjulian	if (hci_recv(s, b, &n0) == ERROR)
580107120Sjulian		return (ERROR);
581107120Sjulian	if (n0 < sizeof(*e)) {
582107120Sjulian		errno = EIO;
583107120Sjulian		return (ERROR);
584107120Sjulian	}
585107120Sjulian
586107120Sjulian	if (e->event == NG_HCI_EVENT_REMOTE_NAME_REQ_COMPL) {
587107120Sjulian		ng_hci_remote_name_req_compl_ep	*ep =
588107120Sjulian				(ng_hci_remote_name_req_compl_ep *)(e + 1);
589107120Sjulian
590107120Sjulian		if (ep->status != 0x00) {
591107120Sjulian			fprintf(stdout, "Status: %s [%#02x]\n",
592107120Sjulian				hci_status2str(ep->status), ep->status);
593107120Sjulian			return (FAILED);
594107120Sjulian		}
595107120Sjulian
596121054Semax		fprintf(stdout, "BD_ADDR: %s\n", hci_bdaddr2str(&ep->bdaddr));
597107120Sjulian		fprintf(stdout, "Name: %s\n", ep->name);
598107120Sjulian	} else
599107120Sjulian		goto again;
600107120Sjulian
601107120Sjulian	return (OK);
602107120Sjulian} /* hci_remote_name_request */
603107120Sjulian
604107120Sjulian/* Send Read_Remote_Supported_Features command to the unit */
605107120Sjulianstatic int
606107120Sjulianhci_read_remote_supported_features(int s, int argc, char **argv)
607107120Sjulian{
608107120Sjulian	int				 n;
609107120Sjulian	char				 b[512];
610107120Sjulian	ng_hci_read_remote_features_cp	 cp;
611107120Sjulian	ng_hci_event_pkt_t		*e = (ng_hci_event_pkt_t *) b;
612107120Sjulian	char				 buffer[1024];
613107120Sjulian
614107120Sjulian	/* parse command parameters */
615107120Sjulian	switch (argc) {
616107120Sjulian	case 1:
617107120Sjulian		/* connecton handle */
618107120Sjulian		if (sscanf(argv[0], "%d", &n) != 1 || n < 0 || n > 0x0eff)
619107120Sjulian			return (USAGE);
620107120Sjulian
621107120Sjulian		cp.con_handle = (n & 0x0fff);
622107120Sjulian		cp.con_handle = htole16(cp.con_handle);
623107120Sjulian		break;
624107120Sjulian
625107120Sjulian	default:
626107120Sjulian		return (USAGE);
627107120Sjulian	}
628107120Sjulian
629107120Sjulian	/* send request and expect status response */
630107120Sjulian	n = sizeof(b);
631107120Sjulian	if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL,
632107120Sjulian			NG_HCI_OCF_READ_REMOTE_FEATURES),
633107120Sjulian			(char const *) &cp, sizeof(cp), b, &n) == ERROR)
634107120Sjulian		return (ERROR);
635107120Sjulian
636107120Sjulian	if (*b != 0x00)
637107120Sjulian		return (FAILED);
638107120Sjulian
639107120Sjulian	/* wait for event */
640107120Sjulianagain:
641107120Sjulian	n = sizeof(b);
642107120Sjulian	if (hci_recv(s, b, &n) == ERROR)
643107120Sjulian		return (ERROR);
644107120Sjulian
645107120Sjulian	if (n < sizeof(*e)) {
646107120Sjulian		errno = EIO;
647107120Sjulian		return (ERROR);
648107120Sjulian	}
649107120Sjulian
650107120Sjulian	if (e->event == NG_HCI_EVENT_READ_REMOTE_FEATURES_COMPL) {
651107120Sjulian		ng_hci_read_remote_features_compl_ep	*ep =
652107120Sjulian				(ng_hci_read_remote_features_compl_ep *)(e + 1);
653107120Sjulian
654107120Sjulian		if (ep->status != 0x00) {
655107120Sjulian			fprintf(stdout, "Status: %s [%#02x]\n",
656107120Sjulian				hci_status2str(ep->status), ep->status);
657107120Sjulian			return (FAILED);
658107120Sjulian		}
659107120Sjulian
660107120Sjulian		fprintf(stdout, "Connection handle: %d\n",
661107120Sjulian			le16toh(ep->con_handle));
662107120Sjulian		fprintf(stdout, "Features: ");
663107120Sjulian		for (n = 0; n < sizeof(ep->features); n++)
664107120Sjulian			fprintf(stdout, "%#02x ", ep->features[n]);
665107120Sjulian		fprintf(stdout, "\n%s\n", hci_features2str(ep->features,
666107120Sjulian			buffer, sizeof(buffer)));
667107120Sjulian	} else
668107120Sjulian		goto again;
669107120Sjulian
670107120Sjulian	return (OK);
671107120Sjulian} /* hci_read_remote_supported_features */
672107120Sjulian
673107120Sjulian/* Send Read_Remote_Version_Information command to the unit */
674107120Sjulianstatic int
675107120Sjulianhci_read_remote_version_information(int s, int argc, char **argv)
676107120Sjulian{
677107120Sjulian	int				 n;
678107120Sjulian	char				 b[512];
679107120Sjulian	ng_hci_read_remote_ver_info_cp	 cp;
680107120Sjulian	ng_hci_event_pkt_t		*e = (ng_hci_event_pkt_t *) b;
681107120Sjulian
682107120Sjulian	/* parse command parameters */
683107120Sjulian	switch (argc) {
684107120Sjulian	case 1:
685107120Sjulian		/* connecton handle */
686107120Sjulian		if (sscanf(argv[0], "%d", &n) != 1 || n < 0 || n > 0x0eff)
687107120Sjulian			return (USAGE);
688107120Sjulian
689107120Sjulian		cp.con_handle = (n & 0x0fff);
690107120Sjulian		cp.con_handle = htole16(cp.con_handle);
691107120Sjulian		break;
692107120Sjulian
693107120Sjulian	default:
694107120Sjulian		return (USAGE);
695107120Sjulian	}
696107120Sjulian
697107120Sjulian	/* send request and expect status response */
698107120Sjulian	n = sizeof(b);
699107120Sjulian	if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL,
700107120Sjulian			NG_HCI_OCF_READ_REMOTE_VER_INFO),
701107120Sjulian			(char const *) &cp, sizeof(cp), b, &n) == ERROR)
702107120Sjulian		return (ERROR);
703107120Sjulian
704107120Sjulian	if (*b != 0x00)
705107120Sjulian		return (FAILED);
706107120Sjulian
707107120Sjulian	/* wait for event */
708107120Sjulianagain:
709107120Sjulian	n = sizeof(b);
710107120Sjulian	if (hci_recv(s, b, &n) == ERROR)
711107120Sjulian		return (ERROR);
712107120Sjulian
713107120Sjulian	if (n < sizeof(*e)) {
714107120Sjulian		errno = EIO;
715107120Sjulian		return (ERROR);
716107120Sjulian	}
717107120Sjulian
718107120Sjulian	if (e->event == NG_HCI_EVENT_READ_REMOTE_VER_INFO_COMPL) {
719107120Sjulian		ng_hci_read_remote_ver_info_compl_ep	*ep =
720107120Sjulian				(ng_hci_read_remote_ver_info_compl_ep *)(e + 1);
721107120Sjulian
722107120Sjulian		if (ep->status != 0x00) {
723107120Sjulian			fprintf(stdout, "Status: %s [%#02x]\n",
724107120Sjulian				hci_status2str(ep->status), ep->status);
725107120Sjulian			return (FAILED);
726107120Sjulian		}
727107120Sjulian
728107120Sjulian		ep->manufacturer = le16toh(ep->manufacturer);
729107120Sjulian
730107120Sjulian		fprintf(stdout, "Connection handle: %d\n",
731107120Sjulian			le16toh(ep->con_handle));
732155964Smarkus		fprintf(stdout, "LMP version: %s [%#02x]\n",
733155964Smarkus			hci_lmpver2str(ep->lmp_version), ep->lmp_version);
734107120Sjulian		fprintf(stdout, "LMP sub-version: %#04x\n",
735107120Sjulian			le16toh(ep->lmp_subversion));
736107120Sjulian		fprintf(stdout, "Manufacturer: %s [%#04x]\n",
737107120Sjulian			hci_manufacturer2str(ep->manufacturer),
738107120Sjulian			ep->manufacturer);
739107120Sjulian	} else
740107120Sjulian		goto again;
741107120Sjulian
742107120Sjulian	return (OK);
743107120Sjulian} /* hci_read_remote_version_information */
744107120Sjulian
745107120Sjulian/* Send Read_Clock_Offset command to the unit */
746107120Sjulianstatic int
747107120Sjulianhci_read_clock_offset(int s, int argc, char **argv)
748107120Sjulian{
749107120Sjulian	int				 n;
750107120Sjulian	char				 b[512];
751107120Sjulian	ng_hci_read_clock_offset_cp	 cp;
752107120Sjulian	ng_hci_event_pkt_t		*e = (ng_hci_event_pkt_t *) b;
753107120Sjulian
754107120Sjulian	/* parse command parameters */
755107120Sjulian	switch (argc) {
756107120Sjulian	case 1:
757107120Sjulian		/* connecton handle */
758107120Sjulian		if (sscanf(argv[0], "%d", &n) != 1 || n < 0 || n > 0x0eff)
759107120Sjulian			return (USAGE);
760107120Sjulian
761107120Sjulian		cp.con_handle = (n & 0x0fff);
762107120Sjulian		cp.con_handle = htole16(cp.con_handle);
763107120Sjulian		break;
764107120Sjulian
765107120Sjulian	default:
766107120Sjulian		return (USAGE);
767107120Sjulian	}
768107120Sjulian
769107120Sjulian	/* send request and expect status response */
770107120Sjulian	n = sizeof(b);
771107120Sjulian	if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL,
772107120Sjulian			NG_HCI_OCF_READ_CLOCK_OFFSET),
773107120Sjulian			(char const *) &cp, sizeof(cp), b, &n) == ERROR)
774107120Sjulian		return (ERROR);
775107120Sjulian
776107120Sjulian	if (*b != 0x00)
777107120Sjulian		return (FAILED);
778107120Sjulian
779107120Sjulian	/* wait for event */
780107120Sjulianagain:
781107120Sjulian	n = sizeof(b);
782107120Sjulian	if (hci_recv(s, b, &n) == ERROR)
783107120Sjulian		return (ERROR);
784107120Sjulian
785107120Sjulian	if (n < sizeof(*e)) {
786107120Sjulian		errno = EIO;
787107120Sjulian		return (ERROR);
788107120Sjulian	}
789107120Sjulian
790107120Sjulian	if (e->event == NG_HCI_EVENT_READ_CLOCK_OFFSET_COMPL) {
791107120Sjulian		ng_hci_read_clock_offset_compl_ep	*ep =
792107120Sjulian				(ng_hci_read_clock_offset_compl_ep *)(e + 1);
793107120Sjulian
794107120Sjulian		if (ep->status != 0x00) {
795107120Sjulian			fprintf(stdout, "Status: %s [%#02x]\n",
796107120Sjulian				hci_status2str(ep->status), ep->status);
797107120Sjulian			return (FAILED);
798107120Sjulian		}
799107120Sjulian
800107120Sjulian		fprintf(stdout, "Connection handle: %d\n",
801107120Sjulian			le16toh(ep->con_handle));
802107120Sjulian		fprintf(stdout, "Clock offset: %#04x\n",
803107120Sjulian			le16toh(ep->clock_offset));
804107120Sjulian	} else
805107120Sjulian		goto again;
806107120Sjulian
807107120Sjulian	return (OK);
808107120Sjulian} /* hci_read_clock_offset */
809107120Sjulian
810107120Sjulianstruct hci_command	link_control_commands[] = {
811107120Sjulian{
812107120Sjulian"inquiry <LAP> <inquiry_length> <num_reponses>",
813107120Sjulian"\nThis command will cause the Bluetooth unit to enter Inquiry Mode.\n" \
814107120Sjulian"Inquiry Mode is used to discover other nearby Bluetooth units. The LAP\n" \
815107120Sjulian"input parameter contains the LAP from which the inquiry access code shall\n" \
816107120Sjulian"be derived when the inquiry procedure is made. The Inquiry_Length parameter\n"\
817107120Sjulian"specifies the total duration of the Inquiry Mode and, when this time\n" \
818107120Sjulian"expires, Inquiry will be halted. The Num_Responses parameter specifies the\n" \
819107120Sjulian"number of responses that can be received before the Inquiry is halted.\n\n" \
820107120Sjulian"\t<LAP>            - xx:xx:xx; 9e:8b:33 (GIAC), 93:8b:00 (LDIAC)\n" \
821107120Sjulian"\t<inquiry_length> - dd; total length == dd * 1.28 sec\n" \
822107120Sjulian"\t<num_responses>  - dd",
823107120Sjulian&hci_inquiry
824107120Sjulian},
825107120Sjulian{
826107120Sjulian"create_connection <BD_ADDR> <pkt> <rep_mode> <ps_mode> <clck_off> <role_sw>",
827107120Sjulian"" \
828133178Semax"\t<BD_ADDR> - xx:xx:xx:xx:xx:xx BD_ADDR or name\n\n" \
829107120Sjulian"\t<pkt>     - xxxx; packet type\n" \
830107120Sjulian"" \
831107120Sjulian"\t\tACL packets\n" \
832107120Sjulian"\t\t-----------\n" \
833107120Sjulian"\t\t0x0008 DM1\n" \
834107120Sjulian"\t\t0x0010 DH1\n" \
835107120Sjulian"\t\t0x0400 DM3\n" \
836107120Sjulian"\t\t0x0800 DH3\n" \
837107120Sjulian"\t\t0x4000 DM5\n" \
838107120Sjulian"\t\t0x8000 DH5\n\n" \
839107120Sjulian"" \
840107120Sjulian"\trep_mode  - d; page scan repetition mode\n" \
841107120Sjulian"" \
842107120Sjulian"\t\tPage scan repetition modes\n" \
843107120Sjulian"\t\t--------------------------\n" \
844107120Sjulian"\t\t0 Page scan repetition mode 0\n" \
845107120Sjulian"\t\t1 Page scan repetition mode 1\n" \
846107120Sjulian"\t\t2 Page scan repetition mode 2\n" \
847107120Sjulian"\n" \
848107120Sjulian"\tps_mode   - d; Page scan mode\n" \
849107120Sjulian"" \
850107120Sjulian"\t\tPage scan modes\n" \
851107120Sjulian"\t\t---------------\n" \
852107120Sjulian"\t\t0 Mandatory page scan mode\n" \
853107120Sjulian"\t\t1 Optional page scan mode1\n" \
854107120Sjulian"\t\t2 Optional page scan mode2\n" \
855107120Sjulian"\t\t3 Optional page scan mode3\n" \
856107120Sjulian"\n" \
857107120Sjulian"\tclck_off  - dddd; clock offset. Use 0 if unknown\n\n" \
858107120Sjulian"\trole_sw   - d; allow (1) or deny role switch\n",
859107120Sjulian&hci_create_connection
860107120Sjulian},
861107120Sjulian{
862107120Sjulian"disconnect <connection_handle> <reason>",
863107120Sjulian"\nThe Disconnection command is used to terminate an existing connection.\n" \
864107120Sjulian"The connection handle command parameter indicates which connection is to\n" \
865107120Sjulian"be disconnected. The Reason command parameter indicates the reason for\n" \
866107120Sjulian"ending the connection.\n\n" \
867107120Sjulian"\t<connection_handle> - dddd; connection handle\n" \
868107120Sjulian"\t<reason>            - dd; reason; usually 19 (0x13) - user ended;\n" \
869107120Sjulian"\t                      also 0x05, 0x13-0x15, 0x1A, 0x29",
870107120Sjulian&hci_disconnect
871107120Sjulian},
872107120Sjulian{
873107120Sjulian"add_sco_connection <acl connection handle> <packet type>",
874107120Sjulian"This command will cause the link manager to create a SCO connection using\n" \
875107120Sjulian"the ACL connection specified by the connection handle command parameter.\n" \
876107120Sjulian"The Link Manager will determine how the new connection is established. This\n"\
877107120Sjulian"connection is determined by the current state of the device, its piconet,\n" \
878107120Sjulian"and the state of the device to be connected. The packet type command parameter\n" \
879107120Sjulian"specifies which packet types the Link Manager should use for the connection.\n"\
880107120Sjulian"The Link Manager must only use the packet type(s) specified by the packet\n" \
881107120Sjulian"type command parameter for sending HCI SCO data packets. Multiple packet\n" \
882107120Sjulian"types may be specified for the packet type command parameter by performing\n" \
883107120Sjulian"a bitwise OR operation of the different packet types. Note: An SCO connection\n" \
884107120Sjulian"can only be created when an ACL connection already exists and when it is\n" \
885107120Sjulian"not put in park mode.\n\n" \
886107120Sjulian"\t<connection_handle> - dddd; ACL connection handle\n" \
887107120Sjulian"\t<packet_type>       - xxxx; packet type\n" \
888107120Sjulian"" \
889107120Sjulian"\t\tSCO packets\n" \
890107120Sjulian"\t\t-----------\n" \
891107120Sjulian"\t\t0x0020 HV1\n" \
892107120Sjulian"\t\t0x0040 HV2\n" \
893107120Sjulian"\t\t0x0080 HV3\n",
894107120Sjulian&hci_add_sco_connection
895107120Sjulian},
896107120Sjulian{
897107120Sjulian"change_connection_packet_type <connection_hande> <packet_type>",
898107120Sjulian"The Change_Connection_Packet_Type command is used to change which packet\n" \
899107120Sjulian"types can be used for a connection that is currently established. This\n" \
900107120Sjulian"allows current connections to be dynamically modified to support different\n" \
901107120Sjulian"types of user data. The Packet_Type command parameter specifies which\n" \
902107120Sjulian"packet types the Link Manager can use for the connection. Multiple packet\n" \
903107120Sjulian"types may be specified for the Packet_Type command parameter by bitwise OR\n" \
904107120Sjulian"operation of the different packet types.\n\n" \
905107120Sjulian"\t<connection_handle> - dddd; connection handle\n" \
906107120Sjulian"\t<packet_type>       - xxxx; packet type mask\n" \
907107120Sjulian"" \
908107120Sjulian"\t\tACL packets\n" \
909107120Sjulian"\t\t-----------\n" \
910107120Sjulian"\t\t0x0008 DM1\n" \
911107120Sjulian"\t\t0x0010 DH1\n" \
912107120Sjulian"\t\t0x0400 DM3\n" \
913107120Sjulian"\t\t0x0800 DH3\n" \
914107120Sjulian"\t\t0x4000 DM5\n" \
915107120Sjulian"\t\t0x8000 DH5\n\n" \
916107120Sjulian"" \
917107120Sjulian"\t\tSCO packets\n" \
918107120Sjulian"\t\t-----------\n" \
919107120Sjulian"\t\t0x0020 HV1\n" \
920107120Sjulian"\t\t0x0040 HV2\n" \
921107120Sjulian"\t\t0x0080 HV3\n" \
922107120Sjulian"",
923107120Sjulian&hci_change_connection_packet_type
924107120Sjulian},
925107120Sjulian{
926133178Semax"remote_name_request <BD_ADDR> <ps_rep_mode> <ps_mode> <clock_offset>",
927107120Sjulian"\nThe Remote_Name_Request command is used to obtain the user-friendly\n" \
928107120Sjulian"name of another Bluetooth unit.\n\n" \
929133178Semax"\t<BD_ADDR>      - xx:xx:xx:xx:xx:xx BD_ADDR or name\n" \
930107120Sjulian"\t<ps_rep_mode>  - dd; page scan repetition mode [0-2]\n" \
931107120Sjulian"\t<ps_mode>      - dd; page scan mode [0-3]\n" \
932107120Sjulian"\t<clock_offset> - xxxx; clock offset [0 - 0xffff]",
933107120Sjulian&hci_remote_name_request
934107120Sjulian},
935107120Sjulian{
936107120Sjulian"read_remote_supported_features <connection_handle>",
937107120Sjulian"\nThis command requests a list of the supported features for the remote\n" \
938107120Sjulian"unit identified by the connection handle parameter. The connection handle\n" \
939107120Sjulian"must be a connection handle for an ACL connection.\n\n" \
940107120Sjulian"\t<connection_handle> - dddd; connection handle",
941107120Sjulian&hci_read_remote_supported_features
942107120Sjulian},
943107120Sjulian{
944107120Sjulian"read_remote_version_information <connection_handle>",
945107120Sjulian"\nThis command will obtain the values for the version information for the\n" \
946107120Sjulian"remote Bluetooth unit identified by the connection handle parameter. The\n" \
947107120Sjulian"connection handle must be a connection handle for an ACL connection.\n\n" \
948122451Semax"\t<connection_handle> - dddd; connection handle",
949107120Sjulian&hci_read_remote_version_information
950107120Sjulian},
951107120Sjulian{
952107120Sjulian"read_clock_offset <connection_handle>",
953122451Semax"\nThis command allows the Host to read the clock offset from the remote unit.\n" \
954122451Semax"\t<connection_handle> - dddd; connection handle",
955107120Sjulian&hci_read_clock_offset
956107120Sjulian},
957107120Sjulian{
958107120SjulianNULL,
959107120Sjulian}};
960107120Sjulian
961