/*
 * 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., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 */

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

#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;
}
