/*
 * Support for host VHCIs inside qemu scatternets.
 *
 * 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, see <http://www.gnu.org/licenses/>.
 */

#include "qemu/osdep.h"
#include "sysemu/bt.h"
#include "hw/bt.h"
#include "qemu/main-loop.h"

#define VHCI_DEV	"/dev/vhci"
#define VHCI_UDEV	"/dev/hci_vhci"

struct bt_vhci_s {
    int fd;
    struct HCIInfo *info;

    uint8_t hdr[4096];
    int len;
};

static void vhci_read(void *opaque)
{
    struct bt_vhci_s *s = (struct bt_vhci_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 the PDU\n", errno);
        return;
    }

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

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

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

            pktlen = MIN(((pkt[3] << 8) | pkt[2]) + 4, s->len);
            s->info->acl_send(s->info, 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->info->sco_send(s->info, pkt, pktlen);
            s->len -= pktlen;
            pkt += pktlen;
            break;

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

static void vhci_host_send(void *opaque,
                int type, const uint8_t *data, int len)
{
    struct bt_vhci_s *s = (struct bt_vhci_s *) opaque;
#if 0
    uint8_t pkt = type;
    struct iovec iv[2];

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

    while (writev(s->fd, iv, 2) < 0)
        if (errno != EAGAIN && errno != EINTR) {
            fprintf(stderr, "qemu: error %i writing bluetooth packet.\n",
                            errno);
            return;
        }
#else
    /* Apparently VHCI wants us to write everything in one chunk :-(  */
    static uint8_t buf[4096];

    buf[0] = type;
    memcpy(buf + 1, data, len);

    while (write(s->fd, buf, len + 1) < 0)
        if (errno != EAGAIN && errno != EINTR) {
            fprintf(stderr, "qemu: error %i writing bluetooth packet.\n",
                            errno);
            return;
        }
#endif
}

static void vhci_out_hci_packet_event(void *opaque,
                const uint8_t *data, int len)
{
    vhci_host_send(opaque, HCI_EVENT_PKT, data, len);
}

static void vhci_out_hci_packet_acl(void *opaque,
                const uint8_t *data, int len)
{
    vhci_host_send(opaque, HCI_ACLDATA_PKT, data, len);
}

void bt_vhci_init(struct HCIInfo *info)
{
    struct bt_vhci_s *s;
    int err[2];
    int fd;

    fd = open(VHCI_DEV, O_RDWR);
    err[0] = errno;
    if (fd < 0) {
        fd = open(VHCI_UDEV, O_RDWR);
        err[1] = errno;
    }

    if (fd < 0) {
        fprintf(stderr, "qemu: Can't open `%s': %s (%i)\n",
                        VHCI_DEV, strerror(err[0]), err[0]);
        fprintf(stderr, "qemu: Can't open `%s': %s (%i)\n",
                        VHCI_UDEV, strerror(err[1]), err[1]);
        exit(-1);
    }

    s = g_malloc0(sizeof(struct bt_vhci_s));
    s->fd = fd;
    s->info = info ?: qemu_next_hci();
    s->info->opaque = s;
    s->info->evt_recv = vhci_out_hci_packet_event;
    s->info->acl_recv = vhci_out_hci_packet_acl;

    qemu_set_fd_handler(s->fd, vhci_read, NULL, s);
}
