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

📄 usb.c

📁 基于at89c51snd1c的硬盘MP3播放器
💻 C
📖 第 1 页 / 共 2 页
字号:
 UEPSTAX=(UEPSTAX & (~0x80));
 USB_usb_endp0_in=0;
}

void get_max_LUN(void)                   //获取磁盘最大逻辑单元号
{
 unsigned char max_LUN=MAX_LUN;          //只有一个逻辑单元
 UEPNUM=0;
 UEPSTAX=(UEPSTAX | 0x80);               //数据阶段的输入
 write_endpoint_buff(0,1,&(max_LUN));
 UEPSTAX=(UEPSTAX & (~0x80));
 USB_usb_endp0_in=0;
}

void mass_storage_reset(void)            //USB大容量存储设备复位
{
 write_endpoint_buff(0,0,0);
 USB_usb_endp0_in=0;
 USB_setup_packet_out=0;
 SCSI_Command=1;
 SCSI_Data=0;
}


void get_descriptor(void)                    //获取描述符
{
 if(!USB_not_end)
  {
   switch(MSB(Control_Data.DeviceRequest.wValue))
    {
     case DEVICE_DESCRIPTOR:
          Control_Data.wCount=sizeof(DEVICE_DESCRIPTOR_STRUCT);
          Control_Data.pData=(unsigned char *)(&device_descriptor);
          break;
     case CONFIGURATION_DESCRIPTOR:
     Control_Data.wCount=SWAP(con_int_endp_descriptor.configuration_descriptor.wTotalLength);
     Control_Data.pData=(unsigned char *)(&con_int_endp_descriptor);
     if(Control_Data.wLength<Control_Data.wCount)Control_Data.wCount=Control_Data.wLength;
     break;
     case STRING_DESCRIPTOR:
          if(LSB(Control_Data.DeviceRequest.wValue)==0)
           {
             Control_Data.wCount=LANGUAGE_ID[0];
             Control_Data.pData=LANGUAGE_ID;
           }
          if(LSB(Control_Data.DeviceRequest.wValue)==2)
           {
            Control_Data.wCount=device_serial_number[0];
		    Control_Data.pData=device_serial_number;
		   }
	      break;
    }
   if(Control_Data.wLength<Control_Data.wCount)Control_Data.wCount=Control_Data.wLength;
  }
 if(Control_Data.wCount>=MAX_CONTROL_DATA_SIZE)
  {
   UEPNUM=0;
   UEPSTAX=(UEPSTAX | 0x80);       //数据阶段的输入
   write_endpoint_buff(0,MAX_CONTROL_DATA_SIZE,Control_Data.pData);
   UEPSTAX=(UEPSTAX & (~0x80));
   Control_Data.pData+=MAX_CONTROL_DATA_SIZE;
   Control_Data.wCount-=MAX_CONTROL_DATA_SIZE;
   if(USB_set_addr)USB_not_end=1;
   else USB_usb_endp0_in=0;
   return;
  }
 else
  {
   UEPNUM=0;
   UEPSTAX=(UEPSTAX | 0x80);       //数据阶段的输入
   write_endpoint_buff(0,Control_Data.wCount,Control_Data.pData);
   UEPSTAX=(UEPSTAX & (~0x80));
   USB_setup_packet_in=0;
   USB_usb_endp0_in=0;
   return;
  }      
}

void endp0_out(void)                            //终端点0输出中断处理
{
 if(status_setup_packet)
  {
   Control_Data.wLength=0;
   Control_Data.wCount=0;
   if(read_endpoint_buff(0,sizeof(Control_Data.DeviceRequest),(unsigned char *)(&(Control_Data.DeviceRequest)))!=sizeof(REQUESTCMD))
    {
     error(1);
	 return;
	}
  UEPNUM=0;
  UEPSTAX= UEPSTAX & (~0x04);  //清除SETUP标记
  Control_Data.DeviceRequest.wValue=SWAP(Control_Data.DeviceRequest.wValue);
  Control_Data.DeviceRequest.wIndex=SWAP(Control_Data.DeviceRequest.wIndex);
  Control_Data.DeviceRequest.wLength=SWAP(Control_Data.DeviceRequest.wLength);
  Control_Data.wLength=Control_Data.DeviceRequest.wLength;
  USB_not_end=0;
  USB_usb_endp0_in=1;
  USB_setup_packet_in=0;
  USB_setup_packet_out=0;
  if(Control_Data.DeviceRequest.bmRequestType&0x80){USB_setup_packet_in=1;return;}
  else {USB_setup_packet_out=1;return;}
 }
 else
  {
   read_endpoint_buff(0,0,0);
  }
}

void endp0_in(void)                                        //终端点0输入处理
{
 if(USB_setup_packet_in||USB_not_end)
  {
   if((Control_Data.DeviceRequest.bmRequestType==0xA1)&&(Control_Data.DeviceRequest.bRequest==0xFE))get_max_LUN();
   switch(Control_Data.DeviceRequest.bmRequestType&0x7B)
    {
	 case 0:
	   switch (Control_Data.DeviceRequest.bRequest)
	    {
	     case 0: get_status(0);break;
	     case 6: get_descriptor();break;
	     case 8: get_configuration();break;
		 default:break;
	    }
	 case 1:
	   switch (Control_Data.DeviceRequest.bRequest)
	    {
         case  0: get_status(1);break;
	     case 10: get_interface();break;
         default: break;
		}
	 case 2:
	  {
       if(Control_Data.DeviceRequest.bRequest==0)get_status(2);  
	  }
	 default: break;
    }
  return;
  }
 if(USB_setup_packet_out)
  {
   if((Control_Data.DeviceRequest.bmRequestType==0x21)&&(Control_Data.DeviceRequest.bRequest==0xFF))
    mass_storage_reset();

   switch(Control_Data.DeviceRequest.bmRequestType&0x03)
    {
	 case 0:
     switch (Control_Data.DeviceRequest.bRequest)
      {
	   case     CLEAR_FEATURE: clear_feature(0);break;
	   case       SET_FEATURE: set_feature(0);break;
	   case       SET_ADDRESS: set_usb_address();break;                  //set_address	           
	   case    SET_DESCRIPTOR: set_descriptor();break;                //set_descriptor
	   case SET_CONFIGURATION: set_configuration(); break;         //set_configurat               	          
  	   default: break;
	  }break;
	 case 1:
      switch (Control_Data.DeviceRequest.bRequest)
	   {
	    case CLEAR_FEATURE:  clear_feature(1);break;
	    case   SET_FEATURE:  set_feature(1); break;
        case SET_INTERFACE: set_interface();break;
	    default: break;
        }break;
	 case 2:
	  switch (Control_Data.DeviceRequest.bRequest)
	   {
	    case CLEAR_FEATURE: clear_feature(2);break;
	    case   SET_FEATURE: set_feature(2);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;
 write_endpoint_buff(1,sizeof(CSW),(unsigned char *)(&csw));
 USB_usb_endp1_in=0;
 USB_usb_endp2_out=0;
 SCSI_Command=1;
 SCSI_Data=0;
}


void write_10(void)                                                         //SCSI写操作
{
 unsigned long int LBA,Byte_Count;
 unsigned char i;
 if(SCSI_Data)
  {
   ((unsigned char*)&LBA)[0]=cbw.CBWCB[2];
   ((unsigned char*)&LBA)[1]=cbw.CBWCB[3];
   ((unsigned char*)&LBA)[2]=cbw.CBWCB[4];
   ((unsigned char*)&LBA)[3]=cbw.CBWCB[5];
   ((unsigned char*)&Byte_Count)[0]=0;
   ((unsigned char*)&Byte_Count)[1]=cbw.CBWCB[7];
   ((unsigned char*)&Byte_Count)[2]=cbw.CBWCB[8];
   ((unsigned char*)&Byte_Count)[3]=0;
   Byte_Count<<=1;
   pData=buffer;
   while(USB_usb_endp2_out)
    {
     if((((unsigned char *)&Byte_Count)[3]==0)&&((((unsigned char *)&Byte_Count)[2]&0x01)==0))
      {
       wait_IDE_busy();
       write_IDE_LBA(LBA);
       write_IDE_sector_count(1);
       write_IDE_command(IDE_Write_Sectors);
       IDE_Address=IDE_Data;
       set_IDE_address();
       LBA++;
      }
     while(!(RXOUTB0||RXOUTB1));
     if(Byte_Count>MAX_BULK_DATA_SIZE)
	  {
       UEPNUM=2;               //选择端点
       for(i=0;i<MAX_BULK_DATA_SIZE;i++)
        {
         while(!IDE_IORDY);
         IDE_DIOW=0;
         IDE_DATA_L=UEPDATX;
         i++;
         IDE_DATA_H=UEPDATX;
         IDE_DIOW=1;
        }
       UEPSTAX=UEPSTAX & (~0x42);//清除RXOUTB 位
	   Byte_Count-=MAX_BULK_DATA_SIZE;
	  }
     else 
	  {
       UEPNUM=2;               //选择端点
       for(i=0;i<Byte_Count;i++)
        {
         while(!IDE_IORDY);
         IDE_DIOW=0;
         IDE_DATA_L=UEPDATX;
         i++;
         IDE_DATA_H=UEPDATX;
         IDE_DIOW=1;
        }
       UEPSTAX=UEPSTAX & (~0x42);//清除RXOUTB 位             
       Return_CSW(0x00,SUCCESS);
       wait_IDE_busy();
       IDE_Address=IDE_Bus_Not_Use;
       set_IDE_address();
	  }
    }
  }
 else
  {
   error(3);
  }
}

void endp2_out(void)                                                     //主端点输出处理
{
 if(SCSI_Command)
  {
   if(read_endpoint_buff(2,sizeof(CBW),(unsigned char *)(&cbw))!=sizeof(CBW)){error(2);return;}
   if(cbw.dCBWSignature!=0x55534243){error(3);return;}
   SCSI_Command=0;
   SCSI_Data=1;
   if(cbw.bmCBWFlags&0x80)
    {
	 USB_usb_endp1_in=1;
	 USB_usb_endp2_out=0;
	}
   else
    {
	 USB_usb_endp1_in=0;
	 USB_usb_endp2_out=1;
     switch(cbw.CBWCB[0])
      {
       case        Write_10: USB_LED=!USB_LED;write_10();break;
       case Test_Unit_Ready: Return_CSW(0x00,SUCCESS);break; 
       case          Verify: Return_CSW(0x00,SUCCESS);break;
	   default             : Return_CSW(cbw.dCBWDataTransgerLength,FAIL);break;
	  }
	}
  }
 else
  {
   read_endpoint_buff(2,0,0);
  }
}


void read_10(void)                                                              //SCSI读处理
{
 unsigned long int LBA=0,Byte_Count;
 unsigned char i;
 if(SCSI_Data)
  {
   ((unsigned char*)&LBA)[0]=cbw.CBWCB[2];
   ((unsigned char*)&LBA)[1]=cbw.CBWCB[3];
   ((unsigned char*)&LBA)[2]=cbw.CBWCB[4];
   ((unsigned char*)&LBA)[3]=cbw.CBWCB[5];
   ((unsigned char*)&Byte_Count)[0]=0;
   ((unsigned char*)&Byte_Count)[1]=cbw.CBWCB[7];
   ((unsigned char*)&Byte_Count)[2]=cbw.CBWCB[8];
   ((unsigned char*)&Byte_Count)[3]=0;
   Byte_Count<<=1;
   pData=buffer;
   while(USB_usb_endp1_in)
    {
     if((((unsigned char *)&Byte_Count)[3]==0)&&((((unsigned char *)&Byte_Count)[2]&0x01)==0))
      {
       write_IDE_LBA(LBA);
       write_IDE_sector_count(1);
       write_IDE_command(IDE_Read_Sectors);
       IDE_Address=IDE_Data;
       set_IDE_address();
       IDE_DATA_H=0xFF;
       IDE_DATA_L=0xFF;
       LBA++;
      }
     if(Byte_Count>MAX_BULK_DATA_SIZE)
     {
      UEPNUM=1;                                 //选择端点
      for(i=0;i<MAX_BULK_DATA_SIZE;i++)         //填数据寄存器
       {
        while(!IDE_IORDY);                      //等待IDE IO口忙
        IDE_DIOR=0;                             //发读信号
        UEPDATX=IDE_DATA_L;                     //读低字节
        i++;
        UEPDATX=IDE_DATA_H;                     //读高字节
        IDE_DIOR=1;                             //
       }
      UEPSTAX=UEPSTAX | 0x10;                   //设置TXRDY位
      while(!( UEPSTAX & 0x01 ));				//等待TXCMP
      UEPSTAX=UEPSTAX & (~0x01);				//清除TXCMP
      Byte_Count-=MAX_BULK_DATA_SIZE;
     }
    else
     {
      UEPNUM=1;                          //选择端点
      for(i=0;i<Byte_Count;i++)         //填数据寄存器
       {
        while(!IDE_IORDY);
        IDE_DIOR=0;
        UEPDATX=IDE_DATA_L;
        i++;
        UEPDATX=IDE_DATA_H;
        IDE_DIOR=1;
       }
      UEPSTAX=UEPSTAX | 0x10;              //设置TXRDY位
      while(!( UEPSTAX & 0x01 ));				//等待TXCMP
      UEPSTAX=UEPSTAX & (~0x01);					//清除TXCMP
      Return_CSW(0x00,SUCCESS);
      
      IDE_Address=IDE_Bus_Not_Use;
      set_IDE_address();
      IDE_DATA_L=0xFF;
     }
   }
 }
 else error(2);return;
}

void endp1_in(void)                                      //主端点输入处理
{
    switch(cbw.CBWCB[0])
    {
     case              Read_10: USB_LED=!USB_LED;read_10();break;
     case              Inquiry: write_endpoint_buff(1,0x24,DISK_INF);Return_CSW(0x00,SUCCESS); break;
     case        Read_Capacity: write_endpoint_buff(1,0x08,DISK_CAPACITY);Return_CSW(0x00,SUCCESS);break;
     case Read_Format_capacity: write_endpoint_buff(1,0x00,0x00);Return_CSW(cbw.dCBWDataTransgerLength,FAIL);break;
     case        Request_Sense: write_endpoint_buff(1,0x12,SENSE);Return_CSW(0x00,SUCCESS);break;
	 case       Medium_Removal: Return_CSW(0x00,SUCCESS);break;
	 case                 0x1a: write_endpoint_buff(1,0x00,0x00);Return_CSW(cbw.dCBWDataTransgerLength,FAIL);break;
     default                  : write_endpoint_buff(1,0x00,0x00);Return_CSW(cbw.dCBWDataTransgerLength,FAIL);break;
	}
}

void usb(void)
{
 LCD_go_home();
 prints("移动硬盘模式 ");
 LCD_line_feed();
 prints("             ");
 disconnect_usb();
 init_usb();
 connect_usb();
 while(1)
  { 
   read_usb_status();
   if(status_bus_reset){usb_bus_reset();continue;}
   if(status_suspend_change){usb_bus_suspend();continue;}
   if(status_control_out_port){endp0_out();continue;}
   if(status_control_in_port&&USB_usb_endp0_in){endp0_in();continue;}
   if(status_main_out_port){endp2_out();continue;}
   if(status_main_in_port&&USB_usb_endp1_in){endp1_in();continue;}
   if(key)
    {
     if(remove_enable)
      {
       if(key==KEY_OK)
        {
         key=0;
         status=STOP;
         USBCON=0x40;
         disconnect_usb();
         return;
        }
      }
     else
      {
       key=0;
      }
    }
  }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -