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

📄 usb.c

📁 PDIUSB12+51做 U盘程序,可以将自己的系统单做U盘跟 电脑通信
💻 C
📖 第 1 页 / 共 4 页
字号:
						}
			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 + -