1 /* $NetBSD: hci.c,v 1.1 2006/06/19 15:44:56 gdamore Exp $ */ 2 3 /*- 4 * Copyright (c) 2006 Itronix Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of Itronix Inc. may not be used to endorse 16 * or promote products derived from this software without specific 17 * prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY 23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 * ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 /* 32 * Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com> 33 * All rights reserved. 34 * 35 * Redistribution and use in source and binary forms, with or without 36 * modification, are permitted provided that the following conditions 37 * are met: 38 * 1. Redistributions of source code must retain the above copyright 39 * notice, this list of conditions and the following disclaimer. 40 * 2. Redistributions in binary form must reproduce the above copyright 41 * notice, this list of conditions and the following disclaimer in the 42 * documentation and/or other materials provided with the distribution. 43 * 44 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 45 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 46 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 47 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 48 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 49 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 50 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 51 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 52 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 53 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 54 * SUCH DAMAGE. 55 */ 56 57 #include <sys/cdefs.h> 58 __RCSID("$NetBSD: hci.c,v 1.1 2006/06/19 15:44:56 gdamore Exp $"); 59 60 #include <sys/ioctl.h> 61 #include <sys/time.h> 62 #include <bluetooth.h> 63 #include <errno.h> 64 #include <event.h> 65 #include <string.h> 66 #include <syslog.h> 67 #include <unistd.h> 68 69 #include "bthcid.h" 70 71 static struct event hci_ev; 72 73 static void process_hci 74 (int, short, void *); 75 76 static int process_pin_code_request_event 77 (int, struct sockaddr_bt *, bdaddr_t *); 78 static int process_link_key_request_event 79 (int, struct sockaddr_bt *, bdaddr_t *); 80 static int process_link_key_notification_event 81 (int, struct sockaddr_bt *, hci_link_key_notification_ep *); 82 83 static int send_link_key_reply 84 (int, struct sockaddr_bt *, bdaddr_t *, uint8_t *); 85 static int send_hci_cmd 86 (int, struct sockaddr_bt *, uint16_t, size_t, void *); 87 88 static char dev_name[HCI_DEVNAME_SIZE]; 89 90 /* Initialise HCI Events */ 91 int 92 init_hci(bdaddr_t *bdaddr) 93 { 94 struct sockaddr_bt sa; 95 struct hci_filter filter; 96 int hci; 97 98 hci = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); 99 if (hci < 0) 100 return -1; 101 102 memset(&sa, 0, sizeof(sa)); 103 sa.bt_len = sizeof(sa); 104 sa.bt_family = AF_BLUETOOTH; 105 bdaddr_copy(&sa.bt_bdaddr, bdaddr); 106 if (bind(hci, (struct sockaddr *)&sa, sizeof(sa)) < 0) { 107 close(hci); 108 return -1; 109 } 110 111 memset(&filter, 0, sizeof(filter)); 112 hci_filter_set(HCI_EVENT_PIN_CODE_REQ, &filter); 113 hci_filter_set(HCI_EVENT_LINK_KEY_REQ, &filter); 114 hci_filter_set(HCI_EVENT_LINK_KEY_NOTIFICATION, &filter); 115 116 if (setsockopt(hci, BTPROTO_HCI, SO_HCI_EVT_FILTER, 117 (const void *)&filter, sizeof(filter)) < 0) { 118 close(hci); 119 return -1; 120 } 121 122 event_set(&hci_ev, hci, EV_READ | EV_PERSIST, process_hci, NULL); 123 if (event_add(&hci_ev, NULL) < 0) { 124 close(hci); 125 return -1; 126 } 127 128 return 0; 129 } 130 131 /* Process an HCI event */ 132 static void 133 process_hci(int sock, short ev, void *arg) 134 { 135 char buffer[HCI_EVENT_PKT_SIZE]; 136 hci_event_hdr_t *event = (hci_event_hdr_t *)buffer; 137 struct sockaddr_bt addr; 138 int n; 139 socklen_t size; 140 141 size = sizeof(addr); 142 n = recvfrom(sock, buffer, sizeof(buffer), 0, 143 (struct sockaddr *) &addr, &size); 144 if (n < 0) { 145 syslog(LOG_ERR, "Could not receive from HCI socket. " 146 "%s (%d)", strerror(errno), errno); 147 148 return; 149 } 150 151 if (event->type != HCI_EVENT_PKT) { 152 syslog(LOG_ERR, "Received unexpected HCI packet, " 153 "type=%#x", event->type); 154 155 return; 156 } 157 158 if (!bt_devname(dev_name, &addr.bt_bdaddr)) 159 strlcpy(dev_name, "unknown", sizeof(dev_name)); 160 161 switch (event->event) { 162 case HCI_EVENT_PIN_CODE_REQ: 163 process_pin_code_request_event(sock, &addr, 164 (bdaddr_t *)(event + 1)); 165 break; 166 167 case HCI_EVENT_LINK_KEY_REQ: 168 process_link_key_request_event(sock, &addr, 169 (bdaddr_t *)(event + 1)); 170 break; 171 172 case HCI_EVENT_LINK_KEY_NOTIFICATION: 173 process_link_key_notification_event(sock, &addr, 174 (hci_link_key_notification_ep *)(event + 1)); 175 break; 176 177 default: 178 syslog(LOG_ERR, "Received unexpected HCI event, " 179 "event=%#x", event->event); 180 break; 181 } 182 183 return; 184 } 185 186 /* Process PIN_Code_Request event */ 187 static int 188 process_pin_code_request_event(int sock, struct sockaddr_bt *addr, 189 bdaddr_t *bdaddr) 190 { 191 uint8_t *pin; 192 193 syslog(LOG_DEBUG, "Got PIN_Code_Request event from %s, " 194 "remote bdaddr %s", 195 dev_name, 196 bt_ntoa(bdaddr, NULL)); 197 198 pin = lookup_pin(&addr->bt_bdaddr, bdaddr); 199 if (pin != NULL) 200 return send_pin_code_reply(sock, addr, bdaddr, pin); 201 202 if (send_client_request(&addr->bt_bdaddr, bdaddr, sock) == 0) 203 return send_pin_code_reply(sock, addr, bdaddr, NULL); 204 205 return 0; 206 } 207 208 /* Process Link_Key_Request event */ 209 static int 210 process_link_key_request_event(int sock, struct sockaddr_bt *addr, 211 bdaddr_t *bdaddr) 212 { 213 uint8_t *key; 214 215 syslog(LOG_DEBUG, 216 "Got Link_Key_Request event from %s, remote bdaddr %s", 217 dev_name, bt_ntoa(bdaddr, NULL)); 218 219 key = lookup_key(&addr->bt_bdaddr, bdaddr); 220 221 if (key != NULL) { 222 syslog(LOG_DEBUG, "Found Key, remote bdaddr %s", 223 bt_ntoa(bdaddr, NULL)); 224 225 return send_link_key_reply(sock, addr, bdaddr, key); 226 } 227 228 syslog(LOG_DEBUG, "Could not find link key for remote bdaddr %s", 229 bt_ntoa(bdaddr, NULL)); 230 231 return send_link_key_reply(sock, addr, bdaddr, NULL); 232 } 233 234 /* Send PIN_Code_[Negative]_Reply */ 235 int 236 send_pin_code_reply(int sock, struct sockaddr_bt *addr, 237 bdaddr_t *bdaddr, uint8_t *pin) 238 { 239 int n; 240 241 if (pin != NULL) { 242 hci_pin_code_rep_cp cp; 243 244 syslog(LOG_DEBUG, "Sending PIN_Code_Reply to %s " 245 "for remote bdaddr %s", 246 dev_name, 247 bt_ntoa(bdaddr, NULL)); 248 249 bdaddr_copy(&cp.bdaddr, bdaddr); 250 memcpy(cp.pin, pin, HCI_PIN_SIZE); 251 252 n = HCI_PIN_SIZE; 253 while (n > 0 && pin[n - 1] == 0) 254 n--; 255 cp.pin_size = n; 256 257 n = send_hci_cmd(sock, addr, 258 HCI_CMD_PIN_CODE_REP, sizeof(cp), &cp); 259 260 } else { 261 syslog(LOG_DEBUG, "Sending PIN_Code_Negative_Reply to %s " 262 "for remote bdaddr %s", 263 dev_name, 264 bt_ntoa(bdaddr, NULL)); 265 266 n = send_hci_cmd(sock, addr, HCI_CMD_PIN_CODE_NEG_REP, 267 sizeof(bdaddr_t), bdaddr); 268 } 269 270 if (n < 0) { 271 syslog(LOG_ERR, "Could not send PIN code reply to %s " 272 "for remote bdaddr %s. %s (%d)", 273 dev_name, 274 bt_ntoa(bdaddr, NULL), 275 strerror(errno), 276 errno); 277 278 return -1; 279 } 280 281 return 0; 282 } 283 284 /* Send Link_Key_[Negative]_Reply */ 285 static int 286 send_link_key_reply(int sock, struct sockaddr_bt *addr, 287 bdaddr_t *bdaddr, uint8_t *key) 288 { 289 int n; 290 291 if (key != NULL) { 292 hci_link_key_rep_cp cp; 293 294 bdaddr_copy(&cp.bdaddr, bdaddr); 295 memcpy(&cp.key, key, sizeof(cp.key)); 296 297 syslog(LOG_DEBUG, "Sending Link_Key_Reply to %s " 298 "for remote bdaddr %s", 299 dev_name, bt_ntoa(bdaddr, NULL)); 300 301 n = send_hci_cmd(sock, addr, HCI_CMD_LINK_KEY_REP, sizeof(cp), &cp); 302 } else { 303 hci_link_key_neg_rep_cp cp; 304 305 bdaddr_copy(&cp.bdaddr, bdaddr); 306 307 syslog(LOG_DEBUG, "Sending Link_Key_Negative_Reply to %s " 308 "for remote bdaddr %s", 309 dev_name, bt_ntoa(bdaddr, NULL)); 310 311 n = send_hci_cmd(sock, addr, HCI_CMD_LINK_KEY_NEG_REP, sizeof(cp), &cp); 312 } 313 314 if (n < 0) { 315 syslog(LOG_ERR, "Could not send link key reply to %s " 316 "for remote bdaddr %s. %s (%d)", 317 dev_name, bt_ntoa(bdaddr, NULL), 318 strerror(errno), errno); 319 return -1; 320 } 321 322 return 0; 323 } 324 325 /* Process Link_Key_Notification event */ 326 static int 327 process_link_key_notification_event(int sock, struct sockaddr_bt *addr, 328 hci_link_key_notification_ep *ep) 329 { 330 331 syslog(LOG_DEBUG, "Got Link_Key_Notification event from %s, " 332 "remote bdaddr %s", 333 dev_name, 334 bt_ntoa(&ep->bdaddr, NULL)); 335 336 save_key(&addr->bt_bdaddr, &ep->bdaddr, ep->key); 337 return 0; 338 } 339 340 /* Send HCI Command Packet to socket */ 341 static int 342 send_hci_cmd(int sock, struct sockaddr_bt *sa, uint16_t opcode, size_t len, void *buf) 343 { 344 char msg[HCI_CMD_PKT_SIZE]; 345 hci_cmd_hdr_t *h = (hci_cmd_hdr_t *)msg; 346 347 h->type = HCI_CMD_PKT; 348 h->opcode = htole16(opcode); 349 h->length = len; 350 351 if (len > 0) 352 memcpy(msg + sizeof(hci_cmd_hdr_t), buf, len); 353 354 return sendto(sock, msg, sizeof(hci_cmd_hdr_t) + len, 0, 355 (struct sockaddr *)sa, sizeof(*sa)); 356 } 357