usb_template_msc.c 6.19 KB
Newer Older
1
/* $FreeBSD$ */
2
/*-
3
 * Copyright (c) 2008 Hans Petter Selasky <hselasky@FreeBSD.org>
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * This file contains the USB templates for an USB Mass Storage Device.
 */

32
33
34
#ifdef USB_GLOBAL_INCLUDE_FILE
#include USB_GLOBAL_INCLUDE_FILE
#else
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
#include <sys/queue.h>
#include <sys/types.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/bus.h>
#include <sys/module.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/condvar.h>
#include <sys/sysctl.h>
#include <sys/sx.h>
#include <sys/unistd.h>
#include <sys/callout.h>
#include <sys/malloc.h>
#include <sys/priv.h>
53

54
55
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
56

57
#include <dev/usb/template/usb_template.h>
58
#endif			/* USB_GLOBAL_INCLUDE_FILE */
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116

enum {
	STRING_LANG_INDEX,
	STRING_MSC_DATA_INDEX,
	STRING_MSC_CONFIG_INDEX,
	STRING_MSC_VENDOR_INDEX,
	STRING_MSC_PRODUCT_INDEX,
	STRING_MSC_SERIAL_INDEX,
	STRING_MSC_MAX,
};

#define	STRING_LANG \
  0x09, 0x04,				/* American English */

#define	STRING_MSC_DATA	\
  'U', 0, 'S', 0, 'B', 0, ' ', 0, \
  'M', 0, 'a', 0, 's', 0, 's', 0, \
  ' ', 0, 'S', 0, 't', 0, 'o', 0, \
  'r', 0, 'a', 0, 'g', 0, 'e', 0, \
  ' ', 0, 'I', 0, 'n', 0, 't', 0, \
  'e', 0, 'r', 0, 'f', 0, 'a', 0, \
  'c', 0, 'e', 0,

#define	STRING_MSC_CONFIG \
  'D', 0, 'e', 0, 'f', 0, 'a', 0, \
  'u', 0, 'l', 0, 't', 0, ' ', 0, \
  'c', 0, 'o', 0, 'n', 0, 'f', 0, \
  'i', 0, 'g', 0,

#define	STRING_MSC_VENDOR \
  'F', 0, 'r', 0, 'e', 0, 'e', 0, \
  'B', 0, 'S', 0, 'D', 0, ' ', 0, \
  'f', 0, 'o', 0, 'u', 0, 'n', 0, \
  'd', 0, 'a', 0, 't', 0, 'i', 0, \
  'o', 0, 'n', 0,

#define	STRING_MSC_PRODUCT \
  'U', 0, 'S', 0, 'B', 0, ' ', 0, \
  'M', 0, 'e', 0, 'm', 0, 'o', 0, \
  'r', 0, 'y', 0, ' ', 0, 'S', 0, \
  't', 0, 'i', 0, 'c', 0, 'k', 0

#define	STRING_MSC_SERIAL \
  'M', 0, 'a', 0, 'r', 0, 'c', 0, \
  'h', 0, ' ', 0, '2', 0, '0', 0, \
  '0', 0, '8', 0,

/* make the real string descriptors */

USB_MAKE_STRING_DESC(STRING_LANG, string_lang);
USB_MAKE_STRING_DESC(STRING_MSC_DATA, string_msc_data);
USB_MAKE_STRING_DESC(STRING_MSC_CONFIG, string_msc_config);
USB_MAKE_STRING_DESC(STRING_MSC_VENDOR, string_msc_vendor);
USB_MAKE_STRING_DESC(STRING_MSC_PRODUCT, string_msc_product);
USB_MAKE_STRING_DESC(STRING_MSC_SERIAL, string_msc_serial);

/* prototypes */

117
static usb_temp_get_string_desc_t msc_get_string_desc;
118

119
static const struct usb_temp_packet_size bulk_mps = {
120
121
122
123
	.mps[USB_SPEED_FULL] = 64,
	.mps[USB_SPEED_HIGH] = 512,
};

124
static const struct usb_temp_endpoint_desc bulk_in_ep = {
125
126
127
128
129
130
131
132
133
	.pPacketSize = &bulk_mps,
#ifdef USB_HIP_IN_EP_0
	.bEndpointAddress = USB_HIP_IN_EP_0,
#else
	.bEndpointAddress = UE_DIR_IN,
#endif
	.bmAttributes = UE_BULK,
};

134
static const struct usb_temp_endpoint_desc bulk_out_ep = {
135
136
137
138
139
140
141
142
143
	.pPacketSize = &bulk_mps,
#ifdef USB_HIP_OUT_EP_0
	.bEndpointAddress = USB_HIP_OUT_EP_0,
#else
	.bEndpointAddress = UE_DIR_OUT,
#endif
	.bmAttributes = UE_BULK,
};

144
static const struct usb_temp_endpoint_desc *msc_data_endpoints[] = {
145
146
147
148
149
	&bulk_in_ep,
	&bulk_out_ep,
	NULL,
};

150
static const struct usb_temp_interface_desc msc_data_interface = {
151
152
153
154
155
156
157
	.ppEndpoints = msc_data_endpoints,
	.bInterfaceClass = UICLASS_MASS,
	.bInterfaceSubClass = UISUBCLASS_SCSI,
	.bInterfaceProtocol = UIPROTO_MASS_BBB,
	.iInterface = STRING_MSC_DATA_INDEX,
};

158
static const struct usb_temp_interface_desc *msc_interfaces[] = {
159
160
161
162
	&msc_data_interface,
	NULL,
};

163
static const struct usb_temp_config_desc msc_config_desc = {
164
165
166
167
168
169
	.ppIfaceDesc = msc_interfaces,
	.bmAttributes = UC_BUS_POWERED,
	.bMaxPower = 25,		/* 50 mA */
	.iConfiguration = STRING_MSC_CONFIG_INDEX,
};

170
static const struct usb_temp_config_desc *msc_configs[] = {
171
172
173
174
	&msc_config_desc,
	NULL,
};

175
const struct usb_temp_device_desc usb_template_msc = {
176
177
	.getStringDesc = &msc_get_string_desc,
	.ppConfigDesc = msc_configs,
178
179
	.idVendor = USB_TEMPLATE_VENDOR,
	.idProduct = 0x0012,
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
	.bcdDevice = 0x0100,
	.bDeviceClass = UDCLASS_COMM,
	.bDeviceSubClass = 0,
	.bDeviceProtocol = 0,
	.iManufacturer = STRING_MSC_VENDOR_INDEX,
	.iProduct = STRING_MSC_PRODUCT_INDEX,
	.iSerialNumber = STRING_MSC_SERIAL_INDEX,
};

/*------------------------------------------------------------------------*
 *	msc_get_string_desc
 *
 * Return values:
 * NULL: Failure. No such string.
 * Else: Success. Pointer to string descriptor is returned.
 *------------------------------------------------------------------------*/
static const void *
msc_get_string_desc(uint16_t lang_id, uint8_t string_index)
{
	static const void *ptr[STRING_MSC_MAX] = {
		[STRING_LANG_INDEX] = &string_lang,
		[STRING_MSC_DATA_INDEX] = &string_msc_data,
		[STRING_MSC_CONFIG_INDEX] = &string_msc_config,
		[STRING_MSC_VENDOR_INDEX] = &string_msc_vendor,
		[STRING_MSC_PRODUCT_INDEX] = &string_msc_product,
		[STRING_MSC_SERIAL_INDEX] = &string_msc_serial,
	};

	if (string_index == 0) {
		return (&string_lang);
	}
	if (lang_id != 0x0409) {
		return (NULL);
	}
	if (string_index < STRING_MSC_MAX) {
		return (ptr[string_index]);
	}
	return (NULL);
}