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