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 <usb/dev/driver.h>
00037 #include <usb/debug.h>
00038 #include <usb/classes/classes.h>
00039 #include <usb/classes/massstor.h>
00040 #include <errno.h>
00041 #include <str_error.h>
00042 #include <str.h>
00043 #include <ctype.h>
00044 #include "cmds.h"
00045 #include "scsi.h"
00046 #include "mast.h"
00047
00048 #define BITS_GET_MASK(type, bitcount) (((type)(1 << (bitcount)))-1)
00049 #define BITS_GET_MID_MASK(type, bitcount, offset) \
00050 ((type)( BITS_GET_MASK(type, (bitcount) + (offset)) - BITS_GET_MASK(type, bitcount) ))
00051 #define BITS_GET(type, number, bitcount, offset) \
00052 ((type)( (number) & (BITS_GET_MID_MASK(type, bitcount, offset)) ) >> (offset))
00053
00054 #define INQUIRY_RESPONSE_LENGTH 36
00055
00056 #define STR_UNKNOWN "<unknown>"
00057
00059 static const char *str_peripheral_device_types[] = {
00060 "direct-access device",
00061 "sequential-access device",
00062 "printer device",
00063 "processor device",
00064 "write-once device",
00065 "CDROM device",
00066 "scanner device",
00067 "optical memory device",
00068 "medium changer",
00069 "communications device",
00070 "graphic arts pre-press device",
00071 "graphic arts pre-press device",
00072 "storage array controller device",
00073 "enclosure services device",
00074 "simplified direct-access device",
00075 "optical card reader/writer device",
00076 "bridging expander",
00077 "object-based storage device",
00078 "automation driver interface",
00079 STR_UNKNOWN,
00080 STR_UNKNOWN,
00081 STR_UNKNOWN,
00082 STR_UNKNOWN,
00083 STR_UNKNOWN,
00084 STR_UNKNOWN,
00085 STR_UNKNOWN,
00086 STR_UNKNOWN,
00087 STR_UNKNOWN,
00088 STR_UNKNOWN,
00089 STR_UNKNOWN,
00090 "well-known logical unit",
00091 "uknown or no device state"
00092 };
00093 #define str_peripheral_device_types_count \
00094 (sizeof(str_peripheral_device_types)/sizeof(str_peripheral_device_types[0]))
00095
00104 const char *usb_str_masstor_scsi_peripheral_device_type(int type)
00105 {
00106 if ((type < 0)
00107 || ((size_t)type >= str_peripheral_device_types_count)) {
00108 return STR_UNKNOWN;
00109 }
00110 return str_peripheral_device_types[type];
00111 }
00112
00117 static void trim_trailing_spaces(char *name)
00118 {
00119 size_t len = str_length(name);
00120 while ((len > 0) && isspace((int) name[len - 1])) {
00121 name[len - 1] = 0;
00122 len--;
00123 }
00124 }
00125
00134 int usb_massstor_inquiry(usb_device_t *dev,
00135 size_t bulk_in_idx, size_t bulk_out_idx,
00136 usb_massstor_inquiry_result_t *inquiry_result)
00137 {
00138 scsi_cmd_inquiry_t inquiry = {
00139 .op_code = 0x12,
00140 .lun_evpd = 0,
00141 .page_code = 0,
00142 .alloc_length = host2uint16_t_be(INQUIRY_RESPONSE_LENGTH),
00143 .ctrl = 0
00144 };
00145 size_t response_len;
00146 uint8_t response[INQUIRY_RESPONSE_LENGTH];
00147
00148 int rc;
00149
00150 rc = usb_massstor_data_in(dev, bulk_in_idx, bulk_out_idx,
00151 0xDEADBEEF, 0, (uint8_t *) &inquiry, sizeof(inquiry),
00152 response, INQUIRY_RESPONSE_LENGTH, &response_len);
00153
00154 if (rc != EOK) {
00155 usb_log_error("Failed to probe device %s using %s: %s.\n",
00156 dev->ddf_dev->name, "SCSI:INQUIRY", str_error(rc));
00157 return rc;
00158 }
00159
00160 if (response_len < 8) {
00161 usb_log_error("The SCSI response is too short.\n");
00162 return ERANGE;
00163 }
00164
00165
00166
00167
00168
00169 bzero(inquiry_result, sizeof(*inquiry_result));
00170
00171
00172 inquiry_result->peripheral_device_type
00173 = BITS_GET(uint8_t, response[0], 5, 0);
00174 inquiry_result->removable = BITS_GET(uint8_t, response[1], 1, 7);
00175
00176 if (response_len < 32) {
00177 return EOK;
00178 }
00179
00180 str_ncpy(inquiry_result->vendor_id, 9,
00181 (const char *) &response[8], 8);
00182 trim_trailing_spaces(inquiry_result->vendor_id);
00183
00184 str_ncpy(inquiry_result->product_and_revision, 12,
00185 (const char *) &response[16], 11);
00186 trim_trailing_spaces(inquiry_result->product_and_revision);
00187
00188 return EOK;
00189 }
00190