Linux Audio

Check our new training course

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