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

📄 bulk_only.c

📁 这个是一个完整的MP3项目
💻 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 + -