Home | History | Annotate | Line # | Download | only in btplay
      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