xref: /netbsd-src/share/examples/rump/btplay/btplay.c (revision 5219b831d7cf4035750948406a8b8474881b8f37)
1*5219b831Spooka /*      $NetBSD: btplay.c,v 1.1 2010/03/22 12:21:37 pooka Exp $	*/
2*5219b831Spooka 
3*5219b831Spooka /*
4*5219b831Spooka  * Copyright (c) 2010 Antti Kantee.  All Rights Reserved.
5*5219b831Spooka  *
6*5219b831Spooka  * Redistribution and use in source and binary forms, with or without
7*5219b831Spooka  * modification, are permitted provided that the following conditions
8*5219b831Spooka  * are met:
9*5219b831Spooka  * 1. Redistributions of source code must retain the above copyright
10*5219b831Spooka  *    notice, this list of conditions and the following disclaimer.
11*5219b831Spooka  * 2. Redistributions in binary form must reproduce the above copyright
12*5219b831Spooka  *    notice, this list of conditions and the following disclaimer in the
13*5219b831Spooka  *    documentation and/or other materials provided with the distribution.
14*5219b831Spooka  *
15*5219b831Spooka  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
16*5219b831Spooka  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17*5219b831Spooka  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18*5219b831Spooka  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19*5219b831Spooka  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20*5219b831Spooka  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21*5219b831Spooka  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22*5219b831Spooka  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23*5219b831Spooka  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24*5219b831Spooka  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25*5219b831Spooka  * SUCH DAMAGE.
26*5219b831Spooka  */
27*5219b831Spooka 
28*5219b831Spooka /*
29*5219b831Spooka  * Little demo showing how to use bluetooth stack in rump.  Searches
30*5219b831Spooka  * for a peer and prints a little info for it.
31*5219b831Spooka  */
32*5219b831Spooka 
33*5219b831Spooka #include <sys/types.h>
34*5219b831Spooka #include <sys/ioctl.h>
35*5219b831Spooka #include <sys/time.h>
36*5219b831Spooka #include <sys/socket.h>
37*5219b831Spooka 
38*5219b831Spooka #include <rump/rump.h>
39*5219b831Spooka #include <rump/rump_syscalls.h>
40*5219b831Spooka 
41*5219b831Spooka #include <netbt/bluetooth.h>
42*5219b831Spooka #include <netbt/hci.h>
43*5219b831Spooka 
44*5219b831Spooka #include <bluetooth.h>
45*5219b831Spooka #include <err.h>
46*5219b831Spooka #include <paths.h>
47*5219b831Spooka #include <string.h>
48*5219b831Spooka #include <stdio.h>
49*5219b831Spooka #include <stdlib.h>
50*5219b831Spooka #include <unistd.h>
51*5219b831Spooka 
52*5219b831Spooka const char *btclasses[] = {
53*5219b831Spooka 	"misc.",
54*5219b831Spooka 	"computer",
55*5219b831Spooka 	"phone",
56*5219b831Spooka 	"LAN",
57*5219b831Spooka 	"audio-video",
58*5219b831Spooka 	"peripheral",
59*5219b831Spooka 	"imaging",
60*5219b831Spooka 	"wearable",
61*5219b831Spooka 	"toy",
62*5219b831Spooka };
63*5219b831Spooka 
64*5219b831Spooka int
main(int argc,char * argv[])65*5219b831Spooka main(int argc, char *argv[])
66*5219b831Spooka {
67*5219b831Spooka 	struct sockaddr_bt sbt;
68*5219b831Spooka 	bdaddr_t peeraddr;
69*5219b831Spooka 	uint8_t msg[1024];
70*5219b831Spooka 	hci_inquiry_cp inq;
71*5219b831Spooka 	hci_cmd_hdr_t *cmd;
72*5219b831Spooka 	hci_event_hdr_t *evp;
73*5219b831Spooka 	struct hci_filter filt;
74*5219b831Spooka 	struct btreq btr;
75*5219b831Spooka 	int s, gotpeer = 0;
76*5219b831Spooka 
77*5219b831Spooka 	rump_boot_sethowto(RUMP_AB_VERBOSE);
78*5219b831Spooka 	rump_init();
79*5219b831Spooka 
80*5219b831Spooka 	s = rump_sys_socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
81*5219b831Spooka 	if (s == -1)
82*5219b831Spooka 		err(1, "socket");
83*5219b831Spooka 
84*5219b831Spooka 	/* enable first device, print name and address */
85*5219b831Spooka 	memset(&btr, 0, sizeof(btr));
86*5219b831Spooka 	if (rump_sys_ioctl(s, SIOCNBTINFO, &btr) == -1)
87*5219b831Spooka 		err(1, "no bt device?");
88*5219b831Spooka 
89*5219b831Spooka 	btr.btr_flags |= BTF_UP;
90*5219b831Spooka 	if (rump_sys_ioctl(s, SIOCSBTFLAGS, &btr) == -1)
91*5219b831Spooka 		err(1, "raise interface");
92*5219b831Spooka 	if (rump_sys_ioctl(s, SIOCGBTINFO, &btr) == -1)
93*5219b831Spooka 		err(1, "reget info");
94*5219b831Spooka 
95*5219b831Spooka 	memset(&sbt, 0, sizeof(sbt));
96*5219b831Spooka 	sbt.bt_len = sizeof(sbt);
97*5219b831Spooka 	sbt.bt_family = AF_BLUETOOTH;
98*5219b831Spooka 	bdaddr_copy(&sbt.bt_bdaddr, &btr.btr_bdaddr);
99*5219b831Spooka 
100*5219b831Spooka 	if (rump_sys_bind(s, (struct sockaddr *)&sbt, sizeof(sbt)) == -1)
101*5219b831Spooka 		err(1, "bind");
102*5219b831Spooka 	if (rump_sys_connect(s, (struct sockaddr *)&sbt, sizeof(sbt)) == -1)
103*5219b831Spooka 		err(1, "connect");
104*5219b831Spooka 
105*5219b831Spooka 	printf("device %s, addr %s\n",
106*5219b831Spooka 	    btr.btr_name, bt_ntoa(&btr.btr_bdaddr, NULL));
107*5219b831Spooka 
108*5219b831Spooka 	/* allow to receive various messages we need later */
109*5219b831Spooka 	memset(&filt, 0, sizeof(filt));
110*5219b831Spooka 	hci_filter_set(HCI_EVENT_COMMAND_COMPL, &filt);
111*5219b831Spooka 	hci_filter_set(HCI_EVENT_INQUIRY_RESULT, &filt);
112*5219b831Spooka 	hci_filter_set(HCI_EVENT_INQUIRY_COMPL, &filt);
113*5219b831Spooka 	hci_filter_set(HCI_EVENT_REMOTE_NAME_REQ_COMPL, &filt);
114*5219b831Spooka 	if (rump_sys_setsockopt(s, BTPROTO_HCI, SO_HCI_EVT_FILTER,
115*5219b831Spooka 	    &filt, sizeof(filt)) == -1)
116*5219b831Spooka 		err(1, "setsockopt");
117*5219b831Spooka 
118*5219b831Spooka 	cmd = (void *)msg;
119*5219b831Spooka 	evp = (void *)msg;
120*5219b831Spooka 
121*5219b831Spooka 	/* discover peer.  first, send local access profile general inquiry */
122*5219b831Spooka 	inq.lap[0] = 0x33;
123*5219b831Spooka 	inq.lap[1] = 0x8b;
124*5219b831Spooka 	inq.lap[2] = 0x9e;
125*5219b831Spooka 	inq.inquiry_length = 4;
126*5219b831Spooka 	inq.num_responses = 1;
127*5219b831Spooka 
128*5219b831Spooka 	cmd->type = HCI_CMD_PKT;
129*5219b831Spooka 	cmd->opcode = htole16(HCI_CMD_INQUIRY);
130*5219b831Spooka 	cmd->length = sizeof(inq);
131*5219b831Spooka 	memcpy(cmd+1, &inq, sizeof(inq));
132*5219b831Spooka 
133*5219b831Spooka 	if (rump_sys_sendto(s, msg, sizeof(*cmd)+sizeof(inq), 0, NULL, 0) == -1)
134*5219b831Spooka 		err(1, "send inquiry");
135*5219b831Spooka 	memset(msg, 0, sizeof(msg));
136*5219b831Spooka 	if (rump_sys_recvfrom(s, msg, sizeof(msg), 0, NULL, NULL) == -1)
137*5219b831Spooka 		err(1, "recv inq response");
138*5219b831Spooka 	if (evp->event != HCI_EVENT_COMMAND_COMPL)
139*5219b831Spooka 		errx(1, "excepted command compl");
140*5219b831Spooka 
141*5219b831Spooka 	/* then, wait for response */
142*5219b831Spooka 	for (;;) {
143*5219b831Spooka 		if (rump_sys_recvfrom(s, msg, sizeof(msg), 0, NULL, NULL) == -1)
144*5219b831Spooka 			err(1, "recv inq result");
145*5219b831Spooka 
146*5219b831Spooka 		if (evp->event == HCI_EVENT_INQUIRY_COMPL)
147*5219b831Spooka 			break;
148*5219b831Spooka 		if (evp->event == HCI_EVENT_INQUIRY_RESULT) {
149*5219b831Spooka 			hci_inquiry_response *r;
150*5219b831Spooka 			unsigned class;
151*5219b831Spooka 
152*5219b831Spooka 			r = (void *)(msg + sizeof(hci_event_hdr_t)
153*5219b831Spooka 			    + sizeof(hci_inquiry_result_ep));
154*5219b831Spooka 			bdaddr_copy(&peeraddr, &r[0]. bdaddr);
155*5219b831Spooka 			printf("my peer: %s, ", bt_ntoa(&peeraddr, NULL));
156*5219b831Spooka 			class = r[0].uclass[1] & 0x1f;
157*5219b831Spooka 			printf("major class: %d (%s)\n", class,
158*5219b831Spooka 			    class < __arraycount(btclasses)
159*5219b831Spooka 			      ? btclasses[class] : "unknown");
160*5219b831Spooka 			gotpeer = 1;
161*5219b831Spooka 		}
162*5219b831Spooka 	}
163*5219b831Spooka 
164*5219b831Spooka 	/* found peer.  ask for its name */
165*5219b831Spooka 	if (gotpeer) {
166*5219b831Spooka 		hci_remote_name_req_cp nreq;
167*5219b831Spooka 		hci_remote_name_req_compl_ep *nresp;
168*5219b831Spooka 
169*5219b831Spooka 		memset(&nreq, 0, sizeof(nreq));
170*5219b831Spooka 		bdaddr_copy(&nreq.bdaddr, &peeraddr);
171*5219b831Spooka 
172*5219b831Spooka 		cmd->type = HCI_CMD_PKT;
173*5219b831Spooka 		cmd->opcode = htole16(HCI_CMD_REMOTE_NAME_REQ);
174*5219b831Spooka 		cmd->length = sizeof(nreq);
175*5219b831Spooka 		memcpy(cmd+1, &nreq, sizeof(nreq));
176*5219b831Spooka 
177*5219b831Spooka 		if (rump_sys_sendto(s, msg, sizeof(*cmd)+sizeof(nreq), 0,
178*5219b831Spooka 		    NULL, 0) == -1)
179*5219b831Spooka 			err(1, "send name req");
180*5219b831Spooka 		memset(msg, 0, sizeof(msg));
181*5219b831Spooka 		if (rump_sys_recvfrom(s, msg, sizeof(msg), 0, NULL, NULL) == -1)
182*5219b831Spooka 			err(1, "recv inq response");
183*5219b831Spooka 		if (evp->event != HCI_EVENT_REMOTE_NAME_REQ_COMPL)
184*5219b831Spooka 			errx(1, "excepted nreq compl");
185*5219b831Spooka 
186*5219b831Spooka 		nresp = (void *)(evp+1);
187*5219b831Spooka 		printf("peer name: %s\n", nresp->name);
188*5219b831Spooka 	}
189*5219b831Spooka 
190*5219b831Spooka 	return 0;
191*5219b831Spooka }
192