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