亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? scsi.c

?? 單片機上實現(xiàn)U盤功能
?? C
字號:
/******************************************************************
   本程序只供學習使用,未經(jīng)作者許可,不得用于其它任何用途
			
        歡迎訪問我的USB專區(qū):http://group.ednchina.com/93/
        歡迎訪問我的blog:   http://www.ednchina.com/blog/computer00
                             http://computer00.21ic.org

        感謝PCB贊助商——電子園: http://bbs.cepark.com/

SCSI.c file

作者:電腦圈圈
建立日期: 2008.08.15
修改日期: 2008.08.20
版本:V1.1
版權所有,盜版必究。
Copyright(C) 電腦圈圈 2008-2018
All rights reserved            
*******************************************************************/


#include "MyType.H"
#include "UsbCore.h"
#include "PDIUSBD12.h"
#include "SCSI.h"
#include "Uart.h"
#include "config.h"
#include "FAT.h"

//定義端點2最大包長度為64字節(jié)
#define EP2_SIZE 64

//處理端點2數(shù)據(jù)的緩沖區(qū)
idata uint8 Ep2Buffer[EP2_SIZE];

uint32 ByteAddr;  //字節(jié)地址

//INQUIRY命令需要返回的數(shù)據(jù)
//請對照書中INQUIRY命令響應數(shù)據(jù)格式
code uint8 DiskInf[36]=
{
 0x00, //磁盤設備
 0x00, //其中最高位D7為RMB。RMB=0,表示不可移除設備。如果RMB=1,則為可移除設備。
 0x00, //各種版本號0
 0x01, //數(shù)據(jù)響應格式
 0x1F, //附加數(shù)據(jù)長度,為31字節(jié)
 0x00, //保留
 0x00, //保留
 0x00, //保留
 0xB5,0xE7,0XC4,0xD4,0xC8,0xA6,0xC8,0xA6, //廠商標識,為字符串“電腦圈圈”
 
 //產品標識,為字符串“自己做的假U盤”
 0xD7,0xD4,0xBC,0xBA,0xD7,0xF6,0xB5,0xC4,0xBC,0xD9,0x55,0xC5,0xCC,0x00,0x00,0x00,
 0x31,0x2E,0x30,0x31 //產品版本號,為1.01
};

//READ_FORMAT_CAPACITIES命令需要返回的數(shù)據(jù)
//請對照書中READ_FORMAT_CAPACITIES命令響應數(shù)據(jù)格式
code uint8 MaximumCapacity[12]=
{
 0x00, 0x00, 0x00, //保留
 0x08,  //容量列表長度
 0x01, 0x00, 0x00, 0x00,  //塊數(shù)(最大支持8GB)
 0x03, //描述符代碼為3,表示最大支持的格式化容量
 0x00, 0x02, 0x00 //每塊大小為512字節(jié)
};

//READ_CAPACITY命令需要返回的數(shù)據(jù)
code uint8 DiskCapacity[8]=
{
 0x00,0x03,0xFF,0xFF, //能夠訪問的最大邏輯塊地址
 0x00,0x00,0x02,0x00  //塊的長度
 //所以該磁盤的容量為
 //(0x3FFFF+1)*0x200 = 0x8000000 = 128*1024*1024 = 128MB.
};

//REQUEST SENSE命令需要返回的數(shù)據(jù),這里固定為無效命令
//請參看書總數(shù)據(jù)結構的解釋
code uint8 SenseData[18]=
{
 0x70, //錯誤代碼,固定為0x70
 0x00, //保留
 0x05, //Sense Key為0x05,表示無效請求(ILLEGAL REQUEST)
 0x00, 0x00, 0x00, 0x00, //Information為0
 0x0A, //附加數(shù)據(jù)長度為10字節(jié)
 0x00, 0x00, 0x00, 0x00, //保留
 0x20, //Additional Sense Code(ASC)為0x20,表示無效命令操作碼(INVALID COMMAND OPERATION CODE)
 0x00, //Additional Sense Code Qualifier(ASCQ)為0
 0x00, 0x00, 0x00, 0x00 //保留
};

uint8 * pEp2SendData;
uint32 Ep2DataLength;

/********************************************************************
函數(shù)功能:從CBW中獲取傳輸數(shù)據(jù)的字節(jié)數(shù)。
入口參數(shù):無。
返    回:需要傳輸?shù)淖止?jié)數(shù)。
備    注:無。
********************************************************************/
uint32 GetDataTransferLength(void)
{
 uint32 Len;
 
 //CBW[8]~CBW[11]為傳輸長度(小端結構)
 
 Len=CBW[11];
 Len=Len*256+CBW[10];
 Len=Len*256+CBW[9];
 Len=Len*256+CBW[8];
 
 return Len;
}
////////////////////////End of function//////////////////////////////

/********************************************************************
函數(shù)功能:從CBW中獲取邏輯塊地址LBA的字節(jié)數(shù)。
入口參數(shù):無。
返    回:邏輯塊地址LBA。
備    注:無。
********************************************************************/
uint32 GetLba(void)
{
 uint32 Lba;
 
 //讀和寫命令時,CBW[17]~CBW[20]為邏輯塊地址(大端結構)
 
 Lba=CBW[17];
 Lba=Lba*256+CBW[18];
 Lba=Lba*256+CBW[19];
 Lba=Lba*256+CBW[20];
 
 return Lba;
}
////////////////////////End of function//////////////////////////////

/********************************************************************
函數(shù)功能:填充CSW。
入口參數(shù):Residue:剩余字節(jié)數(shù);Status:命令執(zhí)行的狀態(tài)。
返    回:無。
備    注:無。
********************************************************************/
void SetCsw(uint32 Residue, uint8 Status)
{
 //設置CSW的簽名,其實可以不用每次都設置的,
 //開始初始化設置一次就行了,這里每次都設置
 CSW[0]='U';
 CSW[1]='S';
 CSW[2]='B';
 CSW[3]='S';
 
 //復制dCBWTag到CSW的dCSWTag中去
 CSW[4]=CBW[4];
 CSW[5]=CBW[5];
 CSW[6]=CBW[6];
 CSW[7]=CBW[7];
    
 //剩余字節(jié)數(shù)
 CSW[8]=Residue&0xFF;
 CSW[9]=(Residue>>8)&0xFF;
 CSW[10]=(Residue>>16)&0xFF;
 CSW[11]=(Residue>>24)&0xFF;
 
 //命令執(zhí)行的狀態(tài),0表示成功,1表示失敗。
 CSW[12]=Status;
}
////////////////////////End of function//////////////////////////////

/********************************************************************
函數(shù)功能:獲取磁盤數(shù)據(jù)函數(shù)。
入口參數(shù):無。
返    回:無。
備    注:無。
********************************************************************/
void GetDiskData(void)
{
 //判斷該返回什么數(shù)據(jù)
 if(ByteAddr==0) pEp2SendData=Dbr; //返回DBR
 if(ByteAddr==512) pEp2SendData=Fat; //返回FAT
 if((ByteAddr>=576)&&(ByteAddr<16896)) pEp2SendData=Zeros;
 if(ByteAddr==16896) pEp2SendData=Fat; //返回FAT(備份FAT)
 if((ByteAddr>=16960)&&(ByteAddr<33280)) pEp2SendData=Zeros;
 if(ByteAddr==33280) pEp2SendData=RootDir; //返回根目錄
 if((ByteAddr>=33344)&&(ByteAddr<49664)) pEp2SendData=Zeros;
 if(ByteAddr==49664) pEp2SendData=TestFileData; //返回文件數(shù)據(jù)
 if(ByteAddr>50175) pEp2SendData=Zeros;
 
 ByteAddr+=EP2_SIZE; //調整字節(jié)地址,每次發(fā)送最大包長度的數(shù)據(jù)
}
////////////////////////End of function//////////////////////////////

/********************************************************************
函數(shù)功能:將數(shù)據(jù)通過端點2發(fā)送。
入口參數(shù):無。
返    回:無。
備    注:當發(fā)送數(shù)據(jù)長度為0,并且處于數(shù)據(jù)階段時,將自動發(fā)送CSW。
********************************************************************/
void Ep2SendData(void)
{
 if(Ep2DataLength==0) //如果需要發(fā)送的數(shù)據(jù)長度為0
 {
  if(TransportStage==DATA_STAGE) //并且處于數(shù)據(jù)階段
  {
   //則直接進入狀態(tài)階段
   TransportStage=STATUS_STAGE;
   Ep2DataLength=sizeof(CSW); //數(shù)據(jù)長度為CSW的大小
   pEp2SendData=CSW; //返回的數(shù)據(jù)為CSW
  }
  else
  {
   return; //如果是狀態(tài)階段的數(shù)據(jù)發(fā)送完畢,則返回
  }
 }
 
#ifdef DEBUG0
 if(TransportStage==STATUS_STAGE)
 {
  Prints("狀態(tài)階段。\r\n");
 }
#endif

 //如果要發(fā)送的長度比端點2最大包長要多,則分多個包發(fā)送
 if(Ep2DataLength>EP2_SIZE)
 {
  //發(fā)送端點2最大長度字節(jié)
  D12WriteEndpointBuffer(5,EP2_SIZE,pEp2SendData);
  //指針移動EP2_SIZE字節(jié)
  pEp2SendData+=EP2_SIZE;
  Ep2DataLength-=EP2_SIZE;
  //如果是READ(10)命令,并且是數(shù)據(jù)階段,則需要獲取磁盤數(shù)據(jù)
  if((CBW[15]==READ_10)&&(TransportStage==DATA_STAGE))
  {
   GetDiskData(); //獲取磁盤數(shù)據(jù)
  }
 }
 else
 {
  //可以全部發(fā)送完
  D12WriteEndpointBuffer(5,(uint8)Ep2DataLength,pEp2SendData);
  Ep2DataLength=0;  //傳輸長度為0  
  //如果是數(shù)據(jù)發(fā)送完畢,則進入僅批量傳輸協(xié)議的狀態(tài)階段
  if(TransportStage==DATA_STAGE)
  {
   TransportStage=STATUS_STAGE;
   Ep2DataLength=sizeof(CSW); //數(shù)據(jù)長度為CSW的大小
   pEp2SendData=CSW; //返回的數(shù)據(jù)為CSW
  }
  else if(TransportStage==STATUS_STAGE) //如果是狀態(tài)階段完畢,則進入到命令階段
  {
   TransportStage=COMMAND_STAGE;  //進入到命令階段
  }
 }
}
////////////////////////End of function//////////////////////////////

/********************************************************************
函數(shù)功能:處理SCSI命令的函數(shù)。
入口參數(shù):無。
返    回:無。
備    注:雖然叫SCSI命令,但是實際使用的是UFI命令。
********************************************************************/
void ProcScsiCommand(void)
{
 TransportStage=DATA_STAGE; //進入到數(shù)據(jù)階段
 
 //CBW中偏移量為15的字段為命令的類型
 switch(CBW[15])
 {
  case INQUIRY:  //INQUIRY命令
  #ifdef DEBUG0
   Prints("查詢命令。返回數(shù)據(jù):\r\n");
  #endif
   pEp2SendData=DiskInf; //返回磁盤信息
   Ep2DataLength=GetDataTransferLength(); //獲取需要返回的長度
   SetCsw(Ep2DataLength-sizeof(DiskInf),0); //設置剩余字節(jié)數(shù)以及狀態(tài)成功
   if(Ep2DataLength>sizeof(DiskInf)) //如果請求的數(shù)據(jù)比實際的要長
   {
    Ep2DataLength=sizeof(DiskInf); //則只返回實際的長度
   }
   Ep2SendData(); //返回數(shù)據(jù)
  break;
  
  case READ_FORMAT_CAPACITIES: //讀格式化容量
  #ifdef DEBUG0
   Prints("讀格式化容量命令。返回數(shù)據(jù):\r\n");
  #endif
   pEp2SendData=MaximumCapacity; //返回最大格式化容量信息
   Ep2DataLength=GetDataTransferLength(); //獲取需要返回的長度
   SetCsw(Ep2DataLength-sizeof(MaximumCapacity),0); //設置剩余字節(jié)數(shù)以及狀態(tài)成功
   if(Ep2DataLength>sizeof(MaximumCapacity)) //如果請求的數(shù)據(jù)比實際的要長
   {
    Ep2DataLength=sizeof(MaximumCapacity); //則只返回實際的長度
   }
   Ep2SendData(); //返回數(shù)據(jù)
  break;
  
  case READ_CAPACITY: //讀容量命令
  #ifdef DEBUG0
   Prints("讀容量命令。返回數(shù)據(jù):\r\n");
  #endif
   pEp2SendData=DiskCapacity; //返回磁盤容量
   Ep2DataLength=GetDataTransferLength(); //獲取需要返回的長度
   SetCsw(Ep2DataLength-sizeof(DiskCapacity),0); //設置剩余字節(jié)數(shù)以及狀態(tài)成功
   if(Ep2DataLength>sizeof(DiskCapacity)) //如果請求的數(shù)據(jù)比實際的要長
   {
    Ep2DataLength=sizeof(DiskCapacity); //則只返回實際的長度
   }
   Ep2SendData(); //返回數(shù)據(jù)
  break;
  
  case READ_10: //READ(10)命令
  #ifdef DEBUG0
   Prints("READ(10)命令。返回數(shù)據(jù):\r\n");
  #endif
   Ep2DataLength=GetDataTransferLength(); //獲取需要返回的長度
   ByteAddr=GetLba()*512; //獲取字節(jié)地址,字節(jié)地址為邏輯塊地址乘以每塊大小
   SetCsw(0,0); //設置剩余字節(jié)數(shù)為0,狀態(tài)成功
   GetDiskData(); //獲取需要返回的數(shù)據(jù)
   Ep2SendData(); //返回數(shù)據(jù)
  break;
  
  case WRITE_10: //WRITE(10)命令
  #ifdef DEBUG0
   Prints("WRITE(10)命令。輸出數(shù)據(jù):\r\n");
  #endif
   Ep2DataLength=GetDataTransferLength(); //獲取需要返回的長度
   SetCsw(0,0); //設置剩余字節(jié)數(shù)為0,狀態(tài)成功
  break;
  
  case REQUEST_SENSE: //該命令詢問前一個命令執(zhí)行失敗的原因
  #ifdef DEBUG0
   Prints("REQUEST SENSE命令。返回SENSE數(shù)據(jù)(無效命令):\r\n");
  #endif
   pEp2SendData=SenseData; //返回探測數(shù)據(jù)
   Ep2DataLength=GetDataTransferLength(); //獲取需要返回的長度
   SetCsw(Ep2DataLength-sizeof(SenseData),0); //設置剩余字節(jié)數(shù)以及狀態(tài)成功
   if(Ep2DataLength>sizeof(SenseData)) //如果請求的數(shù)據(jù)比實際的要長
   {
    Ep2DataLength=sizeof(SenseData); //則只返回實際的長度
   }
   Ep2SendData(); //返回數(shù)據(jù)
  break;
  
  case TEST_UNIT_READY: //測試磁盤是否準備好
   Ep2DataLength=0; //設置長度為0,發(fā)送數(shù)據(jù)將返回CSW
   SetCsw(0,0); //設置CSW為成功
   Ep2SendData(); //返回CSW
  break;
  
  default: //其它命令不認,返回執(zhí)行失敗
   if(CBW[12]&0x80) Ep2DataLength=1; //如果為輸入請求,則隨便返回1字節(jié)
   else Ep2DataLength=0; //否則為輸出請求,則設置長度為0,直接返回CSW
   SetCsw(GetDataTransferLength()-Ep2DataLength,1); //設置CSW為失敗
   Ep2SendData(); //返回CSW
  break;
 }
}
////////////////////////End of function//////////////////////////////

/********************************************************************
函數(shù)功能:處理輸出數(shù)據(jù)。
入口參數(shù):無。
返    回:無。
備    注:無。
********************************************************************/
void ProcScsiOutData(void)
{
 uint8 Len;
 //讀端點2數(shù)據(jù)
 Len=D12ReadEndpointBuffer(4,EP2_SIZE,Ep2Buffer);
 Ep2DataLength-=Len;
 //清除端點緩沖區(qū)
 D12ClearBuffer();
 //由于沒有存儲器,這里將緩沖區(qū)清0模擬數(shù)據(jù)處理
 while(Len)
 {
  Ep2Buffer[Len]=0; //緩沖區(qū)清0
  Len--;
 }
 
 //數(shù)據(jù)傳輸完畢,進入到狀態(tài)階段
 if(Ep2DataLength==0)
 {
  //此時Ep2DataLength為0,并且處于數(shù)據(jù)階段,調用發(fā)送數(shù)據(jù)函數(shù)將返回CSW
  Ep2SendData();
 }
}
////////////////////////End of function//////////////////////////////

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
日韩主播视频在线| caoporen国产精品视频| 亚洲国产日韩综合久久精品| 成人免费小视频| 国产精品二三区| 国产精品视频第一区| 国产日韩欧美高清| 国产欧美视频一区二区| 久久久精品tv| 中国av一区二区三区| 中文字幕欧美日本乱码一线二线| 亚洲成人第一页| 日韩高清不卡一区二区三区| 日韩精品一二区| 久久www免费人成看片高清| 久久se这里有精品| 丁香婷婷深情五月亚洲| 北条麻妃一区二区三区| 色综合久久中文字幕综合网 | 欧美性一二三区| 欧美日韩情趣电影| 日韩欧美综合在线| 精品精品欲导航| 中文字幕欧美日本乱码一线二线| 国产精品高潮呻吟| 亚洲综合视频在线观看| 日日摸夜夜添夜夜添亚洲女人| 日本不卡一区二区| 国内精品嫩模私拍在线| 国产91丝袜在线播放0| 91一区二区三区在线观看| 欧美丝袜丝nylons| 欧美本精品男人aⅴ天堂| 久久久久国产一区二区三区四区| 国产精品伦一区| 亚洲午夜精品久久久久久久久| 美女视频黄免费的久久| 国产传媒一区在线| 色欧美日韩亚洲| 欧美大片顶级少妇| 亚洲欧洲99久久| 天堂一区二区在线免费观看| 国产麻豆精品久久一二三| 91在线精品一区二区三区| 欧美精选一区二区| 欧美国产精品一区二区三区| 一区二区三区四区不卡在线 | 成人深夜福利app| 91国产福利在线| 欧美大片国产精品| 亚洲欧美日韩国产另类专区| 天天爽夜夜爽夜夜爽精品视频| 国产剧情一区二区三区| 欧美日韩在线三级| 国产日韩高清在线| 香蕉成人伊视频在线观看| 国产成人免费视频网站高清观看视频| 国产亚洲1区2区3区| 亚洲激情五月婷婷| 激情欧美日韩一区二区| 欧美伊人精品成人久久综合97| 欧美tickling挠脚心丨vk| 亚洲黄色片在线观看| 韩国av一区二区| 欧美日韩小视频| 国产精品理论片| 精品一区二区三区香蕉蜜桃| 欧美亚洲愉拍一区二区| 欧美国产一区视频在线观看| 美女视频免费一区| 欧美日韩卡一卡二| 亚洲图片激情小说| 国产精品一区二区x88av| 7777精品伊人久久久大香线蕉的| 17c精品麻豆一区二区免费| 狠狠网亚洲精品| 欧美精品自拍偷拍动漫精品| 亚洲人成网站影音先锋播放| 国产精品538一区二区在线| 91精品国产欧美一区二区成人| ●精品国产综合乱码久久久久| 国产永久精品大片wwwapp| 67194成人在线观看| 亚洲一区在线播放| 色综合欧美在线视频区| 国产喷白浆一区二区三区| 蜜桃传媒麻豆第一区在线观看| 欧美日韩国产一级二级| 亚洲男女一区二区三区| 成人美女视频在线观看| 久久久久久久久久久黄色| 久久电影网站中文字幕 | 日韩一区二区三区精品视频| 亚洲自拍偷拍综合| 一本大道久久a久久精品综合| 国产精品网站在线观看| 国产精品一区二区黑丝| 日韩精品一区二区三区中文不卡| 视频一区中文字幕国产| 91成人看片片| 亚洲综合色噜噜狠狠| 91蜜桃网址入口| 亚洲欧美日韩在线播放| 99re成人精品视频| 亚洲视频免费在线| 色先锋aa成人| 亚洲日本韩国一区| 色欧美片视频在线观看| 一区二区三区精品视频在线| 色综合久久久久久久久| 亚洲精品国产一区二区三区四区在线| 91麻豆自制传媒国产之光| 亚洲黄色免费电影| 欧美日韩一区二区三区不卡| 丝袜a∨在线一区二区三区不卡| 欧美裸体bbwbbwbbw| 在线日韩国产精品| 亚洲成人黄色小说| 日韩限制级电影在线观看| 美国十次了思思久久精品导航| 精品剧情在线观看| 国产传媒欧美日韩成人| 国产精品网站在线| 色婷婷综合五月| 亚洲1区2区3区4区| 日韩欧美资源站| 国产aⅴ综合色| 亚洲三级免费观看| 欧美高清激情brazzers| 捆绑紧缚一区二区三区视频 | 1024精品合集| 欧美三级日本三级少妇99| 轻轻草成人在线| 国产亚洲欧美色| 色综合久久久久综合体| 天堂在线亚洲视频| 久久欧美中文字幕| 91麻豆精品在线观看| 五月激情综合色| 国产亚洲综合色| 91小视频免费看| 秋霞午夜av一区二区三区| 国产性做久久久久久| 色欧美日韩亚洲| 黑人精品欧美一区二区蜜桃| 国产精品久久久久久久蜜臀| 欧美日本视频在线| 国产乱码精品一区二区三区忘忧草| 一区精品在线播放| 日韩一区二区麻豆国产| 成人免费不卡视频| 首页综合国产亚洲丝袜| 国产精品嫩草久久久久| 91精品久久久久久久91蜜桃| 国产精品99久久久| 婷婷综合在线观看| 中文字幕不卡三区| 制服丝袜国产精品| 99视频一区二区三区| 日韩高清不卡在线| 中文字幕视频一区二区三区久| 欧美一区二区成人| 91丝袜高跟美女视频| 久久国产精品99精品国产| 亚洲精品国产品国语在线app| 26uuu精品一区二区三区四区在线 26uuu精品一区二区在线观看 | 国产亚洲欧美日韩在线一区| 精品视频999| 99国产精品99久久久久久| 免费在线观看日韩欧美| 亚洲另类在线一区| 久久精品欧美一区二区三区麻豆| 国产乱子伦视频一区二区三区 | 日韩欧美视频在线| 色94色欧美sute亚洲线路一ni| 精品夜夜嗨av一区二区三区| 亚洲国产一区二区a毛片| 国产欧美日韩麻豆91| 欧美一级二级三级乱码| 91久久人澡人人添人人爽欧美| 国产精品99久久不卡二区| 午夜久久电影网| 亚洲欧洲中文日韩久久av乱码| 国产亚洲制服色| 日韩精品一区二区三区中文不卡 | 亚洲欧美在线视频| 久久午夜羞羞影院免费观看| 777a∨成人精品桃花网| 欧美中文字幕一区二区三区 | 91福利精品第一导航| 粗大黑人巨茎大战欧美成人| 看国产成人h片视频| 午夜av电影一区| 亚洲电影你懂得| 亚洲欧洲av在线| 欧美国产日本韩| 国产女人18毛片水真多成人如厕| 欧美tickling网站挠脚心| 日韩一级视频免费观看在线| 51精品国自产在线|