📄 devmscd.c
字号:
/************************************************************* * 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 + -