
// Copyright 2017 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 <fuchsia/hardware/usb/function/c/banjo.h>
#include <fuchsia/hardware/usb/peripheral/block/c/fidl.h>
#include <lib/ddk/debug.h>
#include <lib/ddk/device.h>
#include <lib/ddk/driver.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <zircon/device/usb-peripheral.h>
#include <zircon/hw/usb/ums.h>
#include <zircon/process.h>
#include <zircon/syscalls.h>

#include <usb/usb-request.h>

#include "src/devices/block/drivers/ums-function/usb_ums_bind.h"

#define BLOCK_SIZE 512L
#define STORAGE_SIZE (4L * 1024L * 1024L * 1024L)
#define BLOCK_COUNT (STORAGE_SIZE / BLOCK_SIZE)
#define DATA_REQ_SIZE 16384
#define BULK_MAX_PACKET 512

typedef enum {
  DATA_STATE_NONE,
  DATA_STATE_READ,
  DATA_STATE_WRITE,
  DATA_STATE_FAILED
} ums_data_state_t;

static struct {
  usb_interface_descriptor_t intf;
  usb_endpoint_descriptor_t out_ep;
  usb_endpoint_descriptor_t in_ep;
} descriptors = {
    .intf =
        {
            .b_length = sizeof(usb_interface_descriptor_t),
            .b_descriptor_type = USB_DT_INTERFACE,
            //      .b_interface_number set later
            .b_alternate_setting = 0,
            .b_num_endpoints = 2,
            .b_interface_class = USB_CLASS_MSC,
            .b_interface_sub_class = USB_SUBCLASS_MSC_SCSI,
            .b_interface_protocol = USB_PROTOCOL_MSC_BULK_ONLY,
            .i_interface = 0,
        },
    .out_ep =
        {
            .b_length = sizeof(usb_endpoint_descriptor_t),
            .b_descriptor_type = USB_DT_ENDPOINT,
            //      .b_endpoint_address set later
            .bm_attributes = USB_ENDPOINT_BULK,
            .w_max_packet_size = htole16(BULK_MAX_PACKET),
            .b_interval = 0,
        },
    .in_ep =
        {
            .b_length = sizeof(usb_endpoint_descriptor_t),
            .b_descriptor_type = USB_DT_ENDPOINT,
            //      .b_endpoint_address set later
            .bm_attributes = USB_ENDPOINT_BULK,
            .w_max_packet_size = htole16(BULK_MAX_PACKET),
            .b_interval = 0,
        },
};

typedef struct {
  zx_device_t* zxdev;
  usb_function_protocol_t function;
  usb_request_t* cbw_req;
  bool cbw_req_complete;
  usb_request_t* data_req;
  bool data_req_complete;
  usb_request_t* csw_req;
  bool csw_req_complete;

  // vmo for backing storage
  zx_handle_t storage_handle;
  void* storage;

  // command we are currently handling
  ums_cbw_t current_cbw;
  // data transferred for the current command
  uint32_t data_length;

  // state for data transfers
  ums_data_state_t data_state;
  // state for reads and writes
  zx_off_t data_offset;
  size_t data_remaining;

  uint8_t bulk_out_addr;
  uint8_t bulk_in_addr;
  size_t parent_req_size;
  bool writeback_cache;
  bool writeback_cache_report;
  thrd_t thread;
  bool active;
  cnd_t event;
  mtx_t mtx;
  atomic_int pending_request_count;
} usb_ums_t;

static void ums_cbw_complete(void* ctx, usb_request_t* req);
static void ums_data_complete(void* ctx, usb_request_t* req);
static void ums_csw_complete(void* ctx, usb_request_t* req);

static void usb_request_queue(void* ctx, usb_function_protocol_t* function, usb_request_t* req,
                              const usb_request_complete_t* completion) {
  usb_ums_t* ums = (usb_ums_t*)ctx;
  atomic_fetch_add(&ums->pending_request_count, 1);
  usb_function_request_queue(function, req, completion);
}

static void ums_completion_callback(void* ctx, usb_request_t* req) {
  usb_ums_t* ums = (usb_ums_t*)ctx;
  mtx_lock(&ums->mtx);
  if (req == ums->cbw_req) {
    ums->cbw_req_complete = true;
  } else {
    if (req == ums->data_req) {
      ums->data_req_complete = true;
    } else {
      ums->csw_req_complete = true;
    }
  }
  cnd_signal(&ums->event);
  mtx_unlock(&ums->mtx);
}

static void ums_function_queue_data(usb_ums_t* ums, usb_request_t* req) {
  ums->data_length += req->header.length;
  req->header.ep_address =
      ums->current_cbw.bmCBWFlags & USB_DIR_IN ? ums->bulk_in_addr : ums->bulk_out_addr;
  usb_request_complete_t complete = {
      .callback = ums_completion_callback,
      .ctx = ums,
  };
  usb_request_queue(ums, &ums->function, req, &complete);
}

static void ums_queue_csw(usb_ums_t* ums, uint8_t status) {
  // first queue next cbw so it is ready to go
  usb_request_complete_t cbw_complete = {
      .callback = ums_completion_callback,
      .ctx = ums,
  };
  usb_request_queue(ums, &ums->function, ums->cbw_req, &cbw_complete);

  usb_request_t* req = ums->csw_req;
  ums_csw_t* csw;
  usb_request_mmap(req, (void**)&csw);

  csw->dCSWSignature = htole32(CSW_SIGNATURE);
  csw->dCSWTag = ums->current_cbw.dCBWTag;
  csw->dCSWDataResidue =
      htole32(le32toh(ums->current_cbw.dCBWDataTransferLength) - ums->data_length);
  csw->bmCSWStatus = status;

  req->header.length = sizeof(ums_csw_t);
  usb_request_complete_t csw_complete = {
      .callback = ums_completion_callback,
      .ctx = ums,
  };
  usb_request_queue(ums, &ums->function, ums->csw_req, &csw_complete);
}

static void ums_continue_transfer(usb_ums_t* ums) {
  usb_request_t* req = ums->data_req;

  size_t length = ums->data_remaining;
  if (length > DATA_REQ_SIZE) {
    length = DATA_REQ_SIZE;
  }
  req->header.length = length;

  if (ums->data_state == DATA_STATE_READ) {
    size_t result = usb_request_copy_to(req, ums->storage + ums->data_offset, length, 0);
    ZX_ASSERT(result == length);
    ums_function_queue_data(ums, req);
  } else if (ums->data_state == DATA_STATE_WRITE) {
    ums_function_queue_data(ums, req);
  } else {
    zxlogf(ERROR, "ums_continue_transfer: bad data state %d", ums->data_state);
  }
}

static void ums_start_transfer(usb_ums_t* ums, ums_data_state_t state, uint64_t lba,
                               uint32_t blocks) {
  zx_off_t offset = lba * BLOCK_SIZE;
  size_t length = blocks * BLOCK_SIZE;

  if (offset + length > STORAGE_SIZE) {
    zxlogf(ERROR, "ums_start_transfer: transfer out of range state: %d, lba: %zu blocks: %u", state,
           lba, blocks);
    // TODO(voydanoff) report error to host
    return;
  }

  ums->data_state = state;
  ums->data_offset = offset;
  ums->data_remaining = length;

  ums_continue_transfer(ums);
}

static void ums_handle_inquiry(usb_ums_t* ums, ums_cbw_t* cbw) {
  zxlogf(DEBUG, "ums_handle_inquiry");

  usb_request_t* req = ums->data_req;
  uint8_t* buffer;
  usb_request_mmap(req, (void**)&buffer);
  memset(buffer, 0, UMS_INQUIRY_TRANSFER_LENGTH);
  req->header.length = UMS_INQUIRY_TRANSFER_LENGTH;

  // fill in inquiry result
  buffer[0] = 0;     // Peripheral Device Type: Direct access block device
  buffer[1] = 0x80;  // Removable
  buffer[2] = 6;     // Version SPC-4
  buffer[3] = 0x12;  // Response Data Format
  memcpy(buffer + 8, "Google  ", 8);
  memcpy(buffer + 16, "Zircon UMS      ", 16);
  memcpy(buffer + 32, "1.00", 4);

  ums_function_queue_data(ums, req);
}

static void ums_handle_test_unit_ready(usb_ums_t* ums, ums_cbw_t* cbw) {
  zxlogf(DEBUG, "ums_handle_test_unit_ready");

  // no data phase here. Just return status OK
  ums_queue_csw(ums, CSW_SUCCESS);
}

static void ums_handle_request_sense(usb_ums_t* ums, ums_cbw_t* cbw) {
  zxlogf(DEBUG, "ums_handle_request_sense");

  usb_request_t* req = ums->data_req;
  uint8_t* buffer;
  usb_request_mmap(req, (void**)&buffer);
  memset(buffer, 0, UMS_REQUEST_SENSE_TRANSFER_LENGTH);
  req->header.length = UMS_REQUEST_SENSE_TRANSFER_LENGTH;

  // TODO(voydanoff) This is a hack. Figure out correct values to return here.
  buffer[0] = 0x70;   // Response Code
  buffer[2] = 5;      // Illegal Request
  buffer[7] = 10;     // Additional Sense Length
  buffer[12] = 0x20;  // Additional Sense Code

  ums_function_queue_data(ums, req);
}

static void ums_handle_read_capacity10(usb_ums_t* ums, ums_cbw_t* cbw) {
  zxlogf(DEBUG, "ums_handle_read_capacity10");

  usb_request_t* req = ums->data_req;
  scsi_read_capacity_10_t* data;
  usb_request_mmap(req, (void**)&data);

  uint64_t lba = BLOCK_COUNT - 1;
  if (lba > UINT32_MAX) {
    data->lba = htobe32(UINT32_MAX);
  } else {
    data->lba = htobe32(lba);
  }
  data->block_length = htobe32(BLOCK_SIZE);

  req->header.length = sizeof(*data);
  ums_function_queue_data(ums, req);
}

static void ums_handle_read_capacity16(usb_ums_t* ums, ums_cbw_t* cbw) {
  zxlogf(DEBUG, "ums_handle_read_capacity16");

  usb_request_t* req = ums->data_req;
  scsi_read_capacity_16_t* data;
  usb_request_mmap(req, (void**)&data);
  memset(data, 0, sizeof(*data));

  data->lba = htobe64(BLOCK_COUNT - 1);
  data->block_length = htobe32(BLOCK_SIZE);

  req->header.length = sizeof(*data);
  ums_function_queue_data(ums, req);
}

static void ums_handle_mode_sense6(usb_ums_t* ums, ums_cbw_t* cbw) {
  zxlogf(DEBUG, "ums_handle_mode_sense6");
  scsi_mode_sense_6_command_t command;
  memcpy(&command, cbw->CBWCB, sizeof(command));
  usb_request_t* req = ums->data_req;
  scsi_mode_sense_6_data_t* data;
  usb_request_mmap(req, (void**)&data);
  memset(data, 0, sizeof(*data));
  req->header.length = sizeof(*data);
  if (command.page == 0x3F && ums->writeback_cache_report) {
    // Special request (cache page)
    // 20 byte response.
    ((unsigned char*)data)[6] = 1 << 2;  // Write Cache enable bit
    req->header.length = 20;
  }
  ums_function_queue_data(ums, req);
}

static void ums_handle_read10(usb_ums_t* ums, ums_cbw_t* cbw) {
  zxlogf(DEBUG, "ums_handle_read10");

  scsi_command10_t* command = (scsi_command10_t*)cbw->CBWCB;
  uint64_t lba = be32toh(command->lba);
  uint32_t blocks = ((uint32_t)command->length_hi << 8) | (uint32_t)command->length_lo;
  ums_start_transfer(ums, DATA_STATE_READ, lba, blocks);
}

static void ums_handle_read12(usb_ums_t* ums, ums_cbw_t* cbw) {
  zxlogf(DEBUG, "ums_handle_read12");

  scsi_command12_t* command = (scsi_command12_t*)cbw->CBWCB;
  uint64_t lba = be32toh(command->lba);
  uint32_t blocks = be32toh(command->length);
  ums_start_transfer(ums, DATA_STATE_READ, lba, blocks);
}

static void ums_handle_read16(usb_ums_t* ums, ums_cbw_t* cbw) {
  zxlogf(DEBUG, "ums_handle_read16");

  scsi_command16_t* command = (scsi_command16_t*)cbw->CBWCB;
  uint64_t lba = be64toh(command->lba);
  uint32_t blocks = be32toh(command->length);
  ums_start_transfer(ums, DATA_STATE_READ, lba, blocks);
}

static void ums_handle_write10(usb_ums_t* ums, ums_cbw_t* cbw) {
  zxlogf(DEBUG, "ums_handle_write10");

  scsi_command10_t* command = (scsi_command10_t*)cbw->CBWCB;
  uint64_t lba = be32toh(command->lba);
  uint32_t blocks = ((uint32_t)command->length_hi << 8) | (uint32_t)command->length_lo;
  ums_start_transfer(ums, DATA_STATE_WRITE, lba, blocks);
}

static void ums_handle_write12(usb_ums_t* ums, ums_cbw_t* cbw) {
  zxlogf(DEBUG, "ums_handle_write12");

  scsi_command12_t* command = (scsi_command12_t*)cbw->CBWCB;
  uint64_t lba = be32toh(command->lba);
  uint32_t blocks = be32toh(command->length);
  ums_start_transfer(ums, DATA_STATE_WRITE, lba, blocks);
}

static void ums_handle_write16(usb_ums_t* ums, ums_cbw_t* cbw) {
  zxlogf(DEBUG, "ums_handle_write16");

  scsi_command16_t* command = (scsi_command16_t*)cbw->CBWCB;
  uint64_t lba = be64toh(command->lba);
  uint32_t blocks = be32toh(command->length);
  ums_start_transfer(ums, DATA_STATE_WRITE, lba, blocks);
}

static void ums_handle_cbw(usb_ums_t* ums, ums_cbw_t* cbw) {
  if (le32toh(cbw->dCBWSignature) != CBW_SIGNATURE) {
    zxlogf(ERROR, "ums_handle_cbw: bad dCBWSignature 0x%x", le32toh(cbw->dCBWSignature));
    return;
  }

  // reset data length for computing residue
  ums->data_length = 0;

  // all SCSI commands have opcode in the same place, so using scsi_command6_t works here.
  scsi_command6_t* command = (scsi_command6_t*)cbw->CBWCB;
  switch (command->opcode) {
    case UMS_INQUIRY:
      ums_handle_inquiry(ums, cbw);
      break;
    case UMS_TEST_UNIT_READY:
      ums_handle_test_unit_ready(ums, cbw);
      break;
    case UMS_REQUEST_SENSE:
      ums_handle_request_sense(ums, cbw);
      break;
    case UMS_READ_CAPACITY10:
      ums_handle_read_capacity10(ums, cbw);
      break;
    case UMS_READ_CAPACITY16:
      ums_handle_read_capacity16(ums, cbw);
      break;
    case UMS_MODE_SENSE6:
      ums_handle_mode_sense6(ums, cbw);
      break;
    case UMS_READ10:
      ums_handle_read10(ums, cbw);
      break;
    case UMS_READ12:
      ums_handle_read12(ums, cbw);
      break;
    case UMS_READ16:
      ums_handle_read16(ums, cbw);
      break;
    case UMS_WRITE10:
      ums_handle_write10(ums, cbw);
      break;
    case UMS_WRITE12:
      ums_handle_write12(ums, cbw);
      break;
    case UMS_WRITE16:
      ums_handle_write16(ums, cbw);
      break;
    case UMS_SYNCHRONIZE_CACHE:
      // TODO: This is presently untestable.
      // Implement this once we have a means of testing this.
      break;
    default:
      zxlogf(DEBUG, "ums_handle_cbw: unsupported opcode %d", command->opcode);
      if (cbw->dCBWDataTransferLength) {
        // queue zero length packet to satisfy data phase
        usb_request_t* req = ums->data_req;
        req->header.length = 0;
        ums->data_state = DATA_STATE_FAILED;
        ums_function_queue_data(ums, req);
      }
      ums_queue_csw(ums, CSW_FAILED);
      break;
  }
}

static void ums_cbw_complete(void* ctx, usb_request_t* req) {
  usb_ums_t* ums = ctx;

  zxlogf(DEBUG, "ums_cbw_complete %d %ld", req->response.status, req->response.actual);

  if (req->response.status == ZX_OK && req->response.actual == sizeof(ums_cbw_t)) {
    ums_cbw_t* cbw = &ums->current_cbw;
    memset(cbw, 0, sizeof(*cbw));
    __UNUSED size_t result = usb_request_copy_from(req, cbw, sizeof(*cbw), 0);
    ums_handle_cbw(ums, cbw);
  }
}

static void ums_data_complete(void* ctx, usb_request_t* req) {
  usb_ums_t* ums = ctx;

  zxlogf(DEBUG, "ums_data_complete %d %ld", req->response.status, req->response.actual);

  if (ums->data_state == DATA_STATE_WRITE) {
    size_t result =
        usb_request_copy_from(req, ums->storage + ums->data_offset, req->response.actual, 0);
    ZX_ASSERT(result == req->response.actual);
  } else if (ums->data_state == DATA_STATE_FAILED) {
    ums->data_state = DATA_STATE_NONE;
    ums_queue_csw(ums, CSW_FAILED);
    return;
  } else {
    ums->data_state = DATA_STATE_NONE;
    ums_queue_csw(ums, CSW_SUCCESS);
    return;
  }

  ums->data_offset += req->response.actual;
  if (ums->data_remaining > req->response.actual) {
    ums->data_remaining -= req->response.actual;
  } else {
    ums->data_remaining = 0;
  }

  if (ums->data_remaining > 0) {
    ums_continue_transfer(ums);
  } else {
    ums->data_state = DATA_STATE_NONE;
    ums_queue_csw(ums, CSW_SUCCESS);
  }
}

static void ums_csw_complete(void* ctx, usb_request_t* req) {
  zxlogf(DEBUG, "ums_csw_complete %d %ld", req->response.status, req->response.actual);
}

static size_t ums_get_descriptors_size(void* ctx) { return sizeof(descriptors); }

static void ums_get_descriptors(void* ctx, uint8_t* buffer, size_t buffer_size,
                                size_t* out_actual) {
  size_t length = sizeof(descriptors);
  if (length > buffer_size) {
    length = buffer_size;
  }
  memcpy(buffer, &descriptors, length);
  *out_actual = length;
}

static zx_status_t ums_control(void* ctx, const usb_setup_t* setup, const uint8_t* write_buffer,
                               size_t write_size, uint8_t* out_read_buffer, size_t read_size,
                               size_t* out_read_actual) {
  if (setup->bm_request_type == (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) &&
      setup->b_request == USB_REQ_GET_MAX_LUN && setup->w_value == 0 && setup->w_index == 0 &&
      setup->w_length >= sizeof(uint8_t)) {
    *((uint8_t*)out_read_buffer) = 0;
    *out_read_actual = sizeof(uint8_t);
    return ZX_OK;
  }

  return ZX_ERR_NOT_SUPPORTED;
}

static zx_status_t ums_set_configured(void* ctx, bool configured, usb_speed_t speed) {
  zxlogf(DEBUG, "ums_set_configured %d %d", configured, speed);
  usb_ums_t* ums = ctx;
  zx_status_t status;

  // TODO(voydanoff) fullspeed and superspeed support
  if (configured) {
    if ((status = usb_function_config_ep(&ums->function, &descriptors.out_ep, NULL)) != ZX_OK ||
        (status = usb_function_config_ep(&ums->function, &descriptors.in_ep, NULL)) != ZX_OK) {
      zxlogf(ERROR, "ums_set_configured: usb_function_config_ep failed");
    }
  } else {
    if ((status = usb_function_disable_ep(&ums->function, ums->bulk_out_addr)) != ZX_OK ||
        (status = usb_function_disable_ep(&ums->function, ums->bulk_in_addr)) != ZX_OK) {
      zxlogf(ERROR, "ums_set_configured: usb_function_disable_ep failed");
    }
  }

  if (configured && status == ZX_OK) {
    // queue first read on OUT endpoint
    usb_request_complete_t cbw_complete = {
        .callback = ums_completion_callback,
        .ctx = ums,
    };
    usb_request_queue(ums, &ums->function, ums->cbw_req, &cbw_complete);
  }
  return status;
}

static zx_status_t ums_set_interface(void* ctx, uint8_t interface, uint8_t alt_setting) {
  return ZX_ERR_NOT_SUPPORTED;
}

usb_function_interface_protocol_ops_t ums_device_ops = {
    .get_descriptors_size = ums_get_descriptors_size,
    .get_descriptors = ums_get_descriptors,
    .control = ums_control,
    .set_configured = ums_set_configured,
    .set_interface = ums_set_interface,
};

static void usb_ums_unbind(void* ctx) {
  zxlogf(DEBUG, "usb_ums_unbind");
  usb_ums_t* ums = ctx;

  usb_function_cancel_all(&ums->function, ums->bulk_out_addr);
  usb_function_cancel_all(&ums->function, ums->bulk_in_addr);
  usb_function_cancel_all(&ums->function, descriptors.intf.b_interface_number);

  mtx_lock(&ums->mtx);
  ums->active = false;
  cnd_signal(&ums->event);
  mtx_unlock(&ums->mtx);
  int retval;
  thrd_join(ums->thread, &retval);
  device_unbind_reply(ums->zxdev);
}

static void usb_ums_release(void* ctx) {
  zxlogf(DEBUG, "usb_ums_release");
  usb_ums_t* ums = ctx;

  if (ums->storage) {
    zx_vmar_unmap(zx_vmar_root_self(), (uintptr_t)ums->storage, STORAGE_SIZE);
  }
  if (ums->cbw_req) {
    usb_request_release(ums->cbw_req);
  }
  if (ums->data_req) {
    usb_request_release(ums->data_req);
  }
  if (ums->cbw_req) {
    usb_request_release(ums->csw_req);
  }
  cnd_destroy(&ums->event);
  mtx_destroy(&ums->mtx);
  free(ums);
}

static zx_status_t usb_ums_enable_writeback_cache(void* ctx, fidl_txn_t* txn) {
  usb_ums_t* ums = (usb_ums_t*)ctx;
  ums->writeback_cache = true;
  return fuchsia_hardware_usb_peripheral_block_DeviceEnableWritebackCache_reply(txn, ZX_OK);
}

static zx_status_t usb_ums_disable_writeback_cache(void* ctx, fidl_txn_t* txn) {
  usb_ums_t* ums = (usb_ums_t*)ctx;
  ums->writeback_cache = false;
  return fuchsia_hardware_usb_peripheral_block_DeviceDisableWritebackCache_reply(txn, ZX_OK);
}

static zx_status_t usb_ums_set_writeback_cache_reported(void* ctx, bool report, fidl_txn_t* txn) {
  usb_ums_t* ums = (usb_ums_t*)ctx;
  ums->writeback_cache_report = report;
  return fuchsia_hardware_usb_peripheral_block_DeviceSetWritebackCacheReported_reply(txn, ZX_OK);
}

fuchsia_hardware_usb_peripheral_block_Device_ops_t usb_cache_proto = {
    .EnableWritebackCache = usb_ums_enable_writeback_cache,
    .DisableWritebackCache = usb_ums_disable_writeback_cache,
    .SetWritebackCacheReported = usb_ums_set_writeback_cache_reported,
};

static zx_status_t usb_ums_message(void* ctx, fidl_incoming_msg_t* msg, fidl_txn_t* txn) {
  return fuchsia_hardware_usb_peripheral_block_Device_dispatch(ctx, txn, msg, &usb_cache_proto);
}

static zx_protocol_device_t usb_ums_proto = {
    .version = DEVICE_OPS_VERSION,
    .unbind = usb_ums_unbind,
    .release = usb_ums_release,
    .message = usb_ums_message,
};
static zx_handle_t vmo = 0;

static int usb_ums_thread(void* ctx) {
  usb_ums_t* ums = (usb_ums_t*)ctx;
  while (1) {
    mtx_lock(&ums->mtx);
    if (!(ums->cbw_req_complete || ums->csw_req_complete || ums->data_req_complete ||
          (!ums->active))) {
      cnd_wait(&ums->event, &ums->mtx);
    }
    mtx_unlock(&ums->mtx);
    if (!ums->active && !atomic_load(&ums->pending_request_count)) {
      return 0;
    }
    if (ums->cbw_req_complete) {
      atomic_fetch_add(&ums->pending_request_count, -1);
      ums->cbw_req_complete = false;
      ums_cbw_complete(ums, ums->cbw_req);
    }
    if (ums->csw_req_complete) {
      atomic_fetch_add(&ums->pending_request_count, -1);
      ums->csw_req_complete = false;
      ums_csw_complete(ums, ums->csw_req);
    }
    if (ums->data_req_complete) {
      atomic_fetch_add(&ums->pending_request_count, -1);
      ums->data_req_complete = false;
      ums_data_complete(ums, ums->data_req);
    }
  }
  return 0;
}

zx_status_t usb_ums_bind(void* ctx, zx_device_t* parent) {
  zxlogf(INFO, "usb_ums_bind");

  usb_ums_t* ums = calloc(1, sizeof(usb_ums_t));
  if (!ums) {
    return ZX_ERR_NO_MEMORY;
  }
  ums->data_state = DATA_STATE_NONE;
  ums->active = true;
  mtx_init(&ums->mtx, 0);
  atomic_init(&ums->pending_request_count, 0);
  cnd_init(&ums->event);
  zx_status_t status = ZX_OK;
  ums->writeback_cache = false;
  ums->writeback_cache_report = false;
  status = device_get_protocol(parent, ZX_PROTOCOL_USB_FUNCTION, &ums->function);
  if (status != ZX_OK) {
    goto fail;
  }

  ums->parent_req_size = usb_function_get_request_size(&ums->function);
  ZX_DEBUG_ASSERT(ums->parent_req_size != 0);

  status = usb_function_alloc_interface(&ums->function, &descriptors.intf.b_interface_number);
  if (status != ZX_OK) {
    zxlogf(ERROR, "usb_ums_bind: usb_function_alloc_interface failed");
    goto fail;
  }
  status = usb_function_alloc_ep(&ums->function, USB_DIR_OUT, &ums->bulk_out_addr);
  if (status != ZX_OK) {
    zxlogf(ERROR, "usb_ums_bind: usb_function_alloc_ep failed");
    goto fail;
  }
  status = usb_function_alloc_ep(&ums->function, USB_DIR_IN, &ums->bulk_in_addr);
  if (status != ZX_OK) {
    zxlogf(ERROR, "usb_ums_bind: usb_function_alloc_ep failed");
    goto fail;
  }
  descriptors.out_ep.b_endpoint_address = ums->bulk_out_addr;
  descriptors.in_ep.b_endpoint_address = ums->bulk_in_addr;

  status =
      usb_request_alloc(&ums->cbw_req, BULK_MAX_PACKET, ums->bulk_out_addr, ums->parent_req_size);
  if (status != ZX_OK) {
    goto fail;
  }
  // Endpoint for data_req depends on current_cbw.bmCBWFlags,
  // and will be set in ums_function_queue_data.
  status = usb_request_alloc(&ums->data_req, DATA_REQ_SIZE, 0, ums->parent_req_size);
  if (status != ZX_OK) {
    goto fail;
  }
  status =
      usb_request_alloc(&ums->csw_req, BULK_MAX_PACKET, ums->bulk_in_addr, ums->parent_req_size);
  if (status != ZX_OK) {
    goto fail;
  }
  // create and map a VMO
  if (!vmo) {
    status = zx_vmo_create(STORAGE_SIZE, 0, &vmo);
    if (status != ZX_OK) {
      goto fail;
    }
  }
  ums->storage_handle = vmo;
  status = zx_vmar_map(zx_vmar_root_self(), ZX_VM_PERM_READ | ZX_VM_PERM_WRITE, 0,
                       ums->storage_handle, 0, STORAGE_SIZE, (zx_vaddr_t*)&ums->storage);
  if (status != ZX_OK) {
    goto fail;
  }

  ums->csw_req->header.length = sizeof(ums_csw_t);

  device_add_args_t args = {
      .version = DEVICE_ADD_ARGS_VERSION,
      .name = "usb-ums-function",
      .ctx = ums,
      .ops = &usb_ums_proto,
  };
  args.proto_id = ZX_PROTOCOL_CACHE_TEST;

  status = device_add(parent, &args, &ums->zxdev);
  if (status != ZX_OK) {
    zxlogf(ERROR, "usb_device_bind add_device failed %d", status);
    goto fail;
  }

  usb_function_set_interface(&ums->function, ums, &ums_device_ops);
  thrd_create_with_name(&ums->thread, usb_ums_thread, ums, "ums_worker");
  return ZX_OK;

fail:
  usb_ums_release(ums);
  return status;
}

static zx_driver_ops_t usb_ums_ops = {
    .version = DRIVER_OPS_VERSION,
    .bind = usb_ums_bind,
};

// clang-format off
ZIRCON_DRIVER(usb_ums, usb_ums_ops, "zircon", "0.1");
