1 /* $NetBSD: device.c,v 1.2 2007/12/15 16:03:30 perry Exp $ */
4 * Copyright (c) 2007 Iain Hibbert
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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 the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #include <sys/cdefs.h>
31 __RCSID("$NetBSD: device.c,v 1.2 2007/12/15 16:03:30 perry Exp $");
33 #include <bluetooth.h>
42 * read/write stored link keys packet, with space for one key
44 struct stored_link_keys
{
48 uint8_t key
[HCI_KEY_SIZE
];
55 * send command 'opcode' with command packet 'cptr' of size 'clen'
56 * call 'func_cc' on command_complete event
57 * call 'func_ev' on event 'event'
58 * callbacks return -1 (failure), 0 (continue) or 1 (success)
61 hci_req(uint16_t opcode
, void *cptr
, size_t clen
, int (*func_cc
)(void *),
62 uint8_t event
, int (*func_ev
)(void *))
64 uint8_t buf
[sizeof(hci_cmd_hdr_t
) + HCI_CMD_PKT_SIZE
];
65 struct sockaddr_bt sa
;
71 memset(&f
, 0, sizeof(f
));
72 hci_filter_set(HCI_EVENT_COMMAND_COMPL
, &f
);
73 if (event
!= 0) hci_filter_set(event
, &f
);
75 memset(&sa
, 0, sizeof(sa
));
76 sa
.bt_len
= sizeof(sa
);
77 sa
.bt_family
= AF_BLUETOOTH
;
78 bdaddr_copy(&sa
.bt_bdaddr
, &laddr
);
80 hdr
= (hci_cmd_hdr_t
*)buf
;
81 hdr
->type
= HCI_CMD_PKT
;
82 hdr
->opcode
= htole16(opcode
);
85 memcpy(buf
+ sizeof(hci_cmd_hdr_t
), cptr
, clen
);
89 if ((fd
= socket(PF_BLUETOOTH
, SOCK_RAW
, BTPROTO_HCI
)) < 0
90 || setsockopt(fd
, BTPROTO_HCI
, SO_HCI_EVT_FILTER
, &f
, sizeof(f
)) < 0
91 || bind(fd
, (struct sockaddr
*)&sa
, sizeof(sa
)) < 0
92 || connect(fd
, (struct sockaddr
*)&sa
, sizeof(sa
)) < 0
93 || send(fd
, buf
, sizeof(hci_cmd_hdr_t
) + clen
, 0) < 0)
96 ep
= (hci_event_hdr_t
*)buf
;
98 if (recv(fd
, buf
, sizeof(buf
), 0) < 0)
101 if (ep
->event
== HCI_EVENT_COMMAND_COMPL
) {
102 hci_command_compl_ep
*cc
;
104 cc
= (hci_command_compl_ep
*)(ep
+ 1);
105 if (opcode
!= le16toh(cc
->opcode
))
108 rv
= func_cc(cc
+ 1);
115 if (event
!= 0 && event
== ep
->event
) {
116 rv
= func_ev(ep
+ 1);
125 if (fd
>= 0) close(fd
);
126 return rv
> 0 ? true : false;
130 * List keys on device
134 list_device_cc(void *arg
)
136 hci_read_stored_link_key_rp
*rp
= arg
;
144 printf("read %d keys (max %d)\n", rp
->num_keys_read
, rp
->max_num_keys
);
150 list_device_ev(void *arg
)
152 struct stored_link_keys
*ep
= arg
;
155 for (i
= 0 ; i
< ep
->num_keys
; i
++) {
157 print_addr("bdaddr", &ep
->key
[i
].addr
);
158 print_key("device key", ep
->key
[i
].key
);
167 hci_read_stored_link_key_cp cp
;
169 bdaddr_copy(&cp
.bdaddr
, BDADDR_ANY
);
172 return hci_req(HCI_CMD_READ_STORED_LINK_KEY
,
173 &cp
, sizeof(cp
), list_device_cc
,
174 HCI_EVENT_RETURN_LINK_KEYS
, list_device_ev
);
178 * Read key from device
182 read_device_cc(void *arg
)
185 /* if we got here, no key was found */
190 read_device_ev(void *arg
)
192 struct stored_link_keys
*ep
= arg
;
194 if (ep
->num_keys
!= 1
195 || !bdaddr_same(&ep
->key
[0].addr
, &raddr
))
198 memcpy(key
, ep
->key
[0].key
, HCI_KEY_SIZE
);
205 hci_read_stored_link_key_cp cp
;
207 bdaddr_copy(&cp
.bdaddr
, &raddr
);
210 return hci_req(HCI_CMD_READ_STORED_LINK_KEY
,
211 &cp
, sizeof(cp
), read_device_cc
,
212 HCI_EVENT_RETURN_LINK_KEYS
, read_device_ev
);
216 * Write key to device
219 write_device_cc(void *arg
)
221 hci_write_stored_link_key_rp
*rp
= arg
;
223 if (rp
->status
|| rp
->num_keys_written
!= 1) {
234 struct stored_link_keys cp
;
237 bdaddr_copy(&cp
.key
[0].addr
, &raddr
);
238 memcpy(cp
.key
[0].key
, key
, HCI_KEY_SIZE
);
240 return hci_req(HCI_CMD_WRITE_STORED_LINK_KEY
,
241 &cp
, sizeof(cp
), write_device_cc
,
246 * Clear key from device
249 clear_device_cc(void *arg
)
251 hci_delete_stored_link_key_rp
*rp
= arg
;
253 if (rp
->status
|| rp
->num_keys_deleted
!= 1) {
264 hci_delete_stored_link_key_cp cp
;
266 cp
.delete_all
= 0x00;
267 bdaddr_copy(&cp
.bdaddr
, &raddr
);
269 return hci_req(HCI_CMD_DELETE_STORED_LINK_KEY
,
270 &cp
, sizeof(cp
), clear_device_cc
,