File:  [Qemu by Fabrice Bellard] / qemu / bt-host.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 16:50:17 2018 UTC (3 years, 1 month ago) by root
Branches: qemu, MAIN
CVS tags: qemu0105, qemu0104, qemu0103, qemu0102, qemu0101, qemu0100, HEAD
qemu 0.10.0

    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