📄 bulk_only.c
字号:
/*
* Copyright (c) 2004,北京博创兴业科技有限公司
* All rights reserved.
*
* 文件名称:bulk_only.c
* 文件标识:bulk_only
* 摘 要:批量传输函数定义
*
* 当前版本:2.0
* 作 者:Kent
* 完成日期:2004年5月20日
*
* 取代版本:1.1
* 原作者 :Frank
* 完成日期:2003年8月10日
*/
//this file to process the request about bulk_only
#include <string.h>
#include "bulk_only.h"
#include "fat16.h"
#include "usbdisk.h"
#include "uart.h"
#include "flash.h"
#include "atmelusbci.h"
//extern unsigned char EpBuf[];
unsigned char *BulkPoint = 0;
unsigned char *BulkStartPoint = 0;
long unsigned int dDataResiduce = 0;//USB传输过程中,未传完的剩余数据
unsigned char bulk_state = 0; //当前传送状态
unsigned char *pCurrentBuf; //数据传送指针
long int nBufCount = 0; //传送数据当前位置
//unsigned char MSC_dCBWSignature[] = {0x55, 0x53, 0x42, 0x43};
//unsigned char MSC_dCSWSignature[] = {0x55, 0x53, 0x42, 0x53};
//以下是SCSI命令的命令字与其代码的对应表
#define Format_Unit 0x04
#define Inquiry 0x12
#define Mode_Select 0x55
#define Mode_Sense 0x1A
#define Medium_Removal 0x1E
#define Read10 0x28
#define Read12 0xA8
#define Read_Capacity 0x25
#define Read_Format_Capacities 0x23
#define Request_Sense 0x03
#define Rezero 0x01
#define Seek10 0x2B
#define Send_Diag 0x1D
#define Start_Stop_Unit 0x1B
#define Test_Unit_Ready 0x00
#define Verify 0x2F
#define Write10 0x2A
#define Write12 0xAA
#define Write_And_Verify 0x2E
/****************************************/
#define SCSI_MSPGCD_TPP 0x1c
#define SCSI_MSPGCD_RETALL 0x3f
//unsigned char Bulk_Out_Buf[64]; //64字节的端点缓存
unsigned char Page_Buf[512]; //512字节的页缓存
unsigned int Fat_Buf[544] _at_ 0x320;//1024字节的FAT表缓存
short int Transfer_Length; //要传送的扁区长度
long int Logical_Block_Address; //逻辑地址
long int nCurrentPage, nBeginPage; //当前扇区和超始扇区
long int nCurrentBlock; //当前Block
//SCSI-Inquiry命令的返回数据
code unsigned char B_InquiryData[] = {
0x00, //Direct Access Device
0x80, //RMB
0x00, //ISO/ECMA/ANSI
0x01, //Response Data Format
0x1f, //Additional Length
0x00, //Reserved
0x00, //Reserved
0x00, //Reserved
'U', 'P', '-', 'T', 'E', 'C', 'H', ' ', //Vendor Information
'M', 'P', '3', ' ', 'P', 'l', 'a', 'y', 'e', 'r', ' ', 'V', '2', '.', '0', '0',//Product Identification
0, 0, 0, 0}; //Product Revision Level n.nn
//code unsigned char CapactiyLstHd[]={0x00,0x00,0x00,0x10};
//code unsigned char bBlockLength[]={0x00,0x02,0x00}; //512 Byte
//code unsigned char nLastLBAddr[]={0x00,0x01,0xf3,0xff}; //Last Logical Block Address for 64MB
//SCSI-Read_Format_capacities命令的返回数据
code unsigned char B_Read_Format_capacities[] = {0x00, 0x00, 0x00, 0x10, //capacity list header
0x00, 0x00, 0x04, 0x00, 0x01, 0x00, 0x02, 0x00, //capacity descriptor
// Number of Blocks =1024,unformatted media,blocklength = 512Bytes
0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00 //Formattable Capacity Descriptors
};
//SCSI-Read_Capacity命令的返回数据
code unsigned char B_Read_Capacity[] = {
0x00, 0x00, 0xff, 0xe0, //Last Logical Block Address for 64MB
0x00, 0x00, 0x02, 0x00 //block length in bytes
};
//SCSI-Mode_Sense命令的返回数据
code unsigned char B_Mode_Sense_ALL[] = {0x0b, 0x00,//Mode Data Length
0x00, 0x08, 0x00, 0x00,
0x7d, 0, 0, 0, 0x02, 0x00
};
//SCSI-Mode_Sense命令的返回数据
code unsigned char B_Mode_Sense_TPP[] = {0xf0, 0x00,//Mode Data Length
05, 00, 00, 00, 00, 0x0b, 00, 00, 00, 00, 0x24, 00, 00, 00, 00, 00
};
//SCSI-Mode_Sense命令的返回数据
code unsigned char B_Mode_Sense_ZERO[] = {0x00, 0x06,//Mode Data Length
0x00, //Medium Type Code
0,//write enabled
0, 0, 0, 0//reserved
};
typedef struct _STRUCT_CBW
{
unsigned char dCBWSignature[4];
unsigned char dCBWTag[4]; //dCBWTag of CBW
long unsigned int dCBWDataTransferLength;//dCBWDataTransferLength of CBW
unsigned char bmCBWFlags;
unsigned char bCBWLUN;
unsigned char bCBWCBLength;
unsigned char CBWCB[12];//for UFI Command all have 12bit
} struct_CBW ;
struct_CBW bulk_CBW;
//CSW数据内容,默认都为Good Status
unsigned char bulk_CSW[13] = {0x55, 0x53, 0x42, 0x53, // bytes 4 dCSWSignature
0x00, 0x00, 0x00, 0x00, //bytes 4 dCSWTag
0, 0, 0, 0, //bytes 4 dDataResiduce
0x00}; //bCSWStatus 00=good state.
//解析CBW块的数据内容
void InterpretCBW()
{
int i;
// printu("InterpretCBW");
//保存dCSWTag
bulk_CSW[4] = *(BulkStartPoint + 4);
bulk_CSW[5] = *(BulkStartPoint + 5);
bulk_CSW[6] = *(BulkStartPoint + 6);
bulk_CSW[7] = *(BulkStartPoint + 7);
//读取CBWCB
for (i=0; i<12; i++)
{
bulk_CBW.CBWCB[i] = *(BulkStartPoint + i + 15);
}
switch (bulk_CBW.CBWCB[0])
{//根据各个不同的命令字,处理相应的命令
// case 0x04 : UFI_Reserved(); break;
case Inquiry : UFI_Inquiry(); break;
// case 0x55 : UFI_Reserved(); break;
case Mode_Sense : UFI_Mode_Sense(); break;
case Read10 : UFI_Read10(); break;
// case 0xA8 : UFI_Reserved(); break;
case Read_Capacity : UFI_Read_Capacity(); break;
case Read_Format_Capacities : UFI_Read_Format_Capacities(); break;
// case 0x03 : UFI_Reserved(); break;
// case 0x01 : UFI_Reserved(); break;
// case 0x2B : UFI_Reserved(); break;
// case 0x1D : UFI_Reserved(); break;
// case 0x1B : UFI_Reserved(); break;
case Test_Unit_Ready : UFI_Test_Unit_Ready(); break;
case Verify : UFI_Verify(); break;
case Write10 : UFI_Write10(); break;
// case 0xAA : UFI_Reserved(); break;
// case 0x2E : UFI_Reserved(); break;
case Medium_Removal : UFI_Medium_Removal(); break;
default : UFI_Reserved(); break;
}
}
void UFI_Inquiry()
{
if (bulk_CBW.CBWCB[4] == 0)
return;
bulk_state = BULK_DATA_END;//置传输状态为Bulk_Data_End,当这个阶段完成后,程序会接着传送CSW,符合USB协议要求
WriteEpBulk(1, sizeof (B_InquiryData), B_InquiryData);//向Bulk-In端点写入数据
}
void UFI_Read_Format_Capacities()
{
if (bulk_CBW.CBWCB[7] == 0 && bulk_CBW.CBWCB[8] == 0)
return;
bulk_state = BULK_DATA_END;//置传输状态为Bulk_Data_End
WriteEpBulk(1, sizeof (B_Read_Format_capacities), B_Read_Format_capacities);//向Bulk-In端点写入数据
}
void UFI_Read_Capacity()
{
bulk_state = BULK_DATA_END;//置传输状态为Bulk_Data_End
WriteEpBulk(1, sizeof (B_Read_Capacity), B_Read_Capacity);//向Bulk-In端点写入数据
}
void UFI_Mode_Sense()
{
dDataResiduce = bulk_CBW.dCBWDataTransferLength;
bulk_state = BULK_DATA_END;//置传输状态为Bulk_Data_End
if (bulk_CBW.CBWCB[2] == SCSI_MSPGCD_TPP)
{ //Page Code=Timer and Potect Page
WriteEpBulk(1, sizeof (B_Mode_Sense_TPP), B_Mode_Sense_TPP);
}
else if(bulk_CBW.CBWCB[2] == SCSI_MSPGCD_RETALL)
{ //Page Code=All
WriteEpBulk(1, sizeof (B_Mode_Sense_ALL), B_Mode_Sense_ALL);
}
else
{ //Page Code=Zero
WriteEpBulk(1, sizeof (B_Mode_Sense_ZERO), B_Mode_Sense_ZERO);
}
}
void UFI_Read10()
{
int i;
// printu("UFI_Read10__1\n");
for (i=0; i<4; i++)
{
Logical_Block_Address = (Logical_Block_Address << 8) + bulk_CBW.CBWCB[2 + i]; //要传的数据的起始簇
}
Transfer_Length = bulk_CBW.CBWCB[7] * 256 + bulk_CBW.CBWCB[8]; //要传的扇区数
nCurrentPage = Logical_Block_Address % 0x20; //由逻辑地址块取真实扇区
nCurrentBlock = Logical_Block_Address = Logical_Block_Address / 0x20 + Root_Cluster; //由逻辑地址块取簇
nBufCount=0; //传送数据当前位置
ReadPage(Logical_Block_Address, nCurrentPage, Page_Buf);//读出当前簇的512个字节数据
Transfer_Length--; //传输扇区数减1
nCurrentPage++; //指向下一扇区
bulk_state = BULK_DATA_TRANS; //置传输状态为传数状态
pCurrentBuf = Page_Buf; //将当前数据缓存指针传给送数指数
WriteEpBulk(1, 64, pCurrentBuf);//传送第一个64字节
}
void TransDataGoOn()
{
// int i;
if (nBufCount < 0x1c0)
{ //如果一个扇区数据未传完
nBufCount += 0x40; //指向下一个64字节
WriteEpBulk(1, 64, pCurrentBuf + nBufCount);//将当前64个字节传输出去
}
else if(Transfer_Length > 0)
{ //如果总扇区未传完,
if(nCurrentPage == 0x20)
{ //扇区数满32时,指向下一个Block
nCurrentBlock++;
nCurrentPage = 0; //扇区数重新指向0
}
ReadPage(nCurrentBlock, nCurrentPage, Page_Buf); //读新的一个扇区
nCurrentPage++; //指向下一扇区
Transfer_Length--;
nBufCount =0; //重新计另一扁区
pCurrentBuf = Page_Buf;
bulk_state = BULK_DATA_TRANS;
WriteEpBulk(1, 64, pCurrentBuf); //写第一次
}
else
{
bulk_state = BULK_DATA_END; //数据传输结束,置传输状态
nBufCount = 0; //指针复位
TransmitCSW();
}
}
void UFI_Write10()
{
int i;
for (i=0; i<4; i++)
{
Logical_Block_Address = (Logical_Block_Address << 8) + bulk_CBW.CBWCB[2 + i]; //要传的数据的起始簇
}
Transfer_Length = bulk_CBW.CBWCB[7] * 256 + bulk_CBW.CBWCB[8]; //要传的扇区数
nBeginPage = nCurrentPage = Logical_Block_Address % 0x20; //由逻辑地址块取真实扇区
nCurrentBlock = Logical_Block_Address = Logical_Block_Address/0x20 + Root_Cluster; //由逻辑地址块取簇
bulk_state = BULK_DATA_RECIEVE;//置状态为数据接收状态
//如果目标Block小于6,或是起始扇区不为零,则擦除1000Block作为缓存Erase The Buf
if ((nCurrentBlock<6)||nBeginPage)
{
Erase_Cluster(1000);//Erase The Buf
}
else
{
Erase_Cluster(nCurrentBlock);//否则直接擦除目标Blcok,准备存入数据Erase The Block to be write
}
}
void Trans_Data2PC()
{
int i;
// printuf("E:%x\n",nBufCount/0x40);
// memcpy(Page_Buf+nBufCount,Bulk_Out_Buf,64);//将Bulk_Out端点中的64bytes的数据移入512的Page_buf中共8次
// dDataResiduce -=0x40;
// nBufCount+=0x40;
nBufCount = 512;
BulkPoint = Page_Buf;//Bulk指针退回到开始
// if((Transfer_Length==1) &&(dDataResiduce==0x40)) WriteEpBulk(1, sizeof(bulk_CSW), bulk_CSW);
//如果满512字节时,
if (((nBufCount % 0x200 == 0) && nBufCount >= 0x200) || (nBufCount == 0x00))
{
//如果写前6个Block或是超始Page不为0时,则需要缓存,先将数据写入第1000Block中
if ((nCurrentBlock < 6) || nBeginPage)
{
WritePage(1000, nCurrentPage, Page_Buf);
}
else
{
WritePage(nCurrentBlock, nCurrentPage, Page_Buf);//否则,直接写入目标Block
}
nCurrentPage++; //指向下一扇区
Transfer_Length--; //已传输扇区减1
nBufCount = 0; //准备下一个扇区接收
}
// if(((Transfer_Length%0x20)==0) && (Transfer_Length>=0x20)&&(nCurrentPage == 0x20)){
if ((Transfer_Length > 0) && (nCurrentPage == 0x20))
{
nBufCount = 0;
// Write2Flash(nCurrentBlock,nBeginPage,nCurrentPage-1,Flash_One_Page);
if ((nCurrentBlock < 6) || nBeginPage)
{//如果采用了缓存,则需要保留部分数据
for (i=0; i<nBeginPage; i++)
{
ReadPage(nCurrentBlock, i, Page_Buf);//将起始Block以前的数据移入缓存中
WritePage(1000, i, Page_Buf);
}
Erase_Cluster(nCurrentBlock);//擦除目标Block
for (i=0; i<32; i++)
{//将缓存中的数据存入目标Block中
ReadPage(1000, i, Page_Buf);
WritePage(nCurrentBlock, i, Page_Buf);
}
}
nCurrentBlock++;//指向下一个Block
nCurrentPage = 0;
nBeginPage = 0;
// Erase_Cluster(1000);
//根据下一个Block的位置,决定是否缓存,并擦除目标位置
if ((nCurrentBlock < 6) || nBeginPage)
{
Erase_Cluster(1000);//Write One 32k Buf,Erase The Buf for next transaction
}
else
{
Erase_Cluster(nCurrentBlock);//Erase The Block to be write
}
// Uart_Printf("%x\n",Transfer_Length);
}
if (Transfer_Length == 0)
{//数据传送完毕后,将当前缓存中的所有内容写入Flash
nBufCount = 0;
// Write2Flash(nCurrentBlock,nBeginPage,nCurrentPage-1,Flash_One_Page);
if ((nCurrentBlock < 6) || nBeginPage)
{
for (i=0; i<nBeginPage; i++)
{
ReadPage(nCurrentBlock, i, Page_Buf);
WritePage(1000, i, Page_Buf);
}
for (i=nCurrentPage; i<32; i++)
{
ReadPage(nCurrentBlock, i, Page_Buf);
WritePage(1000, i, Page_Buf);
}
Erase_Cluster(nCurrentBlock);
for (i=0; i<32; i++)
{
ReadPage(1000, i, Page_Buf);
WritePage(nCurrentBlock, i, Page_Buf);
}
}
TransmitCSW();//向主机发送CSW
}
}
void UFI_Medium_Removal()
{
TransmitCSW(); //直接返回CSW
}
void UFI_Test_Unit_Ready()
{
TransmitCSW(); //Flash Disk are always ready!
}
void TransmitCSW()
{
unsigned char i;
// WriteEpBulk(1, sizeof(bulk_CSW), bulk_CSW); //向端点发送CSW
// bulk_state = BULK_CSW_END; //置传输状态。
UEPNUM = 1;//指向相应端点
UEPSTAX |= DIR;//设置方向为写Set for status of a Control In transaction
for (i=0; i<13; i++)
{
UEPDATX = bulk_CSW[i];//将数据写入端点
}
UEPSTAX |= TXRDY;//发送数据Sending the data,this action will switch between bank0 and bank1
bulk_state = BULK_CSW_END; //置传输状态。
}
void TransRequestGoOn()
{
if (dDataResiduce > 0x40)
{//如果要传送的数据大于64,则置传输状态为请求数据传送状态
dDataResiduce -= 0x40;
bulk_state = BULK_REQEST_TRANS;
nBufCount += 0x40;
WriteEpBulk(1, 64, pCurrentBuf + nBufCount);
}
else
{//如果小于64,则置数据传输完毕状态
bulk_state = BULK_DATA_END;
nBufCount += 0x40;
WriteEpBulk(1, dDataResiduce, pCurrentBuf + nBufCount);
nBufCount = 0; //prepare for nexe into
}
}
void UFI_Verify()
{
TransmitCSW();//直接返回CSW
}
void UFI_Reserved()
{
printuf("\nUFI Function 0x%x doesn't Defined!", bulk_CBW.CBWCB[0]);
TransmitCSW();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -