• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * mass_storage.c -- Mass Storage USB Gadget
4  *
5  * Copyright (C) 2003-2008 Alan Stern
6  * Copyright (C) 2009 Samsung Electronics
7  *                    Author: Michal Nazarewicz <mina86@mina86.com>
8  * All rights reserved.
9  */
10 
11 
12 /*
13  * The Mass Storage Gadget acts as a USB Mass Storage device,
14  * appearing to the host as a disk drive or as a CD-ROM drive.  In
15  * addition to providing an example of a genuinely useful gadget
16  * driver for a USB device, it also illustrates a technique of
17  * double-buffering for increased throughput.  Last but not least, it
18  * gives an easy way to probe the behavior of the Mass Storage drivers
19  * in a USB host.
20  *
21  * Since this file serves only administrative purposes and all the
22  * business logic is implemented in f_mass_storage.* file.  Read
23  * comments in this file for more detailed description.
24  */
25 
26 
27 #include <linux/kernel.h>
28 #include <linux/usb/ch9.h>
29 #include <linux/module.h>
30 
31 /*-------------------------------------------------------------------------*/
32 
33 #define DRIVER_DESC		"Mass Storage Gadget"
34 #define DRIVER_VERSION		"2009/09/11"
35 
36 /*
37  * Thanks to NetChip Technologies for donating this product ID.
38  *
39  * DO NOT REUSE THESE IDs with any other driver!!  Ever!!
40  * Instead:  allocate your own, using normal USB-IF procedures.
41  */
42 #define FSG_VENDOR_ID	0x0525	/* NetChip */
43 #define FSG_PRODUCT_ID	0xa4a5	/* Linux-USB File-backed Storage Gadget */
44 
45 #include "f_mass_storage.h"
46 
47 /*-------------------------------------------------------------------------*/
48 USB_GADGET_COMPOSITE_OPTIONS();
49 
50 static struct usb_device_descriptor msg_device_desc = {
51 	.bLength =		sizeof msg_device_desc,
52 	.bDescriptorType =	USB_DT_DEVICE,
53 
54 	/* .bcdUSB = DYNAMIC */
55 	.bDeviceClass =		USB_CLASS_PER_INTERFACE,
56 
57 	/* Vendor and product id can be overridden by module parameters.  */
58 	.idVendor =		cpu_to_le16(FSG_VENDOR_ID),
59 	.idProduct =		cpu_to_le16(FSG_PRODUCT_ID),
60 	.bNumConfigurations =	1,
61 };
62 
63 static const struct usb_descriptor_header *otg_desc[2];
64 
65 static struct usb_string strings_dev[] = {
66 	[USB_GADGET_MANUFACTURER_IDX].s = "",
67 	[USB_GADGET_PRODUCT_IDX].s = DRIVER_DESC,
68 	[USB_GADGET_SERIAL_IDX].s = "",
69 	{  } /* end of list */
70 };
71 
72 static struct usb_gadget_strings stringtab_dev = {
73 	.language       = 0x0409,       /* en-us */
74 	.strings        = strings_dev,
75 };
76 
77 static struct usb_gadget_strings *dev_strings[] = {
78 	&stringtab_dev,
79 	NULL,
80 };
81 
82 static struct usb_function_instance *fi_msg;
83 static struct usb_function *f_msg;
84 
85 /****************************** Configurations ******************************/
86 
87 static struct fsg_module_parameters mod_data = {
88 	.stall = 1
89 };
90 #ifdef CONFIG_USB_GADGET_DEBUG_FILES
91 
92 static unsigned int fsg_num_buffers = CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS;
93 
94 #else
95 
96 /*
97  * Number of buffers we will use.
98  * 2 is usually enough for good buffering pipeline
99  */
100 #define fsg_num_buffers	CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS
101 
102 #endif /* CONFIG_USB_GADGET_DEBUG_FILES */
103 
104 FSG_MODULE_PARAMETERS(/* no prefix */, mod_data);
105 
msg_do_config(struct usb_configuration * c)106 static int msg_do_config(struct usb_configuration *c)
107 {
108 	int ret;
109 
110 	if (gadget_is_otg(c->cdev->gadget)) {
111 		c->descriptors = otg_desc;
112 		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
113 	}
114 
115 	f_msg = usb_get_function(fi_msg);
116 	if (IS_ERR(f_msg))
117 		return PTR_ERR(f_msg);
118 
119 	ret = usb_add_function(c, f_msg);
120 	if (ret)
121 		goto put_func;
122 
123 	return 0;
124 
125 put_func:
126 	usb_put_function(f_msg);
127 	return ret;
128 }
129 
130 static struct usb_configuration msg_config_driver = {
131 	.label			= "Linux File-Backed Storage",
132 	.bConfigurationValue	= 1,
133 	.bmAttributes		= USB_CONFIG_ATT_SELFPOWER,
134 };
135 
136 
137 /****************************** Gadget Bind ******************************/
138 
msg_bind(struct usb_composite_dev * cdev)139 static int msg_bind(struct usb_composite_dev *cdev)
140 {
141 	struct fsg_opts *opts;
142 	struct fsg_config config;
143 	int status;
144 
145 	fi_msg = usb_get_function_instance("mass_storage");
146 	if (IS_ERR(fi_msg))
147 		return PTR_ERR(fi_msg);
148 
149 	fsg_config_from_params(&config, &mod_data, fsg_num_buffers);
150 	opts = fsg_opts_from_func_inst(fi_msg);
151 
152 	opts->no_configfs = true;
153 	status = fsg_common_set_num_buffers(opts->common, fsg_num_buffers);
154 	if (status)
155 		goto fail;
156 
157 	status = fsg_common_set_cdev(opts->common, cdev, config.can_stall);
158 	if (status)
159 		goto fail_set_cdev;
160 
161 	fsg_common_set_sysfs(opts->common, true);
162 	status = fsg_common_create_luns(opts->common, &config);
163 	if (status)
164 		goto fail_set_cdev;
165 
166 	fsg_common_set_inquiry_string(opts->common, config.vendor_name,
167 				      config.product_name);
168 
169 	status = usb_string_ids_tab(cdev, strings_dev);
170 	if (status < 0)
171 		goto fail_string_ids;
172 	msg_device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
173 
174 	if (gadget_is_otg(cdev->gadget) && !otg_desc[0]) {
175 		struct usb_descriptor_header *usb_desc;
176 
177 		usb_desc = usb_otg_descriptor_alloc(cdev->gadget);
178 		if (!usb_desc)
179 			goto fail_string_ids;
180 		usb_otg_descriptor_init(cdev->gadget, usb_desc);
181 		otg_desc[0] = usb_desc;
182 		otg_desc[1] = NULL;
183 	}
184 
185 	status = usb_add_config(cdev, &msg_config_driver, msg_do_config);
186 	if (status < 0)
187 		goto fail_otg_desc;
188 
189 	usb_composite_overwrite_options(cdev, &coverwrite);
190 	dev_info(&cdev->gadget->dev,
191 		 DRIVER_DESC ", version: " DRIVER_VERSION "\n");
192 	return 0;
193 
194 fail_otg_desc:
195 	kfree(otg_desc[0]);
196 	otg_desc[0] = NULL;
197 fail_string_ids:
198 	fsg_common_remove_luns(opts->common);
199 fail_set_cdev:
200 	fsg_common_free_buffers(opts->common);
201 fail:
202 	usb_put_function_instance(fi_msg);
203 	return status;
204 }
205 
msg_unbind(struct usb_composite_dev * cdev)206 static int msg_unbind(struct usb_composite_dev *cdev)
207 {
208 	if (!IS_ERR(f_msg))
209 		usb_put_function(f_msg);
210 
211 	if (!IS_ERR(fi_msg))
212 		usb_put_function_instance(fi_msg);
213 
214 	kfree(otg_desc[0]);
215 	otg_desc[0] = NULL;
216 
217 	return 0;
218 }
219 
220 /****************************** Some noise ******************************/
221 
222 static struct usb_composite_driver msg_driver = {
223 	.name		= "g_mass_storage",
224 	.dev		= &msg_device_desc,
225 	.max_speed	= USB_SPEED_SUPER_PLUS,
226 	.needs_serial	= 1,
227 	.strings	= dev_strings,
228 	.bind		= msg_bind,
229 	.unbind		= msg_unbind,
230 };
231 
232 module_usb_composite_driver(msg_driver);
233 
234 MODULE_DESCRIPTION(DRIVER_DESC);
235 MODULE_AUTHOR("Michal Nazarewicz");
236 MODULE_LICENSE("GPL");
237