📄 file_storage.c
字号:
/* Bulk-only data structures */
/* Command Block Wrapper */
struct bulk_cb_wrap {
__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_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))
/*-------------------------------------------------------------------------*/
/*
* These definitions will permit the compiler to avoid generating code for
* parts of the driver that aren't used in the non-TEST version. Even gcc
* can recognize when a test of a constant expression yields a dead code
* path.
*/
#ifdef CONFIG_USB_FILE_STORAGE_TEST
#define transport_is_bbb() (mod_data.transport_type == USB_PR_BULK)
#define transport_is_cbi() (mod_data.transport_type == USB_PR_CBI)
#define protocol_is_scsi() (mod_data.protocol_type == USB_SC_SCSI)
#else
#define transport_is_bbb() 1
#define transport_is_cbi() 0
#define protocol_is_scsi() 1
#endif /* CONFIG_USB_FILE_STORAGE_TEST */
struct lun {
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;
u32 sense_data;
u32 sense_data_info;
u32 unit_attention_data;
struct device dev;
};
#define backing_file_is_open(curlun) ((curlun)->filp != NULL)
static inline struct lun *dev_to_lun(struct device *dev)
{
return container_of(dev, struct lun, dev);
}
/* 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 */
#define NUM_BUFFERS 2
enum fsg_buffer_state {
BUF_STATE_EMPTY = 0,
BUF_STATE_FULL,
BUF_STATE_BUSY
};
struct fsg_buffhd {
void *buf;
dma_addr_t dma;
volatile 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;
volatile int inreq_busy;
struct usb_request *outreq;
volatile 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
};
struct fsg_dev {
/* lock protects: state, all the req_busy's, and cbbuf_cmnd */
spinlock_t lock;
struct usb_gadget *gadget;
/* filesem protects: backing files in use */
struct rw_semaphore filesem;
struct usb_ep *ep0; // Handy copy of gadget->ep0
struct usb_request *ep0req; // For control responses
volatile unsigned int ep0_req_tag;
const char *ep0req_name;
struct usb_request *intreq; // For interrupt responses
volatile int intreq_busy;
struct fsg_buffhd *intr_buffhd;
unsigned int bulk_out_maxpacket;
enum fsg_state state; // For exception handling
unsigned int exception_req_tag;
u8 config, new_config;
unsigned int running : 1;
unsigned int bulk_in_enabled : 1;
unsigned int bulk_out_enabled : 1;
unsigned int intr_in_enabled : 1;
unsigned int phase_error : 1;
unsigned int short_packet_received : 1;
unsigned int bad_lun_okay : 1;
unsigned long atomic_bitflags;
#define REGISTERED 0
#define CLEAR_BULK_HALTS 1
#define SUSPENDED 2
struct usb_ep *bulk_in;
struct usb_ep *bulk_out;
struct usb_ep *intr_in;
struct fsg_buffhd *next_buffhd_to_fill;
struct fsg_buffhd *next_buffhd_to_drain;
struct fsg_buffhd buffhds[NUM_BUFFERS];
wait_queue_head_t thread_wqh;
int thread_wakeup_needed;
struct completion thread_notifier;
int thread_pid;
struct task_struct *thread_task;
sigset_t thread_signal_mask;
int cmnd_size;
u8 cmnd[MAX_COMMAND_SIZE];
enum data_direction data_dir;
u32 data_size;
u32 data_size_from_cmnd;
u32 tag;
unsigned int lun;
u32 residue;
u32 usb_amount_left;
/* The CB protocol offers no way for a host to know when a command
* has completed. As a result the next command may arrive early,
* and we will still have to handle it. For that reason we need
* a buffer to store new commands when using CB (or CBI, which
* does not oblige a host to wait for command completion either). */
int cbbuf_cmnd_size;
u8 cbbuf_cmnd[MAX_COMMAND_SIZE];
unsigned int nluns;
struct lun *luns;
struct lun *curlun;
struct completion lun_released;
};
typedef void (*fsg_routine_t)(struct fsg_dev *);
static int inline exception_in_progress(struct fsg_dev *fsg)
{
return (fsg->state > FSG_STATE_IDLE);
}
/* Make bulk-out requests be divisible by the maxpacket size */
static void inline set_bulk_out_req_length(struct fsg_dev *fsg,
struct fsg_buffhd *bh, unsigned int length)
{
unsigned int rem;
bh->bulk_out_intended_length = length;
rem = length % fsg->bulk_out_maxpacket;
if (rem > 0)
length += fsg->bulk_out_maxpacket - rem;
bh->outreq->length = length;
}
static struct fsg_dev *the_fsg;
static struct usb_gadget_driver fsg_driver;
static void close_backing_file(struct lun *curlun);
static void close_all_backing_files(struct fsg_dev *fsg);
/*-------------------------------------------------------------------------*/
#ifdef DUMP_MSGS
static void dump_msg(struct fsg_dev *fsg, const char *label,
const u8 *buf, unsigned int length)
{
unsigned int start, num, i;
char line[52], *p;
if (length >= 512)
return;
DBG(fsg, "%s, length %u:\n", label, length);
start = 0;
while (length > 0) {
num = min(length, 16u);
p = line;
for (i = 0; i < num; ++i) {
if (i == 8)
*p++ = ' ';
sprintf(p, " %02x", buf[i]);
p += 3;
}
*p = 0;
printk(KERN_DEBUG "%6x: %s\n", start, line);
buf += num;
start += num;
length -= num;
}
}
static void inline dump_cdb(struct fsg_dev *fsg)
{}
#else
static void inline dump_msg(struct fsg_dev *fsg, const char *label,
const u8 *buf, unsigned int length)
{}
static void inline dump_cdb(struct fsg_dev *fsg)
{
int i;
char cmdbuf[3*MAX_COMMAND_SIZE + 1];
for (i = 0; i < fsg->cmnd_size; ++i)
sprintf(cmdbuf + i*3, " %02x", fsg->cmnd[i]);
VDBG(fsg, "SCSI CDB: %s\n", cmdbuf);
}
#endif /* DUMP_MSGS */
static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep)
{
const char *name;
if (ep == fsg->bulk_in)
name = "bulk-in";
else if (ep == fsg->bulk_out)
name = "bulk-out";
else
name = ep->name;
DBG(fsg, "%s set halt\n", name);
return usb_ep_set_halt(ep);
}
/*-------------------------------------------------------------------------*/
/* Routines for unaligned data access */
static u16 inline get_be16(u8 *buf)
{
return ((u16) buf[0] << 8) | ((u16) buf[1]);
}
static u32 inline get_be32(u8 *buf)
{
return ((u32) buf[0] << 24) | ((u32) buf[1] << 16) |
((u32) buf[2] << 8) | ((u32) buf[3]);
}
static void inline put_be16(u8 *buf, u16 val)
{
buf[0] = val >> 8;
buf[1] = val;
}
static void inline put_be32(u8 *buf, u32 val)
{
buf[0] = val >> 24;
buf[1] = val >> 16;
buf[2] = val >> 8;
buf[3] = val & 0xff;
}
/*-------------------------------------------------------------------------*/
/*
* DESCRIPTORS ... most are static, but strings and (full) configuration
* descriptors are built on demand. Also the (static) config and interface
* descriptors are adjusted during fsg_bind().
*/
#define STRING_MANUFACTURER 1
#define STRING_PRODUCT 2
#define STRING_SERIAL 3
#define STRING_CONFIG 4
#define STRING_INTERFACE 5
/* There is only one configuration. */
#define CONFIG_VALUE 1
static struct usb_device_descriptor
device_desc = {
.bLength = sizeof device_desc,
.bDescriptorType = USB_DT_DEVICE,
.bcdUSB = __constant_cpu_to_le16(0x0200),
.bDeviceClass = USB_CLASS_PER_INTERFACE,
/* The next three values can be overridden by module parameters */
.idVendor = __constant_cpu_to_le16(DRIVER_VENDOR_ID),
.idProduct = __constant_cpu_to_le16(DRIVER_PRODUCT_ID),
.bcdDevice = __constant_cpu_to_le16(0xffff),
.iManufacturer = STRING_MANUFACTURER,
.iProduct = STRING_PRODUCT,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -