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 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