📄 msbridge.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 + -