source: mainline/uspace/drv/usbmast/main.c@ bc02b83

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

Add generic function for data IN on mass storage

Also, more information is printed about device that is
plugged in.

  • Property mode set to 100644
File size: 5.7 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 "cmds.h"
43#include "scsi.h"
44#include "mast.h"
45
46#define NAME "usbmast"
47
48#define BULK_IN_EP 0
49#define BULK_OUT_EP 1
50
51#define GET_BULK_IN(dev) ((dev)->pipes[BULK_IN_EP].pipe)
52#define GET_BULK_OUT(dev) ((dev)->pipes[BULK_OUT_EP].pipe)
53
54static usb_endpoint_description_t bulk_in_ep = {
55 .transfer_type = USB_TRANSFER_BULK,
56 .direction = USB_DIRECTION_IN,
57 .interface_class = USB_CLASS_MASS_STORAGE,
58 .interface_subclass = USB_MASSSTOR_SUBCLASS_SCSI,
59 .interface_protocol = USB_MASSSTOR_PROTOCOL_BBB,
60 .flags = 0
61};
62static usb_endpoint_description_t bulk_out_ep = {
63 .transfer_type = USB_TRANSFER_BULK,
64 .direction = USB_DIRECTION_OUT,
65 .interface_class = USB_CLASS_MASS_STORAGE,
66 .interface_subclass = USB_MASSSTOR_SUBCLASS_SCSI,
67 .interface_protocol = USB_MASSSTOR_PROTOCOL_BBB,
68 .flags = 0
69};
70
71usb_endpoint_description_t *mast_endpoints[] = {
72 &bulk_in_ep,
73 &bulk_out_ep,
74 NULL
75};
76
77#define BITS_GET_MASK(type, bitcount) (((type)(1 << (bitcount)))-1)
78#define BITS_GET_MID_MASK(type, bitcount, offset) \
79 ((type)( BITS_GET_MASK(type, (bitcount) + (offset)) - BITS_GET_MASK(type, bitcount) ))
80#define BITS_GET(type, number, bitcount, offset) \
81 ((type)( (number) & (BITS_GET_MID_MASK(type, bitcount, offset)) ) >> (offset))
82
83#define INQUIRY_RESPONSE_LENGTH 35
84
85static void try_inquiry(usb_device_t *dev)
86{
87 scsi_cmd_inquiry_t inquiry = {
88 .op_code = 0x12,
89 .lun_evpd = 0,
90 .page_code = 0,
91 .alloc_length = INQUIRY_RESPONSE_LENGTH,
92 .ctrl = 0
93 };
94 size_t response_len;
95 uint8_t response[INQUIRY_RESPONSE_LENGTH];
96
97 int rc;
98
99 rc = usb_massstor_data_in(GET_BULK_IN(dev), GET_BULK_OUT(dev),
100 0xDEADBEEF, 0, (uint8_t *) &inquiry, sizeof(inquiry),
101 response, INQUIRY_RESPONSE_LENGTH, &response_len);
102
103 if (rc != EOK) {
104 usb_log_error("Failed to probe device %s using %s: %s.\n",
105 dev->ddf_dev->name, "SCSI:INQUIRY", str_error(rc));
106 return;
107 }
108
109 if (response_len < 8) {
110 usb_log_error("The SCSI response is too short.\n");
111 return;
112 }
113
114 /*
115 * This is an ugly part of the code. We will parse the returned
116 * data by hand and try to get as many useful data as possible.
117 */
118 int device_type = BITS_GET(uint8_t, response[0], 5, 0);
119 int removable = BITS_GET(uint8_t, response[1], 1, 7);
120
121 usb_log_info("SCSI information for device `%s':\n", dev->ddf_dev->name);
122 usb_log_info(" - peripheral device type: %d\n", device_type);
123 usb_log_info(" - removable: %s\n", removable ? "yes" : "no");
124
125 if (response_len < 32) {
126 return;
127 }
128
129 char dev_vendor[9];
130 str_ncpy(dev_vendor, 9, (const char *) &response[8], 8);
131 usb_log_info(" - vendor: '%s'\n", dev_vendor);
132
133 char dev_product[9];
134 str_ncpy(dev_product, 9, (const char *) &response[16], 8);
135 usb_log_info(" - product: '%s'\n", dev_vendor);
136}
137
138/** Callback when new device is attached and recognized as a mass storage.
139 *
140 * @param dev Representation of a the USB device.
141 * @return Error code.
142 */
143static int usbmast_add_device(usb_device_t *dev)
144{
145 int rc;
146 const char *fun_name = "ctl";
147
148 ddf_fun_t *ctl_fun = ddf_fun_create(dev->ddf_dev, fun_exposed,
149 fun_name);
150 if (ctl_fun == NULL) {
151 usb_log_error("Failed to create control function.\n");
152 return ENOMEM;
153 }
154 rc = ddf_fun_bind(ctl_fun);
155 if (rc != EOK) {
156 usb_log_error("Failed to bind control function: %s.\n",
157 str_error(rc));
158 return rc;
159 }
160
161 usb_log_info("Pretending to control mass storage `%s'.\n",
162 dev->ddf_dev->name);
163 usb_log_debug(" Bulk in endpoint: %d [%zuB].\n",
164 dev->pipes[BULK_IN_EP].pipe->endpoint_no,
165 (size_t) dev->pipes[BULK_IN_EP].descriptor->max_packet_size);
166 usb_log_debug("Bulk out endpoint: %d [%zuB].\n",
167 dev->pipes[BULK_OUT_EP].pipe->endpoint_no,
168 (size_t) dev->pipes[BULK_OUT_EP].descriptor->max_packet_size);
169
170 try_inquiry(dev);
171
172 return EOK;
173}
174
175/** USB mass storage driver ops. */
176static usb_driver_ops_t usbmast_driver_ops = {
177 .add_device = usbmast_add_device,
178};
179
180/** USB mass storage driver. */
181static usb_driver_t usbmast_driver = {
182 .name = NAME,
183 .ops = &usbmast_driver_ops,
184 .endpoints = mast_endpoints
185};
186
187int main(int argc, char *argv[])
188{
189 usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
190
191 return usb_driver_main(&usbmast_driver);
192}
193
194/**
195 * @}
196 */
Note: See TracBrowser for help on using the repository browser.