source: mainline/uspace/drv/usbmast/inquiry.c@ 70c12d6

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

Fix inquiry of USB mass storage

The problem was bad endianness in SCSI command descriptor block
(damn, why we need different endianness at all?).

  • Property mode set to 100644
File size: 5.0 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/devdrv.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>"
57static const char *str_peripheral_device_types[] = {
58 "direct-access device",
59 "sequential-access device",
60 "printer device",
61 "processor device",
62 "write-once device",
63 "CDROM device",
64 "scanner device",
65 "optical memory device",
66 "medium changer",
67 "communications device",
68 "graphic arts pre-press device",
69 "graphic arts pre-press device",
70 "storage array controller device",
71 "enclosure services device",
72 "simplified direct-access device",
73 "optical card reader/writer device",
74 "bridging expander",
75 "object-based storage device",
76 "automation driver interface",
77 STR_UNKNOWN, // 0x13
78 STR_UNKNOWN, // 0x14
79 STR_UNKNOWN, // 0x15
80 STR_UNKNOWN, // 0x16
81 STR_UNKNOWN, // 0x17
82 STR_UNKNOWN, // 0x18
83 STR_UNKNOWN, // 0x19
84 STR_UNKNOWN, // 0x1A
85 STR_UNKNOWN, // 0x1B
86 STR_UNKNOWN, // 0x1C
87 STR_UNKNOWN, // 0x1D
88 "well-known logical unit",
89 "uknown or no device state"
90};
91#define str_peripheral_device_types_count \
92 (sizeof(str_peripheral_device_types)/sizeof(str_peripheral_device_types[0]))
93
94const char *usb_str_masstor_scsi_peripheral_device_type(int type)
95{
96 if ((type < 0)
97 || ((size_t)type >= str_peripheral_device_types_count)) {
98 return STR_UNKNOWN;
99 }
100 return str_peripheral_device_types[type];
101}
102
103static void trim_trailing_spaces(char *name)
104{
105 size_t len = str_length(name);
106 while ((len > 0) && isspace((int) name[len - 1])) {
107 name[len - 1] = 0;
108 len--;
109 }
110}
111
112int usb_massstor_inquiry(usb_device_t *dev,
113 size_t bulk_in_idx, size_t bulk_out_idx,
114 usb_massstor_inquiry_result_t *inquiry_result)
115{
116 scsi_cmd_inquiry_t inquiry = {
117 .op_code = 0x12,
118 .lun_evpd = 0,
119 .page_code = 0,
120 .alloc_length = host2uint16_t_be(INQUIRY_RESPONSE_LENGTH),
121 .ctrl = 0
122 };
123 size_t response_len;
124 uint8_t response[INQUIRY_RESPONSE_LENGTH];
125
126 int rc;
127
128 rc = usb_massstor_data_in(dev, bulk_in_idx, bulk_out_idx,
129 0xDEADBEEF, 0, (uint8_t *) &inquiry, sizeof(inquiry),
130 response, INQUIRY_RESPONSE_LENGTH, &response_len);
131
132 if (rc != EOK) {
133 usb_log_error("Failed to probe device %s using %s: %s.\n",
134 dev->ddf_dev->name, "SCSI:INQUIRY", str_error(rc));
135 return rc;
136 }
137
138 if (response_len < 8) {
139 usb_log_error("The SCSI response is too short.\n");
140 return ERANGE;
141 }
142
143 /*
144 * This is an ugly part of the code. We will parse the returned
145 * data by hand and try to get as many useful data as possible.
146 */
147 bzero(inquiry_result, sizeof(*inquiry_result));
148
149 /* This shall be returned by all devices. */
150 inquiry_result->peripheral_device_type
151 = BITS_GET(uint8_t, response[0], 5, 0);
152 inquiry_result->removable = BITS_GET(uint8_t, response[1], 1, 7);
153
154 if (response_len < 32) {
155 return EOK;
156 }
157
158 str_ncpy(inquiry_result->vendor_id, 9,
159 (const char *) &response[8], 8);
160 trim_trailing_spaces(inquiry_result->vendor_id);
161
162 str_ncpy(inquiry_result->product_and_revision, 12,
163 (const char *) &response[16], 11);
164 trim_trailing_spaces(inquiry_result->product_and_revision);
165
166 return EOK;
167}
168
169/**
170 * @}
171 */
Note: See TracBrowser for help on using the repository browser.