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

📄 msbridge.c

📁 linux下的usb开发
💻 C
字号:
/************************************************************* * Philips USB Mass Storage Class driver Interface * * (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:	msbridge.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/module.h>#include <linux/pci.h>#include <linux/kernel.h>#include <linux/delay.h>#include <linux/ioport.h>#include <linux/sched.h>#include <linux/devfs_fs_kernel.h>#include <linux/slab.h>#include <linux/smp_lock.h>#include <linux/errno.h>#include <linux/init.h>#include <linux/timer.h>#include <linux/list.h>#include <linux/interrupt.h>  /* for in_interrupt() */#undef DEBUG#include <linux/usb.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/system.h>#include <asm/unaligned.h>#include <asm/uaccess.h>#include "pdc_intf.h"#include "devmscd.h"#include "msbridge.h"#define		MODULE_NAME			"msbridge"typedef struct devmscd_intf_info {		__u8					notif;			/* Notification type */	__u8					use;				__u8					notif_pending;	__u8					*cmd;			/* mass storage command */	wait_queue_head_t 		read_wq;		/* read wait queue */	__u8					read_lock;		/* read lock */	__u32					read_bytes;		/* read response (from device) bytes */	wait_queue_head_t 		write_wq;		/* Write wait queue (TODO) */	__u8					write_lock;		/* Write lock */	__u32					write_bytes;	/* Write response bytes */	struct fasync_struct 	*fasync_q;		/* Asynchronous notification */	} devmscd_intf_info_t;/*------------------------------------------------------------------* *                 local function declerations                      * *------------------------------------------------------------------*/static ssize_t devmscd_intf_read(struct file *fp, char *dest, size_t count, loff_t *ppos);static ssize_t devmscd_intf_write(struct file *fp, const char *buf, size_t count, loff_t *ppos);static	int	devmscd_intf_open( struct inode *inode, struct file *fp);static	int	devmscd_intf_close( struct inode *inode, struct file *fp);static	int devmscd_intf_fasync( int	fd, struct file *fp, int mode);static	int	devmscd_intf_ioctl(struct inode *inode, struct file *fp, 					unsigned int	cmd, unsigned long arg);static void devmscd_disk_write(mscd_req_t *req);static void devmscd_disk_read(mscd_req_t *req);/*------------------------------------------------------------------* *                 global variable declerations                     * *------------------------------------------------------------------*/static struct file_operations devmscd_intf_fops = {	owner:		THIS_MODULE,	read:		devmscd_intf_read,	write:		devmscd_intf_write,	poll:		NULL,	ioctl:		devmscd_intf_ioctl,	open:		devmscd_intf_open,	release:	devmscd_intf_close,	fasync:		devmscd_intf_fasync,};struct devmscd_intf_info	intf_info;struct devmscd_intf_info	*devmscd_intf;__u8	rcvd_data[0x20000];__u8	send_data[0x20000];mscd_req_t		mscd_read_req, mscd_write_req;mscdbridge_req_t	*mscd_req = NULL;/*------------------------------------------------------------------* *                 local function definitions                       * *------------------------------------------------------------------*//*  * Send read command to the class driver. */ssize_t devmscd_intf_read(struct file *fp, char *dest, size_t count, loff_t *ppos) {	devmscd_intf_info_t	*intf = (devmscd_intf_info_t*)fp->private_data;	intf->read_lock = 1;//	devmscd_read_data(rcvd_data, count);	mscd_fill_req((&mscd_read_req), MSCD_READ, 			rcvd_data, count, 			devmscd_disk_write, NULL);	devmscd_submit_req(&mscd_read_req);	while(intf->read_lock) {		interruptible_sleep_on(&intf->read_wq);        if (signal_pending(current))         	return -ERESTARTSYS;    	}	memcpy(dest, rcvd_data, intf->read_bytes);	return intf->read_bytes;}/*  * Send read command to the class driver. */ssize_t devmscd_intf_write(struct file *fp, const char *buf, size_t count, loff_t *ppos){	devmscd_intf_info_t	*intf = (devmscd_intf_info_t*)fp->private_data;	memcpy(send_data,buf, count);	intf->write_lock = 1;//	devmscd_write_data(send_data, count);	mscd_fill_req((&mscd_write_req), MSCD_WRITE, 			send_data, count, 			devmscd_disk_read, NULL);	devmscd_submit_req(&mscd_write_req);	while(intf->write_lock) {		interruptible_sleep_on(&intf->write_wq);        if (signal_pending(current))         	return -ERESTARTSYS;    	}//	printk("coming out of write loop %x\n", intf->write_bytes);	return intf->write_bytes;}/* * Intialize the wait queues */int	devmscd_intf_open( struct inode *inode, struct file *fp) {	//	printk("devmscd_intf_open(inode=%p,fp=%p)\n",inode,fp);	fp->private_data = devmscd_intf;	/* set the OTG controller data in file */	init_waitqueue_head(&devmscd_intf->read_wq);	init_waitqueue_head(&devmscd_intf->write_wq);	devmscd_intf->use++;	MOD_INC_USE_COUNT;					/* Increment the module count */	return 0;}/* * cancel any asynchronous notification */int	devmscd_intf_close( struct inode *inode, struct file *fp) {//	printk("devmscd_intf_close(inode=%p,fp=%p)\n",inode,fp);		MOD_DEC_USE_COUNT;					/* Decrement module count */	if(devmscd_intf->use) devmscd_intf->use--;	devmscd_intf_fasync(-1,fp, 0);	/* cancel asynchronous notification to application */	return 0;}/* *  Set/reset asynchronous notification to the application */int devmscd_intf_fasync( int	fd, struct file *fp, int mode) {	int result;	devmscd_intf_info_t	*intf = (devmscd_intf_info_t*)fp->private_data;//	printk("devmscd_intf_fasync(fd=%d,fp=%p,mode=%d)\n",fd,fp,mode);	result =  fasync_helper(fd, fp, mode, &intf->fasync_q);	if(result >= 0 && intf->notif_pending) {		if(intf->fasync_q) {				kill_fasync( &intf->fasync_q, SIGIO, POLL_IN);				intf->notif_pending = 0;		}	}	return result;}/* *  perform the IO control operations for the application */int	devmscd_intf_ioctl(struct inode *inode, struct file *fp, 					unsigned int	cmd, unsigned long arg) {	devmscd_intf_info_t	*intf = (devmscd_intf_info_t*)fp->private_data;	int				ret = 0;	mscd_cmd_res_t	cmd_res;	switch(cmd) {		case MSCD_IOC_GET_NOTIF:						copy_to_user((mscd_notif_t *)arg, &intf->notif, sizeof(mscd_notif_t));		break;		case MSCD_IOC_GET_COMMAND:						if(mscd_req) {				copy_to_user((mscd_command_t *)arg, intf->cmd, sizeof(mscd_command_t));			} else {				return -EINVAL;			}		break;		case MSCD_IOC_SET_CMD_RES:			copy_from_user(&cmd_res, (mscd_cmd_res_t *)arg, sizeof(mscd_cmd_res_t));			if(mscd_req && mscd_req->complete) {				mscd_req_t	*req = mscd_req;				req->status = cmd_res.status;				mscd_req = NULL;				req->complete(req);			}//			devmscd_set_command_res(cmd_res.status);			break;	}	return ret;}/* * Wake up any pending read requests */void devmscd_disk_read(mscd_req_t *req){//	printk("devmscd_disk_read()\n");	devmscd_intf->write_bytes = req->res_data_len;	devmscd_intf->write_lock = 0;	wake_up_interruptible(&devmscd_intf->write_wq);	return;}/* * Wake up any pending write requests */void devmscd_disk_write(mscd_req_t *req){//	printk("devmscd_disk_write()\n");	devmscd_intf->read_bytes = req->res_data_len;	devmscd_intf->read_lock = 0;	wake_up_interruptible(&devmscd_intf->read_wq);	return;}int mscdbridge_submit_req(mscdbridge_req_t *req){	int	result = MSCD_SUCCESS;	switch(req->req_type) {				case MSCDBRIDGE_DEINIT:			req->status = MSCD_SUCCESS;			devfs_unregister_chrdev(DEVMSCD_MAJOR,DRIVER_NAME);			devmscd_intf  = NULL;			break;		case MSCDBRIDGE_INIT:			req->status = MSCD_SUCCESS;			devmscd_intf  = &intf_info;			devmscd_intf->use = 0;			devmscd_intf->notif_pending = 0;			result = devfs_register_chrdev(DEVMSCD_MAJOR, DRIVER_NAME, &devmscd_intf_fops);			break;		case MSCD_COMMAND:			/* Store the request */			mscd_req = req;			devmscd_intf->cmd = req->data_buff;		case MSCDBRIDGE_RESET:			/*			 * Send notification to the mass storage device			 */			req->status = MSCD_SUCCESS;			devmscd_intf->notif = req->req_type;			if(devmscd_intf->fasync_q) {				kill_fasync( &devmscd_intf->fasync_q, SIGIO, POLL_IN);			} else {				devmscd_intf->notif_pending = 1;			}			break;	}	return result;}

⌨️ 快捷键说明

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