source: mainline/uspace/drv/usbmast/inquiry.c@ ff41576d

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since ff41576d was 7d521e24, checked in by Vojtech Horky <vojtechhorky@…>, 14 years ago

libusbdev uses include usb/dev

  • Property mode set to 100644
File size: 5.8 KB
Line 
1/*
2 * Copyright (c) 2011 Vojtech Horky
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup drvusbmast
30 * @{
31 */
32/**
33 * @file
34 * Main routines of USB mass storage driver.
35 */
36#include <usb/dev/driver.h>
37#include <usb/debug.h>
38#include <usb/classes/classes.h>
39#include <usb/classes/massstor.h>
40#include <errno.h>
41#include <str_error.h>
42#include <str.h>
43#include <ctype.h>
44#include "cmds.h"
45#include "scsi.h"
46#include "mast.h"
47
48#define BITS_GET_MASK(type, bitcount) (((type)(1 << (bitcount)))-1)
49#define BITS_GET_MID_MASK(type, bitcount, offset) \
50 ((type)( BITS_GET_MASK(type, (bitcount) + (offset)) - BITS_GET_MASK(type, bitcount) ))
51#define BITS_GET(type, number, bitcount, offset) \
52 ((type)( (number) & (BITS_GET_MID_MASK(type, bitcount, offset)) ) >> (offset))
53
54#define INQUIRY_RESPONSE_LENGTH 36
55
56#define STR_UNKNOWN "<unknown>"
57
58/** String constants for SCSI peripheral device types. */
59static const char *str_peripheral_device_types[] = {
60 "direct-access device",
61 "sequential-access device",
62 "printer device",
63 "processor device",
64 "write-once device",
65 "CDROM device",
66 "scanner device",
67 "optical memory device",
68 "medium changer",
69 "communications device",
70 "graphic arts pre-press device",
71 "graphic arts pre-press device",
72 "storage array controller device",
73 "enclosure services device",
74 "simplified direct-access device",
75 "optical card reader/writer device",
76 "bridging expander",
77 "object-based storage device",
78 "automation driver interface",
79 STR_UNKNOWN, // 0x13
80 STR_UNKNOWN, // 0x14
81 STR_UNKNOWN, // 0x15
82 STR_UNKNOWN, // 0x16
83 STR_UNKNOWN, // 0x17
84 STR_UNKNOWN, // 0x18
85 STR_UNKNOWN, // 0x19
86 STR_UNKNOWN, // 0x1A
87 STR_UNKNOWN, // 0x1B
88 STR_UNKNOWN, // 0x1C
89 STR_UNKNOWN, // 0x1D
90 "well-known logical unit",
91 "uknown or no device state"
92};
93#define str_peripheral_device_types_count \
94 (sizeof(str_peripheral_device_types)/sizeof(str_peripheral_device_types[0]))
95
96/** Get string representation for SCSI peripheral device type.
97 *
98 * See for example here for a list
99 * http://en.wikipedia.org/wiki/SCSI_Peripheral_Device_Type.
100 *
101 * @param type SCSI peripheral device type code.
102 * @return String representation.
103 */
104const char *usb_str_masstor_scsi_peripheral_device_type(int type)
105{
106 if ((type < 0)
107 || ((size_t)type >= str_peripheral_device_types_count)) {
108 return STR_UNKNOWN;
109 }
110 return str_peripheral_device_types[type];
111}
112
113/** Trim trailing spaces from a string (rewrite with string terminator).
114 *
115 * @param name String to be trimmed (in-out parameter).
116 */
117static void trim_trailing_spaces(char *name)
118{
119 size_t len = str_length(name);
120 while ((len > 0) && isspace((int) name[len - 1])) {
121 name[len - 1] = 0;
122 len--;
123 }
124}
125
126/** Perform SCSI INQUIRY command on USB mass storage device.
127 *
128 * @param dev USB device.
129 * @param bulk_in_idx Index (in dev->pipes) of bulk in pipe.
130 * @param bulk_out_idx Index of bulk out pipe.
131 * @param inquiry_result Where to store parsed inquiry result.
132 * @return Error code.
133 */
134int usb_massstor_inquiry(usb_device_t *dev,
135 size_t bulk_in_idx, size_t bulk_out_idx,
136 usb_massstor_inquiry_result_t *inquiry_result)
137{
138 scsi_cmd_inquiry_t inquiry = {
139 .op_code = 0x12,
140 .lun_evpd = 0,
141 .page_code = 0,
142 .alloc_length = host2uint16_t_be(INQUIRY_RESPONSE_LENGTH),
143 .ctrl = 0
144 };
145 size_t response_len;
146 uint8_t response[INQUIRY_RESPONSE_LENGTH];
147
148 int rc;
149
150 rc = usb_massstor_data_in(dev, bulk_in_idx, bulk_out_idx,
151 0xDEADBEEF, 0, (uint8_t *) &inquiry, sizeof(inquiry),
152 response, INQUIRY_RESPONSE_LENGTH, &response_len);
153
154 if (rc != EOK) {
155 usb_log_error("Failed to probe device %s using %s: %s.\n",
156 dev->ddf_dev->name, "SCSI:INQUIRY", str_error(rc));
157 return rc;
158 }
159
160 if (response_len < 8) {
161 usb_log_error("The SCSI response is too short.\n");
162 return ERANGE;
163 }
164
165 /*
166 * This is an ugly part of the code. We will parse the returned
167 * data by hand and try to get as many useful data as possible.
168 */
169 bzero(inquiry_result, sizeof(*inquiry_result));
170
171 /* This shall be returned by all devices. */
172 inquiry_result->peripheral_device_type
173 = BITS_GET(uint8_t, response[0], 5, 0);
174 inquiry_result->removable = BITS_GET(uint8_t, response[1], 1, 7);
175
176 if (response_len < 32) {
177 return EOK;
178 }
179
180 str_ncpy(inquiry_result->vendor_id, 9,
181 (const char *) &response[8], 8);
182 trim_trailing_spaces(inquiry_result->vendor_id);
183
184 str_ncpy(inquiry_result->product_and_revision, 12,
185 (const char *) &response[16], 11);
186 trim_trailing_spaces(inquiry_result->product_and_revision);
187
188 return EOK;
189}
190
191/**
192 * @}
193 */
Note: See TracBrowser for help on using the repository browser.