📄 usb.c
字号:
}
case 2: switch(Control_Data.DeviceRequest.bRequest)//这里的2表示:bmRequestType=10000010,即数据是从设备的端点到主机
{
case 0:Get_Status(2);OutputS("得到端点的状态\n\r");break;//这里的2表示发送的是端点的状态
default:break;
}
default:break;
}
return;//如果是一个从设备到主机的输入事务,那么上面的完了之后,就返回主函数,不需要继续执行了
}
if(usb_flags.flags.setup_packet_out) //这里表示如果是一个从主机到设备的输出事务
{
OutputS("主机到设备事务\n\r");
if((Control_Data.DeviceRequest.bmRequestType==0x21)&&(Control_Data.DeviceRequest.bRequest==0xFF)) //不知道为什么!用BUS HOUND也没有看出相关的请求。但是串口调试时有。
Mass_Storage_Reset();
switch(Control_Data.DeviceRequest.bmRequestType&0x03)//判断最后三位确定接收者是设备、接口或者端点。
{
case 0: switch(Control_Data.DeviceRequest.bRequest) //如果是0,则表明需要操作的是设备
{
case CLEAR_FEATURE: Clear_Feature(0);OutputS("清除设备特性\n\r");break;
case SET_ADDRESS: Set_Usb_Address();OutputS("设置USB地址\n\r");break;
case SET_CONFIGURATION: Set_Configuration();OutputS("设置配置\n\r");break;
case SET_DESCRIPTOR: Set_Descriptor();OutputS("设置描述符\n\r");break;
case SET_FEATURE: Set_Feature(0);OutputS("设置设备特性\n\r");break;
default:break;
}
break;
case 1: switch(Control_Data.DeviceRequest.bRequest) //如果比较的结果是1,则表明操作的是接口
{
case CLEAR_FEATURE: Clear_Feature(1);OutputS("清除接口特性\n\r");break;
case SET_FEATURE: Set_Feature(1);OutputS("设置借口特性\n\r");break;
case SET_INTERFACE: Set_Interface();OutputS("设置接口\n\r");break;
default:break;
}
break;
case 2: switch(Control_Data.DeviceRequest.bRequest)//如果比较的结果是2,则表明操作的是端点
{
case CLEAR_FEATURE: Clear_Feature(2);OutputS("清除端点特性\n\r");break;
case SET_FEATURE: Set_Feature(2);OutputS("设置端点特性\n\r");break;
default:break;
}
break;
default:break;
}
}
}
void Return_CSW(unsigned long int DataResidue,unsigned char status) //返回CSW数据包
{
csw.dCSWTag=cbw.dCBWTag;
csw.dCSWDataResidue=DataResidue;
csw.bCSWStatus=status;
while(Chioce_Endp(5)&0x01); //如果端点2输出缓冲区满,则等待。如果空,继续执行。
Write_Endp_Buffer(5,sizeof(CSW),(unsigned char *)(&csw));//向端点2输出缓冲区写CSW应答包
usb_flags.flags.usb_endp2_in=0; //清除端点2输出输入标志
usb_flags.flags.usb_endp2_out=0;
SCSI.Status.Command=1; //SCSI命令标志置1
SCSI.Status.Data=0;
}
void write_10(void) //SCSI写操作
{
unsigned long int LBA,Byte_Count;
unsigned char i;
if(SCSI.Status.Data) //如果是数据
{
for(i=0;i<4;i++)
{
LBA<<=8;
LBA+=cbw.CBWCB[2+i]; //LBA中存放其实扇区地址(其实扇区地址是主机发给设备的,设备接收后放在CBW结构体的CBWCB2-5四个字节中)
}
// pData=get_physical_addr(LBA);
Byte_Count=0;
Byte_Count+=cbw.CBWCB[7];
Byte_Count<<=8;
Byte_Count+=cbw.CBWCB[8]; //Byte_Count存放传输的扇区数和需要传输的数据长度
Byte_Count<<=9;
while(usb_flags.flags.usb_endp2_out) //如果是数据是从主机到设备,则端点2输入缓冲区接收数据。
{
while(!(Chioce_Endp(4)&0x01)); //端点2输出满,则等待
if(Byte_Count>64)
{
Read_Endp_Buffer(4,64,buffer); //读缓冲区
Byte_Count-=64;
}
else
{
Read_Endp_Buffer(4,Byte_Count,buffer);
Return_CSW(0x00,SUCCESS); //数据接收完之后,给主机返回一个CSW包。
}
}
}
}
void endp2_out(void) //主端点输出处理
{
// printc(0xcc);
if(SCSI.Status.Command) //如果传送过来的是命令
{
OutputS("传送过来的是CSW命令\n\r");
if(Read_Endp_Buffer(4,sizeof(CBW),(unsigned char *)(&cbw))!=sizeof(CBW)){error(2);return;}
if(cbw.dCBWSignature!=0x55534243){error(3);return;}
SCSI.Status.Command=0; //命令此时已经放入cbw结构体中,下面要传送的是数据。因此命令标志需要清除
SCSI.Status.Data=1; //置位数据标志
if(cbw.bmCBWFlags&0x80) //如果cbw.bmCBWFlags的最高位为1,表示数据从设备到主机,即主机接收数据。
{
OutputS("该CSW命令要求设备输入数据,此时将跟一个输入事务\n\r");
usb_flags.flags.usb_endp2_in=1;
usb_flags.flags.usb_endp2_out=0;
}
else //如果cbw.bmCBWFlags的最高位为0,表示数据从主机到设备,即设备接收数据,主机发送数据。
{
OutputS("该CSW命令要求设备接收数据\n\r");
usb_flags.flags.usb_endp2_in=0;
usb_flags.flags.usb_endp2_out=1;
switch(cbw.CBWCB[0]) //cbw.CBWCB[0]中存放的是主机传送过来的特定的命令,根据主机传送过来的特定的命令码做相应处理。
{
case Write_10: write_10();OutputS("向介质写数据\n\r");break;
case Test_Unit_Ready: Return_CSW(0x00,SUCCESS);OutputS("请求设备是否处于Ready状态\n\r");break;
case Verify: Return_CSW(0x00,SUCCESS);OutputS("验证\n\r");break;
default : Return_CSW(cbw.dCBWDataTransgerLength,FAIL);break;
}
}
}
else //如果传送过来的不是命令
{
Read_Endp_Last_Status(4); //读端点2输出缓冲区最后状态(即清楚中断标志),
Chioce_Endp(4);
Clear_Buffer();
}
}
unsigned char *get_physical_addr(unsigned long int LBA) //从LBA获取物理地址
{
if(LBA==0)return DBR;
if(LBA==2)return FAT;
if(LBA==0x40)return ZERO;
if(LBA==0X0A)return FAT;
}
void read_10(void) //SCSI读处理
{
unsigned long int LBA=0,Byte_Count;
unsigned long int count=0;
unsigned char i;
if(SCSI.Status.Data)
{
for(i=0;i<4;i++)
{
LBA<<=8;
LBA+=cbw.CBWCB[2+i];
}
pData=get_physical_addr(LBA);
Byte_Count=0;
Byte_Count+=cbw.CBWCB[7];
Byte_Count<<=8;
Byte_Count+=cbw.CBWCB[8];
Byte_Count<<=9;
i=0;
while(usb_flags.flags.usb_endp2_in)
{
if(LBA==0)
if(count<512)pData=DBR+count;
else
if(count==512)pData=FAT;
else pData=ZERO;
if(LBA==2)
// if(count<64)pData=FAT;
// else
// if(count==512*7)pData=FAT;
// else
pData=ZERO;
if(LBA==8)
// if(count<512)pData=ZERO;
// else
// if(count==512)pData=FAT;
// else
pData=ZERO;
if(LBA==0x10)
if(count==512)pData=FAT;
else pData=ZERO;
if(LBA==0x21)
if(count==0)
// else
pData=ROOT_DIR;
else pData=ZERO;
if(LBA==0x40)
if(count<240)pData=FILE_DATA+count;
else
pData=ZERO;
while(Chioce_Endp(5)&0x01);
if(Byte_Count>MAX_BULK_DATA_SIZE)
{
Write_Endp_Buffer(5,MAX_BULK_DATA_SIZE,pData);
// pData+=MAX_BULK_DATA_SIZE;
Byte_Count-=MAX_BULK_DATA_SIZE;
// SCSI.Status.Data=1;
}
else
{
Write_Endp_Buffer(5,Byte_Count,pData);
Return_CSW(0x00,SUCCESS);
}
count+=64;
}
}
else error(2);return;
}
void endp2_in(void) //主端点输入处理
{
switch(cbw.CBWCB[0])
{
case Read_10: OutputS("读介质数据\n\r");read_10();break;
case Inquiry: OutputS("索取器件信息\n\r");Write_Endp_Buffer(5,0x24,DISK_INF);Return_CSW(0x00,SUCCESS); break;
case Read_Capacity: OutputS("要求设备返回当前容量\n\r");Write_Endp_Buffer(5,0x08,DISK_CAPACITY);Return_CSW(0x00,SUCCESS);break;
case Read_Format_capacity: OutputS("查询当前容量及可用空间\n\r");Write_Endp_Buffer(5,0x00,0x00);Return_CSW(cbw.dCBWDataTransgerLength,FAIL);break;
case Request_Sense: OutputS("设备返回执行结果\n\r");Write_Endp_Buffer(5,0x12,SENSE);Return_CSW(0x00,SUCCESS);break;
case Medium_Removal: OutputS("写保护\n\r");Return_CSW(0x00,SUCCESS);break;
case 0x1a: Write_Endp_Buffer(5,0x00,0x00);Return_CSW(cbw.dCBWDataTransgerLength,FAIL);break;
default : Write_Endp_Buffer(5,0x00,0x00);Return_CSW(cbw.dCBWDataTransgerLength,FAIL);break;
}
}
void main(void)
{
USB_CS=0;
Disconnect_Usb();
Delay(1000);
Init_Port(9600);
// init_comport(57600);
Init_Usb();
Connect_Usb();
//OutputS("谭超自己做的的假U盘 \n");
// send_to_comport('O');
// send_to_comport('K');
while(1)
{
if(!USB_INT)
{
Read_Interrupt_Register();
// delay(10);
// OutputC(Interrupt_Register.Register[0]);
// OutputC('\n');
// OutputC(Interrupt_Register.Register[1]);
// OutputC('\n');
if(Interrupt_Register.Interrupt.bus_reset){OutputS("主机要求总线复位\n\r");Usb_Bus_Reset();continue;}
if(Interrupt_Register.Interrupt.suspend_change){OutputS("主机要求总线挂起\n\r");Usb_Bus_Suspend();continue;}
if(Interrupt_Register.Interrupt.control_out_port){OutputS("主机输出数据到端点0\n\r");Endp0_Out();continue;}
if(Interrupt_Register.Interrupt.control_in_port&&usb_flags.flags.usb_endp0_in){OutputS("主机要求从端点0得到数据\n\r");Endp0_In();continue;}
// if(Interrupt_Register.Interrupt.port_out_1)endp1_out();
// if(Interrupt_Register.Interrupt.port_in_1)endp1_in();
if(Interrupt_Register.Interrupt.main_out_port){OutputS("主机输出数据到端点2\n\r");endp2_out();continue;}
if(Interrupt_Register.Interrupt.main_in_port&&usb_flags.flags.usb_endp2_in){OutputS("主机要求从端点2得到数据\n\r");endp2_in();continue;}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -