1/*
2 * storage_common.c -- Common definitions for mass storage functionality
3 *
4 * Copyright (C) 2003-2008 Alan Stern
5 * Copyeight (C) 2009 Samsung Electronics
6 * Author: Michal Nazarewicz (mina86@mina86.com)
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 */
13
14/*
15 * This file requires the following identifiers used in USB strings to
16 * be defined (each of type pointer to char):
17 *  - fsg_string_interface    -- name of the interface
18 */
19
20/*
21 * When USB_GADGET_DEBUG_FILES is defined the module param num_buffers
22 * sets the number of pipeline buffers (length of the fsg_buffhd array).
23 * The valid range of num_buffers is: num >= 2 && num <= 4.
24 */
25
26#include <linux/module.h>
27#include <linux/blkdev.h>
28#include <linux/file.h>
29#include <linux/fs.h>
30#include <linux/usb/composite.h>
31
32#include "storage_common.h"
33
34/* There is only one interface. */
35
36struct usb_interface_descriptor fsg_intf_desc = {
37	.bLength =		sizeof fsg_intf_desc,
38	.bDescriptorType =	USB_DT_INTERFACE,
39
40	.bNumEndpoints =	2,		/* Adjusted during fsg_bind() */
41	.bInterfaceClass =	USB_CLASS_MASS_STORAGE,
42	.bInterfaceSubClass =	USB_SC_SCSI,	/* Adjusted during fsg_bind() */
43	.bInterfaceProtocol =	USB_PR_BULK,	/* Adjusted during fsg_bind() */
44	.iInterface =		FSG_STRING_INTERFACE,
45};
46EXPORT_SYMBOL_GPL(fsg_intf_desc);
47
48/*
49 * Three full-speed endpoint descriptors: bulk-in, bulk-out, and
50 * interrupt-in.
51 */
52
53struct usb_endpoint_descriptor fsg_fs_bulk_in_desc = {
54	.bLength =		USB_DT_ENDPOINT_SIZE,
55	.bDescriptorType =	USB_DT_ENDPOINT,
56
57	.bEndpointAddress =	USB_DIR_IN,
58	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
59	/* wMaxPacketSize set by autoconfiguration */
60};
61EXPORT_SYMBOL_GPL(fsg_fs_bulk_in_desc);
62
63struct usb_endpoint_descriptor fsg_fs_bulk_out_desc = {
64	.bLength =		USB_DT_ENDPOINT_SIZE,
65	.bDescriptorType =	USB_DT_ENDPOINT,
66
67	.bEndpointAddress =	USB_DIR_OUT,
68	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
69	/* wMaxPacketSize set by autoconfiguration */
70};
71EXPORT_SYMBOL_GPL(fsg_fs_bulk_out_desc);
72
73struct usb_descriptor_header *fsg_fs_function[] = {
74	(struct usb_descriptor_header *) &fsg_intf_desc,
75	(struct usb_descriptor_header *) &fsg_fs_bulk_in_desc,
76	(struct usb_descriptor_header *) &fsg_fs_bulk_out_desc,
77	NULL,
78};
79EXPORT_SYMBOL_GPL(fsg_fs_function);
80
81
82/*
83 * USB 2.0 devices need to expose both high speed and full speed
84 * descriptors, unless they only run at full speed.
85 *
86 * That means alternate endpoint descriptors (bigger packets)
87 * and a "device qualifier" ... plus more construction options
88 * for the configuration descriptor.
89 */
90struct usb_endpoint_descriptor fsg_hs_bulk_in_desc = {
91	.bLength =		USB_DT_ENDPOINT_SIZE,
92	.bDescriptorType =	USB_DT_ENDPOINT,
93
94	/* bEndpointAddress copied from fs_bulk_in_desc during fsg_bind() */
95	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
96	.wMaxPacketSize =	cpu_to_le16(512),
97};
98EXPORT_SYMBOL_GPL(fsg_hs_bulk_in_desc);
99
100struct usb_endpoint_descriptor fsg_hs_bulk_out_desc = {
101	.bLength =		USB_DT_ENDPOINT_SIZE,
102	.bDescriptorType =	USB_DT_ENDPOINT,
103
104	/* bEndpointAddress copied from fs_bulk_out_desc during fsg_bind() */
105	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
106	.wMaxPacketSize =	cpu_to_le16(512),
107	.bInterval =		1,	/* NAK every 1 uframe */
108};
109EXPORT_SYMBOL_GPL(fsg_hs_bulk_out_desc);
110
111
112struct usb_descriptor_header *fsg_hs_function[] = {
113	(struct usb_descriptor_header *) &fsg_intf_desc,
114	(struct usb_descriptor_header *) &fsg_hs_bulk_in_desc,
115	(struct usb_descriptor_header *) &fsg_hs_bulk_out_desc,
116	NULL,
117};
118EXPORT_SYMBOL_GPL(fsg_hs_function);
119
120struct usb_endpoint_descriptor fsg_ss_bulk_in_desc = {
121	.bLength =		USB_DT_ENDPOINT_SIZE,
122	.bDescriptorType =	USB_DT_ENDPOINT,
123
124	/* bEndpointAddress copied from fs_bulk_in_desc during fsg_bind() */
125	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
126	.wMaxPacketSize =	cpu_to_le16(1024),
127};
128EXPORT_SYMBOL_GPL(fsg_ss_bulk_in_desc);
129
130struct usb_ss_ep_comp_descriptor fsg_ss_bulk_in_comp_desc = {
131	.bLength =		sizeof(fsg_ss_bulk_in_comp_desc),
132	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP,
133
134	/*.bMaxBurst =		DYNAMIC, */
135};
136EXPORT_SYMBOL_GPL(fsg_ss_bulk_in_comp_desc);
137
138struct usb_endpoint_descriptor fsg_ss_bulk_out_desc = {
139	.bLength =		USB_DT_ENDPOINT_SIZE,
140	.bDescriptorType =	USB_DT_ENDPOINT,
141
142	/* bEndpointAddress copied from fs_bulk_out_desc during fsg_bind() */
143	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
144	.wMaxPacketSize =	cpu_to_le16(1024),
145};
146EXPORT_SYMBOL_GPL(fsg_ss_bulk_out_desc);
147
148struct usb_ss_ep_comp_descriptor fsg_ss_bulk_out_comp_desc = {
149	.bLength =		sizeof(fsg_ss_bulk_in_comp_desc),
150	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP,
151
152	/*.bMaxBurst =		DYNAMIC, */
153};
154EXPORT_SYMBOL_GPL(fsg_ss_bulk_out_comp_desc);
155
156struct usb_descriptor_header *fsg_ss_function[] = {
157	(struct usb_descriptor_header *) &fsg_intf_desc,
158	(struct usb_descriptor_header *) &fsg_ss_bulk_in_desc,
159	(struct usb_descriptor_header *) &fsg_ss_bulk_in_comp_desc,
160	(struct usb_descriptor_header *) &fsg_ss_bulk_out_desc,
161	(struct usb_descriptor_header *) &fsg_ss_bulk_out_comp_desc,
162	NULL,
163};
164EXPORT_SYMBOL_GPL(fsg_ss_function);
165
166
167 /*-------------------------------------------------------------------------*/
168
169/*
170 * If the next two routines are called while the gadget is registered,
171 * the caller must own fsg->filesem for writing.
172 */
173
174void fsg_lun_close(struct fsg_lun *curlun)
175{
176	if (curlun->filp) {
177		LDBG(curlun, "close backing file\n");
178		fput(curlun->filp);
179		curlun->filp = NULL;
180	}
181}
182EXPORT_SYMBOL_GPL(fsg_lun_close);
183
184int fsg_lun_open(struct fsg_lun *curlun, const char *filename)
185{
186	int				ro;
187	struct file			*filp = NULL;
188	int				rc = -EINVAL;
189	struct inode			*inode = NULL;
190	loff_t				size;
191	loff_t				num_sectors;
192	loff_t				min_sectors;
193	unsigned int			blkbits;
194	unsigned int			blksize;
195
196	/* R/W if we can, R/O if we must */
197	ro = curlun->initially_ro;
198	if (!ro) {
199		filp = filp_open(filename, O_RDWR | O_LARGEFILE, 0);
200		if (PTR_ERR(filp) == -EROFS || PTR_ERR(filp) == -EACCES)
201			ro = 1;
202	}
203	if (ro)
204		filp = filp_open(filename, O_RDONLY | O_LARGEFILE, 0);
205	if (IS_ERR(filp)) {
206		LINFO(curlun, "unable to open backing file: %s\n", filename);
207		return PTR_ERR(filp);
208	}
209
210	if (!(filp->f_mode & FMODE_WRITE))
211		ro = 1;
212
213	inode = file_inode(filp);
214	if ((!S_ISREG(inode->i_mode) && !S_ISBLK(inode->i_mode))) {
215		LINFO(curlun, "invalid file type: %s\n", filename);
216		goto out;
217	}
218
219	/*
220	 * If we can't read the file, it's no good.
221	 * If we can't write the file, use it read-only.
222	 */
223	if (!(filp->f_mode & FMODE_CAN_READ)) {
224		LINFO(curlun, "file not readable: %s\n", filename);
225		goto out;
226	}
227	if (!(filp->f_mode & FMODE_CAN_WRITE))
228		ro = 1;
229
230	size = i_size_read(inode->i_mapping->host);
231	if (size < 0) {
232		LINFO(curlun, "unable to find file size: %s\n", filename);
233		rc = (int) size;
234		goto out;
235	}
236
237	if (curlun->cdrom) {
238		blksize = 2048;
239		blkbits = 11;
240	} else if (inode->i_bdev) {
241		blksize = bdev_logical_block_size(inode->i_bdev);
242		blkbits = blksize_bits(blksize);
243	} else {
244		blksize = 512;
245		blkbits = 9;
246	}
247
248	num_sectors = size >> blkbits; /* File size in logic-block-size blocks */
249	min_sectors = 1;
250	if (curlun->cdrom) {
251		min_sectors = 300;	/* Smallest track is 300 frames */
252		if (num_sectors >= 256*60*75) {
253			num_sectors = 256*60*75 - 1;
254			LINFO(curlun, "file too big: %s\n", filename);
255			LINFO(curlun, "using only first %d blocks\n",
256					(int) num_sectors);
257		}
258	}
259	if (num_sectors < min_sectors) {
260		LINFO(curlun, "file too small: %s\n", filename);
261		rc = -ETOOSMALL;
262		goto out;
263	}
264
265	if (fsg_lun_is_open(curlun))
266		fsg_lun_close(curlun);
267
268	curlun->blksize = blksize;
269	curlun->blkbits = blkbits;
270	curlun->ro = ro;
271	curlun->filp = filp;
272	curlun->file_length = size;
273	curlun->num_sectors = num_sectors;
274	LDBG(curlun, "open backing file: %s\n", filename);
275	return 0;
276
277out:
278	fput(filp);
279	return rc;
280}
281EXPORT_SYMBOL_GPL(fsg_lun_open);
282
283
284/*-------------------------------------------------------------------------*/
285
286/*
287 * Sync the file data, don't bother with the metadata.
288 * This code was copied from fs/buffer.c:sys_fdatasync().
289 */
290int fsg_lun_fsync_sub(struct fsg_lun *curlun)
291{
292	struct file	*filp = curlun->filp;
293
294	if (curlun->ro || !filp)
295		return 0;
296	return vfs_fsync(filp, 1);
297}
298EXPORT_SYMBOL_GPL(fsg_lun_fsync_sub);
299
300void store_cdrom_address(u8 *dest, int msf, u32 addr)
301{
302	if (msf) {
303		/* Convert to Minutes-Seconds-Frames */
304		addr >>= 2;		/* Convert to 2048-byte frames */
305		addr += 2*75;		/* Lead-in occupies 2 seconds */
306		dest[3] = addr % 75;	/* Frames */
307		addr /= 75;
308		dest[2] = addr % 60;	/* Seconds */
309		addr /= 60;
310		dest[1] = addr;		/* Minutes */
311		dest[0] = 0;		/* Reserved */
312	} else {
313		/* Absolute sector */
314		put_unaligned_be32(addr, dest);
315	}
316}
317EXPORT_SYMBOL_GPL(store_cdrom_address);
318
319/*-------------------------------------------------------------------------*/
320
321
322ssize_t fsg_show_ro(struct fsg_lun *curlun, char *buf)
323{
324	return sprintf(buf, "%d\n", fsg_lun_is_open(curlun)
325				  ? curlun->ro
326				  : curlun->initially_ro);
327}
328EXPORT_SYMBOL_GPL(fsg_show_ro);
329
330ssize_t fsg_show_nofua(struct fsg_lun *curlun, char *buf)
331{
332	return sprintf(buf, "%u\n", curlun->nofua);
333}
334EXPORT_SYMBOL_GPL(fsg_show_nofua);
335
336ssize_t fsg_show_file(struct fsg_lun *curlun, struct rw_semaphore *filesem,
337		      char *buf)
338{
339	char		*p;
340	ssize_t		rc;
341
342	down_read(filesem);
343	if (fsg_lun_is_open(curlun)) {	/* Get the complete pathname */
344		p = file_path(curlun->filp, buf, PAGE_SIZE - 1);
345		if (IS_ERR(p))
346			rc = PTR_ERR(p);
347		else {
348			rc = strlen(p);
349			memmove(buf, p, rc);
350			buf[rc] = '\n';		/* Add a newline */
351			buf[++rc] = 0;
352		}
353	} else {				/* No file, return 0 bytes */
354		*buf = 0;
355		rc = 0;
356	}
357	up_read(filesem);
358	return rc;
359}
360EXPORT_SYMBOL_GPL(fsg_show_file);
361
362ssize_t fsg_show_cdrom(struct fsg_lun *curlun, char *buf)
363{
364	return sprintf(buf, "%u\n", curlun->cdrom);
365}
366EXPORT_SYMBOL_GPL(fsg_show_cdrom);
367
368ssize_t fsg_show_removable(struct fsg_lun *curlun, char *buf)
369{
370	return sprintf(buf, "%u\n", curlun->removable);
371}
372EXPORT_SYMBOL_GPL(fsg_show_removable);
373
374/*
375 * The caller must hold fsg->filesem for reading when calling this function.
376 */
377static ssize_t _fsg_store_ro(struct fsg_lun *curlun, bool ro)
378{
379	if (fsg_lun_is_open(curlun)) {
380		LDBG(curlun, "read-only status change prevented\n");
381		return -EBUSY;
382	}
383
384	curlun->ro = ro;
385	curlun->initially_ro = ro;
386	LDBG(curlun, "read-only status set to %d\n", curlun->ro);
387
388	return 0;
389}
390
391ssize_t fsg_store_ro(struct fsg_lun *curlun, struct rw_semaphore *filesem,
392		     const char *buf, size_t count)
393{
394	ssize_t		rc;
395	bool		ro;
396
397	rc = strtobool(buf, &ro);
398	if (rc)
399		return rc;
400
401	/*
402	 * Allow the write-enable status to change only while the
403	 * backing file is closed.
404	 */
405	down_read(filesem);
406	rc = _fsg_store_ro(curlun, ro);
407	if (!rc)
408		rc = count;
409	up_read(filesem);
410
411	return rc;
412}
413EXPORT_SYMBOL_GPL(fsg_store_ro);
414
415ssize_t fsg_store_nofua(struct fsg_lun *curlun, const char *buf, size_t count)
416{
417	bool		nofua;
418	int		ret;
419
420	ret = strtobool(buf, &nofua);
421	if (ret)
422		return ret;
423
424	/* Sync data when switching from async mode to sync */
425	if (!nofua && curlun->nofua)
426		fsg_lun_fsync_sub(curlun);
427
428	curlun->nofua = nofua;
429
430	return count;
431}
432EXPORT_SYMBOL_GPL(fsg_store_nofua);
433
434ssize_t fsg_store_file(struct fsg_lun *curlun, struct rw_semaphore *filesem,
435		       const char *buf, size_t count)
436{
437	int		rc = 0;
438
439	if (curlun->prevent_medium_removal && fsg_lun_is_open(curlun)) {
440		LDBG(curlun, "eject attempt prevented\n");
441		return -EBUSY;				/* "Door is locked" */
442	}
443
444	/* Remove a trailing newline */
445	if (count > 0 && buf[count-1] == '\n')
446		((char *) buf)[count-1] = 0;		/* Ugh! */
447
448	/* Load new medium */
449	down_write(filesem);
450	if (count > 0 && buf[0]) {
451		/* fsg_lun_open() will close existing file if any. */
452		rc = fsg_lun_open(curlun, buf);
453		if (rc == 0)
454			curlun->unit_attention_data =
455					SS_NOT_READY_TO_READY_TRANSITION;
456	} else if (fsg_lun_is_open(curlun)) {
457		fsg_lun_close(curlun);
458		curlun->unit_attention_data = SS_MEDIUM_NOT_PRESENT;
459	}
460	up_write(filesem);
461	return (rc < 0 ? rc : count);
462}
463EXPORT_SYMBOL_GPL(fsg_store_file);
464
465ssize_t fsg_store_cdrom(struct fsg_lun *curlun, struct rw_semaphore *filesem,
466			const char *buf, size_t count)
467{
468	bool		cdrom;
469	int		ret;
470
471	ret = strtobool(buf, &cdrom);
472	if (ret)
473		return ret;
474
475	down_read(filesem);
476	ret = cdrom ? _fsg_store_ro(curlun, true) : 0;
477
478	if (!ret) {
479		curlun->cdrom = cdrom;
480		ret = count;
481	}
482	up_read(filesem);
483
484	return ret;
485}
486EXPORT_SYMBOL_GPL(fsg_store_cdrom);
487
488ssize_t fsg_store_removable(struct fsg_lun *curlun, const char *buf,
489			    size_t count)
490{
491	bool		removable;
492	int		ret;
493
494	ret = strtobool(buf, &removable);
495	if (ret)
496		return ret;
497
498	curlun->removable = removable;
499
500	return count;
501}
502EXPORT_SYMBOL_GPL(fsg_store_removable);
503
504MODULE_LICENSE("GPL");
505