00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00036 #include "mast.h"
00037 #include "cmds.h"
00038 #include <bool.h>
00039 #include <errno.h>
00040 #include <str_error.h>
00041 #include <usb/debug.h>
00042 #include <usb/dev/request.h>
00043 
00044 bool usb_mast_verbose = true;
00045 
00046 #define MASTLOG(format, ...) \
00047         do { \
00048                 if (usb_mast_verbose) { \
00049                         usb_log_debug("USB cl08: " format, ##__VA_ARGS__); \
00050                 } \
00051         } while (false)
00052 
00066 int usb_massstor_data_in(usb_device_t *dev,
00067     size_t bulk_in_pipe_index, size_t bulk_out_pipe_index,
00068     uint32_t tag, uint8_t lun, void *cmd, size_t cmd_size,
00069     void *in_buffer, size_t in_buffer_size, size_t *received_size)
00070 {
00071         int rc;
00072         size_t act_size;
00073         usb_pipe_t *bulk_in_pipe = dev->pipes[bulk_in_pipe_index].pipe;
00074         usb_pipe_t *bulk_out_pipe = dev->pipes[bulk_out_pipe_index].pipe;
00075 
00076         
00077         usb_massstor_cbw_t cbw;
00078         usb_massstor_cbw_prepare(&cbw, tag, in_buffer_size,
00079             USB_DIRECTION_IN, lun, cmd_size, cmd);
00080 
00081         
00082         rc = usb_pipe_write(bulk_out_pipe, &cbw, sizeof(cbw));
00083         MASTLOG("CBW '%s' sent: %s.\n",
00084             usb_debug_str_buffer((uint8_t *) &cbw, sizeof(cbw), 0),
00085             str_error(rc));
00086         if (rc != EOK) {
00087                 return rc;
00088         }
00089 
00090         
00091         act_size = 0;
00092         rc = usb_pipe_read(bulk_in_pipe, in_buffer, in_buffer_size, &act_size);
00093         MASTLOG("Received %zuB (%s): %s.\n", act_size,
00094             usb_debug_str_buffer((uint8_t *) in_buffer, act_size, 0),
00095             str_error(rc));
00096         if (rc != EOK) {
00097                 return rc;
00098         }
00099 
00100         
00101         usb_massstor_csw_t csw;
00102         size_t csw_size;
00103         rc = usb_pipe_read(bulk_in_pipe, &csw, sizeof(csw), &csw_size);
00104         MASTLOG("CSW '%s' received (%zuB): %s.\n",
00105             usb_debug_str_buffer((uint8_t *) &csw, csw_size, 0), csw_size,
00106             str_error(rc));
00107         if (rc != EOK) {
00108                 return rc;
00109         }
00110         if (csw_size != sizeof(csw)) {
00111                 return ERANGE;
00112         }
00113 
00114         if (csw.dCSWTag != tag) {
00115                 return EBADCHECKSUM;
00116         }
00117 
00118         
00119 
00120 
00121         if (csw.dCSWStatus != 0) {
00122                 
00123                 
00124                 return EXDEV;
00125         }
00126 
00127         size_t residue = (size_t) uint32_usb2host(csw.dCSWDataResidue);
00128         if (residue > in_buffer_size) {
00129                 return ERANGE;
00130         }
00131         if (act_size != in_buffer_size - residue) {
00132                 return ERANGE;
00133         }
00134         if (received_size != NULL) {
00135                 *received_size = in_buffer_size - residue;
00136         }
00137 
00138         return EOK;
00139 }
00140 
00146 int usb_massstor_reset(usb_device_t *dev)
00147 {
00148         return usb_control_request_set(&dev->ctrl_pipe,
00149             USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
00150             0xFF, 0, dev->interface_no, NULL, 0);
00151 }
00152 
00162 void usb_massstor_reset_recovery(usb_device_t *dev,
00163     size_t bulk_in_idx, size_t bulk_out_idx)
00164 {
00165         
00166 
00167 
00168         usb_massstor_reset(dev);
00169         usb_pipe_clear_halt(&dev->ctrl_pipe, dev->pipes[bulk_in_idx].pipe);
00170         usb_pipe_clear_halt(&dev->ctrl_pipe, dev->pipes[bulk_out_idx].pipe);
00171 }
00172 
00184 int usb_massstor_get_max_lun(usb_device_t *dev)
00185 {
00186         uint8_t max_lun;
00187         size_t data_recv_len;
00188         int rc = usb_control_request_get(&dev->ctrl_pipe,
00189             USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
00190             0xFE, 0, dev->interface_no, &max_lun, 1, &data_recv_len);
00191         if (rc != EOK) {
00192                 return rc;
00193         }
00194         if (data_recv_len != 1) {
00195                 return EEMPTY;
00196         }
00197         return (int) max_lun;
00198 }
00199 
00208 size_t usb_masstor_get_lun_count(usb_device_t *dev)
00209 {
00210         int max_lun = usb_massstor_get_max_lun(dev);
00211         if (max_lun < 0) {
00212                 max_lun = 1;
00213         } else {
00214                 max_lun++;
00215         }
00216 
00217         return (size_t) max_lun;
00218 }
00219