?? usb.c
字號:
/*********************************************************************************************************
**
** MP3 and U Disk Source Code
** Copyright (c) 2005,北京博創興業科技有限公司
** All Rights Reserved
** V3.00.0
**
**--------------文件信息--------------------------------------------------------------------------------
**文 件 名: USB.C
**創 建 人: Frank Wang Xiao Jun
**創 建 日 期: 2003.12
**描 述: ATMEL AT89C51SND1單片機USB硬件寄存器的配置以及Bulk_Only協議和U盤的實現
**
**--------------歷史版本信息----------------------------------------------------------------------------
** 創建人: Frank Wang Xiao Jun
** 版 本: V1.00.0
** 日 期: 2003.12
** 描 述: ATMEL AT89C51SND1單片機USB硬件寄存器的配置以及Bulk_Only協議和U盤的實現
**
**------------------------------------------------------------------------------------------------------
** 修改人: Kent Zou Ying
** 版 本: V2.00.0
** 日 期: 2004. 5
** 描 述: ATMEL AT89C51SND1單片機USB硬件寄存器的配置以及Bulk_Only協議和U盤的實現
**
**--------------當前版本修訂------------------------------------------------------------------------------
** 修改人: Phoenix Hua Yue Guang
** 版 本: V3.00.0
** 日 期: 2005.3
** 描 述: ATMEL AT89C51SND1單片機USB硬件寄存器的配置以及Bulk_Only協議和U盤的實現
**
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "REGSND1.H"
#include "USBDEF.H"
#include "UART.h"
/*
//時鐘參數宏
#define Rdiv 11
//USB寄存器設置相關的宏定義
#define PLLRES (0x1<<3) //PLLCON
#define PLLEN (0x1<<1)
#define USBE (0x1<<7) //USBCON
#define EEOFINT (0x1<<4)
#define FEN (0x1<<7)
#define FADDEN (0x1)
#define CONFG (0x1<<1)
#define DIR (0x1<<7) //UEPSTAX
#define RXOUTB1 (0x1<<6)
#define STALLRQ (0x1<<5)
#define TXRDY (0x1<<4)
#define STLCRC (0x1<<3)
#define RXSETUP (0x1<<2)
#define RXOUTB0 (0x1<<1)
#define TXCMP (0x1<<0)
//USB 請求的bRequert的含意宏
#define get_status 0x00 //取得狀態
#define clear_feature 0x01 //清除特性
#define reserved 0x02 //保留
#define set_feature 0x03 //設置特性
#define set_address 0x05 //設置地址
#define get_descriptor 0x06 //取得描述符
#define get_configuration 0x08 //取得配置
#define set_configuration 0x09 //設置配置
#define get_interface 0x0a //取得接口
#define set_interface 0x0b //設置接口
void AtmelUSBInit() //用于USB的PLL時鐘20M晶振時如下設置
{
int data i;
PLLNDIV = 0x04; //設置PLL時鐘
PLLCON |= (0x3&Rdiv)<<6;
PLLRDIV = (0x3ff&Rdiv)>>2;
USBCLK=0;
PLLCON&=(~PLLRES); //使能PLL
PLLCON|=PLLEN;
USBCON&=(~USBE); //關閉USB并復位USB
for(i=0;i<3000;i++); //等待PLL工作穩定
USBCON|=USBE; //開啟USB控制器
}
void EpEnable(void) //初始化USB端點
{
UEPNUM=0x00; UEPCONX=0x80;
UEPNUM=0x01; UEPCONX=0x86;
UEPNUM=0x02; UEPCONX=0x82;
UEPRST=0x07; UEPRST= 0x00;
UEPIEN=0x07; USBIEN|=EEOFINT;
USBADDR=FEN;
}
unsigned char ReadEp(unsigned char EpNum,unsigned char *Data) //讀取端口數據
{
unsigned char data i=0;
UEPNUM=EpNum; //指端口號
while(i<UBYCTLX) //讀數據到緩沖//UBYCTX得到數據長度
{
Data[i++]=UEPDATX;
}
UEPSTAX&=~(RXOUTB0|RXOUTB1|RXSETUP); //清除相關位
return(i);
}
void WriteEp(unsigned char EpNum,unsigned char nLength,unsigned char *Data) //寫端口數據
{
unsigned char data i=0;
UEPNUM=EpNum; //選擇端口
UEPSTAX|=DIR; //控制方向
while(nLength--) UEPDATX=Data[i++]; //寫入FIFO
UEPSTAX|=TXRDY; //開始發送
while(!(UEPSTAX&TXCMP)) ;
UEPSTAX&=(~(TXCMP)); //清除TXCMP
}
//-------------以下用于對端點進行處理
void Set_Address(unsigned char EpNum) //設置USB地址1-127
{
WriteEp(0,0,0); //在Status階段過后才能改變設備地址
USBADDR|=EpNum;
USBADDR|=FEN; //設置地址
USBCON|=FADDEN; //地址使能
}
//設備描述符
code unsigned char Device_Descriptor[18] = {
0x12, //0x12
0x01, //DEVICE descriptor
0x10, 0x01, //spec rev level (BCD) 1.0
0x0, //device class
0x0, //device subclass
0x0, //device protocol
0x20, //max packet size
0x05, 0x82, //National's vendor ID
0x00, 0x11, //National's product ID
0x00, 0x00, //National's revision ID
0, //index of manuf. string
0, //index of prod. string
0, //index of ser. # string
0x01 //number of configs.
};
//配置描述符
code unsigned char Configuration_Descriptor_All[32] = {
9, //Size of Descriptor in Bytes
2, //Configuration Descriptor (0x02)
0x20, //Total length in bytes of data returned LSB
0x00, //MSB
1, //Number of Interfaces
1, //Value to use as an argument to select this configuration
0, //Index of String Descriptor describing this configuration
0x80,
0xfa, //Maximum Power Consumption in 2mA units
9,
4,
0, //the index of the interface descriptor Number of Interface
0, //Value used to select alternative setting
2, //EndPoint Number Used in this Descriptor
8, //Class Code (Assigned by USB Org)
6, //interface subclass1=RBC,2=SFF,3=QIC,4=UFI,5=SFF,6=SCSI
0x50, //bulk 0nly Transport
0, //Index of String Descriptor Describing this interface
//Bulk-in Endpoint
0x07, //length of this desc.
0x05, //ENDPOINT descriptor TYPE
0x81, //address (IN) Endpoint 4 84
0x02, //attributes (BULK)
0x40, 0x00, //max packet size (64)
0x0, //Does not apply to Bulk endpoints
//Bulk-out Endpoint
0x07, //length of this desc.
0x05, //ENDPOINT descriptor TYPE
0x02, //address (OUT) Endpoint 5 05
0x02, //attributes (BULK)
0x40, 0x00, //max packet size (64)
0x0 //Does not apply to Bulk endpoints
};
void Get_Descriptor(unsigned char DesType,unsigned char nLength) //得到描述符
{
if(DesType==0x01) //取設備描述符
WriteEp(0,18,Device_Descriptor);
if((DesType==0x02)&&(nLength==0x09)) //取端口描述符
WriteEp(0,9,Configuration_Descriptor_All);
if((DesType==0x02)&&(nLength==0xff)) //取端點描述符
{
WriteEp(0,32,Configuration_Descriptor_All);
WriteEp(0,2,&Device_Descriptor[4]);
}
if((DesType==0x02)&&(nLength==0x20))
WriteEp(0,32,Configuration_Descriptor_All); //取配置描述符
}
void Set_Configuration(unsigned char wValue) //設置配置
{
if(wValue == 0)
{
UEPNUM=0x00; UEPCONX=0x80;
UEPNUM=0x01; UEPCONX=0x86;
UEPNUM=0x02; UEPCONX=0x82;
USBCON&=(~CONFG);
WriteEp(0,0,0); //狀態傳送階段之前完成指定操作
}
else if(wValue == 1)
{
UEPNUM=0x00; UEPCONX=0x80;
UEPNUM=0x01; UEPCONX=0x86;
UEPNUM=0x02; UEPCONX=0x82;
USBCON|=CONFG;
WriteEp(0,0,0); //狀態傳送階段之前完成指定操作
}
}
void Ep0() //---端點0處理主函數
{
unsigned char data DT[32]={0,};
unsigned char data i;
i = ReadEp(0,DT);
if (((DT[0] & 0x60)==0) && i)
{
switch (DT[1])
{
case set_address :Set_Address(DT[2]); break; //設置地址
case get_descriptor :Get_Descriptor(DT[3],DT[6]); break; //取描述符
case set_configuration :Set_Configuration(DT[2]); break; //設置配置
default :; break;
}
}
else if(DT[0]==0xa1) //非標準USB請求
{
WriteEp(0,0,0);
}
}
//-----------------------------------------------------------------------------/
// 以下為利用Bulk_Only傳輸協議的函數部分 //
//-----------------------------------------------------------------------------/
unsigned char data bulk_CSW[]={0x55,0x53,0x42,0x53, // bytes 4 dCSWSignature
0x00,0x00,0x00,0x00, //bytes 4 dCSWTag
0x00,0x00,0x00,0x00, //bytes 4 dDataResiduce
0x00}; //bCSWStatus 00=good state.
typedef struct _STRUCT_CBW
{
unsigned char CBWCB[12]; //for UFI Command all have 12bit
} struct_CBW;
struct_CBW data bulk_CBW;
void WriteEpBulk(unsigned char EpNum,unsigned char nLength,unsigned char *Data)
{
unsigned char data i;
UEPNUM=EpNum; //---設置端點號
UEPSTAX|=DIR; //...設置為In模式
for(i=0;i<nLength;i++) UEPDATX=Data[i]; //---填緩沖區
UEPSTAX|=TXRDY; //---發送數據
}
void TransmitCSW() //向Host返回CSW
{
WriteEpBulk(1, sizeof(bulk_CSW), bulk_CSW);
while(!(UEPSTAX&TXCMP)) ;
UEPSTAX&=(~(TXCMP)); //清除TXCMP
UEPINT = 0;
}
void main_txdone() //數據發送完畢給出回復
{
UEPSTAX&=(~(TXCMP)); //清除TXCMP
TransmitCSW();
}
//////////////////////////////////有關輸出端點的調用//////////////////////////////////////////////
#define Inquiry 0x12
#define Mode_Sense 0x1A
#define Read10 0x28
#define Read_Capacity 0x25
#define Read_Format_Capacities 0x23
#define Test_Unit_Ready 0x00
#define Verify 0x2F
#define Write10 0x2A
#define Medium_Removal 0x1E
#define SCSI_MSPGCD_TPP 0x1C
#define SCSI_MSPGCD_RETALL 0x3F
//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', '3', '.', '0', '0',//Product Identification
0, 0, 0, 0}; //Product Revision Level n.nn
//SCSI-Read_Format_capacities命令的返回數據
code unsigned char B_Read_Format_capacities[] = {0x00, 0x00, 0x00, 0x10, //capacity list header
0x00, 0x00, 0x07, 0xf5, 0x01, 0x00, 0x02, 0x00, //capacity descriptor
//Number of Blocks =2037,unformatted media,blocklength = 512Bytes
0x00, 0x00, 0x07, 0xfd, 0x00, 0x00, 0x02, 0x00 //Formattable Capacity Descriptors
};
//SCSI-Read_Capacity命令的返回數據
code unsigned char B_Read_Capacity[] = {
0x00, 0x00, 0xfe, 0xa0, //Last Logical Block Address for 32MB
0x00, 0x00, 0x02, 0x00 //block length in bytes
};
//SCSI-Mode_Sense命令的返回數據
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -