inquiry.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2011 Vojtech Horky
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  * - Redistributions in binary form must reproduce the above copyright
00012  *   notice, this list of conditions and the following disclaimer in the
00013  *   documentation and/or other materials provided with the distribution.
00014  * - The name of the author may not be used to endorse or promote products
00015  *   derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00019  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00020  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00022  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00023  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00024  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00026  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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, // 0x13
00080         STR_UNKNOWN, // 0x14
00081         STR_UNKNOWN, // 0x15
00082         STR_UNKNOWN, // 0x16
00083         STR_UNKNOWN, // 0x17
00084         STR_UNKNOWN, // 0x18
00085         STR_UNKNOWN, // 0x19
00086         STR_UNKNOWN, // 0x1A
00087         STR_UNKNOWN, // 0x1B
00088         STR_UNKNOWN, // 0x1C
00089         STR_UNKNOWN, // 0x1D
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          * This is an ugly part of the code. We will parse the returned
00167          * data by hand and try to get as many useful data as possible.
00168          */
00169         bzero(inquiry_result, sizeof(*inquiry_result));
00170 
00171         /* This shall be returned by all devices. */
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 

Generated on Thu Jun 2 07:45:44 2011 for HelenOS/USB by  doxygen 1.4.7