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

📄 devmscd.c

📁 linux下的usb开发
💻 C
📖 第 1 页 / 共 2 页
字号:
/************************************************************* * Philips USB Mass Storage Class driver (Device side) * * (c) 2002 Koninklijke Philips Electronics N.V., All rights reserved *  * This  source code and any compilation or derivative thereof is the * proprietary information of Koninklijke Philips Electronics N.V. * and is confidential in nature. * Under no circumstances is this software to be exposed to or placed * under an Open Source License of any type without the expressed * written permission of Koninklijke Philips Electronics N.V. * * File Name:	devmscd.c * * History:	 * *	Version	Date		Author		Comments * ------------------------------------------------- * 	1.0		09/23/02	SYARRA		Initial Creation * * Note: use tab space 4 *************************************************************/#include <linux/config.h>#define	MODULE#include <linux/types.h>#include <linux/string.h>#include <linux/kernel.h>#include <linux/delay.h>#include <linux/timer.h>#include <linux/mm.h>#include <linux/ioport.h>#include <linux/interrupt.h>#include <linux/major.h>#include <linux/errno.h>#include <linux/slab.h>#include <linux/module.h>#include <linux/vmalloc.h>#include <linux/init.h>#include <linux/tqueue.h>#include <asm/byteorder.h>#include <asm/irq.h>#include <asm/segment.h>#include <asm/io.h>#include <linux/proc_fs.h>#include <linux/poll.h>#include "pdc_intf.h"#include "devmscd.h"#include "mscdbridge.h"#if 0#define		devmscd_change_state(dev, new_state)	\				dev->state = new_state;	\				printk("devmscd state = %s\n",devmscd_state_name[new_state])#else#define		devmscd_change_state(dev, new_state)	\				dev->state = new_state#endif/*--------------------------------------------------------------* *               local variables declerations *--------------------------------------------------------------*/struct devmscd_device	devmscd_dev;struct pdc_urb			read_urb, write_urb, csw_urb;mscdbridge_req_t		bridge_req;mscd_req_t				*bridge_read_req, *bridge_write_req;struct pdc_pipe_desc	bulk_pipe_desc[2];#if 0static	char	devmscd_state_name[DEVMSCD_DATA_OUT+1][20] = {		"DEVMSCD_IDLE    ",		"DEVMSCD_CBW     ",		"DEVMSCD_CSW     ",		"DEVMSCD_DATA_IN ",		"DEVMSCD_DATA_OUT"};#endif/*--------------------------------------------------------------* *               local function declerations *--------------------------------------------------------------*/static	int devmscd_class_req(void *__dev, __u8	*req);static	int devmscd_configure(void *__dev, unsigned char cfg);static	void devmscd_reset(struct devmscd_device *dev);static	void devmscd_read_urb_complete(struct pdc_urb *urb);static	void devmscd_write_urb_complete(struct pdc_urb *urb);static	void devmscd_set_command_res(mscdbridge_req_t *req);static int devmscd_read_data(__u8 *buff, __u32 bytes);static int devmscd_write_data(__u8 *buff, __u32 bytes);/*--------------------------------------------------------------* *               external function definitions *--------------------------------------------------------------*//*  * This function currently supports read, write operations. * Stores the request and calls the corresponding read or write function * Currently queueing is not implemented */int devmscd_submit_req(mscd_req_t	*req){	int result = MSCD_SUCCESS;	func_debug(("devmscd_submit_req(%p)\n",req))	switch(req->req_type) {		case MSCD_READ:			/* Bridge wants to receive data from the USB Host */			if(!bridge_read_req) {				req->status = MSCD_PENDING;				bridge_read_req = req;				return devmscd_read_data(req->data_buff, req->req_data_len);			}			break;				case MSCD_WRITE:				/* Bridge wants to send data to the USB Host */			if(!bridge_write_req) {				req->status = MSCD_PENDING;				bridge_write_req = req;				return devmscd_write_data(req->data_buff, req->req_data_len);			}			break;		default:			result = MSCD_FAILED;			break;	}	return result;} /* End of devmscd_submit_req *//*  * This function currently supports read, write operations. * rears the request and calls the corresponding usb device cancel operation * Currently queueing is not implemented */int devmscd_cancel_req(mscd_req_t	*req){	int result = MSCD_SUCCESS;	func_debug(("devmscd_cancel_req(%p)\n",req))	switch(req->req_type) {		case MSCD_READ:			if(bridge_read_req) {				/* There is a read request pending, so clear this */				bridge_read_req = NULL;				if(read_urb.status != PDC_URB_COMPLETE)					return pdc_cancel_urb(&read_urb);				else return MSCD_SUCCESS;			}			break;				case MSCD_WRITE:				if(bridge_write_req) {				/* There is a write request pending, so clear this */				bridge_read_req = NULL;				if(write_urb.status != PDC_URB_COMPLETE)					return pdc_cancel_urb(&write_urb);				else return MSCD_SUCCESS;			}			break;		default:			/* Not supported */			result = MSCD_FAILED;			break;	}	return result;} /* End of devmscd_cancel_req *//*--------------------------------------------------------------* *               local function definitions *--------------------------------------------------------------*//*  * Make the URB req and call the Peripheral controller driver * read function */int devmscd_read_data(__u8 *buff, __u32 bytes){	func_debug(("devmscd_read_data(%p,%x)\n",buff,bytes))		/* Fill the read URB */	read_urb.next = NULL;	read_urb.pipe = devmscd_dev.data_in_pipe;	read_urb.pipe_type = PDC_PIPE_BULK;	read_urb.operation = PDC_OPR_READ;	read_urb.status = PDC_URB_PENDING;	read_urb.transfer_buffer = buff;	read_urb.transfer_buffer_length = bytes;	read_urb.actual_length = 0x00;	read_urb.complete = devmscd_read_urb_complete;	/* call back function */	return pdc_submit_urb(&read_urb);} /* End of devmscd_read_data *//*  * Make the URB req and call the Peripheral controller driver * write function. */int devmscd_write_data(__u8 *buff, __u32 bytes){	struct pdc_urb	*urb;	func_debug(("devmscd_write_data(%p,%x)\n",buff,bytes))		if(bytes == DEVMSCD_CSW_LENGTH)	urb = &csw_urb;	else urb = &write_urb;		/* Fill the wrtite URB */	urb->next = NULL;	urb->pipe = devmscd_dev.data_out_pipe;	read_urb.pipe_type = PDC_PIPE_BULK;	urb->operation = PDC_OPR_WRITE;	urb->status = PDC_URB_PENDING;	urb->transfer_buffer = buff;	urb->transfer_buffer_length = bytes;	urb->actual_length = 0x00;	urb->complete = devmscd_write_urb_complete;	/* transfer residue will be updated in the call back function */	return pdc_submit_urb(urb);} /* End of devmscd_write_data *//*  * If the command response is not success, stall the endpoint. * Fill the CSW and send it to the host. Go back to IDLE state. */void devmscd_set_command_res(mscdbridge_req_t *req){	struct devmscd_device	*dev = &devmscd_dev;	__u8	status = req->status;	struct pdc_pipe_opr		bulk_pipe_opr;	func_debug(("devmscd_set_command_res(%p)\n",req))	if(dev->state != DEVMSCD_IDLE) {		if((status != MSCD_SUCCESS) && (dev->cbw[12]&0x80)) {				/* Stall Bulk In End Point */				bulk_pipe_opr.handle = dev->data_out_pipe;				bulk_pipe_opr.context = (unsigned long) dev;				bulk_pipe_opr.opr = PDC_PIPE_STALL;				pdc_pipe_operation(&bulk_pipe_opr);		} else if(status == MSCD_SUCCESS && dev->tx_residue) {			if(read_urb.status == PDC_URB_COMPLETE && write_urb.status == PDC_URB_COMPLETE) {				mdelay(3);				bulk_pipe_opr.handle = dev->data_out_pipe;				bulk_pipe_opr.context = (unsigned long) dev;				bulk_pipe_opr.opr = PDC_PIPE_STALL;				pdc_pipe_operation(&bulk_pipe_opr);			} else {				dev->status_queue = 1;			}		}						/*		 * Copy the transfer residue to the Command status Word 		 */		dev->csw[8] = dev->tx_residue & 0xFF;       	dev->csw[9] = (dev->tx_residue >> 8) & 0xFF;		dev->csw[10] = (dev->tx_residue >> 16) & 0xFF;       	dev->csw[11] = (dev->tx_residue >> 24) & 0xFF;       	dev->csw[12] = status;		devmscd_change_state(dev, DEVMSCD_CSW);		/* If no read or write operations are not in progress		 * send the status to the host, else wait for the read, 		 * or write operation to finish		 */		if((read_urb.status == PDC_URB_COMPLETE && write_urb.status == PDC_URB_COMPLETE) && (dev->status_queue == 0)) {			devmscd_read_data(dev->cbw,DEVMSCD_CBW_LENGTH);			devmscd_change_state(dev, DEVMSCD_IDLE);			devmscd_write_data(dev->csw, DEVMSCD_CSW_LENGTH);		} else {			/* Wait for the  data stage to finish */			dev->status_queue = 1;		}	} else {		/* 		 * Command response received in idle state , Might be a reset has done		 * or .... Ignore this		 */		detail_debug(("Command response received in Invalid state, Ignored\n"))	}	

⌨️ 快捷键说明

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