Contiki 2.6

usb-rbc.c

00001 #include <usb-msc-bulk.h>
00002 #include <usb-api.h>
00003 #include <usb-core.h>
00004 #include <sys/process.h>
00005 #include <stdio.h>
00006 #include <rbc_const.h>
00007 #include <rbc_struct.h>
00008 #include <string.h>
00009 
00010 #ifdef DEBUG
00011 #define PRINTF(...) printf(__VA_ARGS__)
00012 #else
00013 #define PRINTF(...)
00014 #endif
00015 
00016 #ifndef USB_RBC_NUM_BLOCKS
00017 #define USB_RBC_NUM_BLOCKS 32
00018 #endif
00019 
00020 static struct spc2_sense_data sense_data =
00021   {
00022     SCSI_SENSE_CURRENT_ERROR,
00023     0,
00024     0,
00025     {0},
00026     (sizeof(struct spc2_sense_data)
00027      - offsetof(struct spc2_sense_data, command_specific))
00028   };
00029 
00030 static void
00031 scsi_error(unsigned int sense_key, unsigned int asc, int32_t info)
00032 {
00033   sense_data.response_code = SCSI_SENSE_INFORMATION_VALID | SCSI_SENSE_CURRENT_ERROR;
00034   sense_data.information[0] = (info >> 24) & 0xff;
00035   sense_data.information[1] = (info >> 16) & 0xff;
00036   sense_data.information[2] = (info >> 8) & 0xff;
00037   sense_data.information[3] = info & 0xff;
00038   sense_data.sense_key = sense_key;
00039   sense_data.asc = (asc >> 8) & 0xff;
00040   sense_data.ascq = asc & 0xff;
00041 }
00042 
00043 static void
00044 scsi_ok()
00045 {
00046   sense_data.response_code = SCSI_SENSE_CURRENT_ERROR;
00047   sense_data.sense_key = SCSI_SENSE_KEY_NO_SENSE;
00048   sense_data.asc = 0x00;
00049   sense_data.ascq = 0x00;
00050 };
00051 
00052 static const struct spc2_std_inquiry_data std_inquiry_data =
00053   {
00054     SCSI_STD_INQUIRY_CONNECTED | SCSI_STD_INQUIRY_TYPE_RBC,
00055     0,
00056     SCSI_STD_INQUIRY_VERSION_SPC2,
00057     0,
00058     (sizeof(struct spc2_std_inquiry_data)
00059      - offsetof(struct spc2_std_inquiry_data, flags3)),
00060     0,
00061     0,
00062     0,
00063     {'F','l','u','f','w','a','r','e'},
00064     {'T','e','s','t',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '},
00065     {'0','.','1',' '}
00066   };
00067 
00068 #define UNIT_NAME {'F','l','u','f','f','w','a','r','e',' ', \
00069  'P','s','e','u','d','o',' ','D','i','s','k'}
00070 #define UNIT_NAME_LENGTH 21
00071 
00072 static const struct 
00073 {
00074   struct spc2_vital_product_data_head head;
00075   struct {
00076     struct spc2_vital_product_data_head head;
00077     char unit_name[UNIT_NAME_LENGTH];
00078   } descriptor;
00079 } CC_BYTE_ALIGNED device_identification_data =
00080   {
00081     {
00082       SCSI_STD_INQUIRY_CONNECTED | SCSI_STD_INQUIRY_TYPE_RBC,
00083       SCSI_PAGE_DEVICE_IDENTIFICATION,
00084       0,
00085       sizeof(device_identification_data.descriptor),
00086     },
00087     {
00088       {
00089         SCSI_CODE_SET_ACSII,
00090         SCSI_IDENTIFIER_TYPE_NON_UNIQUE,
00091         0,
00092         sizeof(device_identification_data.descriptor.unit_name)
00093       },
00094       UNIT_NAME
00095     }
00096   };
00097       
00098 
00099 static const struct 
00100 {
00101   struct spc2_vital_product_data_head head;
00102   uint8_t supported[3];
00103 } CC_BYTE_ALIGNED supported_pages_data =
00104   {
00105     {
00106       SCSI_STD_INQUIRY_CONNECTED | SCSI_STD_INQUIRY_TYPE_RBC,
00107       SCSI_PAGE_SUPPORTED_PAGES,
00108       0,
00109       sizeof(supported_pages_data.supported),
00110     },
00111     {SCSI_PAGE_SUPPORTED_PAGES, SCSI_PAGE_UNIT_SERIAL_NUMBER,
00112      SCSI_PAGE_DEVICE_IDENTIFICATION}
00113   };
00114 
00115 static const struct 
00116 {
00117   struct spc2_vital_product_data_head head;
00118   uint8_t serial_number[8];
00119 } CC_BYTE_ALIGNED unit_serial_number_data = {
00120   {
00121       SCSI_STD_INQUIRY_CONNECTED | SCSI_STD_INQUIRY_TYPE_RBC,
00122       SCSI_PAGE_SUPPORTED_PAGES,
00123       0,
00124       sizeof(unit_serial_number_data.serial_number)
00125   },
00126   {'1','2','3','4','5','6','7','8'}
00127 };
00128 
00129 static usb_msc_handler_status
00130 handle_inquiry_cmd(struct usb_msc_command_state *state)
00131 {
00132   struct spc2_inquiry_cmd *cmd = (struct spc2_inquiry_cmd*)state->command;
00133   if (cmd->flags & SCSI_INQUIRY_FLAG_CMDDT) {
00134     scsi_error(SCSI_SENSE_KEY_ILLEGAL_REQUEST,SCSI_ASC_INVALID_FIELD_IN_CDB,
00135                cmd->allocation_length);
00136     return USB_MSC_HANDLER_FAILED;
00137   }
00138   if (cmd->flags & SCSI_INQUIRY_FLAG_EVPD) {
00139     PRINTF("Requested page %02x\n", cmd->page);
00140     switch (cmd->page) {
00141     case SCSI_PAGE_SUPPORTED_PAGES:
00142       usb_msc_send_data((uint8_t *)&supported_pages_data,
00143                         sizeof(supported_pages_data),
00144                         USB_MSC_DATA_SEND | USB_MSC_DATA_LAST);
00145       break;
00146     case SCSI_PAGE_DEVICE_IDENTIFICATION:
00147       usb_msc_send_data((uint8_t *)&device_identification_data,
00148                         sizeof(device_identification_data),
00149                         USB_MSC_DATA_SEND | USB_MSC_DATA_LAST);
00150       break;
00151     case SCSI_PAGE_UNIT_SERIAL_NUMBER:
00152       usb_msc_send_data((uint8_t *)&unit_serial_number_data,
00153                         sizeof(unit_serial_number_data),
00154                         USB_MSC_DATA_SEND | USB_MSC_DATA_LAST);
00155       break;
00156     default:
00157       scsi_error(SCSI_SENSE_KEY_ILLEGAL_REQUEST,SCSI_ASC_INVALID_FIELD_IN_CDB,
00158                  cmd->allocation_length);
00159       return USB_MSC_HANDLER_FAILED;
00160     }
00161     return USB_MSC_HANDLER_OK;
00162   } else {
00163     if (cmd->page != 0) {
00164       scsi_error(SCSI_SENSE_KEY_ILLEGAL_REQUEST,SCSI_ASC_INVALID_FIELD_IN_CDB,
00165                  cmd->allocation_length);
00166       return USB_MSC_HANDLER_FAILED;
00167     }
00168     usb_msc_send_data((uint8_t *)&std_inquiry_data,
00169                         sizeof(std_inquiry_data),
00170                         USB_MSC_DATA_SEND | USB_MSC_DATA_LAST);
00171   }
00172   return USB_MSC_HANDLER_OK;
00173 }
00174 
00175 static usb_msc_handler_status
00176 handle_request_sense_cmd(struct usb_msc_command_state *state)
00177 {
00178   usb_msc_send_data((uint8_t *)&sense_data,
00179                     sizeof(sense_data),
00180                     USB_MSC_DATA_SEND | USB_MSC_DATA_LAST);
00181   return USB_MSC_HANDLER_OK;
00182 }
00183 
00184 static usb_msc_handler_status
00185 handle_test_unit_ready_cmd(struct usb_msc_command_state *state)
00186 {
00187   scsi_ok();
00188   return USB_MSC_HANDLER_OK;
00189 }
00190 
00191 static const struct rbc_read_capacity_data read_capacity_data =
00192   {
00193     HOST32_TO_BE_BYTES(USB_RBC_NUM_BLOCKS-1),
00194     HOST32_TO_BE_BYTES(512)
00195   };
00196   
00197 static usb_msc_handler_status
00198 handle_read_capacity(struct usb_msc_command_state *state)
00199 {
00200   usb_msc_send_data((uint8_t *)&read_capacity_data,
00201                     sizeof(read_capacity_data),
00202                     USB_MSC_DATA_SEND | USB_MSC_DATA_LAST);
00203   return USB_MSC_HANDLER_OK;
00204 }
00205 
00206 static const struct mode_sense_data {
00207   struct spc2_mode_parameter_header_6 header;
00208   struct rbc_device_parameters_page page;
00209 } CC_BYTE_ALIGNED mode_sense_data =
00210   {
00211     {
00212       (sizeof(mode_sense_data)
00213        - offsetof(struct mode_sense_data, header.medium_type)),
00214       0,0,0
00215     },
00216     {
00217       {SCSI_MODE_RBC_DEVICE_PAGE | SCSI_MODE_PAGE_SP,
00218       sizeof(mode_sense_data) - offsetof(struct mode_sense_data, page.flags1)},
00219       SCSI_MODE_WCD,
00220       HOST16_TO_BE_BYTES(512),
00221       HOST40_TO_BE_BYTES((long long)USB_RBC_NUM_BLOCKS),
00222       0x80,
00223       (SCSI_MODE_FORMATD | SCSI_MODE_LOCKD),
00224       0
00225     }
00226   };
00227 
00228 static usb_msc_handler_status
00229 handle_mode_sense(struct usb_msc_command_state *state)
00230 {
00231   struct spc2_mode_sence_6_cmd *cmd =
00232     (struct spc2_mode_sence_6_cmd*)state->command;
00233   PRINTF("%ld - %ld - %ld\n", sizeof(struct mode_sense_data), offsetof(struct mode_sense_data, page.flags1),offsetof(struct mode_sense_data, page.reserved));
00234   switch(cmd->page_code) {
00235   case SCSI_MODE_RBC_DEVICE_PAGE:
00236   case SCSI_MODE_SENSE_ALL_PAGES:
00237     usb_msc_send_data((uint8_t *)&mode_sense_data,
00238                       sizeof(mode_sense_data),
00239                       USB_MSC_DATA_SEND | USB_MSC_DATA_LAST);
00240     break;
00241   default:
00242     scsi_error(SCSI_SENSE_KEY_ILLEGAL_REQUEST,SCSI_ASC_INVALID_FIELD_IN_CDB,
00243                cmd->allocation_length);
00244     return USB_MSC_HANDLER_FAILED;
00245   }
00246   return USB_MSC_HANDLER_OK;
00247 }
00248 
00249 static usb_msc_handler_status
00250 handle_mode_select(struct usb_msc_command_state *state)
00251 {
00252   /* Can't change anything */
00253   return USB_MSC_HANDLER_OK;
00254 }
00255 static uint8_t disk_blocks[USB_RBC_NUM_BLOCKS][512];
00256 
00257 static usb_msc_handler_status
00258 handle_read(struct usb_msc_command_state *state)
00259 {
00260   struct rbc_read_cmd *cmd = (struct rbc_read_cmd*)state->command;
00261   unsigned long lba = be32_to_host(cmd->logical_block_address);
00262   unsigned long blocks = be16_to_host(cmd->transfer_length);
00263   PRINTF("Requested %ld blocks at %ld\n", blocks, lba);
00264   if (lba >= USB_RBC_NUM_BLOCKS || lba + blocks > USB_RBC_NUM_BLOCKS) {
00265     scsi_error(SCSI_SENSE_KEY_ILLEGAL_REQUEST,SCSI_ASC_INVALID_FIELD_IN_CDB,
00266                blocks);
00267     return USB_MSC_HANDLER_FAILED;
00268   }
00269   usb_msc_send_data((uint8_t *)&disk_blocks[lba], blocks * 512,
00270                     USB_MSC_DATA_SEND | USB_MSC_DATA_LAST);
00271   scsi_ok();
00272   return USB_MSC_HANDLER_OK;
00273 }
00274 
00275 static void
00276 handle_write_done(struct usb_msc_command_state *state)
00277 {
00278   PRINTF("Wrote data\n");
00279   state->status = MASS_BULK_CSW_STATUS_PASSED;
00280   scsi_ok();
00281 }
00282 
00283 static usb_msc_handler_status
00284 handle_write(struct usb_msc_command_state *state)
00285 {
00286   struct rbc_write_cmd *cmd = (struct rbc_write_cmd*)state->command;
00287   unsigned long lba = be32_to_host(cmd->logical_block_address);
00288   unsigned long blocks = be16_to_host(cmd->transfer_length);
00289   if (lba >= USB_RBC_NUM_BLOCKS || lba + blocks > USB_RBC_NUM_BLOCKS) {
00290     scsi_error(SCSI_SENSE_KEY_ILLEGAL_REQUEST,SCSI_ASC_INVALID_FIELD_IN_CDB,
00291                blocks);
00292     return USB_MSC_HANDLER_FAILED;
00293   }
00294   PRINTF("Writing %ld blocks at %ld\n", blocks, lba);
00295   usb_msc_receive_data(disk_blocks[lba], blocks * 512,
00296                        USB_MSC_DATA_RECEIVE | USB_MSC_DATA_LAST
00297                        | USB_MSC_DATA_DO_CALLBACK);
00298   state->data_cb = handle_write_done;
00299   return USB_MSC_HANDLER_DELAYED;
00300 }
00301 
00302 static usb_msc_handler_status
00303 handle_start_stop_unit(struct usb_msc_command_state *state)
00304 {
00305   scsi_ok();
00306   return USB_MSC_HANDLER_OK;
00307 }
00308 
00309 static usb_msc_handler_status
00310 handle_verify(struct usb_msc_command_state *state)
00311 {
00312   scsi_ok();
00313   return USB_MSC_HANDLER_OK;
00314 }
00315 
00316 usb_msc_handler_status
00317 usb_msc_handle_command(struct usb_msc_command_state *state)
00318 {
00319 
00320   usb_msc_handler_status ret;
00321   PRINTF("Got CBW %02x\n", state->command[0]);
00322   switch(state->command[0]) {
00323   case SCSI_CMD_INQUIRY:
00324     ret = handle_inquiry_cmd(state);
00325     break;
00326   case SCSI_CMD_REQUEST_SENSE:
00327     ret = handle_request_sense_cmd(state);
00328     break;
00329   case SCSI_CMD_TEST_UNIT_READY:
00330     ret = handle_test_unit_ready_cmd(state);
00331     break;
00332   case SCSI_CMD_READ_CAPACITY:
00333     ret = handle_read_capacity(state);
00334     break;
00335   case SCSI_CMD_MODE_SENSE_6:
00336     ret = handle_mode_sense(state);
00337     break;
00338   case SCSI_CMD_MODE_SELECT_6:
00339     ret = handle_mode_select(state);
00340     break;
00341   case SCSI_CMD_READ_10:
00342     ret = handle_read(state);
00343     break;
00344   case SCSI_CMD_WRITE_10:
00345     ret = handle_write(state);
00346     break;
00347   case SCSI_CMD_VERIFY_10:
00348     ret = handle_verify(state);
00349     break;
00350   case SCSI_CMD_START_STOP_UNIT:
00351     ret = handle_start_stop_unit(state);
00352     break;
00353   default:
00354     printf("Unhandled request: %02x\n", state->command[0]);
00355     scsi_error(SCSI_SENSE_KEY_ILLEGAL_REQUEST,
00356                SCSI_ASC_INVALID_COMMAND_OPERATION,0);
00357     return USB_MSC_HANDLER_FAILED;
00358   }
00359   return ret;
00360 }
00361 
00362 void
00363 usb_msc_command_handler_init()
00364 {
00365 }