/* $NetBSD: btplay.c,v 1.1 2010/03/22 12:21:37 pooka Exp $ */ /* * Copyright (c) 2010 Antti Kantee. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Little demo showing how to use bluetooth stack in rump. Searches * for a peer and prints a little info for it. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include const char *btclasses[] = { "misc.", "computer", "phone", "LAN", "audio-video", "peripheral", "imaging", "wearable", "toy", }; int main(int argc, char *argv[]) { struct sockaddr_bt sbt; bdaddr_t peeraddr; uint8_t msg[1024]; hci_inquiry_cp inq; hci_cmd_hdr_t *cmd; hci_event_hdr_t *evp; struct hci_filter filt; struct btreq btr; int s, gotpeer = 0; rump_boot_sethowto(RUMP_AB_VERBOSE); rump_init(); s = rump_sys_socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); if (s == -1) err(1, "socket"); /* enable first device, print name and address */ memset(&btr, 0, sizeof(btr)); if (rump_sys_ioctl(s, SIOCNBTINFO, &btr) == -1) err(1, "no bt device?"); btr.btr_flags |= BTF_UP; if (rump_sys_ioctl(s, SIOCSBTFLAGS, &btr) == -1) err(1, "raise interface"); if (rump_sys_ioctl(s, SIOCGBTINFO, &btr) == -1) err(1, "reget info"); memset(&sbt, 0, sizeof(sbt)); sbt.bt_len = sizeof(sbt); sbt.bt_family = AF_BLUETOOTH; bdaddr_copy(&sbt.bt_bdaddr, &btr.btr_bdaddr); if (rump_sys_bind(s, (struct sockaddr *)&sbt, sizeof(sbt)) == -1) err(1, "bind"); if (rump_sys_connect(s, (struct sockaddr *)&sbt, sizeof(sbt)) == -1) err(1, "connect"); printf("device %s, addr %s\n", btr.btr_name, bt_ntoa(&btr.btr_bdaddr, NULL)); /* allow to receive various messages we need later */ memset(&filt, 0, sizeof(filt)); hci_filter_set(HCI_EVENT_COMMAND_COMPL, &filt); hci_filter_set(HCI_EVENT_INQUIRY_RESULT, &filt); hci_filter_set(HCI_EVENT_INQUIRY_COMPL, &filt); hci_filter_set(HCI_EVENT_REMOTE_NAME_REQ_COMPL, &filt); if (rump_sys_setsockopt(s, BTPROTO_HCI, SO_HCI_EVT_FILTER, &filt, sizeof(filt)) == -1) err(1, "setsockopt"); cmd = (void *)msg; evp = (void *)msg; /* discover peer. first, send local access profile general inquiry */ inq.lap[0] = 0x33; inq.lap[1] = 0x8b; inq.lap[2] = 0x9e; inq.inquiry_length = 4; inq.num_responses = 1; cmd->type = HCI_CMD_PKT; cmd->opcode = htole16(HCI_CMD_INQUIRY); cmd->length = sizeof(inq); memcpy(cmd+1, &inq, sizeof(inq)); if (rump_sys_sendto(s, msg, sizeof(*cmd)+sizeof(inq), 0, NULL, 0) == -1) err(1, "send inquiry"); memset(msg, 0, sizeof(msg)); if (rump_sys_recvfrom(s, msg, sizeof(msg), 0, NULL, NULL) == -1) err(1, "recv inq response"); if (evp->event != HCI_EVENT_COMMAND_COMPL) errx(1, "excepted command compl"); /* then, wait for response */ for (;;) { if (rump_sys_recvfrom(s, msg, sizeof(msg), 0, NULL, NULL) == -1) err(1, "recv inq result"); if (evp->event == HCI_EVENT_INQUIRY_COMPL) break; if (evp->event == HCI_EVENT_INQUIRY_RESULT) { hci_inquiry_response *r; unsigned class; r = (void *)(msg + sizeof(hci_event_hdr_t) + sizeof(hci_inquiry_result_ep)); bdaddr_copy(&peeraddr, &r[0]. bdaddr); printf("my peer: %s, ", bt_ntoa(&peeraddr, NULL)); class = r[0].uclass[1] & 0x1f; printf("major class: %d (%s)\n", class, class < __arraycount(btclasses) ? btclasses[class] : "unknown"); gotpeer = 1; } } /* found peer. ask for its name */ if (gotpeer) { hci_remote_name_req_cp nreq; hci_remote_name_req_compl_ep *nresp; memset(&nreq, 0, sizeof(nreq)); bdaddr_copy(&nreq.bdaddr, &peeraddr); cmd->type = HCI_CMD_PKT; cmd->opcode = htole16(HCI_CMD_REMOTE_NAME_REQ); cmd->length = sizeof(nreq); memcpy(cmd+1, &nreq, sizeof(nreq)); if (rump_sys_sendto(s, msg, sizeof(*cmd)+sizeof(nreq), 0, NULL, 0) == -1) err(1, "send name req"); memset(msg, 0, sizeof(msg)); if (rump_sys_recvfrom(s, msg, sizeof(msg), 0, NULL, NULL) == -1) err(1, "recv inq response"); if (evp->event != HCI_EVENT_REMOTE_NAME_REQ_COMPL) errx(1, "excepted nreq compl"); nresp = (void *)(evp+1); printf("peer name: %s\n", nresp->name); } return 0; }