// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <ddk/binding.h>
#include <ddk/device.h>
#include <ddk/driver.h>
#include <driver/usb.h>
#include <zircon/device/bt-hci.h>
#include <zircon/listnode.h>
#include <zircon/status.h>

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <threads.h>
#include <unistd.h>

#define EVENT_REQ_COUNT 8

// TODO(armansito): Consider increasing these.
#define ACL_READ_REQ_COUNT 8
#define ACL_WRITE_REQ_COUNT 8

#define CMD_BUF_SIZE 255 + 3   // 3 byte header + payload
#define EVENT_BUF_SIZE 255 + 2 // 2 byte header + payload

// The number of currently supported HCI channel endpoints. We currently have
// one channel for command/event flow and one for ACL data flow. The sniff channel is managed
// separately.
#define NUM_CHANNELS 2

// Uncomment these to force using a particular Bluetooth module
// #define USB_VID 0x0a12  // CSR
// #define USB_PID 0x0001

typedef struct {
    zx_device_t* mxdev;
    zx_device_t* usb_mxdev;
    usb_protocol_t usb;

    zx_handle_t cmd_channel;
    zx_handle_t acl_channel;
    zx_handle_t snoop_channel;

    zx_wait_item_t read_wait_items[NUM_CHANNELS];
    uint32_t read_wait_item_count;

    bool read_thread_running;

    void* intr_queue;

    // for accumulating HCI events
    uint8_t event_buffer[EVENT_BUF_SIZE];
    size_t event_buffer_offset;
    size_t event_buffer_packet_length;

    // pool of free USB requests
    list_node_t free_event_reqs;
    list_node_t free_acl_read_reqs;
    list_node_t free_acl_write_reqs;

    mtx_t mutex;
} hci_t;

static void queue_acl_read_requests_locked(hci_t* hci) {
    list_node_t* node;
    while ((node = list_remove_head(&hci->free_acl_read_reqs)) != NULL) {
        iotxn_t* txn = containerof(node, iotxn_t, node);
        iotxn_queue(hci->usb_mxdev, txn);
    }
}

static void queue_interrupt_requests_locked(hci_t* hci) {
    list_node_t* node;
    while ((node = list_remove_head(&hci->free_event_reqs)) != NULL) {
        iotxn_t* txn = containerof(node, iotxn_t, node);
        iotxn_queue(hci->usb_mxdev, txn);
    }
}

static void cmd_channel_cleanup_locked(hci_t* hci) {
    if (hci->cmd_channel == ZX_HANDLE_INVALID) return;

    zx_handle_close(hci->cmd_channel);
    hci->cmd_channel = ZX_HANDLE_INVALID;
}

static void acl_channel_cleanup_locked(hci_t* hci) {
    if (hci->acl_channel == ZX_HANDLE_INVALID) return;

    zx_handle_close(hci->acl_channel);
    hci->acl_channel = ZX_HANDLE_INVALID;
}

static void snoop_channel_cleanup_locked(hci_t* hci) {
    if (hci->snoop_channel == ZX_HANDLE_INVALID) return;

    zx_handle_close(hci->snoop_channel);
    hci->snoop_channel = ZX_HANDLE_INVALID;
}

static void snoop_channel_write_locked(hci_t* hci, uint8_t flags, uint8_t* bytes, size_t length) {
    if (hci->snoop_channel == ZX_HANDLE_INVALID)
        return;

    // We tack on a flags byte to the beginning of the payload.
    uint8_t snoop_buffer[length + 1];
    snoop_buffer[0] = flags;
    memcpy(snoop_buffer + 1, bytes, length);
    zx_status_t status = zx_channel_write(hci->snoop_channel, 0, snoop_buffer, length + 1, NULL, 0);
    if (status < 0) {
        printf("usb-bt-hci: failed to write to snoop channel: %s\n", zx_status_get_string(status));
        snoop_channel_cleanup_locked(hci);
    }
}

static void hci_event_complete(iotxn_t* txn, void* cookie) {
    hci_t* hci = (hci_t*)cookie;
    mtx_lock(&hci->mutex);

    // Handle the interrupt as long as either the command channel or the snoop
    // channel is open.
    if (hci->cmd_channel == ZX_HANDLE_INVALID && hci->snoop_channel == ZX_HANDLE_INVALID)
        goto out2;

    if (txn->status == ZX_OK) {
        uint8_t* buffer;
        iotxn_mmap(txn, (void **)&buffer);
        size_t length = txn->actual;
        size_t packet_size = buffer[1] + 2;

        // simple case - packet fits in received data
        if (hci->event_buffer_offset == 0 && length >= 2) {
            if (packet_size == length) {
                if (hci->cmd_channel != ZX_HANDLE_INVALID) {
                    zx_status_t status = zx_channel_write(hci->cmd_channel, 0, buffer, length, NULL, 0);
                    if (status < 0) {
                        printf("hci_interrupt failed to write: %s\n", zx_status_get_string(status));
                    }
                }
                snoop_channel_write_locked(hci, BT_HCI_SNOOP_FLAG_RECEIVED, buffer, length);
                goto out;
            }
        }

        // complicated case - need to accumulate into hci->event_buffer

        if (hci->event_buffer_offset + length > sizeof(hci->event_buffer)) {
            printf("hci->event_buffer would overflow!\n");
            goto out2;
        }

        memcpy(&hci->event_buffer[hci->event_buffer_offset], buffer, length);
        if (hci->event_buffer_offset == 0) {
            hci->event_buffer_packet_length = packet_size;
        } else {
            packet_size = hci->event_buffer_packet_length;
        }
        hci->event_buffer_offset += length;

        // check to see if we have a full packet
        if (packet_size <= hci->event_buffer_offset) {
            zx_status_t status = zx_channel_write(hci->cmd_channel, 0, hci->event_buffer,
                                                  packet_size, NULL, 0);
            if (status < 0) {
                printf("hci_interrupt failed to write: %s\n", zx_status_get_string(status));
            }

            snoop_channel_write_locked(hci, BT_HCI_SNOOP_FLAG_RECEIVED, hci->event_buffer, packet_size);

            uint32_t remaining = hci->event_buffer_offset - packet_size;
            memmove(hci->event_buffer, hci->event_buffer + packet_size, remaining);
            hci->event_buffer_offset = 0;
            hci->event_buffer_packet_length = 0;
        }
    }

out:
    list_add_head(&hci->free_event_reqs, &txn->node);
    queue_interrupt_requests_locked(hci);
out2:
    mtx_unlock(&hci->mutex);
}

static void hci_acl_read_complete(iotxn_t* txn, void* cookie) {
    hci_t* hci = (hci_t*)cookie;

    mtx_lock(&hci->mutex);

    if (txn->status == ZX_OK) {
        void* buffer;
        iotxn_mmap(txn, &buffer);

        // The channel handle could be invalid here (e.g. if no process called
        // the ioctl or they closed their endpoint). Instead of explicitly
        // checking we let zx_channel_write fail with ZX_ERR_BAD_HANDLE or
        // ZX_ERR_PEER_CLOSED.
        zx_status_t status = zx_channel_write(hci->acl_channel, 0, buffer, txn->actual, NULL, 0);
        if (status < 0) {
            printf("hci_acl_read_complete failed to write: %s\n", zx_status_get_string(status));
        }

        // If the snoop channel is open then try to write the packet even if acl_channel was closed.
        snoop_channel_write_locked(
            hci, BT_HCI_SNOOP_FLAG_DATA | BT_HCI_SNOOP_FLAG_RECEIVED, buffer, txn->actual);
    }

    list_add_head(&hci->free_acl_read_reqs, &txn->node);
    queue_acl_read_requests_locked(hci);

    mtx_unlock(&hci->mutex);
}

static void hci_acl_write_complete(iotxn_t* txn, void* cookie) {
    hci_t* hci = (hci_t*)cookie;

    // FIXME what to do with error here?
    mtx_lock(&hci->mutex);
    list_add_tail(&hci->free_acl_write_reqs, &txn->node);

    if (hci->snoop_channel) {
        void* buffer;
        iotxn_mmap(txn, &buffer);
        snoop_channel_write_locked(
            hci, BT_HCI_SNOOP_FLAG_DATA | BT_HCI_SNOOP_FLAG_SENT, buffer, txn->actual);
    }

    mtx_unlock(&hci->mutex);
}

static void hci_build_read_wait_items_locked(hci_t* hci) {
    zx_wait_item_t* items = hci->read_wait_items;
    memset(items, 0, sizeof(hci->read_wait_items));
    uint32_t count = 0;

    if (hci->cmd_channel != ZX_HANDLE_INVALID) {
        items[count].handle = hci->cmd_channel;
        items[count].waitfor = ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED;
        count++;
    }

    if (hci->acl_channel != ZX_HANDLE_INVALID) {
        items[count].handle = hci->acl_channel;
        items[count].waitfor = ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED;
        count++;
    }

    hci->read_wait_item_count = count;
}

static void hci_build_read_wait_items(hci_t* hci) {
    mtx_lock(&hci->mutex);
    hci_build_read_wait_items_locked(hci);
    mtx_unlock(&hci->mutex);
}

// Returns false if there's an error while sending the packet to the hardware or
// if the channel peer closed its endpoint.
static bool hci_handle_cmd_read_events(hci_t* hci, zx_wait_item_t* cmd_item) {
    if (cmd_item->pending & (ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED)) {
        uint8_t buf[CMD_BUF_SIZE];
        uint32_t length = sizeof(buf);
        zx_status_t status =
            zx_channel_read(cmd_item->handle, 0, buf, NULL, length, 0, &length, NULL);
        if (status < 0) {
            printf("hci_read_thread: failed to read from command channel %s\n",
                   zx_status_get_string(status));
            goto fail;
        }

        status = usb_control(&hci->usb, USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_DEVICE,
                             0, 0, 0, buf, length, ZX_TIME_INFINITE);
        if (status < 0) {
            printf("hci_read_thread: usb_control failed: %s\n", zx_status_get_string(status));
            goto fail;
        }

        mtx_lock(&hci->mutex);
        snoop_channel_write_locked(hci, BT_HCI_SNOOP_FLAG_SENT, buf, length);
        mtx_unlock(&hci->mutex);
    }

    return true;

fail:
    mtx_lock(&hci->mutex);
    cmd_channel_cleanup_locked(hci);
    mtx_unlock(&hci->mutex);

    return false;
}

static bool hci_handle_acl_read_events(hci_t* hci, zx_wait_item_t* acl_item) {
    if (acl_item->pending & (ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED)) {
        mtx_lock(&hci->mutex);
        list_node_t* node = list_peek_head(&hci->free_acl_write_reqs);
        mtx_unlock(&hci->mutex);

        // We don't have enough iotxn's. Simply punt the channel read until later.
        if (!node) return node;

        uint8_t buf[BT_HCI_MAX_FRAME_SIZE];
        uint32_t length = sizeof(buf);
        zx_status_t status =
            zx_channel_read(acl_item->handle, 0, buf, NULL, length, 0, &length, NULL);
        if (status < 0) {
            printf("hci_read_thread: failed to read from ACL channel %s\n",
                   zx_status_get_string(status));
            goto fail;
        }

        mtx_lock(&hci->mutex);
        node = list_remove_head(&hci->free_acl_write_reqs);
        mtx_unlock(&hci->mutex);

        // At this point if we don't get a free node from |free_acl_write_reqs| that means that
        // they were cleaned up in hci_release(). Just drop the packet.
        if (!node) return true;

        iotxn_t* txn = containerof(node, iotxn_t, node);
        iotxn_copyto(txn, buf, length, 0);
        txn->length = length;
        iotxn_queue(hci->usb_mxdev, txn);
    }

    return true;

fail:
    mtx_lock(&hci->mutex);
    acl_channel_cleanup_locked(hci);
    mtx_unlock(&hci->mutex);

    return false;
}

static int hci_read_thread(void* arg) {
    hci_t* hci = (hci_t*)arg;

    mtx_lock(&hci->mutex);

    if (hci->read_wait_item_count == 0) {
        printf("hci_read_thread: no channels are open - exiting\n");
        mtx_unlock(&hci->mutex);
        goto done;
    }

    mtx_unlock(&hci->mutex);

    while (1) {
        zx_status_t status = zx_object_wait_many(
            hci->read_wait_items, hci->read_wait_item_count, ZX_TIME_INFINITE);
        if (status < 0) {
            printf("hci_read_thread: zx_object_wait_many failed: %s\n",
                   zx_status_get_string(status));
            mtx_lock(&hci->mutex);
            cmd_channel_cleanup_locked(hci);
            acl_channel_cleanup_locked(hci);
            mtx_unlock(&hci->mutex);
            break;
        }

        for (unsigned i = 0; i < NUM_CHANNELS; ++i) {
            mtx_lock(&hci->mutex);
            zx_wait_item_t item = hci->read_wait_items[i];
            mtx_unlock(&hci->mutex);

            zx_handle_t handle = hci->read_wait_items[i].handle;
            if ((handle == hci->cmd_channel && !hci_handle_cmd_read_events(hci, &item)) ||
                (handle == hci->acl_channel && !hci_handle_acl_read_events(hci, &item))) {
                // There was an error while handling the read events. Rebuild the
                // wait items array to see if any channels are still open.
                hci_build_read_wait_items(hci);
                if (hci->read_wait_item_count == 0) {
                    printf("hci_read_thread: all channels closed - exiting\n");
                    goto done;
                }
            }
        }
    }

done:
    mtx_lock(&hci->mutex);
    hci->read_thread_running = false;
    mtx_unlock(&hci->mutex);

    printf("hci_read_thread: exiting\n");

    return 0;
}

static zx_status_t hci_ioctl(void* ctx, uint32_t op, const void* in_buf, size_t in_len,
                            void* out_buf, size_t out_len, size_t* out_actual) {
    ssize_t result = ZX_ERR_NOT_SUPPORTED;
    hci_t* hci = ctx;

    mtx_lock(&hci->mutex);

    if (op == IOCTL_BT_HCI_GET_COMMAND_CHANNEL) {
        zx_handle_t* reply = out_buf;
        if (out_len < sizeof(*reply)) {
            result = ZX_ERR_BUFFER_TOO_SMALL;
            goto done;
        }

        if (hci->cmd_channel != ZX_HANDLE_INVALID) {
            result = ZX_ERR_ALREADY_BOUND;
            goto done;
        }

        zx_handle_t remote_end;
        zx_status_t status = zx_channel_create(0, &hci->cmd_channel, &remote_end);
        if (status < 0) {
            printf("hci_ioctl: Failed to create command channel: %s\n",
                   zx_status_get_string(status));
            result = ZX_ERR_INTERNAL;
            goto done;
        }

        *reply = remote_end;
        *out_actual = sizeof(*reply);
        result = ZX_OK;
    } else if (op == IOCTL_BT_HCI_GET_ACL_DATA_CHANNEL) {
        zx_handle_t* reply = out_buf;
        if (out_len < sizeof(*reply)) {
            result = ZX_ERR_BUFFER_TOO_SMALL;
            goto done;
        }

        if (hci->acl_channel != ZX_HANDLE_INVALID) {
            result = ZX_ERR_ALREADY_BOUND;
            goto done;
        }

        zx_handle_t remote_end;
        zx_status_t status = zx_channel_create(0, &hci->acl_channel, &remote_end);
        if (status < 0) {
            printf("hci_ioctl: Failed to create ACL data channel: %s\n",
                   zx_status_get_string(status));
            result = ZX_ERR_INTERNAL;
            goto done;
        }

        *reply = remote_end;
        *out_actual = sizeof(*reply);
        result = ZX_OK;
    } else if (op == IOCTL_BT_HCI_GET_SNOOP_CHANNEL) {
        zx_handle_t* reply = out_buf;
        if (out_len < sizeof(*reply)) {
            result = ZX_ERR_BUFFER_TOO_SMALL;
            goto done;
        }

        if (hci->snoop_channel != ZX_HANDLE_INVALID) {
            result = ZX_ERR_ALREADY_BOUND;
            goto done;
        }

        zx_handle_t remote_end;
        zx_status_t status = zx_channel_create(0, &hci->snoop_channel, &remote_end);
        if (status < 0) {
            printf("hci_ioctl: Failed to create snoop channel: %s\n",
                   zx_status_get_string(status));
            result = ZX_ERR_INTERNAL;
            goto done;
        }

        *reply = remote_end;
        *out_actual = sizeof(*reply);
        result = ZX_OK;
    }

    hci_build_read_wait_items_locked(hci);

    // Kick off the hci_read_thread if it's not already running.
    if (result == ZX_OK && !hci->read_thread_running) {
        thrd_t read_thread;
        thrd_create_with_name(&read_thread, hci_read_thread, hci, "hci_read_thread");
        hci->read_thread_running = true;
        thrd_detach(read_thread);
    }

done:
    mtx_unlock(&hci->mutex);
    return result;
}

static void hci_unbind(void* ctx) {
    hci_t* hci = ctx;

    // Close the transport channels so that the host stack is notified of device removal.
    mtx_lock(&hci->mutex);

    cmd_channel_cleanup_locked(hci);
    acl_channel_cleanup_locked(hci);
    snoop_channel_cleanup_locked(hci);

    mtx_unlock(&hci->mutex);

    device_remove(hci->mxdev);
}

static void hci_release(void* ctx) {
    hci_t* hci = ctx;

    mtx_lock(&hci->mutex);

    iotxn_t* txn;
    while ((txn = list_remove_head_type(&hci->free_event_reqs, iotxn_t, node)) != NULL) {
        iotxn_release(txn);
    }
    while ((txn = list_remove_head_type(&hci->free_acl_read_reqs, iotxn_t, node)) != NULL) {
        iotxn_release(txn);
    }
    while ((txn = list_remove_head_type(&hci->free_acl_write_reqs, iotxn_t, node)) != NULL) {
        iotxn_release(txn);
    }

    mtx_unlock(&hci->mutex);

    free(hci);
}

static zx_protocol_device_t hci_device_proto = {
    .version = DEVICE_OPS_VERSION,
    .ioctl = hci_ioctl,
    .unbind = hci_unbind,
    .release = hci_release,
};

static zx_status_t hci_bind(void* ctx, zx_device_t* device, void** cookie) {
    usb_protocol_t usb;

    zx_status_t status = device_get_protocol(device, ZX_PROTOCOL_USB, &usb);
    if (status != ZX_OK) {
        return status;
    }

    // find our endpoints
    usb_desc_iter_t iter;
    zx_status_t result = usb_desc_iter_init(&usb, &iter);
    if (result < 0) return result;

    usb_interface_descriptor_t* intf = usb_desc_iter_next_interface(&iter, true);
    if (!intf || intf->bNumEndpoints != 3) {
        usb_desc_iter_release(&iter);
        return ZX_ERR_NOT_SUPPORTED;
    }

    uint8_t bulk_in_addr = 0;
    uint8_t bulk_out_addr = 0;
    uint8_t intr_addr = 0;
    uint16_t intr_max_packet = 0;

    usb_endpoint_descriptor_t* endp = usb_desc_iter_next_endpoint(&iter);
    while (endp) {
        if (usb_ep_direction(endp) == USB_ENDPOINT_OUT) {
            if (usb_ep_type(endp) == USB_ENDPOINT_BULK) {
                bulk_out_addr = endp->bEndpointAddress;
            }
        } else {
            if (usb_ep_type(endp) == USB_ENDPOINT_BULK) {
                bulk_in_addr = endp->bEndpointAddress;
            } else if (usb_ep_type(endp) == USB_ENDPOINT_INTERRUPT) {
                intr_addr = endp->bEndpointAddress;
                intr_max_packet = usb_ep_max_packet(endp);
            }
        }
        endp = usb_desc_iter_next_endpoint(&iter);
    }
    usb_desc_iter_release(&iter);

    if (!bulk_in_addr || !bulk_out_addr || !intr_addr) {
        printf("hci_bind could not find endpoints\n");
        return ZX_ERR_NOT_SUPPORTED;
    }

    hci_t* hci = calloc(1, sizeof(hci_t));
    if (!hci) {
        printf("Not enough memory for hci_t\n");
        return ZX_ERR_NO_MEMORY;
    }

    list_initialize(&hci->free_event_reqs);
    list_initialize(&hci->free_acl_read_reqs);
    list_initialize(&hci->free_acl_write_reqs);

    mtx_init(&hci->mutex, mtx_plain);

    hci->usb_mxdev = device;
    memcpy(&hci->usb, &usb, sizeof(hci->usb));

    for (int i = 0; i < EVENT_REQ_COUNT; i++) {
        iotxn_t* txn = usb_alloc_iotxn(intr_addr, intr_max_packet);
        if (!txn) {
            status = ZX_ERR_NO_MEMORY;
            goto fail;
        }
        txn->length = intr_max_packet;
        txn->complete_cb = hci_event_complete;
        txn->cookie = hci;
        list_add_head(&hci->free_event_reqs, &txn->node);
    }
    for (int i = 0; i < ACL_READ_REQ_COUNT; i++) {
        iotxn_t* txn = usb_alloc_iotxn(bulk_in_addr, BT_HCI_MAX_FRAME_SIZE);
        if (!txn) {
            status = ZX_ERR_NO_MEMORY;
            goto fail;
        }
        txn->length = BT_HCI_MAX_FRAME_SIZE;
        txn->complete_cb = hci_acl_read_complete;
        txn->cookie = hci;
        list_add_head(&hci->free_acl_read_reqs, &txn->node);
    }
    for (int i = 0; i < ACL_WRITE_REQ_COUNT; i++) {
        iotxn_t* txn = usb_alloc_iotxn(bulk_out_addr, BT_HCI_MAX_FRAME_SIZE);
        if (!txn) {
            status = ZX_ERR_NO_MEMORY;
            goto fail;
        }
        txn->length = BT_HCI_MAX_FRAME_SIZE;
        txn->complete_cb = hci_acl_write_complete;
        txn->cookie = hci;
        list_add_head(&hci->free_acl_write_reqs, &txn->node);
    }

    mtx_lock(&hci->mutex);
    queue_interrupt_requests_locked(hci);
    queue_acl_read_requests_locked(hci);
    mtx_unlock(&hci->mutex);

    device_add_args_t args = {
        .version = DEVICE_ADD_ARGS_VERSION,
        .name = "usb_bt_hci",
        .ctx = hci,
        .ops = &hci_device_proto,
        .proto_id = ZX_PROTOCOL_BLUETOOTH_HCI,
    };

    status = device_add(device, &args, &hci->mxdev);
    if (status == ZX_OK) return ZX_OK;

fail:
    printf("hci_bind failed: %s\n", zx_status_get_string(status));
    hci_release(hci);
    return status;
}

static zx_driver_ops_t usb_bt_hci_driver_ops = {
    .version = DRIVER_OPS_VERSION,
    .bind = hci_bind,
};

ZIRCON_DRIVER_BEGIN(usb_bt_hci, usb_bt_hci_driver_ops, "zircon", "0.1", 4)
    BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_USB),
#if defined(USB_VID) && defined(USB_PID)
    BI_ABORT_IF(NE, BIND_USB_VID, USB_VID),
    BI_MATCH_IF(EQ, BIND_USB_PID, USB_PID),
    BI_ABORT(),
#else
    BI_ABORT_IF(NE, BIND_USB_CLASS, 224),
    BI_ABORT_IF(NE, BIND_USB_SUBCLASS, 1),
    BI_MATCH_IF(EQ, BIND_USB_PROTOCOL, 1),
#endif
ZIRCON_DRIVER_END(usb_bt_hci)
