⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 file_storage.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
	.iInterface =		STRING_INTERFACE,};/* 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,	.bEndpointAddress =	USB_DIR_IN,	.bmAttributes =		USB_ENDPOINT_XFER_INT,	.wMaxPacketSize =	__constant_cpu_to_le16(2),	.bInterval =		32,	// frames -> 32 ms};static const struct usb_descriptor_header *fs_function[] = {	(struct usb_descriptor_header *) &otg_desc,	(struct usb_descriptor_header *) &intf_desc,	(struct usb_descriptor_header *) &fs_bulk_in_desc,	(struct usb_descriptor_header *) &fs_bulk_out_desc,	(struct usb_descriptor_header *) &fs_intr_in_desc,	NULL,};#define FS_FUNCTION_PRE_EP_ENTRIES	2#ifdef	CONFIG_USB_GADGET_DUALSPEED/* * 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_qualifier_descriptordev_qualifier = {	.bLength =		sizeof dev_qualifier,	.bDescriptorType =	USB_DT_DEVICE_QUALIFIER,	.bcdUSB =		__constant_cpu_to_le16(0x0200),	.bDeviceClass =		USB_CLASS_PER_INTERFACE,	.bNumConfigurations =	1,};static struct usb_endpoint_descriptorhs_bulk_in_desc = {	.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 =	__constant_cpu_to_le16(512),};static struct usb_endpoint_descriptorhs_bulk_out_desc = {	.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 =	__constant_cpu_to_le16(512),	.bInterval =		1,	// NAK every 1 uframe};static struct usb_endpoint_descriptorhs_intr_in_desc = {	.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 =	__constant_cpu_to_le16(2),	.bInterval =		9,	// 2**(9-1) = 256 uframes -> 32 ms};static const struct usb_descriptor_header *hs_function[] = {	(struct usb_descriptor_header *) &otg_desc,	(struct usb_descriptor_header *) &intf_desc,	(struct usb_descriptor_header *) &hs_bulk_in_desc,	(struct usb_descriptor_header *) &hs_bulk_out_desc,	(struct usb_descriptor_header *) &hs_intr_in_desc,	NULL,};#define HS_FUNCTION_PRE_EP_ENTRIES	2/* Maxpacket and other transfer characteristics vary by speed. */#define ep_desc(g,fs,hs)	(((g)->speed==USB_SPEED_HIGH) ? (hs) : (fs))#else/* If there's no high speed support, always use the full-speed descriptor. */#define ep_desc(g,fs,hs)	fs#endif	/* !CONFIG_USB_GADGET_DUALSPEED *//* The CBI specification limits the serial string to 12 uppercase hexadecimal * characters. */static char				manufacturer[64];static char				serial[13];/* Static strings, in UTF-8 (for simplicity we use only ASCII characters) */static struct usb_string		strings[] = {	{STRING_MANUFACTURER,	manufacturer},	{STRING_PRODUCT,	longname},	{STRING_SERIAL,		serial},	{STRING_CONFIG,		"Self-powered"},	{STRING_INTERFACE,	"Mass Storage"},	{}};static struct usb_gadget_strings	stringtab = {	.language	= 0x0409,		// en-us	.strings	= strings,};/* * Config descriptors must agree with the code that sets configurations * and with code managing interfaces and their altsettings.  They must * also handle different speeds and other-speed requests. */static int populate_config_buf(struct usb_gadget *gadget,		u8 *buf, u8 type, unsigned index){#ifdef CONFIG_USB_GADGET_DUALSPEED	enum usb_device_speed			speed = gadget->speed;#endif	int					len;	const struct usb_descriptor_header	**function;	if (index > 0)		return -EINVAL;#ifdef CONFIG_USB_GADGET_DUALSPEED	if (type == USB_DT_OTHER_SPEED_CONFIG)		speed = (USB_SPEED_FULL + USB_SPEED_HIGH) - speed;	if (speed == USB_SPEED_HIGH)		function = hs_function;	else#endif		function = fs_function;	/* for now, don't advertise srp-only devices */	if (!gadget->is_otg)		function++;	len = usb_gadget_config_buf(&config_desc, buf, EP0_BUFSIZE, function);	((struct usb_config_descriptor *) buf)->bDescriptorType = type;	return len;}/*-------------------------------------------------------------------------*//* These routines may be called in process context or in_irq */static void wakeup_thread(struct fsg_dev *fsg){	/* Tell the main thread that something has happened */	fsg->thread_wakeup_needed = 1;	wake_up_all(&fsg->thread_wqh);}static void raise_exception(struct fsg_dev *fsg, enum fsg_state new_state){	unsigned long		flags;	/* Do nothing if a higher-priority exception is already in progress.	 * If a lower-or-equal priority exception is in progress, preempt it	 * and notify the main thread by sending it a signal. */	spin_lock_irqsave(&fsg->lock, flags);	if (fsg->state <= new_state) {		fsg->exception_req_tag = fsg->ep0_req_tag;		fsg->state = new_state;		if (fsg->thread_task)			send_sig_info(SIGUSR1, SEND_SIG_FORCED,					fsg->thread_task);	}	spin_unlock_irqrestore(&fsg->lock, flags);}/*-------------------------------------------------------------------------*//* The disconnect callback and ep0 routines.  These always run in_irq, * except that ep0_queue() is called in the main thread to acknowledge * completion of various requests: set config, set interface, and * Bulk-only device reset. */static void fsg_disconnect(struct usb_gadget *gadget){	struct fsg_dev		*fsg = get_gadget_data(gadget);	DBG(fsg, "disconnect or port reset\n");	raise_exception(fsg, FSG_STATE_DISCONNECT);}static int ep0_queue(struct fsg_dev *fsg){	int	rc;	rc = usb_ep_queue(fsg->ep0, fsg->ep0req, GFP_ATOMIC);	if (rc != 0 && rc != -ESHUTDOWN) {		/* We can't do much more than wait for a reset */		WARN(fsg, "error in submission: %s --> %d\n",				fsg->ep0->name, rc);	}	return rc;}static void ep0_complete(struct usb_ep *ep, struct usb_request *req){	struct fsg_dev		*fsg = (struct fsg_dev *) ep->driver_data;	if (req->actual > 0)		dump_msg(fsg, fsg->ep0req_name, req->buf, req->actual);	if (req->status || req->actual != req->length)		DBG(fsg, "%s --> %d, %u/%u\n", __FUNCTION__,				req->status, req->actual, req->length);	if (req->status == -ECONNRESET)		// Request was cancelled		usb_ep_fifo_flush(ep);	if (req->status == 0 && req->context)		((fsg_routine_t) (req->context))(fsg);}/*-------------------------------------------------------------------------*//* Bulk and interrupt endpoint completion handlers. * These always run in_irq. */static void bulk_in_complete(struct usb_ep *ep, struct usb_request *req){	struct fsg_dev		*fsg = (struct fsg_dev *) ep->driver_data;	struct fsg_buffhd	*bh = (struct fsg_buffhd *) req->context;	if (req->status || req->actual != req->length)		DBG(fsg, "%s --> %d, %u/%u\n", __FUNCTION__,				req->status, req->actual, req->length);	if (req->status == -ECONNRESET)		// Request was cancelled		usb_ep_fifo_flush(ep);	/* Hold the lock while we update the request and buffer states */	spin_lock(&fsg->lock);	bh->inreq_busy = 0;	bh->state = BUF_STATE_EMPTY;	spin_unlock(&fsg->lock);	wakeup_thread(fsg);}static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req){	struct fsg_dev		*fsg = (struct fsg_dev *) ep->driver_data;	struct fsg_buffhd	*bh = (struct fsg_buffhd *) req->context;	dump_msg(fsg, "bulk-out", req->buf, req->actual);	if (req->status || req->actual != bh->bulk_out_intended_length)		DBG(fsg, "%s --> %d, %u/%u\n", __FUNCTION__,				req->status, req->actual,				bh->bulk_out_intended_length);	if (req->status == -ECONNRESET)		// Request was cancelled		usb_ep_fifo_flush(ep);	/* Hold the lock while we update the request and buffer states */	spin_lock(&fsg->lock);	bh->outreq_busy = 0;	bh->state = BUF_STATE_FULL;	spin_unlock(&fsg->lock);	wakeup_thread(fsg);}#ifdef CONFIG_USB_FILE_STORAGE_TESTstatic void intr_in_complete(struct usb_ep *ep, struct usb_request *req){	struct fsg_dev		*fsg = (struct fsg_dev *) ep->driver_data;	struct fsg_buffhd	*bh = (struct fsg_buffhd *) req->context;	if (req->status || req->actual != req->length)		DBG(fsg, "%s --> %d, %u/%u\n", __FUNCTION__,				req->status, req->actual, req->length);	if (req->status == -ECONNRESET)		// Request was cancelled		usb_ep_fifo_flush(ep);	/* Hold the lock while we update the request and buffer states */	spin_lock(&fsg->lock);	fsg->intreq_busy = 0;	bh->state = BUF_STATE_EMPTY;	spin_unlock(&fsg->lock);	wakeup_thread(fsg);}#elsestatic void intr_in_complete(struct usb_ep *ep, struct usb_request *req){}#endif /* CONFIG_USB_FILE_STORAGE_TEST *//*-------------------------------------------------------------------------*//* Ep0 class-specific handlers.  These always run in_irq. */#ifdef CONFIG_USB_FILE_STORAGE_TESTstatic void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh){	struct usb_request	*req = fsg->ep0req;	static u8		cbi_reset_cmnd[6] = {			SC_SEND_DIAGNOSTIC, 4, 0xff, 0xff, 0xff, 0xff};	/* Error in command transfer? */	if (req->status || req->length != req->actual ||			req->actual < 6 || req->actual > MAX_COMMAND_SIZE) {		/* Not all controllers allow a protocol stall after		 * receiving control-out data, but we'll try anyway. */		fsg_set_halt(fsg, fsg->ep0);		return;			// Wait for reset	}	/* Is it the special reset command? */	if (req->actual >= sizeof cbi_reset_cmnd &&			memcmp(req->buf, cbi_reset_cmnd,				sizeof cbi_reset_cmnd) == 0) {		/* Raise an exception to stop the current operation		 * and reinitialize our state. */		DBG(fsg, "cbi reset request\n");		raise_exception(fsg, FSG_STATE_RESET);		return;	}	VDBG(fsg, "CB[I] accept device-specific command\n");	spin_lock(&fsg->lock);	/* Save the command for later */	if (fsg->cbbuf_cmnd_size)		WARN(fsg, "CB[I] overwriting previous command\n");	fsg->cbbuf_cmnd_size = req->actual;	memcpy(fsg->cbbuf_cmnd, req->buf, fsg->cbbuf_cmnd_size);	spin_unlock(&fsg->lock);	wakeup_thread(fsg);}#elsestatic void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh){}#endif /* CONFIG_USB_FILE_STORAGE_TEST */static int class_setup_req(struct fsg_dev *fsg,		const struct usb_ctrlrequest *ctrl){	struct usb_request	*req = fsg->ep0req;	int			value = -EOPNOTSUPP;	u16			w_index = le16_to_cpu(ctrl->wIndex);	u16			w_length = le16_to_cpu(ctrl->wLength);	if (!fsg->config)		return value;	/* Handle Bulk-only class-specific requests */	if (transport_is_bbb()) {		switch (ctrl->bRequest) {		case USB_BULK_RESET_REQUEST:			if (ctrl->bRequestType != (USB_DIR_OUT |					USB_TYPE_CLASS | USB_RECIP_INTERFACE))				break;			if (w_index != 0) {				value = -EDOM;				break;			}			/* Raise an exception to stop the current operation			 * and reinitialize our state. */			DBG(fsg, "bulk reset request\n");			raise_exception(fsg, FSG_STATE_RESET);			value = DELAYED_STATUS;			break;		case USB_BULK_GET_MAX_LUN_REQUEST:			if (ctrl->bRequestType != (USB_DIR_IN |					USB_TYPE_CLASS | USB_RECIP_INTERFACE))				break;			if (w_index != 0) {				value = -EDOM;				break;			}			VDBG(fsg, "get max LUN\n");			*(u8 *) req->buf = fsg->nluns - 1;			value = 1;			break;		}	}	/* Handle CBI class-specific requests */	else {		switch (ctrl->bRequest) {		case USB_CBI_ADSC_REQUEST:			if (ctrl->bRequestType != (USB_DIR_OUT |					USB_TYPE_CLASS | USB_RECIP_INTERFACE))				break;			if (w_index != 0) {				value = -EDOM;				break;			}			if (w_length > MAX_COMMAND_SIZE) {				value = -EOVERFLOW;				break;			}			value = w_length;			fsg->ep0req->context = received_cbi_adsc;			break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -