📄 file_storage.c
字号:
/* 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. * * Also, in the non-TEST version, open_backing_file() is only used during * initialization and the sysfs attribute store_xxx routines aren't used * at all. We will define NORMALLY_INIT to mark them as __init so they * don't occupy kernel code space unnecessarily. */#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)#define backing_file_is_open(curlun) ((curlun)->filp != NULL)#define NORMALLY_INIT#else#define transport_is_bbb() 1#define transport_is_cbi() 0#define protocol_is_scsi() 1#define backing_file_is_open(curlun) 1#define NORMALLY_INIT __init#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;#define BUS_ID_SIZE 20 struct __lun_device { char name[BUS_ID_SIZE]; void *driver_data; } 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 2enum 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 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;};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_MSGSstatic 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){}#elsestatic 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;}/*-------------------------------------------------------------------------*//* * 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/* There is only one configuration. */#define CONFIG_VALUE 1static struct usb_device_descriptordevice_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, .iSerialNumber = STRING_SERIAL, .bNumConfigurations = 1,};static struct usb_config_descriptorconfig_desc = { .bLength = sizeof config_desc, .bDescriptorType = USB_DT_CONFIG, /* wTotalLength computed by usb_gadget_config_buf() */ .bNumInterfaces = 1, .bConfigurationValue = CONFIG_VALUE, .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, .bMaxPower = 1, // self-powered};/* There is only one interface. */static struct usb_interface_descriptorintf_desc = { .bLength = sizeof intf_desc, .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()};/* Three full-speed endpoint descriptors: bulk-in, bulk-out, * and interrupt-in. */static struct usb_endpoint_descriptorfs_bulk_in_desc = { .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_descriptorfs_bulk_out_desc = { .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_descriptorfs_intr_in_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -