Annotation of qemu/bt-host.c, revision 1.1.1.1
1.1 root 1: /*
2: * Wrap a host Bluetooth HCI socket in a struct HCIInfo.
3: *
4: * Copyright (C) 2008 Andrzej Zaborowski <balrog@zabor.org>
5: *
6: * This program is free software; you can redistribute it and/or
7: * modify it under the terms of the GNU General Public License as
8: * published by the Free Software Foundation; either version 2 or
9: * (at your option) version 3 of the License.
10: *
11: * This program is distributed in the hope that it will be useful,
12: * but WITHOUT ANY WARRANTY; without even the implied warranty of
13: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14: * GNU General Public License for more details.
15: *
16: * You should have received a copy of the GNU General Public License along
17: * with this program; if not, write to the Free Software Foundation, Inc.,
18: * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19: */
20:
21: #include "qemu-common.h"
22: #include "qemu-char.h"
23: #include "sysemu.h"
24: #include "net.h"
25:
26: #ifndef _WIN32
27: # include <errno.h>
28: # include <sys/ioctl.h>
29: # include <sys/uio.h>
30: # ifdef CONFIG_BLUEZ
31: # include <bluetooth/bluetooth.h>
32: # include <bluetooth/hci.h>
33: # include <bluetooth/hci_lib.h>
34: # else
35: # include "hw/bt.h"
36: # define HCI_MAX_FRAME_SIZE 1028
37: # endif
38:
39: struct bt_host_hci_s {
40: struct HCIInfo hci;
41: int fd;
42:
43: uint8_t hdr[HCI_MAX_FRAME_SIZE];
44: int len;
45: };
46:
47: static void bt_host_send(struct HCIInfo *hci,
48: int type, const uint8_t *data, int len)
49: {
50: struct bt_host_hci_s *s = (struct bt_host_hci_s *) hci;
51: uint8_t pkt = type;
52: struct iovec iv[2];
53: int ret;
54:
55: iv[0].iov_base = &pkt;
56: iv[0].iov_len = 1;
57: iv[1].iov_base = (void *) data;
58: iv[1].iov_len = len;
59:
60: while ((ret = writev(s->fd, iv, 2)) < 0)
61: if (errno != EAGAIN && errno != EINTR) {
62: fprintf(stderr, "qemu: error %i writing bluetooth packet.\n",
63: errno);
64: return;
65: }
66: }
67:
68: static void bt_host_cmd(struct HCIInfo *hci, const uint8_t *data, int len)
69: {
70: bt_host_send(hci, HCI_COMMAND_PKT, data, len);
71: }
72:
73: static void bt_host_acl(struct HCIInfo *hci, const uint8_t *data, int len)
74: {
75: bt_host_send(hci, HCI_ACLDATA_PKT, data, len);
76: }
77:
78: static void bt_host_sco(struct HCIInfo *hci, const uint8_t *data, int len)
79: {
80: bt_host_send(hci, HCI_SCODATA_PKT, data, len);
81: }
82:
83: static int bt_host_read_poll(void *opaque)
84: {
85: struct bt_host_hci_s *s = (struct bt_host_hci_s *) opaque;
86:
87: return !!s->hci.evt_recv;
88: }
89:
90: static void bt_host_read(void *opaque)
91: {
92: struct bt_host_hci_s *s = (struct bt_host_hci_s *) opaque;
93: uint8_t *pkt;
94: int pktlen;
95:
96: /* Seems that we can't read only the header first and then the amount
97: * of data indicated in the header because Linux will discard everything
98: * that's not been read in one go. */
99: s->len = read(s->fd, s->hdr, sizeof(s->hdr));
100:
101: if (s->len < 0) {
102: fprintf(stderr, "qemu: error %i reading HCI frame\n", errno);
103: return;
104: }
105:
106: pkt = s->hdr;
107: while (s->len --)
108: switch (*pkt ++) {
109: case HCI_EVENT_PKT:
110: if (s->len < 2)
111: goto bad_pkt;
112:
113: pktlen = MIN(pkt[1] + 2, s->len);
114: s->hci.evt_recv(s->hci.opaque, pkt, pktlen);
115: s->len -= pktlen;
116: pkt += pktlen;
117:
118: /* TODO: if this is an Inquiry Result event, it's also
119: * interpreted by Linux kernel before we received it, possibly
120: * we should clean the kernel Inquiry cache through
121: * ioctl(s->fd, HCI_INQUIRY, ...). */
122: break;
123:
124: case HCI_ACLDATA_PKT:
125: if (s->len < 4)
126: goto bad_pkt;
127:
128: pktlen = MIN(((pkt[3] << 8) | pkt[2]) + 4, s->len);
129: s->hci.acl_recv(s->hci.opaque, pkt, pktlen);
130: s->len -= pktlen;
131: pkt += pktlen;
132: break;
133:
134: case HCI_SCODATA_PKT:
135: if (s->len < 3)
136: goto bad_pkt;
137:
138: pktlen = MIN(pkt[2] + 3, s->len);
139: s->len -= pktlen;
140: pkt += pktlen;
141:
142: default:
143: bad_pkt:
144: fprintf(stderr, "qemu: bad HCI packet type %02x\n", pkt[-1]);
145: }
146: }
147:
148: static int bt_host_bdaddr_set(struct HCIInfo *hci, const uint8_t *bd_addr)
149: {
150: return -ENOTSUP;
151: }
152:
153: struct HCIInfo *bt_host_hci(const char *id)
154: {
155: struct bt_host_hci_s *s;
156: int fd = -1;
157: # ifdef CONFIG_BLUEZ
158: int dev_id = hci_devid(id);
159: struct hci_filter flt;
160:
161: if (dev_id < 0) {
162: fprintf(stderr, "qemu: `%s' not available\n", id);
163: return 0;
164: }
165:
166: fd = hci_open_dev(dev_id);
167:
168: /* XXX: can we ensure nobody else has the device opened? */
169: # endif
170:
171: if (fd < 0) {
172: fprintf(stderr, "qemu: Can't open `%s': %s (%i)\n",
173: id, strerror(errno), errno);
174: return 0;
175: }
176:
177: # ifdef CONFIG_BLUEZ
178: hci_filter_clear(&flt);
179: hci_filter_all_ptypes(&flt);
180: hci_filter_all_events(&flt);
181:
182: if (setsockopt(fd, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) {
183: fprintf(stderr, "qemu: Can't set HCI filter on socket (%i)\n", errno);
184: return 0;
185: }
186: # endif
187:
188: s = qemu_mallocz(sizeof(struct bt_host_hci_s));
189: s->fd = fd;
190: s->hci.cmd_send = bt_host_cmd;
191: s->hci.sco_send = bt_host_sco;
192: s->hci.acl_send = bt_host_acl;
193: s->hci.bdaddr_set = bt_host_bdaddr_set;
194:
195: qemu_set_fd_handler2(s->fd, bt_host_read_poll, bt_host_read, 0, s);
196:
197: return &s->hci;
198: }
199: #else
200: struct HCIInfo *bt_host_hci(const char *id)
201: {
202: fprintf(stderr, "qemu: bluetooth passthrough not supported (yet)\n");
203:
204: return 0;
205: }
206: #endif
unix.superglobalmegacorp.com