1 /*
2  * Copyright (c) 2022, sakumisu
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #ifndef USB_MSC_H
7 #define USB_MSC_H
8 
9 /* MSC Subclass Codes */
10 #define MSC_SUBCLASS_RBC           0x01 /* Reduced block commands (e.g., flash devices) */
11 #define MSC_SUBCLASS_SFF8020I_MMC2 0x02 /* SFF-8020i/MMC-2 (ATAPI) (e.g., C/DVD) */
12 #define MSC_SUBCLASS_QIC157        0x03 /* QIC-157 (e.g., tape device) */
13 #define MSC_SUBCLASS_UFI           0x04 /* e.g. floppy device */
14 #define MSC_SUBCLASS_SFF8070I      0x05 /* SFF-8070i (e.g. floppy disk) */
15 #define MSC_SUBCLASS_SCSI          0x06 /* SCSI transparent */
16 
17 /* MSC Protocol Codes */
18 #define MSC_PROTOCOL_CBI_INT   0x00 /* CBI transport with command completion interrupt */
19 #define MSC_PROTOCOL_CBI_NOINT 0x01 /* CBI transport without command completion interrupt */
20 #define MSC_PROTOCOL_BULK_ONLY 0x50 /* Bulk only transport */
21 
22 /* MSC Request Codes */
23 #define MSC_REQUEST_RESET       0xFF
24 #define MSC_REQUEST_GET_MAX_LUN 0xFE
25 
26 /** MSC Command Block Wrapper (CBW) Signature */
27 #define MSC_CBW_Signature 0x43425355
28 /** Bulk-only Command Status Wrapper (CSW) Signature */
29 #define MSC_CSW_Signature 0x53425355
30 
31 /** MSC Command Block Status Values */
32 #define CSW_STATUS_CMD_PASSED  0x00
33 #define CSW_STATUS_CMD_FAILED  0x01
34 #define CSW_STATUS_PHASE_ERROR 0x02
35 
36 #define MSC_MAX_CDB_LEN (16) /* Max length of SCSI Command Data Block */
37 
38 /** MSC Bulk-Only Command Block Wrapper (CBW) */
39 struct CBW {
40     uint32_t dSignature;         /* 'USBC' = 0x43425355 */
41     uint32_t dTag;               /* Depends on command id */
42     uint32_t dDataLength;        /* Number of bytes that host expects to transfer */
43     uint8_t bmFlags;             /* Bit 7: Direction=IN (other obsolete or reserved) */
44     uint8_t bLUN;                /* LUN (normally 0) */
45     uint8_t bCBLength;           /* len of cdb[] */
46     uint8_t CB[MSC_MAX_CDB_LEN]; /* Command Data Block */
47 } __PACKED;
48 
49 #define USB_SIZEOF_MSC_CBW 31
50 
51 /** MSC Bulk-Only Command Status Wrapper (CSW) */
52 struct CSW {
53     uint32_t dSignature;   /* 'USBS' = 0x53425355 */
54     uint32_t dTag;         /* Same tag as original command */
55     uint32_t dDataResidue; /* Amount not transferred */
56     uint8_t bStatus;       /* Status of transfer */
57 } __PACKED;
58 
59 #define USB_SIZEOF_MSC_CSW 13
60 
61 /*Length of template descriptor: 23 bytes*/
62 #define MSC_DESCRIPTOR_LEN (9 + 7 + 7)
63 // clang-format off
64 #define MSC_DESCRIPTOR_INIT(bFirstInterface, out_ep, in_ep, wMaxPacketSize, str_idx) \
65     /* Interface */                                              \
66     0x09,                          /* bLength */                 \
67     USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */         \
68     bFirstInterface,               /* bInterfaceNumber */        \
69     0x00,                          /* bAlternateSetting */       \
70     0x02,                          /* bNumEndpoints */           \
71     USB_DEVICE_CLASS_MASS_STORAGE, /* bInterfaceClass */         \
72     MSC_SUBCLASS_SCSI,             /* bInterfaceSubClass */      \
73     MSC_PROTOCOL_BULK_ONLY,        /* bInterfaceProtocol */      \
74     str_idx,                       /* iInterface */              \
75     0x07,                          /* bLength */                 \
76     USB_DESCRIPTOR_TYPE_ENDPOINT,  /* bDescriptorType */         \
77     out_ep,                        /* bEndpointAddress */        \
78     0x02,                          /* bmAttributes */            \
79     WBVAL(wMaxPacketSize),         /* wMaxPacketSize */          \
80     0x00,                          /* bInterval */               \
81     0x07,                          /* bLength */                 \
82     USB_DESCRIPTOR_TYPE_ENDPOINT,  /* bDescriptorType */         \
83     in_ep,                         /* bEndpointAddress */        \
84     0x02,                          /* bmAttributes */            \
85     WBVAL(wMaxPacketSize),         /* wMaxPacketSize */          \
86     0x00                           /* bInterval */
87 // clang-format on
88 
89 #endif /* USB_MSC_H */
90