/*
 * Wrap a host Bluetooth HCI socket in a struct HCIInfo.
 *
 * Copyright (C) 2008 Andrzej Zaborowski  <balrog@zabor.org>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 or
 * (at your option) version 3 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include "qemu-common.h"
#include "qemu-char.h"
#include "sysemu.h"
#include "net.h"

#ifndef _WIN32
# include <errno.h>
# include <sys/ioctl.h>
# include <sys/uio.h>
# ifdef CONFIG_BLUEZ
#  include <bluetooth/bluetooth.h>
#  include <bluetooth/hci.h>
#  include <bluetooth/hci_lib.h>
# else
#  include "hw/bt.h"
#  define HCI_MAX_FRAME_SIZE	1028
# endif

struct bt_host_hci_s {
    struct HCIInfo hci;
    int fd;

    uint8_t hdr[HCI_MAX_FRAME_SIZE];
    int len;
};

static void bt_host_send(struct HCIInfo *hci,
                int type, const uint8_t *data, int len)
{
    struct bt_host_hci_s *s = (struct bt_host_hci_s *) hci;
    uint8_t pkt = type;
    struct iovec iv[2];
    int ret;

    iv[0].iov_base = &pkt;
    iv[0].iov_len  = 1;
    iv[1].iov_base = (void *) data;
    iv[1].iov_len  = len;

    while ((ret = writev(s->fd, iv, 2)) < 0)
        if (errno != EAGAIN && errno != EINTR) {
            fprintf(stderr, "qemu: error %i writing bluetooth packet.\n",
                            errno);
            return;
        }
}

static void bt_host_cmd(struct HCIInfo *hci, const uint8_t *data, int len)
{
    bt_host_send(hci, HCI_COMMAND_PKT, data, len);
}

static void bt_host_acl(struct HCIInfo *hci, const uint8_t *data, int len)
{
    bt_host_send(hci, HCI_ACLDATA_PKT, data, len);
}

static void bt_host_sco(struct HCIInfo *hci, const uint8_t *data, int len)
{
    bt_host_send(hci, HCI_SCODATA_PKT, data, len);
}

static int bt_host_read_poll(void *opaque)
{
    struct bt_host_hci_s *s = (struct bt_host_hci_s *) opaque;

    return !!s->hci.evt_recv;
}

static void bt_host_read(void *opaque)
{
    struct bt_host_hci_s *s = (struct bt_host_hci_s *) opaque;
    uint8_t *pkt;
    int pktlen;

    /* Seems that we can't read only the header first and then the amount
     * of data indicated in the header because Linux will discard everything
     * that's not been read in one go.  */
    s->len = read(s->fd, s->hdr, sizeof(s->hdr));

    if (s->len < 0) {
        fprintf(stderr, "qemu: error %i reading HCI frame\n", errno);
        return;
    }

    pkt = s->hdr;
    while (s->len --)
        switch (*pkt ++) {
        case HCI_EVENT_PKT:
            if (s->len < 2)
                goto bad_pkt;

            pktlen = MIN(pkt[1] + 2, s->len);
            s->hci.evt_recv(s->hci.opaque, pkt, pktlen);
            s->len -= pktlen;
            pkt += pktlen;

            /* TODO: if this is an Inquiry Result event, it's also
             * interpreted by Linux kernel before we received it, possibly
             * we should clean the kernel Inquiry cache through
             * ioctl(s->fd, HCI_INQUIRY, ...).  */
            break;

        case HCI_ACLDATA_PKT:
            if (s->len < 4)
                goto bad_pkt;

            pktlen = MIN(((pkt[3] << 8) | pkt[2]) + 4, s->len);
            s->hci.acl_recv(s->hci.opaque, pkt, pktlen);
            s->len -= pktlen;
            pkt += pktlen;
            break;

        case HCI_SCODATA_PKT:
            if (s->len < 3)
                goto bad_pkt;

            pktlen = MIN(pkt[2] + 3, s->len);
            s->len -= pktlen;
            pkt += pktlen;

        default:
        bad_pkt:
            fprintf(stderr, "qemu: bad HCI packet type %02x\n", pkt[-1]);
        }
}

static int bt_host_bdaddr_set(struct HCIInfo *hci, const uint8_t *bd_addr)
{
    return -ENOTSUP;
}

struct HCIInfo *bt_host_hci(const char *id)
{
    struct bt_host_hci_s *s;
    int fd = -1;
# ifdef CONFIG_BLUEZ
    int dev_id = hci_devid(id);
    struct hci_filter flt;

    if (dev_id < 0) {
        fprintf(stderr, "qemu: `%s' not available\n", id);
        return 0;
    }

    fd = hci_open_dev(dev_id);

    /* XXX: can we ensure nobody else has the device opened?  */
# endif

    if (fd < 0) {
        fprintf(stderr, "qemu: Can't open `%s': %s (%i)\n",
                        id, strerror(errno), errno);
        return 0;
    }

# ifdef CONFIG_BLUEZ
    hci_filter_clear(&flt);
    hci_filter_all_ptypes(&flt);
    hci_filter_all_events(&flt);

    if (setsockopt(fd, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) {
        fprintf(stderr, "qemu: Can't set HCI filter on socket (%i)\n", errno);
        return 0;
    }
# endif

    s = qemu_mallocz(sizeof(struct bt_host_hci_s));
    s->fd = fd;
    s->hci.cmd_send = bt_host_cmd;
    s->hci.sco_send = bt_host_sco;
    s->hci.acl_send = bt_host_acl;
    s->hci.bdaddr_set = bt_host_bdaddr_set;

    qemu_set_fd_handler2(s->fd, bt_host_read_poll, bt_host_read, 0, s);

    return &s->hci;
}
#else
struct HCIInfo *bt_host_hci(const char *id)
{
    fprintf(stderr, "qemu: bluetooth passthrough not supported (yet)\n");

    return 0;
}
#endif
