2009-10-28 18:57:14 +03:00
/*
* storage_common . c - - Common definitions for mass storage functionality
*
* Copyright ( C ) 2003 - 2008 Alan Stern
* Copyeight ( C ) 2009 Samsung Electronics
* Author : Michal Nazarewicz ( m . nazarewicz @ samsung . com )
2009-10-28 18:57:15 +03:00
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*/
/*
* This file requires the following identifiers used in USB strings to
* be defined ( each of type pointer to char ) :
* - fsg_string_manufacturer - - name of the manufacturer
* - fsg_string_product - - name of the product
* - fsg_string_serial - - product ' s serial
* - fsg_string_config - - name of the configuration
* - fsg_string_interface - - name of the interface
* The first four are only needed when FSG_DESCRIPTORS_DEVICE_STRINGS
* macro is defined prior to including this file .
2009-10-28 18:57:14 +03:00
*/
2009-10-28 18:57:15 +03:00
# include <asm/unaligned.h>
2009-10-28 18:57:14 +03:00
/*-------------------------------------------------------------------------*/
# ifndef DEBUG
# undef VERBOSE_DEBUG
# undef DUMP_MSGS
# endif /* !DEBUG */
# ifdef VERBOSE_DEBUG
# define VLDBG LDBG
# else
# define VLDBG(lun, fmt, args...) do { } while (0)
# endif /* VERBOSE_DEBUG */
# define LDBG(lun, fmt, args...) dev_dbg (&(lun)->dev, fmt, ## args)
# define LERROR(lun, fmt, args...) dev_err (&(lun)->dev, fmt, ## args)
# define LWARN(lun, fmt, args...) dev_warn(&(lun)->dev, fmt, ## args)
# define LINFO(lun, fmt, args...) dev_info(&(lun)->dev, fmt, ## args)
# define DBG(d, fmt, args...) dev_dbg (&(d)->gadget->dev, fmt, ## args)
# define VDBG(d, fmt, args...) dev_vdbg(&(d)->gadget->dev, fmt, ## args)
# define ERROR(d, fmt, args...) dev_err (&(d)->gadget->dev, fmt, ## args)
# define WARNING(d, fmt, args...) dev_warn(&(d)->gadget->dev, fmt, ## args)
# define INFO(d, fmt, args...) dev_info(&(d)->gadget->dev, fmt, ## args)
# ifdef DUMP_MSGS
# define dump_msg(fsg, /* const char * */ label, \
/* const u8 * */ buf , /* unsigned */ length ) do { \
if ( length < 512 ) { \
DBG ( fsg , " %s, length %u: \n " , label , length ) ; \
print_hex_dump ( KERN_DEBUG , " " , DUMP_PREFIX_OFFSET , \
16 , 1 , buf , length , 0 ) ; \
} \
} while ( 0 )
# define dump_cdb(fsg) do { } while (0)
# else
# define dump_msg(fsg, /* const char * */ label, \
/* const u8 * */ buf , /* unsigned */ length ) do { } while ( 0 )
# ifdef VERBOSE_DEBUG
# define dump_cdb(fsg) \
print_hex_dump ( KERN_DEBUG , " SCSI CDB: " , DUMP_PREFIX_NONE , \
16 , 1 , ( fsg ) - > cmnd , ( fsg ) - > cmnd_size , 0 ) \
# else
# define dump_cdb(fsg) do { } while (0)
# endif /* VERBOSE_DEBUG */
# endif /* DUMP_MSGS */
/*-------------------------------------------------------------------------*/
/* SCSI device types */
# define TYPE_DISK 0x00
# define TYPE_CDROM 0x05
/* USB protocol value = the transport method */
# define USB_PR_CBI 0x00 // Control/Bulk/Interrupt
# define USB_PR_CB 0x01 // Control/Bulk w/o interrupt
# define USB_PR_BULK 0x50 // Bulk-only
/* USB subclass value = the protocol encapsulation */
# define USB_SC_RBC 0x01 // Reduced Block Commands (flash)
# define USB_SC_8020 0x02 // SFF-8020i, MMC-2, ATAPI (CD-ROM)
# define USB_SC_QIC 0x03 // QIC-157 (tape)
# define USB_SC_UFI 0x04 // UFI (floppy)
# define USB_SC_8070 0x05 // SFF-8070i (removable)
# define USB_SC_SCSI 0x06 // Transparent SCSI
/* Bulk-only data structures */
/* Command Block Wrapper */
2009-10-28 18:57:15 +03:00
struct fsg_bulk_cb_wrap {
2009-10-28 18:57:14 +03:00
__le32 Signature ; // Contains 'USBC'
u32 Tag ; // Unique per command id
__le32 DataTransferLength ; // Size of the data
u8 Flags ; // Direction in bit 7
u8 Lun ; // LUN (normally 0)
u8 Length ; // Of the CDB, <= MAX_COMMAND_SIZE
u8 CDB [ 16 ] ; // Command Data Block
} ;
# define USB_BULK_CB_WRAP_LEN 31
# define USB_BULK_CB_SIG 0x43425355 // Spells out USBC
# define USB_BULK_IN_FLAG 0x80
/* Command Status Wrapper */
struct bulk_cs_wrap {
__le32 Signature ; // Should = 'USBS'
u32 Tag ; // Same as original command
__le32 Residue ; // Amount not transferred
u8 Status ; // See below
} ;
# define USB_BULK_CS_WRAP_LEN 13
# define USB_BULK_CS_SIG 0x53425355 // Spells out 'USBS'
# define USB_STATUS_PASS 0
# define USB_STATUS_FAIL 1
# define USB_STATUS_PHASE_ERROR 2
/* Bulk-only class specific requests */
# define USB_BULK_RESET_REQUEST 0xff
# define USB_BULK_GET_MAX_LUN_REQUEST 0xfe
/* CBI Interrupt data structure */
struct interrupt_data {
u8 bType ;
u8 bValue ;
} ;
# define CBI_INTERRUPT_DATA_LEN 2
/* CBI Accept Device-Specific Command request */
# define USB_CBI_ADSC_REQUEST 0x00
# define MAX_COMMAND_SIZE 16 // Length of a SCSI Command Data Block
/* SCSI commands that we recognize */
# define SC_FORMAT_UNIT 0x04
# define SC_INQUIRY 0x12
# define SC_MODE_SELECT_6 0x15
# define SC_MODE_SELECT_10 0x55
# define SC_MODE_SENSE_6 0x1a
# define SC_MODE_SENSE_10 0x5a
# define SC_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e
# define SC_READ_6 0x08
# define SC_READ_10 0x28
# define SC_READ_12 0xa8
# define SC_READ_CAPACITY 0x25
# define SC_READ_FORMAT_CAPACITIES 0x23
# define SC_READ_HEADER 0x44
# define SC_READ_TOC 0x43
# define SC_RELEASE 0x17
# define SC_REQUEST_SENSE 0x03
# define SC_RESERVE 0x16
# define SC_SEND_DIAGNOSTIC 0x1d
# define SC_START_STOP_UNIT 0x1b
# define SC_SYNCHRONIZE_CACHE 0x35
# define SC_TEST_UNIT_READY 0x00
# define SC_VERIFY 0x2f
# define SC_WRITE_6 0x0a
# define SC_WRITE_10 0x2a
# define SC_WRITE_12 0xaa
/* SCSI Sense Key/Additional Sense Code/ASC Qualifier values */
# define SS_NO_SENSE 0
# define SS_COMMUNICATION_FAILURE 0x040800
# define SS_INVALID_COMMAND 0x052000
# define SS_INVALID_FIELD_IN_CDB 0x052400
# define SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE 0x052100
# define SS_LOGICAL_UNIT_NOT_SUPPORTED 0x052500
# define SS_MEDIUM_NOT_PRESENT 0x023a00
# define SS_MEDIUM_REMOVAL_PREVENTED 0x055302
# define SS_NOT_READY_TO_READY_TRANSITION 0x062800
# define SS_RESET_OCCURRED 0x062900
# define SS_SAVING_PARAMETERS_NOT_SUPPORTED 0x053900
# define SS_UNRECOVERED_READ_ERROR 0x031100
# define SS_WRITE_ERROR 0x030c02
# define SS_WRITE_PROTECTED 0x072700
# define SK(x) ((u8) ((x) >> 16)) // Sense Key byte, etc.
# define ASC(x) ((u8) ((x) >> 8))
# define ASCQ(x) ((u8) (x))
/*-------------------------------------------------------------------------*/
2009-10-28 18:57:15 +03:00
struct fsg_lun {
2009-10-28 18:57:14 +03:00
struct file * filp ;
loff_t file_length ;
loff_t num_sectors ;
unsigned int ro : 1 ;
unsigned int prevent_medium_removal : 1 ;
unsigned int registered : 1 ;
unsigned int info_valid : 1 ;
u32 sense_data ;
u32 sense_data_info ;
u32 unit_attention_data ;
struct device dev ;
} ;
2009-10-28 18:57:15 +03:00
# define fsg_lun_is_open(curlun) ((curlun)->filp != NULL)
2009-10-28 18:57:14 +03:00
2009-10-28 18:57:15 +03:00
static struct fsg_lun * fsg_lun_from_dev ( struct device * dev )
2009-10-28 18:57:14 +03:00
{
2009-10-28 18:57:15 +03:00
return container_of ( dev , struct fsg_lun , dev ) ;
2009-10-28 18:57:14 +03:00
}
/* Big enough to hold our biggest descriptor */
# define EP0_BUFSIZE 256
# define DELAYED_STATUS (EP0_BUFSIZE + 999) // An impossibly large value
/* Number of buffers we will use. 2 is enough for double-buffering */
2009-10-28 18:57:15 +03:00
# define FSG_NUM_BUFFERS 2
2009-10-28 18:57:14 +03:00
enum fsg_buffer_state {
BUF_STATE_EMPTY = 0 ,
BUF_STATE_FULL ,
BUF_STATE_BUSY
} ;
struct fsg_buffhd {
void * buf ;
enum fsg_buffer_state state ;
struct fsg_buffhd * next ;
/* The NetChip 2280 is faster, and handles some protocol faults
* better , if we don ' t submit any short bulk - out read requests .
* So we will record the intended request length here . */
unsigned int bulk_out_intended_length ;
struct usb_request * inreq ;
int inreq_busy ;
struct usb_request * outreq ;
int outreq_busy ;
} ;
enum fsg_state {
FSG_STATE_COMMAND_PHASE = - 10 , // This one isn't used anywhere
FSG_STATE_DATA_PHASE ,
FSG_STATE_STATUS_PHASE ,
FSG_STATE_IDLE = 0 ,
FSG_STATE_ABORT_BULK_OUT ,
FSG_STATE_RESET ,
FSG_STATE_INTERFACE_CHANGE ,
FSG_STATE_CONFIG_CHANGE ,
FSG_STATE_DISCONNECT ,
FSG_STATE_EXIT ,
FSG_STATE_TERMINATED
} ;
enum data_direction {
DATA_DIR_UNKNOWN = 0 ,
DATA_DIR_FROM_HOST ,
DATA_DIR_TO_HOST ,
DATA_DIR_NONE
} ;
/*-------------------------------------------------------------------------*/
static inline u32 get_unaligned_be24 ( u8 * buf )
{
return 0xffffff & ( u32 ) get_unaligned_be32 ( buf - 1 ) ;
}
/*-------------------------------------------------------------------------*/
2009-10-28 18:57:15 +03:00
enum {
FSG_STRING_MANUFACTURER = 1 ,
FSG_STRING_PRODUCT ,
FSG_STRING_SERIAL ,
FSG_STRING_CONFIG ,
FSG_STRING_INTERFACE
} ;
2009-10-28 18:57:14 +03:00
static struct usb_otg_descriptor
2009-10-28 18:57:15 +03:00
fsg_otg_desc = {
. bLength = sizeof fsg_otg_desc ,
2009-10-28 18:57:14 +03:00
. bDescriptorType = USB_DT_OTG ,
. bmAttributes = USB_OTG_SRP ,
} ;
/* There is only one interface. */
static struct usb_interface_descriptor
2009-10-28 18:57:15 +03:00
fsg_intf_desc = {
. bLength = sizeof fsg_intf_desc ,
2009-10-28 18:57:14 +03:00
. bDescriptorType = USB_DT_INTERFACE ,
. bNumEndpoints = 2 , // Adjusted during fsg_bind()
. bInterfaceClass = USB_CLASS_MASS_STORAGE ,
. bInterfaceSubClass = USB_SC_SCSI , // Adjusted during fsg_bind()
. bInterfaceProtocol = USB_PR_BULK , // Adjusted during fsg_bind()
2009-10-28 18:57:15 +03:00
. iInterface = FSG_STRING_INTERFACE ,
2009-10-28 18:57:14 +03:00
} ;
/* Three full-speed endpoint descriptors: bulk-in, bulk-out,
* and interrupt - in . */
static struct usb_endpoint_descriptor
2009-10-28 18:57:15 +03:00
fsg_fs_bulk_in_desc = {
2009-10-28 18:57:14 +03:00
. bLength = USB_DT_ENDPOINT_SIZE ,
. bDescriptorType = USB_DT_ENDPOINT ,
. bEndpointAddress = USB_DIR_IN ,
. bmAttributes = USB_ENDPOINT_XFER_BULK ,
/* wMaxPacketSize set by autoconfiguration */
} ;
static struct usb_endpoint_descriptor
2009-10-28 18:57:15 +03:00
fsg_fs_bulk_out_desc = {
2009-10-28 18:57:14 +03:00
. bLength = USB_DT_ENDPOINT_SIZE ,
. bDescriptorType = USB_DT_ENDPOINT ,
. bEndpointAddress = USB_DIR_OUT ,
. bmAttributes = USB_ENDPOINT_XFER_BULK ,
/* wMaxPacketSize set by autoconfiguration */
} ;
static struct usb_endpoint_descriptor
2009-10-28 18:57:15 +03:00
fsg_fs_intr_in_desc = {
2009-10-28 18:57:14 +03:00
. bLength = USB_DT_ENDPOINT_SIZE ,
. bDescriptorType = USB_DT_ENDPOINT ,
. bEndpointAddress = USB_DIR_IN ,
. bmAttributes = USB_ENDPOINT_XFER_INT ,
. wMaxPacketSize = cpu_to_le16 ( 2 ) ,
. bInterval = 32 , // frames -> 32 ms
} ;
2009-10-28 18:57:15 +03:00
static const struct usb_descriptor_header * fsg_fs_function [ ] = {
( struct usb_descriptor_header * ) & fsg_otg_desc ,
( struct usb_descriptor_header * ) & fsg_intf_desc ,
( struct usb_descriptor_header * ) & fsg_fs_bulk_in_desc ,
( struct usb_descriptor_header * ) & fsg_fs_bulk_out_desc ,
( struct usb_descriptor_header * ) & fsg_fs_intr_in_desc ,
2009-10-28 18:57:14 +03:00
NULL ,
} ;
2009-10-28 18:57:15 +03:00
# define FSG_FS_FUNCTION_PRE_EP_ENTRIES 2
2009-10-28 18:57:14 +03:00
/*
* USB 2.0 devices need to expose both high speed and full speed
* descriptors , unless they only run at full speed .
*
* That means alternate endpoint descriptors ( bigger packets )
* and a " device qualifier " . . . plus more construction options
* for the config descriptor .
*/
static struct usb_endpoint_descriptor
2009-10-28 18:57:15 +03:00
fsg_hs_bulk_in_desc = {
2009-10-28 18:57:14 +03:00
. bLength = USB_DT_ENDPOINT_SIZE ,
. bDescriptorType = USB_DT_ENDPOINT ,
/* bEndpointAddress copied from fs_bulk_in_desc during fsg_bind() */
. bmAttributes = USB_ENDPOINT_XFER_BULK ,
. wMaxPacketSize = cpu_to_le16 ( 512 ) ,
} ;
static struct usb_endpoint_descriptor
2009-10-28 18:57:15 +03:00
fsg_hs_bulk_out_desc = {
2009-10-28 18:57:14 +03:00
. bLength = USB_DT_ENDPOINT_SIZE ,
. bDescriptorType = USB_DT_ENDPOINT ,
/* bEndpointAddress copied from fs_bulk_out_desc during fsg_bind() */
. bmAttributes = USB_ENDPOINT_XFER_BULK ,
. wMaxPacketSize = cpu_to_le16 ( 512 ) ,
. bInterval = 1 , // NAK every 1 uframe
} ;
static struct usb_endpoint_descriptor
2009-10-28 18:57:15 +03:00
fsg_hs_intr_in_desc = {
2009-10-28 18:57:14 +03:00
. bLength = USB_DT_ENDPOINT_SIZE ,
. bDescriptorType = USB_DT_ENDPOINT ,
/* bEndpointAddress copied from fs_intr_in_desc during fsg_bind() */
. bmAttributes = USB_ENDPOINT_XFER_INT ,
. wMaxPacketSize = cpu_to_le16 ( 2 ) ,
. bInterval = 9 , // 2**(9-1) = 256 uframes -> 32 ms
} ;
2009-10-28 18:57:15 +03:00
static const struct usb_descriptor_header * fsg_hs_function [ ] = {
( struct usb_descriptor_header * ) & fsg_otg_desc ,
( struct usb_descriptor_header * ) & fsg_intf_desc ,
( struct usb_descriptor_header * ) & fsg_hs_bulk_in_desc ,
( struct usb_descriptor_header * ) & fsg_hs_bulk_out_desc ,
( struct usb_descriptor_header * ) & fsg_hs_intr_in_desc ,
2009-10-28 18:57:14 +03:00
NULL ,
} ;
2009-10-28 18:57:15 +03:00
# define FSG_HS_FUNCTION_PRE_EP_ENTRIES 2
2009-10-28 18:57:14 +03:00
/* Maxpacket and other transfer characteristics vary by speed. */
static struct usb_endpoint_descriptor *
2009-10-28 18:57:15 +03:00
fsg_ep_desc ( struct usb_gadget * g , struct usb_endpoint_descriptor * fs ,
2009-10-28 18:57:14 +03:00
struct usb_endpoint_descriptor * hs )
{
if ( gadget_is_dualspeed ( g ) & & g - > speed = = USB_SPEED_HIGH )
return hs ;
return fs ;
}
/* Static strings, in UTF-8 (for simplicity we use only ASCII characters) */
2009-10-28 18:57:15 +03:00
static struct usb_string fsg_strings [ ] = {
{ FSG_STRING_MANUFACTURER , fsg_string_manufacturer } ,
{ FSG_STRING_PRODUCT , fsg_string_product } ,
{ FSG_STRING_SERIAL , fsg_string_serial } ,
{ FSG_STRING_CONFIG , fsg_string_config } ,
{ FSG_STRING_INTERFACE , fsg_string_interface } ,
2009-10-28 18:57:14 +03:00
{ }
} ;
2009-10-28 18:57:15 +03:00
static struct usb_gadget_strings fsg_stringtab = {
2009-10-28 18:57:14 +03:00
. language = 0x0409 , // en-us
2009-10-28 18:57:15 +03:00
. strings = fsg_strings ,
2009-10-28 18:57:14 +03:00
} ;
/*-------------------------------------------------------------------------*/
/* If the next two routines are called while the gadget is registered,
* the caller must own fsg - > filesem for writing . */
2009-10-28 18:57:15 +03:00
static int fsg_lun_open ( struct fsg_lun * curlun , const char * filename )
2009-10-28 18:57:14 +03:00
{
int ro ;
struct file * filp = NULL ;
int rc = - EINVAL ;
struct inode * inode = NULL ;
loff_t size ;
loff_t num_sectors ;
loff_t min_sectors ;
/* R/W if we can, R/O if we must */
ro = curlun - > ro ;
if ( ! ro ) {
filp = filp_open ( filename , O_RDWR | O_LARGEFILE , 0 ) ;
if ( - EROFS = = PTR_ERR ( filp ) )
ro = 1 ;
}
if ( ro )
filp = filp_open ( filename , O_RDONLY | O_LARGEFILE , 0 ) ;
if ( IS_ERR ( filp ) ) {
LINFO ( curlun , " unable to open backing file: %s \n " , filename ) ;
return PTR_ERR ( filp ) ;
}
if ( ! ( filp - > f_mode & FMODE_WRITE ) )
ro = 1 ;
if ( filp - > f_path . dentry )
inode = filp - > f_path . dentry - > d_inode ;
if ( inode & & S_ISBLK ( inode - > i_mode ) ) {
if ( bdev_read_only ( inode - > i_bdev ) )
ro = 1 ;
} else if ( ! inode | | ! S_ISREG ( inode - > i_mode ) ) {
LINFO ( curlun , " invalid file type: %s \n " , filename ) ;
goto out ;
}
/* If we can't read the file, it's no good.
* If we can ' t write the file , use it read - only . */
if ( ! filp - > f_op | | ! ( filp - > f_op - > read | | filp - > f_op - > aio_read ) ) {
LINFO ( curlun , " file not readable: %s \n " , filename ) ;
goto out ;
}
if ( ! ( filp - > f_op - > write | | filp - > f_op - > aio_write ) )
ro = 1 ;
size = i_size_read ( inode - > i_mapping - > host ) ;
if ( size < 0 ) {
LINFO ( curlun , " unable to find file size: %s \n " , filename ) ;
rc = ( int ) size ;
goto out ;
}
num_sectors = size > > 9 ; // File size in 512-byte blocks
min_sectors = 1 ;
if ( mod_data . cdrom ) {
num_sectors & = ~ 3 ; // Reduce to a multiple of 2048
min_sectors = 300 * 4 ; // Smallest track is 300 frames
if ( num_sectors > = 256 * 60 * 75 * 4 ) {
num_sectors = ( 256 * 60 * 75 - 1 ) * 4 ;
LINFO ( curlun , " file too big: %s \n " , filename ) ;
LINFO ( curlun , " using only first %d blocks \n " ,
( int ) num_sectors ) ;
}
}
if ( num_sectors < min_sectors ) {
LINFO ( curlun , " file too small: %s \n " , filename ) ;
rc = - ETOOSMALL ;
goto out ;
}
get_file ( filp ) ;
curlun - > ro = ro ;
curlun - > filp = filp ;
curlun - > file_length = size ;
curlun - > num_sectors = num_sectors ;
LDBG ( curlun , " open backing file: %s \n " , filename ) ;
rc = 0 ;
out :
filp_close ( filp , current - > files ) ;
return rc ;
}
2009-10-28 18:57:15 +03:00
static void fsg_lun_close ( struct fsg_lun * curlun )
2009-10-28 18:57:14 +03:00
{
if ( curlun - > filp ) {
LDBG ( curlun , " close backing file \n " ) ;
fput ( curlun - > filp ) ;
curlun - > filp = NULL ;
}
}
/*-------------------------------------------------------------------------*/
/* Sync the file data, don't bother with the metadata.
* This code was copied from fs / buffer . c : sys_fdatasync ( ) . */
2009-10-28 18:57:15 +03:00
static int fsg_lun_fsync_sub ( struct fsg_lun * curlun )
2009-10-28 18:57:14 +03:00
{
struct file * filp = curlun - > filp ;
if ( curlun - > ro | | ! filp )
return 0 ;
return vfs_fsync ( filp , filp - > f_path . dentry , 1 ) ;
}
static void store_cdrom_address ( u8 * dest , int msf , u32 addr )
{
if ( msf ) {
/* Convert to Minutes-Seconds-Frames */
addr > > = 2 ; /* Convert to 2048-byte frames */
addr + = 2 * 75 ; /* Lead-in occupies 2 seconds */
dest [ 3 ] = addr % 75 ; /* Frames */
addr / = 75 ;
dest [ 2 ] = addr % 60 ; /* Seconds */
addr / = 60 ;
dest [ 1 ] = addr ; /* Minutes */
dest [ 0 ] = 0 ; /* Reserved */
} else {
/* Absolute sector */
put_unaligned_be32 ( addr , dest ) ;
}
}