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