File:  [Qemu by Fabrice Bellard] / qemu / bt-host.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 18:23:07 2018 UTC (3 years, 1 month ago) by root
Branches: qemu, MAIN
CVS tags: qemu0150, qemu0141, qemu0140, qemu0130, HEAD
qemu 0.13.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, see <http://www.gnu.org/licenses/>.
   18:  */
   19: 
   20: #include "qemu-common.h"
   21: #include "qemu-char.h"
   22: #include "sysemu.h"
   23: #include "net.h"
   24: #include "bt-host.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: 
   54:     iv[0].iov_base = (void *)&pkt;
   55:     iv[0].iov_len  = 1;
   56:     iv[1].iov_base = (void *) data;
   57:     iv[1].iov_len  = len;
   58: 
   59:     while (writev(s->fd, iv, 2) < 0) {
   60:         if (errno != EAGAIN && errno != EINTR) {
   61:             fprintf(stderr, "qemu: error %i writing bluetooth packet.\n",
   62:                             errno);
   63:             return;
   64:         }
   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 void bt_host_read(void *opaque)
   84: {
   85:     struct bt_host_hci_s *s = (struct bt_host_hci_s *) opaque;
   86:     uint8_t *pkt;
   87:     int pktlen;
   88: 
   89:     /* Seems that we can't read only the header first and then the amount
   90:      * of data indicated in the header because Linux will discard everything
   91:      * that's not been read in one go.  */
   92:     s->len = read(s->fd, s->hdr, sizeof(s->hdr));
   93: 
   94:     if (s->len < 0) {
   95:         fprintf(stderr, "qemu: error %i reading HCI frame\n", errno);
   96:         return;
   97:     }
   98: 
   99:     pkt = s->hdr;
  100:     while (s->len --)
  101:         switch (*pkt ++) {
  102:         case HCI_EVENT_PKT:
  103:             if (s->len < 2)
  104:                 goto bad_pkt;
  105: 
  106:             pktlen = MIN(pkt[1] + 2, s->len);
  107:             s->hci.evt_recv(s->hci.opaque, pkt, pktlen);
  108:             s->len -= pktlen;
  109:             pkt += pktlen;
  110: 
  111:             /* TODO: if this is an Inquiry Result event, it's also
  112:              * interpreted by Linux kernel before we received it, possibly
  113:              * we should clean the kernel Inquiry cache through
  114:              * ioctl(s->fd, HCI_INQUIRY, ...).  */
  115:             break;
  116: 
  117:         case HCI_ACLDATA_PKT:
  118:             if (s->len < 4)
  119:                 goto bad_pkt;
  120: 
  121:             pktlen = MIN(((pkt[3] << 8) | pkt[2]) + 4, s->len);
  122:             s->hci.acl_recv(s->hci.opaque, pkt, pktlen);
  123:             s->len -= pktlen;
  124:             pkt += pktlen;
  125:             break;
  126: 
  127:         case HCI_SCODATA_PKT:
  128:             if (s->len < 3)
  129:                 goto bad_pkt;
  130: 
  131:             pktlen = MIN(pkt[2] + 3, s->len);
  132:             s->len -= pktlen;
  133:             pkt += pktlen;
  134: 
  135:         default:
  136:         bad_pkt:
  137:             fprintf(stderr, "qemu: bad HCI packet type %02x\n", pkt[-1]);
  138:         }
  139: }
  140: 
  141: static int bt_host_bdaddr_set(struct HCIInfo *hci, const uint8_t *bd_addr)
  142: {
  143:     return -ENOTSUP;
  144: }
  145: 
  146: struct HCIInfo *bt_host_hci(const char *id)
  147: {
  148:     struct bt_host_hci_s *s;
  149:     int fd = -1;
  150: # ifdef CONFIG_BLUEZ
  151:     int dev_id = hci_devid(id);
  152:     struct hci_filter flt;
  153: 
  154:     if (dev_id < 0) {
  155:         fprintf(stderr, "qemu: `%s' not available\n", id);
  156:         return 0;
  157:     }
  158: 
  159:     fd = hci_open_dev(dev_id);
  160: 
  161:     /* XXX: can we ensure nobody else has the device opened?  */
  162: # endif
  163: 
  164:     if (fd < 0) {
  165:         fprintf(stderr, "qemu: Can't open `%s': %s (%i)\n",
  166:                         id, strerror(errno), errno);
  167:         return NULL;
  168:     }
  169: 
  170: # ifdef CONFIG_BLUEZ
  171:     hci_filter_clear(&flt);
  172:     hci_filter_all_ptypes(&flt);
  173:     hci_filter_all_events(&flt);
  174: 
  175:     if (setsockopt(fd, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) {
  176:         fprintf(stderr, "qemu: Can't set HCI filter on socket (%i)\n", errno);
  177:         return 0;
  178:     }
  179: # endif
  180: 
  181:     s = qemu_mallocz(sizeof(struct bt_host_hci_s));
  182:     s->fd = fd;
  183:     s->hci.cmd_send = bt_host_cmd;
  184:     s->hci.sco_send = bt_host_sco;
  185:     s->hci.acl_send = bt_host_acl;
  186:     s->hci.bdaddr_set = bt_host_bdaddr_set;
  187: 
  188:     qemu_set_fd_handler(s->fd, bt_host_read, NULL, s);
  189: 
  190:     return &s->hci;
  191: }
  192: #else
  193: struct HCIInfo *bt_host_hci(const char *id)
  194: {
  195:     fprintf(stderr, "qemu: bluetooth passthrough not supported (yet)\n");
  196: 
  197:     return 0;
  198: }
  199: #endif

unix.superglobalmegacorp.com