关于stm32的USB学习笔记之usbcore.c

作者:findstr

转自:http://blog.csdn.net/findstr/article/details/7396362


  1. #include <stm32f10x_lib.h>  
  2. #include "usbreg.h"  
  3. #include "usbcore.h"  
  4. #include "usbuser.h"  
  5. #include "usbcfg.h"  
  6. #include "usb.h"  
  7. #include "usb_hw.h"  
  8. #include "usbdesc.h"  
  9. #include "hid.h"  
  10. #include "hiduser.h"  
  11.   
  12.   
  13. #define _DEBUG_  
  14. #include "debug.h"  
  15.   
  16. #pragma diag_suppress 111,1441  
  17.   
  18. //用来指示USB设备的状态  
  19. WORD    USB_DeviceStatus;  
  20. //用来存储设备的地址  
  21. BYTE    USB_DeviceAddress;  
  22. //用来存储USB当前使用的设备的配置  
  23. BYTE    USB_Configuration;  
  24. //此配置使用端点  
  25. DWORD USB_EndPointMask;  
  26. //用于标志此端点是否已经被停止0~15依次代表15个端点  
  27. DWORD USB_EndPointHalt;  
  28. //此配置使用的接口数  
  29. BYTE  USB_NumInterfaces;  
  30. //每个接口可用的当前接口可替换值  
  31. BYTE  USB_AltSetting[USB_IF_NUM];  
  32.   
  33.   
  34. /*用于临时存储控制传输时的数据包*/  
  35. USB_SETUP_PACKET SetupPacket;  
  36.   
  37. /*用于向主机发送数据的EP0的数据结构*/  
  38. USB_EP_DATA EP0Data;  
  39. /*EP0Buf用于向USB发送数据时用的缓冲区*/  
  40. BYTE    EP0Buf[USB_MAX_PACKET0];  
  41.   
  42. /*功能:复位USB的一些数据标志 
  43.  *参数:无 
  44.  *返回值:无 
  45.  */  
  46. void    USB_ResetCore(void)  
  47. {  
  48.     //默认为总线供电,因为我们的USB现在不都是插在电脑上才能工作的么&^_^  
  49.     USB_DeviceStatus    =   USB_POWER;    
  50.     //在枚举之初地址当然是0  
  51.     USB_DeviceAddress   =   0;  
  52.     //配置描述符的标识从1开始,这里也先置为0  
  53.     USB_Configuration   =   0;  
  54.     //目前使用的是端点0  
  55.     USB_EndPointMask    =   0x00010001;  
  56.     //没有停止的端点  
  57.     USB_EndPointHalt    =   0x00000000;  
  58. }  
  59.   
  60. /*功能:建立阶段,读取建立数据包 
  61.  *参数:无 
  62.  *返回值:无 
  63.  */  
  64. void USB_SetupStage(void)  
  65. {  
  66.      USB_ReadEP(0x00,(BYTE*)&SetupPacket);  
  67. }  
  68. /*功能:建立阶段,In握手包 
  69.  *参数:无 
  70.  *返回值:无 
  71.  */  
  72. void USB_StatusInStage(void)  
  73. {  
  74.      USB_WriteEP(0x80,NULL,0);  
  75. }  
  76. /*功能:建立阶段,Out握手包 
  77.  *参数:无 
  78.  *返回值:无 
  79.  */  
  80. void USB_StatusOutStage(void)  
  81. {  
  82.      USB_ReadEP(0x00,EP0Buf);  
  83. }  
  84. /*功能:数据In阶段 
  85.  *参数:无 
  86.  *返回值:无 
  87.  */  
  88. void USB_DataInStage(void)  
  89. {  
  90.     DWORD   cnt;  
  91.     //先计算引次要发送多少数据  
  92.     if(EP0Data.Count > USB_MAX_PACKET0)  
  93.         cnt = USB_MAX_PACKET0;  
  94.     else  
  95.         cnt = EP0Data.Count;  
  96.     //这里写端点却主机读,则将Dir位置1  
  97.     cnt = USB_WriteEP(0x80,EP0Data.pData,cnt);  
  98.     EP0Data.pData   +=  cnt;  
  99.     EP0Data.Count   -=  cnt;  
  100. }  
  101. /*功能:数据Out阶段 
  102.  *参数:无 
  103.  *返回值:无 
  104.  */  
  105. void USB_DataOutStage(void)  
  106. {  
  107.      DWORD  cnt;  
  108.   
  109.      cnt    =   USB_ReadEP(0x00,EP0Data.pData);  
  110.      EP0Data.pData+=cnt;  
  111.      EP0Data.Count-=cnt;  
  112. }  
  113. /*功能:获取USB设备的状态 
  114.  *参数:无  
  115.  *返回值:TRUE  --->成功 
  116.  *       FALSE  --->错误 
  117.  */  
  118. __inline BOOL   USB_GetStatus(void)  
  119. {  
  120.     DWORD   n,m;  
  121.       
  122.     switch(SetupPacket.bmRequestType.BM.Recipient)  
  123.     {  
  124.         //接收端是设备  
  125.         case REQUEST_TO_DEVICE:  
  126.             //返回设备状态给他  
  127.             EP0Data.pData = (BYTE *)&USB_DeviceStatus;  
  128.             //将状态信息发送给主机  
  129.             USB_DataInStage();  
  130.             break;  
  131.         //接收端是接口  
  132.         case REQUEST_TO_INTERFACE:  
  133.             /*配置描述符的标识从1开始,并且请求的接口号不能大于接口的数目,因为接口数目从0开始 
  134.              *因为我们接口描述符中的接口号是一个字节所以这里wIndex中的数据中人低字节有效 
  135.              */  
  136.             if((USB_Configuration !=0)&&(SetupPacket.wIndex.WB.L < USB_NumInterfaces))  
  137.             {     
  138.                 //清0两个字节,因为根据USB协议此处必须返回0  
  139.                 *((__packed WORD *)EP0Buf) = 0;   
  140.                 EP0Data.pData = EP0Buf;  
  141.                 //发送给主机  
  142.                 USB_DataInStage();  
  143.             }  
  144.             //此接口出现了错误  
  145.             else  
  146.                 return  FALSE;  
  147.             break;  
  148.         case REQUEST_TO_ENDPOINT:  
  149.             //端点号高1位0方向,低4位为端点号  
  150.             n   = SetupPacket.wIndex.WB.L & 0x8f;  
  151.             //m的高16位代表in端点的标志,低16位代表out端点的标志  
  152.             m   = (n&0x80)?(1<<16 )<< (n&0x0f) :(1<<n);  
  153.             //如果配置标识不为0,或配置标识为0,但是是端点0时,才算正常  
  154.             if((USB_Configuration !=0)||((n&0x0f)==0)&&(USB_EndPointMask & m))  
  155.             {  
  156.                 //查看此端点是否已经停用  
  157.                 *((__packed WORD *)EP0Buf) = (USB_EndPointHalt &m )?1:0;  
  158.                 EP0Data.pData = EP0Buf;  
  159.                 //将数据发送给主机  
  160.                 USB_DataInStage();  
  161.             }  
  162.             //说明配置描述符出了问题  
  163.             else  
  164.                 return  FALSE;  
  165.             break;  
  166.         default:  
  167.             return  FALSE;  
  168.     }     
  169.     return TRUE;  
  170. }  
  171. /*功能:设置/清除USB设备的特征 
  172.  *参数:sc 
  173.             0----->清除 
  174.             1----->设置 
  175.  *返回值:TRUE  --->成功 
  176.  *       FALSE  --->错误 
  177.  */  
  178. __inline BOOL USB_SetClrFeature(DWORD   sc)  
  179. {  
  180.     DWORD   n,m;  
  181.     switch(SetupPacket.bmRequestType.BM.Recipient)  
  182.     {  
  183.         //接收端是设备,则清除或设置设备的特性  
  184.         case REQUEST_TO_DEVICE:  
  185.             if(SetupPacket.wValue.W == USB_FEATURE_REMOTE_WAKEUP)  
  186.             {  
  187.                 if(sc)  
  188.                 {  
  189.                     printf("设置设备远程唤醒特性\r\n");  
  190.                     //设置USB状态为使能远程唤醒  
  191.                     USB_DeviceStatus |= USB_GETSTATUS_REMOTE_WAKEUP;  
  192.                     /*stm32硬件本身就支持远程唤醒,这里就不用设置了 
  193.                      *当然,软件支不支持在于对中断屏蔽位的设置 
  194.                      */  
  195.                 }     
  196.                 else  
  197.                 {  
  198.                     printf("清除设备远程唤醒特性\r\n");  
  199.                     USB_DeviceStatus &= ~USB_GETSTATUS_REMOTE_WAKEUP;  
  200.                     /*stm32硬件本身就支持远程唤醒,这里就不用设置了 
  201.                      *当然,软件支不支持在于对中断屏蔽位的设置 
  202.                      */  
  203.                 }  
  204.             }  
  205.             //不支持的请求  
  206.             else  
  207.             {  
  208.                 printf("不支持的请求\r\n");  
  209.                 return FALSE;  
  210.             }  
  211.             break;  
  212.         //接收端是接口  
  213.         case REQUEST_TO_INTERFACE:  
  214.             //接口不支持清除特性  
  215.             printf("清楚设置接口特征不被USB2.0支持\r\n");  
  216.             return  FALSE;  
  217.         //接收端是端点  
  218.         case REQUEST_TO_ENDPOINT:  
  219.             //取得端点号  
  220.             n = SetupPacket.wIndex.WB.L & 0x8F;  
  221. //          printf("请求的端点是:");  
  222. //          printhex(n);  
  223. //          printf("USB_Configuration:");  
  224. //          printhex(USB_Configuration);  
  225. //          printf("USB_EndPointMask");  
  226. //          printhex(USB_EndPointMask);  
  227. //          printf("\r\n");  
  228.             //将端点转化成与EndPointMask一样的格式  
  229.             m = (n & 0x80)?((1<<16) << (n&0x0f)) : (1<<n);  
  230.             /*根据USB协议来说, 
  231.              *地址状态下只有端点0才能使用, 
  232.              *配置状态下可用 
  233.              *不知道他这句是不是bug 
  234.              *原文件引用: 
  235.              *This request is valid when the device is in the Address state; 
  236.              *references to interfaces or to endpoints other than endpoint zero  
  237.              *shall cause the device to respond with a Request Error 
  238.              */  
  239.              /* 此处认为只用配置状态下的非0端点才能清楚特征 ,至于地址状态下没有处理 
  240.               * 
  241.               */  
  242.             if((USB_Configuration !=0) && ((n&0x0f)!=0) && (USB_EndPointMask & m))  
  243.             {  
  244.                 //设置/清楚 某个端点stall状态  
  245.                 if(SetupPacket.wValue.W == USB_FEATURE_ENDPOINT_STALL)  
  246.                 {  
  247.                     //设置  
  248.                     if(sc)  
  249.                     {  
  250.                         printf("设置端点远程唤醒特性\r\n");  
  251.                         //设置请求的端点为stall  
  252.                         USB_SetStallEP(n);  
  253.                         //更新USB的状态位  
  254.                         USB_EndPointHalt |= m;    
  255.                     }  
  256.                     //清楚  
  257.                     else  
  258.                     {  
  259.                         printf("清楚端点远程唤醒特性\r\n");  
  260.                         USB_ClrStallEP(n);  
  261.                         USB_EndPointHalt &= ~m;  
  262.                     }  
  263.   
  264.                 }  
  265.                 //未定义的请求  
  266.                 else  
  267.                 {  
  268.                     printf("不正确的端点请求\r\n");  
  269.                     return FALSE;  
  270.                 }  
  271.             }  
  272.             //不正确的请求时机  
  273.             else  
  274.             {  
  275.                 printf("不正确的请求时机\r\n");  
  276.                 return  FALSE;  
  277.             }  
  278.             break;  
  279.         //未定义的接收端类型  
  280.         default:  
  281.                 printf("未定义的接收端类型\r\n");  
  282.                 printf("接收端为:");  
  283.                 printhex(SetupPacket.bmRequestType.BM.Recipient);  
  284.                 printf("\r\n");  
  285.                 return  FALSE;  
  286.               
  287.     }  
  288.     return TRUE;  
  289. }  
  290. /*功能:用于向主机发送描述符 
  291.  *参数:无  
  292.  *返回值:TRUE  --->成功 
  293.  *       FALSE  --->发生了错误 
  294.  */  
  295. __inline BOOL   USB_GetDescriptor()  
  296. {  
  297.     BYTE    * pD;  
  298.     DWORD   len,n;  
  299.   
  300.     switch (SetupPacket.bmRequestType.BM.Recipient)  
  301.     {  
  302.         //发给设备的请求  
  303.          case REQUEST_TO_DEVICE:  
  304.             switch(SetupPacket.wValue.WB.H)  
  305.             {  
  306.                 //获取设备描述符  
  307.                 case USB_DEVICE_DESCRIPTOR_TYPE:  
  308.                     printf("获取设备描述符\r\n");  
  309.                     EP0Data.pData = (BYTE *)USB_DeviceDescriptor;  
  310.                     len = USB_DEVICE_DESC_SIZE;  
  311.                     break;  
  312.                 //获取配置描述符  
  313.                 case USB_CONFIGURATION_DESCRIPTOR_TYPE:  
  314.                     printf("获取USB配置描述符\r\n");  
  315.                     pD = (BYTE *)USB_ConfigDescriptor;  
  316.                 /* 引用USB协议:The range of values used for a 
  317.                  * descriptor index is from 0 to one less than  
  318.                  * the number of descriptors of that type implemented by the device 
  319.                  * 配置描述符中的标识是从1开始计的,但是,请求中的值是标识值为配置描述符 
  320.                  */  
  321.                  /*由于可能有几个配置描述符所以可能需要描述一下指针*/  
  322.                     for(n=0;n!= SetupPacket.wValue.WB.L;n++)  
  323.                     {  
  324.                         if(((USB_CONFIGURATION_DESCRIPTOR *)pD)-> bLength != 0)  
  325.                         {  
  326.                             pD+=((USB_CONFIGURATION_DESCRIPTOR *)pD)->wTotalLength;  
  327.                         }  
  328.                     }  
  329.                     //如果请求的描述符为空则返回stall  
  330.                     if(((USB_CONFIGURATION_DESCRIPTOR *)pD)->bLength == 0)  
  331.                         return  FALSE;  
  332.                     //设置要传送的指针  
  333.                     EP0Data.pData = pD;  
  334.                     //虽然配置描述符中多了一个字节,但是wTotalLength中没有算上,所以这里不用管,直接用就行了  
  335.                     len = ((USB_CONFIGURATION_DESCRIPTOR*)pD)->wTotalLength;  
  336.                     break;  
  337.                 //字符串描述符  
  338.                 case USB_STRING_DESCRIPTOR_TYPE:  
  339.                     printf("获取字符串描述符\r\n");  
  340.                     EP0Data.pData = (BYTE *)USB_StringDescriptor + SetupPacket.wValue.WB.L;  
  341.                     len = ((USB_STRING_DESCRIPTOR *)EP0Data.pData)->bLength;  
  342.                     break;  
  343.                 default:  
  344.                     return  FALSE;  
  345.             }  
  346.             break;  
  347.         //请求接收端接口  
  348. //      case REQUEST_TO_INTERFACE:  
  349. //          printf("请求接收端接口\r\n");  
  350. //          switch(SetupPacket.wValue.WB.H)  
  351. //          {  
  352. //              //Hid 描述符  
  353. //              case HID_HID_DESCRIPTOR_TYPE:    
  354. //                  printf("请求HID描\r\n");  
  355. //                  break;  
  356. //              case HID_REPORT_DESCRIPTOR_TYPE:  
  357. //                  printf("请求报告描述符\r\n");  
  358. //                  //这里只有一个报告描述符,报告描述符的索引是从0开始计,跟数组是一样的,如是不是0则返回Stall  
  359. //                  if(SetupPacket.wIndex.WB.L != 0)  
  360. //                      return FALSE;  
  361. //                  EP0Data.pData = (BYTE *)HID_ReportDescriptor;  
  362. //                  printf("报告描述符请求的字节:");  
  363. //                  printhex(EP0Data.Count);  
  364. //                  printf("报告描述符本来的长度:");  
  365. //                  printhex(HID_ReportDescSize);  
  366. //                  printf("\r\n");  
  367. //                  len = HID_ReportDescSize;  
  368. //                  break;  
  369. //              default:  
  370. //                  printf("未识别的请求!!!###,类型是:");  
  371. //                  printhex(SetupPacket.wValue.WB.H);  
  372. //                  printf("\r\n");  
  373. //                  break;  
  374. //          }  
  375. //          break;  
  376.         default:  
  377.             return  FALSE;  
  378.     }  
  379.   
  380.     printf("获取描述符成功\r\n");  
  381.     //将数据发送给主机  
  382.     if(EP0Data.Count > len)  
  383.         EP0Data.Count = len;  
  384.     USB_DataInStage();  
  385.     return  TRUE;  
  386. }  
  387. /*功能:设置配置请求 
  388.  *参数:无 
  389.  *返回值:TRUE  --- >成功 
  390.  *       FALSE  --- >失败 
  391.  */  
  392. __inline BOOL USB_SetConfiguration(void)  
  393. {  
  394.     USB_COMMON_DESCRIPTOR * pD;  
  395.     DWORD   alt,n,m;  
  396.     printf("设置配置\r\n");  
  397.     //配置值不能为0  
  398.     if(SetupPacket.wValue.WB.L)  
  399.     {  
  400.         pD=(USB_COMMON_DESCRIPTOR *)USB_ConfigDescriptor;  
  401.         //循环到配置描述符中的最后一个端点描述符  
  402.         while(pD->bLength)  
  403.         {  
  404.              switch(pD->bDescriptorType)  
  405.              {  
  406.                 //此时是配置描述符  
  407.                 case USB_CONFIGURATION_DESCRIPTOR_TYPE:   
  408.                     //如果此配置描述符是主机要设置的配置描述符  
  409.                     if(((USB_CONFIGURATION_DESCRIPTOR * )pD)->bConfigurationValue == SetupPacket.wValue.WB.L)  
  410.                     {  
  411.                         //保存起此时,设备所用的配置值  
  412.                         USB_Configuration = SetupPacket.wValue.WB.L;  
  413.                         //保存起此时,设备所用的配置的接口数目  
  414.                         USB_NumInterfaces = ((USB_CONFIGURATION_DESCRIPTOR*)pD)->bNumInterfaces;  
  415.                         //清0每个接口可替换设置值  
  416.                         for(n=0;n<USB_IF_NUM;n++)  
  417.                         {  
  418.                             USB_AltSetting[n]=0;      
  419.                         }     
  420.                         //我们将所有的以前可能使用的端点禁用,如果需要,在端点描述符中再使能就行了  
  421.                         //这样如果更改了配置就保证了,不会使用到以前配置使用,而本次配置没有使用的端点  
  422.                         //可能是为了防止干扰,猜的^-^!  
  423.                         for(n=1;n<16;n++)  
  424.                         {  
  425.                             if(USB_EndPointMask & (1<<n))  
  426.                                 USB_DisableEP(n);  
  427.                             if(USB_EndPointMask & ((1<<16)<<n))  
  428.                                 USB_DisableEP(n|0x80);  
  429.                         }  
  430.                         //还没有枚举到端点因此这里只使用的是端点0  
  431.                         USB_EndPointMask = 0x00010001;  
  432.                         //刚配置,当然没有停止的端点啊,全新的&_^  
  433.                         USB_EndPointHalt = 0x00000000;  
  434.                         /*在复位时,我们默认是总线供电,现在开始正式运行以前要因为主机会根据我们的配 
  435.                          *置描述符进行调整,一旦配置描述符返回后,配置描述符就生效了,所以这里必须来依据实际 
  436.                          *来重新设置 
  437.                          */  
  438.                         if(((USB_CONFIGURATION_DESCRIPTOR *)pD)->bmAttributes & USB_CONFIG_SELF_POWERED)  
  439.                             USB_DeviceStatus |= USB_GETSTATUS_SELF_POWERED;  
  440.                         else  
  441.                             USB_DeviceStatus &= ~USB_GETSTATUS_SELF_POWERED;  
  442.                     }  
  443.                     //否则略过,下一个配置描述符  
  444.                     else  
  445.                     {  
  446.                         (BYTE *)pD += ((USB_CONFIGURATION_DESCRIPTOR *)pD)->wTotalLength;  
  447.                         continue;         
  448.                     }  
  449.                     break;  
  450.                 //下面是接口描述符  
  451.                 case USB_INTERFACE_DESCRIPTOR_TYPE:  
  452.                     alt = ((USB_INTERFACE_DESCRIPTOR *)pD)->bAlternateSetting;  
  453.                     break;  
  454.                 case USB_ENDPOINT_DESCRIPTOR_TYPE:  
  455.                     //我们仅仅需要处理多个子接口中的第一个就行了,(如果有子接口的话,没有的话刚好也是0)  
  456.                     if(alt == 0)  
  457.                     {  
  458.                         //得到此端点  
  459.                         n = ((USB_ENDPOINT_DESCRIPTOR *)pD)->bEndpointAddress & 0x8f;  
  460.                         //将端点号转化成bit以存储在USB_EndPointMask中去代表我们使用了此端点  
  461.                         m = (n&0x80)?((1<<16)<<(n&0x0f)):(1<<n);  
  462.                         USB_EndPointMask |= m;  
  463.                         //配置端点  
  464.                         USB_ConfigEP((USB_ENDPOINT_DESCRIPTOR  *)pD);  
  465.                         //使能端点  
  466.                         USB_EnableEP(n);  
  467.                         //复位端点,使端点处于确定的端点  
  468.                         USB_ResetEP(n);  
  469.                     }  
  470.                     break;  
  471.              }  
  472.         (BYTE *)pD += pD->bLength;  
  473.         }     
  474.     }  
  475.     //如果请求的配置为0,则我们将所有的配置恢复到地址状态时的配置  
  476.     else  
  477.     {  
  478.         USB_Configuration = 0;  
  479.         for(n=1;n<16;n++)  
  480.         {  
  481.             //如果上一个配置使用了此端点,则disable it  
  482.             if(USB_EndPointMask & (1<<n)) //OUT端点  
  483.                  USB_DisableEP(n);  
  484.             if(USB_EndPointMask & (1<<16)<<n)  //IN端点  
  485.                  USB_DisableEP(n | 0x80);  
  486.         }     
  487.         //清除使用的全部端点,(当然0端点还是除外的)  
  488.         USB_EndPointMask = 0x00010001;  
  489.         USB_EndPointHalt = 0x00000000;  
  490.     }  
  491.     //我们根据USB_Configuration的值来查看我们到底时否找到了所需要的值  
  492.     if(USB_Configuration == SetupPacket.wValue.WB.L)  
  493.     {     
  494.         printf("设置配置成功\r\n");  
  495.         return  TRUE;  
  496.     }  
  497.     else  
  498.     {  
  499.         printf("设置配置失败\r\n");  
  500.         return  FALSE;  
  501.     }  
  502. }  
  503.   
  504. /*功能:用于处理端点0的输入和输出请求函数 
  505.  *参数: USB_EVT_SETUP 枚举时上位机发送的数据包 
  506.  *      USB_EVT_OUT   普通传输时,上位机发送的数据包 
  507.  *      USB_EVT_IN    普通传输时,上位机请求发送数据 
  508.  *返回值:无 
  509.  */  
  510. void USB_EndPoint0 (DWORD event)  
  511. {  
  512. //  printf("进入端点0处理函数\r\n");  
  513.     switch (event)  
  514.     {  
  515.         //控制传输  
  516.         case USB_EVT_SETUP:  
  517.         //  printf("进入建立阶段\r\n");  
  518.             //首先读取主机发来的请求  
  519.             USB_SetupStage();  
  520.             //设置EP0的数据结构  
  521.             EP0Data.Count = SetupPacket.wLength;  
  522.             //识别是何请求  
  523. //          printf("请求是");  
  524. //          printhex(SetupPacket.bRequest);  
  525. //          printf("    被请求对象:");  
  526. //          printhex(SetupPacket.bmRequestType.B);  
  527. //          printf("\r\n");  
  528.             //bRequestType.bit5~bit6代表请求类型  
  529.             switch(SetupPacket.bmRequestType.BM.Type)  
  530.             {  
  531.                 //标准请求  
  532.                 case REQUEST_STANDARD:  
  533.                     switch(SetupPacket.bRequest)  
  534.                     {  
  535.                     //获取USB状态  
  536.                     case USB_REQUEST_GET_STATUS:  
  537.                          //如果状态失败则停止0x81端点  
  538.                         if(!USB_GetStatus())  
  539.                         {  
  540.                             printf("获取状态失败\r\n");  
  541.                             goto    stall_i;  
  542.                         }  
  543.                         break;  
  544.                     case USB_REQUEST_CLEAR_FEATURE:  
  545.                         //如果清除特征失败则停止0x81端点  
  546.                         if(!USB_SetClrFeature(0))  
  547.                         {  
  548.                             printf("清楚特征失败\r\n");  
  549.                             goto stall_i;     
  550.                         }  
  551.                         //成功了握一下手OK  
  552.                         USB_StatusInStage();      
  553.                         break;  
  554.                     case USB_REQUEST_SET_FEATURE:  
  555.                         //如果状态失败则停止0x81端点  
  556.                         if(!USB_SetClrFeature(1))  
  557.                         {  
  558.                             printf("设置特征失败\r\n");  
  559.                             goto stall_i;     
  560.                         }     
  561.                         //成功了握一下手OK  
  562.                         USB_StatusInStage();  
  563.                         break;  
  564.                     case USB_REQUEST_SET_ADDRESS:  
  565.                         switch(SetupPacket.bmRequestType.BM.Recipient)  
  566.                         {  
  567.                             //只支持向设备设置地址  
  568.                             /*USB协议指出必须在改地址前完成检测并对此信息包进行响应 
  569.                              *即USB的设置地址阶段必须在主机接收到0长度数据包后才能进行 
  570.                              *当主机接收到状态阶段的0数据包时将会产生接收中断 
  571.                              *所以放到了USB_EVT_IN处*/  
  572.                             case REQUEST_TO_DEVICE:  
  573.                                 printf("设置地址\r\n");  
  574.                                 USB_DeviceAddress = 0x80 | SetupPacket.wValue.WB.L;  
  575.                                 USB_StatusInStage();  
  576.                                 break;  
  577.                             default:  
  578.                                 printf("未识别的接收端,接收端是");  
  579.                                 printhex(SetupPacket.bmRequestType.BM.Recipient);  
  580.                                 printf("\r\n");  
  581.                                 goto    stall_i;  
  582.                         }  
  583.                         break;  
  584.                     //获取设置描述符  
  585.                     case USB_REQUEST_GET_DESCRIPTOR:  
  586.                         if(!USB_GetDescriptor())  
  587.                             goto    stall_i;  
  588.                         break;  
  589.                     //设置配置请求  
  590.                     case USB_REQUEST_SET_CONFIGURATION:  
  591.                         switch(SetupPacket.bmRequestType.BM.Recipient)  
  592.                         {  
  593.                             //对设备  
  594.                             case REQUEST_TO_DEVICE:  
  595.                                 if(!USB_SetConfiguration())  
  596.                                 {  
  597.                                     //如果失败则对主机返回stall  
  598.                                     goto stall_i;  
  599.                                 }  
  600.                                 //完成了请求,握个手OK  
  601.                                 USB_StatusInStage();  
  602.                                 break;  
  603.                             //不支持对其他类型请求  
  604.                             default:  
  605.                                 goto stall_i;  
  606.                         }  
  607.                         break;  
  608.                     case USB_REQUEST_GET_INTERFACE:  
  609.                         printf("请求接口\r\n");  
  610.                         break;  
  611.                     default:  
  612.                         printf("未识别的请求,请求代码是");  
  613.                         printhex(SetupPacket.bRequest);  
  614.                         printf("\r\n");  
  615.                         break;  
  616.                     }  
  617.                 break;  
  618.                 //类请求  
  619.                 case REQUEST_CLASS:  
  620.                     printf("类请求\r\n");  
  621.                     switch (SetupPacket.bmRequestType.BM.Recipient)  
  622.                     {  
  623.                         //对接口请求  
  624.                         case REQUEST_TO_INTERFACE:  
  625.                             if(SetupPacket.wIndex.WB.L == USB_HID_IF_NUM)  
  626.                             {  
  627.                                 switch(SetupPacket.bRequest)  
  628.                                 {  
  629.                                     case HID_REQUEST_GET_REPORT:  
  630.                                         printf("获取报告描述符\r\n");  
  631.                                         break;  
  632.                                     case HID_REQUEST_SET_REPORT:  
  633.                                         printf("设置报告描述符\r\n");  
  634.                                         break;  
  635.                                     case HID_REQUEST_GET_IDLE:  
  636.                                         printf("获取空闲率\r\n");  
  637.                                         break;  
  638.                                     case HID_REQUEST_SET_IDLE:  
  639.                                         printf("设置空闲\r\n");  
  640.                                         break;  
  641.                                     case HID_REQUEST_GET_PROTOCOL:  
  642.                                         printf("查询报告协议是否在活动\r\n");  
  643.                                         break;                
  644.                                     case HID_REQUEST_SET_PROTOCOL:  
  645.                                         printf("SetReprot\r\n");  
  646.                                         break;    
  647.                                     default:  
  648.                                         printf("不支持的HID请求\r\n");  
  649.                                         break;  
  650.                                 }  
  651.                             }  
  652.                             break;  
  653.                     }  
  654.                     break;  
  655.                 //产商请求  
  656.                 case REQUEST_VENDOR:  
  657.                 //未定义请求  
  658.                 default:  
  659.         stall_i:  
  660.                     USB_SetStallEP(0x80);  
  661.                     break;  
  662.             }  
  663.             break;  
  664.         //接收成功  
  665.         case USB_EVT_OUT:  
  666.             printf("USB_EVT_OUT\r\n");  
  667.             if(SetupPacket.bmRequestType.BM.Dir ==0)  
  668.             {  
  669.                 printf(" 请求是:");  
  670.                 printhex(SetupPacket.bRequest);  
  671.                 printf("\r\n");  
  672.             }  
  673.             //返回握手  
  674.             else  
  675.             {  
  676.                 USB_StatusOutStage();  
  677.             }  
  678.             break;  
  679.         //发送成功  
  680.         case USB_EVT_IN:  
  681.         //  printf("USB_EVT_IN\r\n");  
  682.             if(SetupPacket.bmRequestType.BM.Dir == 1)  
  683.                 USB_DataInStage();  
  684.             /*USB协议指出必须在改地址前完成检测并对此信息包进行响应 
  685.              *即USB的设置地址阶段必须在主机接收到0长度数据包后才能进行 
  686.              *当主机接收到状态阶段的0数据包时将会产生接收中断 
  687.              *所以放到了USB_EVT_IN处*/  
  688.              //原keil库没有加if判断,怀疑为bug,这里判断是否是由于设置地址的状态阶段成功而触发的中断  
  689.              else// if(SetupPacket.bRequest == USB_REQUEST_SET_ADDRESS)  
  690.              {  
  691.                 if(USB_DeviceAddress & 0x80)  
  692.                 {  
  693.                     USB_DeviceAddress &= 0x7f;  
  694.                     USB_SetAddress(USB_DeviceAddress);  
  695.                 }             
  696.              }  
  697.             break;  
  698.     }  
  699.   
  700. }

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值