// 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 <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <threads.h>
#include <unistd.h>
#include <zircon/device/bt-hci.h>
#include <zircon/listnode.h>
#include <zircon/status.h>
#include <zircon/syscalls/port.h>

#include <ddk/binding.h>
#include <ddk/debug.h>
#include <ddk/device.h>
#include <ddk/driver.h>
#include <ddk/protocol/bt/hci.h>
#include <ddk/protocol/usb.h>
#include <usb/usb-request.h>
#include <usb/usb.h>

#define EVENT_REQ_COUNT 8

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

// The maximum HCI ACL frame size used for data transactions
#define ACL_MAX_FRAME_SIZE 1028  // (1024 + 4 bytes for the ACL header)

#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

#define NUM_WAIT_ITEMS NUM_CHANNELS + 1  // add one item for the changed event

// TODO(jamuraa): move these to hw/usb.h (or hw/bluetooth.h if that exists)
#define USB_SUBCLASS_BLUETOOTH 1
#define USB_PROTOCOL_BLUETOOTH 1

typedef struct {
  zx_device_t* zxdev;
  zx_device_t* usb_zxdev;
  usb_protocol_t usb;

  zx_handle_t cmd_channel;
  zx_handle_t acl_channel;
  zx_handle_t snoop_channel;

  // Port to queue PEER_CLOSED signals on
  zx_handle_t snoop_watch;

  // Signaled when a channel opens or closes
  zx_handle_t channels_changed_evt;

  zx_wait_item_t read_wait_items[NUM_WAIT_ITEMS];
  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;
  size_t parent_req_size;
} hci_t;

static void hci_event_complete(void* ctx, usb_request_t* req);
static void hci_acl_read_complete(void* ctx, usb_request_t* req);

static void queue_acl_read_requests_locked(hci_t* hci) {
  usb_request_t* req = NULL;
  usb_request_complete_t complete = {
      .callback = hci_acl_read_complete,
      .ctx = hci,
  };
  while ((req = usb_req_list_remove_head(&hci->free_acl_read_reqs, hci->parent_req_size)) != NULL) {
    usb_request_queue(&hci->usb, req, &complete);
  }
}

static void queue_interrupt_requests_locked(hci_t* hci) {
  usb_request_t* req = NULL;
  usb_request_complete_t complete = {
      .callback = hci_event_complete,
      .ctx = hci,
  };
  while ((req = usb_req_list_remove_head(&hci->free_event_reqs, hci->parent_req_size)) != NULL) {
    usb_request_queue(&hci->usb, req, &complete);
  }
}

static void channel_cleanup_locked(hci_t* hci, zx_handle_t* channel) {
  if (*channel == ZX_HANDLE_INVALID)
    return;

  zx_handle_close(*channel);
  *channel = ZX_HANDLE_INVALID;
  zx_object_signal(hci->channels_changed_evt, 0, ZX_EVENT_SIGNALED);
}

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) {
    if (status != ZX_ERR_PEER_CLOSED) {
      zxlogf(ERROR, "bt-transport-usb: failed to write to snoop channel: %s\n",
             zx_status_get_string(status));
    }
    channel_cleanup_locked(hci, &hci->snoop_channel);
  }
}

static void hci_event_complete(void* ctx, usb_request_t* req) {
  hci_t* hci = (hci_t*)ctx;
  zxlogf(SPEW, "bt-transport-usb: Event received\n");
  mtx_lock(&hci->mutex);
  zx_status_t status;

  // 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 (req->response.status == ZX_OK) {
    uint8_t* buffer;
    zx_status_t status = usb_request_mmap(req, (void*)&buffer);
    if (status != ZX_OK) {
      zxlogf(ERROR, "bt-transport-usb: usb_req_mmap failed: %s\n", zx_status_get_string(status));
      goto out2;
    }
    size_t length = req->response.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) {
            zxlogf(ERROR, "bt-transport-usb: hci_event_complete failed to write: %s\n",
                   zx_status_get_string(status));
          }
        }
        snoop_channel_write_locked(hci, bt_hci_snoop_flags(BT_HCI_SNOOP_TYPE_EVT, true), buffer,
                                   length);
        goto out;
      }
    }

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

    if (hci->event_buffer_offset + length > sizeof(hci->event_buffer)) {
      zxlogf(ERROR, "bt-transport-usb: 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) {
        zxlogf(ERROR, "bt-transport-usb: failed to write: %s\n", zx_status_get_string(status));
      }

      snoop_channel_write_locked(hci, bt_hci_snoop_flags(BT_HCI_SNOOP_TYPE_EVT, true),
                                 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:
  status = usb_req_list_add_head(&hci->free_event_reqs, req, hci->parent_req_size);
  ZX_DEBUG_ASSERT(status == ZX_OK);
  queue_interrupt_requests_locked(hci);
out2:
  mtx_unlock(&hci->mutex);
}

static void hci_acl_read_complete(void* ctx, usb_request_t* req) {
  hci_t* hci = (hci_t*)ctx;
  zxlogf(SPEW, "bt-transport-usb: ACL frame received\n");
  mtx_lock(&hci->mutex);

  if (req->response.status == ZX_OK) {
    void* buffer;
    zx_status_t status = usb_request_mmap(req, &buffer);
    if (status != ZX_OK) {
      zxlogf(ERROR, "bt-transport-usb: usb_req_mmap failed: %s\n", zx_status_get_string(status));
      mtx_unlock(&hci->mutex);
      return;
    }

    if (hci->acl_channel == ZX_HANDLE_INVALID) {
      zxlogf(ERROR, "bt-transport-usb: ACL data received while channel is closed");
    } else {
      status = zx_channel_write(hci->acl_channel, 0, buffer, req->response.actual, NULL, 0);
      if (status < 0) {
        zxlogf(ERROR, "bt-transport-usb: 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_flags(BT_HCI_SNOOP_TYPE_ACL, true), buffer,
                               req->response.actual);
  }

  zx_status_t status = usb_req_list_add_head(&hci->free_acl_read_reqs, req, hci->parent_req_size);
  ZX_DEBUG_ASSERT(status == ZX_OK);
  queue_acl_read_requests_locked(hci);

  mtx_unlock(&hci->mutex);
}

static void hci_acl_write_complete(void* ctx, usb_request_t* req) {
  hci_t* hci = (hci_t*)ctx;

  // FIXME what to do with error here?
  mtx_lock(&hci->mutex);
  zx_status_t status = usb_req_list_add_tail(&hci->free_acl_write_reqs, req, hci->parent_req_size);
  ZX_DEBUG_ASSERT(status == ZX_OK);

  if (hci->snoop_channel) {
    void* buffer;
    zx_status_t status = usb_request_mmap(req, &buffer);
    if (status != ZX_OK) {
      zxlogf(ERROR, "bt-transport-usb: usb_req_mmap failed: %s\n", zx_status_get_string(status));
      mtx_unlock(&hci->mutex);
      return;
    }

    snoop_channel_write_locked(hci, bt_hci_snoop_flags(BT_HCI_SNOOP_TYPE_ACL, false), buffer,
                               req->response.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++;
  }

  items[count].handle = hci->channels_changed_evt;
  items[count].waitfor = ZX_EVENT_SIGNALED;
  count++;

  hci->read_wait_item_count = count;

  zx_object_signal(hci->channels_changed_evt, ZX_EVENT_SIGNALED, 0);
}

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 void 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) {
      zxlogf(ERROR, "hci_read_thread: failed to read from command channel %s\n",
             zx_status_get_string(status));
      goto fail;
    }

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

    mtx_lock(&hci->mutex);
    snoop_channel_write_locked(hci, bt_hci_snoop_flags(BT_HCI_SNOOP_TYPE_CMD, false), buf, length);
    mtx_unlock(&hci->mutex);
  }

  return;

fail:
  mtx_lock(&hci->mutex);
  channel_cleanup_locked(hci, &hci->cmd_channel);
  mtx_unlock(&hci->mutex);
}

static void 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 reqs. Simply punt the channel read until later.
    if (!node)
      return;

    uint8_t buf[ACL_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) {
      zxlogf(ERROR, "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;

    usb_req_internal_t* req_int = containerof(node, usb_req_internal_t, node);
    usb_request_t* req = REQ_INTERNAL_TO_USB_REQ(req_int, hci->parent_req_size);
    usb_request_copy_to(req, buf, length, 0);
    req->header.length = length;
    usb_request_complete_t complete = {
        .callback = hci_acl_write_complete,
        .ctx = hci,
    };
    usb_request_queue(&hci->usb, req, &complete);
  }

  return;

fail:
  mtx_lock(&hci->mutex);
  channel_cleanup_locked(hci, &hci->acl_channel);
  mtx_unlock(&hci->mutex);
}

static bool hci_has_read_channels_locked(hci_t* hci) {
  // One for the signal event, any additional are read channels.
  return hci->read_wait_item_count > 1;
}

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

  mtx_lock(&hci->mutex);

  if (!hci_has_read_channels_locked(hci)) {
    zxlogf(ERROR, "bt-transport-usb: no channels are open - exiting\n");
    hci->read_thread_running = false;
    mtx_unlock(&hci->mutex);
    return 0;
  }

  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) {
      zxlogf(ERROR, "bt-transport-usb: zx_object_wait_many failed (%s) - exiting\n",
             zx_status_get_string(status));
      mtx_lock(&hci->mutex);
      channel_cleanup_locked(hci, &hci->cmd_channel);
      channel_cleanup_locked(hci, &hci->acl_channel);
      mtx_unlock(&hci->mutex);
      break;
    }

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

      if (item.handle == hci->cmd_channel) {
        hci_handle_cmd_read_events(hci, &item);
      } else if (item.handle == hci->acl_channel) {
        hci_handle_acl_read_events(hci, &item);
      }
    }

    // The channels might have been changed by the *_read_events, recheck the event.
    status = zx_object_wait_one(hci->channels_changed_evt, ZX_EVENT_SIGNALED, 0u, NULL);
    if (status == ZX_OK) {
      hci_build_read_wait_items(hci);
      if (!hci_has_read_channels_locked(hci)) {
        zxlogf(ERROR, "bt-transport-usb: all channels closed - exiting\n");
        break;
      }
    }
  }

  mtx_lock(&hci->mutex);
  hci->read_thread_running = false;
  mtx_unlock(&hci->mutex);
  return 0;
}

static zx_status_t hci_open_channel(hci_t* hci, zx_handle_t* in_channel, zx_handle_t in) {
  zx_status_t result = ZX_OK;
  mtx_lock(&hci->mutex);

  if (*in_channel != ZX_HANDLE_INVALID) {
    zxlogf(ERROR, "bt-transport-usb: already bound, failing\n");
    result = ZX_ERR_ALREADY_BOUND;
    goto done;
  }

  *in_channel = in;

  // Kick off the hci_read_thread if it's not already running.
  if (!hci->read_thread_running) {
    hci_build_read_wait_items_locked(hci);
    thrd_t read_thread;
    thrd_create_with_name(&read_thread, hci_read_thread, hci, "bt_usb_read_thread");
    hci->read_thread_running = true;
    thrd_detach(read_thread);
  } else {
    // Poke the changed event to get the new channel.
    zx_object_signal(hci->channels_changed_evt, 0, ZX_EVENT_SIGNALED);
  }

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);

  channel_cleanup_locked(hci, &hci->cmd_channel);
  channel_cleanup_locked(hci, &hci->acl_channel);
  channel_cleanup_locked(hci, &hci->snoop_channel);

  mtx_unlock(&hci->mutex);

  device_remove(hci->zxdev);
}

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

  mtx_lock(&hci->mutex);

  usb_request_t* req;
  while ((req = usb_req_list_remove_head(&hci->free_event_reqs, hci->parent_req_size)) != NULL) {
    usb_request_release(req);
  }
  while ((req = usb_req_list_remove_head(&hci->free_acl_read_reqs, hci->parent_req_size)) != NULL) {
    usb_request_release(req);
  }
  while ((req = usb_req_list_remove_head(&hci->free_acl_write_reqs, hci->parent_req_size)) !=
         NULL) {
    usb_request_release(req);
  }

  mtx_unlock(&hci->mutex);

  free(hci);
}

static zx_status_t hci_open_command_channel(void* ctx, zx_handle_t in) {
  hci_t* hci = ctx;
  return hci_open_channel(hci, &hci->cmd_channel, in);
}

static zx_status_t hci_open_acl_data_channel(void* ctx, zx_handle_t in) {
  hci_t* hci = ctx;
  return hci_open_channel(hci, &hci->acl_channel, in);
}

static zx_status_t hci_open_snoop_channel(void* ctx, zx_handle_t in) {
  hci_t* hci = ctx;

  if (hci->snoop_watch == ZX_HANDLE_INVALID) {
    zx_status_t status = zx_port_create(0, &hci->snoop_watch);
    if (status != ZX_OK) {
      zxlogf(ERROR,
             "bt-transport-usb: failed to create a port to watch snoop channel: "
             "%s\n",
             zx_status_get_string(status));
      return status;
    }
  }

  zx_port_packet_t packet;
  zx_status_t status = zx_port_wait(hci->snoop_watch, 0, &packet);
  if (status == ZX_ERR_TIMED_OUT) {
    zxlogf(ERROR, "bt-transport-usb: timed out: %s\n", zx_status_get_string(status));
  } else if (packet.signal.observed & ZX_CHANNEL_PEER_CLOSED) {
    hci->snoop_channel = ZX_HANDLE_INVALID;
  }

  zx_status_t ret = hci_open_channel(hci, &hci->snoop_channel, in);
  if (ret == ZX_OK) {
    zx_signals_t sigs = ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED;
    zx_object_wait_async(hci->snoop_channel, hci->snoop_watch, 0, sigs, ZX_WAIT_ASYNC_ONCE);
  }
  return ret;
}

static bt_hci_protocol_ops_t hci_protocol_ops = {
    .open_command_channel = hci_open_command_channel,
    .open_acl_data_channel = hci_open_acl_data_channel,
    .open_snoop_channel = hci_open_snoop_channel,
};

static zx_status_t hci_get_protocol(void* ctx, uint32_t proto_id, void* protocol) {
  hci_t* hci = ctx;
  if (proto_id != ZX_PROTOCOL_BT_HCI) {
    // Pass this on for drivers to load firmware / initialize
    return device_get_protocol(hci->usb_zxdev, proto_id, protocol);
  }

  bt_hci_protocol_t* hci_proto = protocol;

  hci_proto->ops = &hci_protocol_ops;
  hci_proto->ctx = ctx;
  return ZX_OK;
};

static zx_protocol_device_t hci_device_proto = {
    .version = DEVICE_OPS_VERSION,
    .get_protocol = hci_get_protocol,
    .unbind = hci_unbind,
    .release = hci_release,
};

static zx_status_t hci_bind(void* ctx, zx_device_t* device) {
  zxlogf(TRACE, "hci_bind\n");
  usb_protocol_t usb;

  zx_status_t status = device_get_protocol(device, ZX_PROTOCOL_USB, &usb);
  if (status != ZX_OK) {
    zxlogf(ERROR, "bt-transport-usb: get protocol failed: %s\n", zx_status_get_string(status));
    return status;
  }

  // find our endpoints
  usb_desc_iter_t iter;
  zx_status_t result = usb_desc_iter_init(&usb, &iter);
  if (result < 0) {
    zxlogf(ERROR, "bt-transport-usb: usb iterator failed: %s\n", zx_status_get_string(status));
    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) {
    zxlogf(ERROR, "bt-transport-usb: bind could not find endpoints\n");
    return ZX_ERR_NOT_SUPPORTED;
  }

  hci_t* hci = calloc(1, sizeof(hci_t));
  if (!hci) {
    zxlogf(ERROR, "bt-transport-usb: 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);

  zx_event_create(0, &hci->channels_changed_evt);

  mtx_init(&hci->mutex, mtx_plain);

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

  hci->parent_req_size = usb_get_request_size(&hci->usb);
  size_t req_size = hci->parent_req_size + sizeof(usb_req_internal_t);
  for (int i = 0; i < EVENT_REQ_COUNT; i++) {
    usb_request_t* req;
    status = usb_request_alloc(&req, intr_max_packet, intr_addr, req_size);
    if (status != ZX_OK) {
      goto fail;
    }
    status = usb_req_list_add_head(&hci->free_event_reqs, req, hci->parent_req_size);
    ZX_DEBUG_ASSERT(status == ZX_OK);
  }
  for (int i = 0; i < ACL_READ_REQ_COUNT; i++) {
    usb_request_t* req;
    status = usb_request_alloc(&req, ACL_MAX_FRAME_SIZE, bulk_in_addr, req_size);
    if (status != ZX_OK) {
      goto fail;
    }
    status = usb_req_list_add_head(&hci->free_acl_read_reqs, req, hci->parent_req_size);
    ZX_DEBUG_ASSERT(status == ZX_OK);
  }
  for (int i = 0; i < ACL_WRITE_REQ_COUNT; i++) {
    usb_request_t* req;
    status = usb_request_alloc(&req, ACL_MAX_FRAME_SIZE, bulk_out_addr, req_size);
    if (status != ZX_OK) {
      goto fail;
    }
    status = usb_req_list_add_head(&hci->free_acl_write_reqs, req, hci->parent_req_size);
    ZX_DEBUG_ASSERT(status == ZX_OK);
  }

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

  // Copy the PID and VID from the underlying BT so that it can be filtered on
  // for HCI drivers
  usb_device_descriptor_t dev_desc;
  usb_get_device_descriptor(&usb, &dev_desc);
  zx_device_prop_t props[] = {
      {BIND_PROTOCOL, 0, ZX_PROTOCOL_BT_TRANSPORT},
      {BIND_USB_VID, 0, dev_desc.idVendor},
      {BIND_USB_PID, 0, dev_desc.idProduct},
  };

  device_add_args_t args = {
      .version = DEVICE_ADD_ARGS_VERSION,
      .name = "bt_transport_usb",
      .ctx = hci,
      .ops = &hci_device_proto,
      .proto_id = ZX_PROTOCOL_BT_TRANSPORT,
      .props = props,
      .prop_count = countof(props),
  };

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

fail:
  zxlogf(ERROR, "bt-transport-usb: 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,
};

// clang-format off
ZIRCON_DRIVER_BEGIN(bt_transport_usb, usb_bt_hci_driver_ops, "zircon", "0.1", 4)
    BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_USB),
    BI_ABORT_IF(NE, BIND_USB_CLASS, USB_CLASS_WIRELESS),
    BI_ABORT_IF(NE, BIND_USB_SUBCLASS, USB_SUBCLASS_BLUETOOTH),
    BI_MATCH_IF(EQ, BIND_USB_PROTOCOL, USB_PROTOCOL_BLUETOOTH),
ZIRCON_DRIVER_END(bt_transport_usb)
