1// Copyright 2017 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#pragma once
6
7#include <inttypes.h>
8#include <ddk/device.h>
9#include <ddk/protocol/block.h>
10#include <ddk/protocol/usb.h>
11#include <lib/sync/completion.h>
12#include <zircon/device/block.h>
13#include <zircon/listnode.h>
14
15#include <threads.h>
16
17// struct representing a block device for a logical unit
18typedef struct {
19    zx_device_t* zxdev;         // block device we publish
20
21    uint64_t total_blocks;
22    uint32_t block_size;
23
24    uint8_t lun;                // our logical unit number
25    uint32_t flags;             // flags for block_info_t
26    bool device_added;
27} ums_block_t;
28
29// main struct for the UMS driver
30typedef struct {
31    zx_device_t* zxdev;         // root device we publish
32    zx_device_t* usb_zxdev;     // USB device we are bound to
33    usb_protocol_t usb;
34
35    uint32_t tag_send;          // next tag to send in CBW
36    uint32_t tag_receive;       // next tag we expect to receive in CSW
37
38    uint8_t max_lun;            // index of last logical unit
39    size_t max_transfer;        // maximum transfer size reported by usb_get_max_transfer_size()
40
41    uint8_t interface_number;
42    uint8_t bulk_in_addr;
43    uint8_t bulk_out_addr;
44    size_t bulk_in_max_packet;
45    size_t bulk_out_max_packet;
46
47    usb_request_t* cbw_req;
48    usb_request_t* data_req;
49    usb_request_t* csw_req;
50
51    usb_request_t data_transfer_req;  // for use in ums_data_transfer
52
53    thrd_t worker_thread;
54    bool dead;
55
56    // list of queued transactions
57    list_node_t queued_txns;
58
59    sync_completion_t txn_completion;    // signals ums_worker_thread when new txns are available
60                                    // and when device is dead
61    mtx_t txn_lock;                 // protects queued_txns, txn_completion and dead
62
63    ums_block_t block_devs[];
64} ums_t;
65#define block_to_ums(block) containerof(block - block->lun, ums_t, block_devs)
66
67typedef struct ums_txn {
68    block_op_t op;
69    list_node_t node;
70    ums_block_t* dev;
71} ums_txn_t;
72#define block_op_to_txn(op) containerof(op, ums_txn_t, op)
73
74zx_status_t ums_block_add_device(ums_t* ums, ums_block_t* dev);
75