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