1 #include <usb-msc-bulk.h>
7 #include <rbc_struct.h>
11 #define PRINTF(...) printf(__VA_ARGS__)
16 #ifndef USB_RBC_NUM_BLOCKS
17 #define USB_RBC_NUM_BLOCKS 32
20 static struct spc2_sense_data sense_data =
22 SCSI_SENSE_CURRENT_ERROR,
26 (
sizeof(
struct spc2_sense_data)
27 - offsetof(struct spc2_sense_data, command_specific))
31 scsi_error(
unsigned int sense_key,
unsigned int asc, int32_t info)
33 sense_data.response_code = SCSI_SENSE_INFORMATION_VALID | SCSI_SENSE_CURRENT_ERROR;
34 sense_data.information[0] = (info >> 24) & 0xff;
35 sense_data.information[1] = (info >> 16) & 0xff;
36 sense_data.information[2] = (info >> 8) & 0xff;
37 sense_data.information[3] = info & 0xff;
38 sense_data.sense_key = sense_key;
39 sense_data.asc = (asc >> 8) & 0xff;
40 sense_data.ascq = asc & 0xff;
46 sense_data.response_code = SCSI_SENSE_CURRENT_ERROR;
47 sense_data.sense_key = SCSI_SENSE_KEY_NO_SENSE;
48 sense_data.asc = 0x00;
49 sense_data.ascq = 0x00;
52 static const struct spc2_std_inquiry_data std_inquiry_data =
54 SCSI_STD_INQUIRY_CONNECTED | SCSI_STD_INQUIRY_TYPE_RBC,
56 SCSI_STD_INQUIRY_VERSION_SPC2,
58 (
sizeof(
struct spc2_std_inquiry_data)
59 - offsetof(struct spc2_std_inquiry_data, flags3)),
63 {
'F',
'l',
'u',
'f',
'w',
'a',
'r',
'e'},
64 {
'T',
'e',
's',
't',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
' '},
68 #define UNIT_NAME {'F','l','u','f','f','w','a','r','e',' ', \
69 'P','s','e','u','d','o',' ','D','i','s','k'}
70 #define UNIT_NAME_LENGTH 21
74 struct spc2_vital_product_data_head head;
76 struct spc2_vital_product_data_head head;
77 char unit_name[UNIT_NAME_LENGTH];
79 } CC_BYTE_ALIGNED device_identification_data =
82 SCSI_STD_INQUIRY_CONNECTED | SCSI_STD_INQUIRY_TYPE_RBC,
83 SCSI_PAGE_DEVICE_IDENTIFICATION,
85 sizeof(device_identification_data.descriptor),
90 SCSI_IDENTIFIER_TYPE_NON_UNIQUE,
92 sizeof(device_identification_data.descriptor.unit_name)
101 struct spc2_vital_product_data_head head;
102 uint8_t supported[3];
103 } CC_BYTE_ALIGNED supported_pages_data =
106 SCSI_STD_INQUIRY_CONNECTED | SCSI_STD_INQUIRY_TYPE_RBC,
107 SCSI_PAGE_SUPPORTED_PAGES,
109 sizeof(supported_pages_data.supported),
111 {SCSI_PAGE_SUPPORTED_PAGES, SCSI_PAGE_UNIT_SERIAL_NUMBER,
112 SCSI_PAGE_DEVICE_IDENTIFICATION}
117 struct spc2_vital_product_data_head head;
118 uint8_t serial_number[8];
119 } CC_BYTE_ALIGNED unit_serial_number_data = {
121 SCSI_STD_INQUIRY_CONNECTED | SCSI_STD_INQUIRY_TYPE_RBC,
122 SCSI_PAGE_SUPPORTED_PAGES,
124 sizeof(unit_serial_number_data.serial_number)
126 {
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8'}
129 static usb_msc_handler_status
130 handle_inquiry_cmd(
struct usb_msc_command_state *state)
132 struct spc2_inquiry_cmd *cmd = (
struct spc2_inquiry_cmd*)state->command;
133 if (cmd->flags & SCSI_INQUIRY_FLAG_CMDDT) {
134 scsi_error(SCSI_SENSE_KEY_ILLEGAL_REQUEST,SCSI_ASC_INVALID_FIELD_IN_CDB,
135 cmd->allocation_length);
136 return USB_MSC_HANDLER_FAILED;
138 if (cmd->flags & SCSI_INQUIRY_FLAG_EVPD) {
139 PRINTF(
"Requested page %02x\n", cmd->page);
141 case SCSI_PAGE_SUPPORTED_PAGES:
142 usb_msc_send_data((uint8_t *)&supported_pages_data,
143 sizeof(supported_pages_data),
144 USB_MSC_DATA_SEND | USB_MSC_DATA_LAST);
146 case SCSI_PAGE_DEVICE_IDENTIFICATION:
147 usb_msc_send_data((uint8_t *)&device_identification_data,
148 sizeof(device_identification_data),
149 USB_MSC_DATA_SEND | USB_MSC_DATA_LAST);
151 case SCSI_PAGE_UNIT_SERIAL_NUMBER:
152 usb_msc_send_data((uint8_t *)&unit_serial_number_data,
153 sizeof(unit_serial_number_data),
154 USB_MSC_DATA_SEND | USB_MSC_DATA_LAST);
157 scsi_error(SCSI_SENSE_KEY_ILLEGAL_REQUEST,SCSI_ASC_INVALID_FIELD_IN_CDB,
158 cmd->allocation_length);
159 return USB_MSC_HANDLER_FAILED;
161 return USB_MSC_HANDLER_OK;
163 if (cmd->page != 0) {
164 scsi_error(SCSI_SENSE_KEY_ILLEGAL_REQUEST,SCSI_ASC_INVALID_FIELD_IN_CDB,
165 cmd->allocation_length);
166 return USB_MSC_HANDLER_FAILED;
168 usb_msc_send_data((uint8_t *)&std_inquiry_data,
169 sizeof(std_inquiry_data),
170 USB_MSC_DATA_SEND | USB_MSC_DATA_LAST);
172 return USB_MSC_HANDLER_OK;
175 static usb_msc_handler_status
176 handle_request_sense_cmd(
struct usb_msc_command_state *state)
178 usb_msc_send_data((uint8_t *)&sense_data,
180 USB_MSC_DATA_SEND | USB_MSC_DATA_LAST);
181 return USB_MSC_HANDLER_OK;
184 static usb_msc_handler_status
185 handle_test_unit_ready_cmd(
struct usb_msc_command_state *state)
188 return USB_MSC_HANDLER_OK;
191 static const struct rbc_read_capacity_data read_capacity_data =
193 HOST32_TO_BE_BYTES(USB_RBC_NUM_BLOCKS-1),
194 HOST32_TO_BE_BYTES(512)
197 static usb_msc_handler_status
198 handle_read_capacity(
struct usb_msc_command_state *state)
200 usb_msc_send_data((uint8_t *)&read_capacity_data,
201 sizeof(read_capacity_data),
202 USB_MSC_DATA_SEND | USB_MSC_DATA_LAST);
203 return USB_MSC_HANDLER_OK;
206 static const struct mode_sense_data {
207 struct spc2_mode_parameter_header_6 header;
208 struct rbc_device_parameters_page page;
209 } CC_BYTE_ALIGNED mode_sense_data =
212 (
sizeof(mode_sense_data)
213 - offsetof(
struct mode_sense_data, header.medium_type)),
217 {SCSI_MODE_RBC_DEVICE_PAGE | SCSI_MODE_PAGE_SP,
218 sizeof(mode_sense_data) - offsetof(
struct mode_sense_data, page.flags1)},
220 HOST16_TO_BE_BYTES(512),
221 HOST40_TO_BE_BYTES((
long long)USB_RBC_NUM_BLOCKS),
223 (SCSI_MODE_FORMATD | SCSI_MODE_LOCKD),
228 static usb_msc_handler_status
229 handle_mode_sense(
struct usb_msc_command_state *state)
231 struct spc2_mode_sence_6_cmd *cmd =
232 (
struct spc2_mode_sence_6_cmd*)state->command;
233 PRINTF(
"%ld - %ld - %ld\n",
sizeof(
struct mode_sense_data), offsetof(
struct mode_sense_data, page.flags1),offsetof(
struct mode_sense_data, page.reserved));
234 switch(cmd->page_code) {
235 case SCSI_MODE_RBC_DEVICE_PAGE:
236 case SCSI_MODE_SENSE_ALL_PAGES:
237 usb_msc_send_data((uint8_t *)&mode_sense_data,
238 sizeof(mode_sense_data),
239 USB_MSC_DATA_SEND | USB_MSC_DATA_LAST);
242 scsi_error(SCSI_SENSE_KEY_ILLEGAL_REQUEST,SCSI_ASC_INVALID_FIELD_IN_CDB,
243 cmd->allocation_length);
244 return USB_MSC_HANDLER_FAILED;
246 return USB_MSC_HANDLER_OK;
249 static usb_msc_handler_status
250 handle_mode_select(
struct usb_msc_command_state *state)
253 return USB_MSC_HANDLER_OK;
255 static uint8_t disk_blocks[USB_RBC_NUM_BLOCKS][512];
257 static usb_msc_handler_status
258 handle_read(
struct usb_msc_command_state *state)
260 struct rbc_read_cmd *cmd = (
struct rbc_read_cmd*)state->command;
261 unsigned long lba = be32_to_host(cmd->logical_block_address);
262 unsigned long blocks = be16_to_host(cmd->transfer_length);
263 PRINTF(
"Requested %ld blocks at %ld\n", blocks, lba);
264 if (lba >= USB_RBC_NUM_BLOCKS || lba + blocks > USB_RBC_NUM_BLOCKS) {
265 scsi_error(SCSI_SENSE_KEY_ILLEGAL_REQUEST,SCSI_ASC_INVALID_FIELD_IN_CDB,
267 return USB_MSC_HANDLER_FAILED;
269 usb_msc_send_data((uint8_t *)&disk_blocks[lba], blocks * 512,
270 USB_MSC_DATA_SEND | USB_MSC_DATA_LAST);
272 return USB_MSC_HANDLER_OK;
276 handle_write_done(
struct usb_msc_command_state *state)
278 PRINTF(
"Wrote data\n");
279 state->status = MASS_BULK_CSW_STATUS_PASSED;
283 static usb_msc_handler_status
284 handle_write(
struct usb_msc_command_state *state)
286 struct rbc_write_cmd *cmd = (
struct rbc_write_cmd*)state->command;
287 unsigned long lba = be32_to_host(cmd->logical_block_address);
288 unsigned long blocks = be16_to_host(cmd->transfer_length);
289 if (lba >= USB_RBC_NUM_BLOCKS || lba + blocks > USB_RBC_NUM_BLOCKS) {
290 scsi_error(SCSI_SENSE_KEY_ILLEGAL_REQUEST,SCSI_ASC_INVALID_FIELD_IN_CDB,
292 return USB_MSC_HANDLER_FAILED;
294 PRINTF(
"Writing %ld blocks at %ld\n", blocks, lba);
295 usb_msc_receive_data(disk_blocks[lba], blocks * 512,
296 USB_MSC_DATA_RECEIVE | USB_MSC_DATA_LAST
297 | USB_MSC_DATA_DO_CALLBACK);
298 state->data_cb = handle_write_done;
299 return USB_MSC_HANDLER_DELAYED;
302 static usb_msc_handler_status
303 handle_start_stop_unit(
struct usb_msc_command_state *state)
306 return USB_MSC_HANDLER_OK;
309 static usb_msc_handler_status
310 handle_verify(
struct usb_msc_command_state *state)
313 return USB_MSC_HANDLER_OK;
316 usb_msc_handler_status
317 usb_msc_handle_command(
struct usb_msc_command_state *state)
320 usb_msc_handler_status ret;
321 PRINTF(
"Got CBW %02x\n", state->command[0]);
322 switch(state->command[0]) {
323 case SCSI_CMD_INQUIRY:
324 ret = handle_inquiry_cmd(state);
326 case SCSI_CMD_REQUEST_SENSE:
327 ret = handle_request_sense_cmd(state);
329 case SCSI_CMD_TEST_UNIT_READY:
330 ret = handle_test_unit_ready_cmd(state);
332 case SCSI_CMD_READ_CAPACITY:
333 ret = handle_read_capacity(state);
335 case SCSI_CMD_MODE_SENSE_6:
336 ret = handle_mode_sense(state);
338 case SCSI_CMD_MODE_SELECT_6:
339 ret = handle_mode_select(state);
341 case SCSI_CMD_READ_10:
342 ret = handle_read(state);
344 case SCSI_CMD_WRITE_10:
345 ret = handle_write(state);
347 case SCSI_CMD_VERIFY_10:
348 ret = handle_verify(state);
350 case SCSI_CMD_START_STOP_UNIT:
351 ret = handle_start_stop_unit(state);
354 printf(
"Unhandled request: %02x\n", state->command[0]);
355 scsi_error(SCSI_SENSE_KEY_ILLEGAL_REQUEST,
356 SCSI_ASC_INVALID_COMMAND_OPERATION,0);
357 return USB_MSC_HANDLER_FAILED;
363 usb_msc_command_handler_init()