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

📄 main.c

📁 HID类程序
💻 C
📖 第 1 页 / 共 3 页
字号:
      CtrlTrfData._byte0|=0b000000001;      // SetB byte0.0,表示使用自身电源
      if(usb_stat.RemoteWakeup == 1)        // usb_stat defined in usbmmap.c
        CtrlTrfData._byte0|=0b00000010;     // Set bit1,是否支持,远程唤醒
     break;
   
     case  RCPT_INTF:          // =1 获取接口状态
      ctrl_trf_session_owner = MUID_USB9; // 两个数据字段=0;
     break;

     case  RCPT_EP:            // =2 如果是获取端点状态
      ctrl_trf_session_owner = MUID_USB9;
      pDst.bRam = (byte*)&ep0Bo+(SetupPkt.EPNum*8)+(SetupPkt.EPDir*4); // 取出状态寄存器地址
      if(*pDst.bRam & _BSTALL) // 判断端点是否停止
       CtrlTrfData._byte0=0x01;// 如果停止表示端点进入一个暂停态  
     break;
   }// end switch
} // end USBStdGetStatusHandler()

/***********************************
*主机请求启用特征值处理函数
************************************/
void USBStdFeatureReqHandler()
{
  if((SetupPkt.bFeature == DEVICE_REMOTE_WAKEUP)&&(SetupPkt.Recipient == RCPT_DEV))  //RCPT_DEV=0,设置设备的远程唤醒状态状态 
  {
     ctrl_trf_session_owner = MUID_USB9;
     if(SetupPkt.bRequest == SET_FEATURE)  // 判断是否是这个请求
       usb_stat.RemoteWakeup = 1;          // 如果配置远程唤醒,状态位置1
     else  //否则是CLEAR_FEATURE
       usb_stat.RemoteWakeup = 0;   
  }//end if 
  
  if((SetupPkt.bFeature == ENDPOINT_HALT)&&(SetupPkt.Recipient == RCPT_EP)&&(SetupPkt.EPNum != 0))// 加上请求的端点不是端点0条件
  {
    ctrl_trf_session_owner = MUID_USB9;
    pDst.bRam = (byte*)&ep0Bo+(SetupPkt.EPNum*8)+(SetupPkt.EPDir*4); //确定端点状态地址
    if(SetupPkt.bRequest == SET_FEATURE)//如果是端点特征配置
      *pDst.bRam = _USIE|_BSTALL;   //把端点状态寄存器设置为SIE所有并使能缓冲器停止
    else   //否则是CLEAR_FEATURE
     {
       if(SetupPkt.EPDir == 1)    // 如果是IN
        *pDst.bRam = _UCPU;       // 端点归CPU
       else
        *pDst.bRam = _USIE|_DAT0|_DTSEN;  //如果是输出的话,端点归SIE用DATA0使能数据同步位
     }// end if 
  }//end if            
}//end USBStdFeatureReqHandler()

/********************************
* USB检测地址状态
********************************/
void mUSBCheckAdrPendingState()  
{
 if(usb_device_state==ADR_PENDING_STATE) 
  {                                       
     UADDR = SetupPkt.bDevADR._byte;     
     if(UADDR > 0)                       
     usb_device_state=ADDRESS_STATE; 
     else                                
     usb_device_state=DEFAULT_STATE; 
  }//end if
}//end mUSBCheckAdrPendingState()

//--------------------------------------------------------- end USB 传输协议(请求)函数定义


//--------------------------------------------------------- HID 函数区
/*******************************
* HID 端点设置函数
*******************************/
void HIDInitEP()
{
   hid_rpt_rx_len=0;                            // HID报表接收字节数清0
  
   HID_UEP = EP_OUT_IN|HSHK_EN; 
   ClearArray((byte*)&usb_alt_intf,MAX_NUM_INT);// 清一个数组,为交替设置MAX_NUM_INT=1,中断端点个数=1
   
   HID_UEP = EP_OUT_IN|HSHK_EN;                 // 初始化端点1
   HID_BD_OUT.Cnt = sizeof(hid_report_out);     // 设置缓冲区大小
   HID_BD_OUT.ADR = (byte*)&hid_report_out;     // 设置缓冲区首地址
   HID_BD_OUT.Stat._byte = _USIE|_DAT0|_DTSEN;  // 端点1的OUT设置
                                                
   HID_BD_IN.ADR = (byte*)&hid_report_in;       // 端点1的IN端点地址设置
   HID_BD_IN.Stat._byte = _UCPU|_DAT1;          // 端点1的IN状态设置
}// end HIDInitEP()


/***********************************
* HID检测请求
***********************************/
void USBCheckHIDRequest()   //HID检测请求,如果USB状态不是空,不会检测,因为那是USB的标准请求时刻
{
  if(SetupPkt.Recipient != RCPT_INTF) return;  // 如果请求不是对接口则退出,对HID 都是对端口说话
  if(SetupPkt.bIntfID != HID_INTF_ID) return;  // 如果HID接口的号不与请求的接口ID相同退出
   
  if(SetupPkt.bRequest == GET_DSC)  // 如果是主机获得描述符
   {
/*
#define DSC_HID         0x21   // HID
#define DSC_RPT         0x22   // 报表
#define DSC_PHY         0x23   // 实体
*/
     switch(SetupPkt.bDscType)
      {
        case 0x21:   // 获得HID描述符
         ctrl_trf_session_owner = MUID_HID;  // 传输归HID所有
         if(usb_active_cfg == 1)             // 即进入配置状态以后才做的事情
          {
           pSrc.bRom = (rom byte*)&cfg01.hid_i00a00;  // 取出HID描述符的首地址
          }
         wCount._word = sizeof(USB_HID_DSC); //取得描述符大小
        break;

        case 0x22:       //报表描述符
         ctrl_trf_session_owner = MUID_HID;  // 传输归HID所有
         if(usb_active_cfg == 1)   
         {              
          pSrc.bRom = (rom byte*)&hid_rpt01; // 报表描述符在ROM内的首地址
          wCount._word = sizeof(hid_rpt01);  // 报表描述符大小
         }                
        break;

        case 0x23:
        default:
        break;
      }//end switch
    usb_stat.ctrl_trf_mem = _ROM;   // 数据存储在ROM区
   }//end if

  if(SetupPkt.RequestType != CLASS) return; // 如果不是特定USB的类请求返回
  switch(SetupPkt.bRequest)    // 选择HID特定请求
   {
     case  GET_REPORT:  // 01 启用主机使用控制传输,来从设备读取数据
      HIDGetReportHandler(); // 主机获得数据处理函数
     break;
    
     case SET_REPORT:   // 09 启用设备控制传输,设备从主机获得数据
      HIDSetReportHandler(); // 设备接收数据处理函数
     break; 

     case GET_IDLE:     // 02 启用主机从设备读取目前的闲置率
      ctrl_trf_session_owner = MUID_HID; // 控制传输的系统归HID所有
      pSrc.bRam = (byte*)&idle_rate;     // 数据以4MS为单位,即一个数代表4MS
      usb_stat.ctrl_trf_mem = _RAM;      // Set memory type 数据存储在RAM区
      wCount._word = 1;
     break;   
  
     case SET_IDLE:
      //说明:0x0a 当数据从上一个报表后再没有改变时,闲置中断输入端点的报表频率来节省带宽
      //      如果HID支持此请求则只有在数据改变时才会发送报表  
       ctrl_trf_session_owner = MUID_HID;
       idle_rate = MSB(SetupPkt.W_Value);
     break;  

     case GET_PROTOCOL:  // 0x03 启用主机了解设备目前作用是启动协议或是报表协议
       ctrl_trf_session_owner = MUID_HID; // 控制传输的系统归HID所有   
       pSrc.bRam = (byte*)&active_protocol;// Set source
       usb_stat.ctrl_trf_mem = _RAM;
       wCount._word = 1;  // 数据长度
     break;

     case SET_PROTOCOL:  // 0x0b 主机指定使用启动协议或是报表协议
       ctrl_trf_session_owner = MUID_HID;
       active_protocol = LSB(SetupPkt.W_Value); //取出协议类型
     break;  
   }//end switch
}//end USBCheckHIDRequest()


/**********************************
* 主机获得数据处理函数
**********************************/
void HIDGetReportHandler()
{
  switch(MSB(SetupPkt.W_Value))
   {
     case 1:      // 输入报表
     switch(LSB(SetupPkt.W_Value))
      {
        case 0:                   // 选择报表ID
          ctrl_trf_session_owner = MUID_HID;   // 控制传输的系统归HID所有
          GetInputReport0();                   // 准备数据发送到主机
        break;
        case 1:                   // 本例只有一个报表
        break;  
      }
     break;

     case 3:    // 主机获得特征
      switch(LSB(SetupPkt.W_Value))
       {
         case 0:
          ctrl_trf_session_owner = MUID_HID;
          GetFeatureReport0();
         break;
         case 1:
         break;
       }   
     break;
   }//end switch 
  usb_stat.ctrl_trf_mem = _RAM;               // Set memory type,数据都放在RAM区
}//end HIDGetReportHandler()

/***********************************
* 设备获得数据处理函数
***********************************/
void HIDSetReportHandler()
{
   switch(MSB(SetupPkt.W_Value))
    {
      case 2:      // 设备获得数据
       switch(LSB(SetupPkt.W_Value))  //选择ID号
        {
          case 0:  // 如果是0号报表
           ctrl_trf_session_owner = MUID_HID;
           pDst.bRam = (byte*)&hid_report_out; //设置数据存储区,当主机数据发送到以后会存储到缓冲区
          break;
        }
      break;
  
      case 3:      // 主机设置特征值
       switch(LSB(SetupPkt.W_Value))
        {
          case 0:
           ctrl_trf_session_owner = MUID_HID;
            pDst.bRam = (byte*)&hid_report_feature;  //设置存储缓冲区 
          break;
        } 
      break;  
    }//end switch
}//end HIDSetReportHandler()

/*******************************
* HID取接收字节长度
*******************************/
byte HIDRxReport(char *buffer, byte len) 
{
  hid_rpt_rx_len = 0;
  if(!HID_BD_OUT.Stat.UOWN)  // 接收主机数据任务结束后端点会归CPU所有
  {
    if(len > HID_BD_OUT.Cnt) // 调整期待接收数据字节数等于实际接收的字节数
     len = HID_BD_OUT.Cnt;   // 
    for(hid_rpt_rx_len = 0; hid_rpt_rx_len < len; hid_rpt_rx_len++)  // 数据读取
    {
      buffer[hid_rpt_rx_len] = hid_report_out[hid_rpt_rx_len]; // 把数据读到缓冲区   
    }  
    HID_BD_OUT.Cnt = sizeof(hid_report_out);  // 准备下一次的数据接收,初始化
    HID_BD_OUT.ADR = (byte*)&hid_report_out; 
    mUSBBufferReady(HID_BD_OUT);   // 准备好下一次的接收,交替DATA端点归SIE所有
  }//end if
  return hid_rpt_rx_len;           // 返回接收字节的长度,如果事务没完成
}//end

/********************************
* HID 发送数据到主机
********************************/
void HIDTxReport(char *buffer, byte len)
{
  byte i;
  if(len > HID_INT_IN_EP_SIZE)    //取出发送数据字节
    len = HID_INT_IN_EP_SIZE;

  for (i = 0; i < len; i++)
   {
     hid_report_in[i] = buffer[i];  //把数据写入发送缓冲区
   }  
  HID_BD_IN.Cnt = len;
  mUSBBufferReady(HID_BD_IN);       //数据开始发送
}//end HIDTxRepor


//--------------------------------------------------------- end HID函数区


//--------------------------------------------------------- 用户函数数区
/********************************
* 准备数据发送到主机
********************************/
void GetInputReport0()
{
  byte count;
  pSrc.bRam = (byte*)&hid_report_in;     // 数据指针指向IN REPORT区,即准备好数据
  wCount._word = HID_INPUT_REPORT_BYTES; // 传输数据字节数,就2个字节
}//end GetInputReport0()

/********************************
*
********************************/
void GetFeatureReport0()
{
  byte count;
  pSrc.bRam = (byte*)&hid_report_feature;       // 准备特征数据地址地址
  wCount._word = HID_FEATURE_REPORT_BYTES;      // 传送两个字节
}//end GetFeatureReport0()

/********************************
* HID输出报表(主机发送)
*********************************/
void HandleControlOutReport()
{
	byte count;              //字节计数器
	switch (MSB(SetupPkt.W_Value))
    {
		case 0x02: // Output report 
    		switch(LSB(SetupPkt.W_Value))
		    {
				case 0: // Report ID 0
					for (count = 1; count <= HID_OUTPUT_REPORT_BYTES; count = count + 1)
					{
						hid_report_in[count-1] = hid_report_out[count-1];
					}				
					break;		
			} // end switch(LSB(SetupPkt.W_Value))

		case 0x03:
    		switch(LSB(SetupPkt.W_Value))
		    {
				case 0: // Report ID 0	
		
				break;
			} // end switch(LSB(SetupPkt.W_Value))		

	} // end switch(MSB(SetupPkt.W_Value))

} // end HandleControlOutReport

/******************************
* 报表查询
******************************/
//检测是否有主机传来的报表
void ReportLoopback()
{
  byte count;   // 定义计数字节
  //获取读缓冲区字节的数目
  number_of_bytes_read = HIDRxReport(receive_buffer, HID_OUTPUT_REPORT_BYTES); 
  
  if (number_of_bytes_read > 0) // 如果接收字节不为0则有数据传入
   {
     //取出主机发送数据到发送缓冲区
     for(count =0 ; count < HID_OUTPUT_REPORT_BYTES; count++) 
      { 
       transmit_buffer[count] = receive_buffer[count]; //2个字节的数据到发送缓冲区
      }//end for      
     while(HID_BD_IN.Stat.UOWN)   // 如果发送缓冲区此时处于发送数据阶段等待
      {
       USBDriverService();
      }//end while
     HIDTxReport(transmit_buffer, HID_INPUT_REPORT_BYTES);  // 数据发送
   } //end if
}//end ReportLoopback()
//--------------------------------------------------------- end用户函数数区

⌨️ 快捷键说明

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