• LPC1768的USB使用-枚举过程


    枚举过程如下

    #ifndef __USBCORE_H__

    #define __USBCORE_H__

     

    /* USB端点0 发送数据结构体*/

    typedef struct _USB_EP_DATA

    {

        U8 *pData;

        U16 Count;

    } USB_EP_DATA;

     

    /* USB全局变量 */

    extern U16 USB_DeviceStatus;

    extern U8 USB_DeviceAddress;

    extern U8 USB_Configuration;

     

    /* 端点0输出数据缓冲区 */

    extern U8 EP0Buf[USB_MAX_PACKET0];

     

    /* 端点输入信息暂存 */

    extern USB_EP_DATA EP0Data;

     

    /* usb setup包数据暂存 */

    extern USB_SETUP_PACKET SetupPacket;

     

    /* usb初始化类内核变量 */

    extern void USB_ResetCore(void);

     

    #endif

    #include "usb.h"

    #include "usbcfg.h"

    #include "usbhw.h"

    #include "usbcore.h"

    #include "usbdesc.h"

    #include "usbuser.h"

     

    #include "hid.h"

     

    #pragma diag_suppress 111,1441

     

     

    U16 USB_DeviceStatus;//usb的设备状态,比如唤醒之类的

     

    U8 USB_DeviceAddress;//usb设备的地址,在枚举阶段主机会设置地址

     

    U8 USB_Configuration;//usb设备的当前配置(usb可以有几套配置)

     

    U8 EP0Buf[USB_MAX_PACKET0];

     

    USB_EP_DATA EP0Data;

     

    USB_SETUP_PACKET SetupPacket;//usb setup包

     

    //usb设备复位

    void USB_ResetCore(void)

    {

     

        USB_DeviceStatus = 0;//设备上电初始状态

        USB_DeviceAddress = 0;

        USB_Configuration = 0;

    }

     

    //usbsetup包的获取

    void USB_SetupStage(void)

    {

        USB_ReadEP(0x00, (U8 *)&SetupPacket);

    }

     

    //usb写入数据 端点0 in

    void USB_DataInStage(void)

    {

        U32 cnt;

     

        if (EP0Data.Count > USB_MAX_PACKET0)

        {

            cnt = USB_MAX_PACKET0;

        } else

        {

            cnt = EP0Data.Count;

        }

        cnt = USB_WriteEP(0x80, EP0Data.pData, cnt);

        EP0Data.pData += cnt;

        EP0Data.Count -= cnt;

    }

     

    //usb输出数据 out

    void USB_DataOutStage(void)

    {

        U32 cnt;

     

        cnt = USB_ReadEP(0x00, EP0Data.pData);

        EP0Data.pData += cnt;

        EP0Data.Count -= cnt;

    }

     

    //usb发送0状态包

    void USB_StatusInStage(void)

    {

        USB_WriteEP(0x80, NULL, 0);

    }

     

    //usb读取状态包

    void USB_StatusOutStage(void)

    {

        USB_ReadEP(0x00, EP0Buf);

    }

     

     

    //usb请求描述符(标准请求)

    __inline BOOL USB_ReqGetDescriptor (void)

    {

        U8 *pD;

        U32 len, n;

     

        switch (SetupPacket.bmRequestType.BM.Recipient)

        {

        case REQUEST_TO_DEVICE://设备请求

            switch (SetupPacket.wValue.WB.H)

            {

            case USB_DEVICE_DESCRIPTOR_TYPE://设备描述符

                EP0Data.pData = (U8 *)USB_DeviceDescriptor;

                len = USB_DEVICE_DESC_SIZE;

                usb_debug_printf("获取设备描述符 ");

                break;

            case USB_CONFIGURATION_DESCRIPTOR_TYPE://配置描述符

                pD = (U8 *)USB_ConfigDescriptor;

                for (n = 0; n != SetupPacket.wValue.WB.L; n++)//可能有多个配置,选择指定的配置

                {

                    if (((USB_CONFIGURATION_DESCRIPTOR *)pD)->bLength != 0)

                    {

                        pD += ((USB_CONFIGURATION_DESCRIPTOR *)pD)->wTotalLength;

                    }

                }

                if (((USB_CONFIGURATION_DESCRIPTOR *)pD)->bLength == 0)

                {

                    usb_debug_printf("没有指定的配置描述符 ");

                    return (__FALSE);

                }

                EP0Data.pData = pD;

                len = ((USB_CONFIGURATION_DESCRIPTOR *)pD)->wTotalLength;

                usb_debug_printf("获取配置描述符 ");

                break;

            case USB_STRING_DESCRIPTOR_TYPE://字符串描述符

                pD = (U8 *)USB_StringDescriptor;

                for (n = 0; n != SetupPacket.wValue.WB.L; n++)//根据字符串描述符的ID选择相应的字符串,这一项和设备描述符中的字符串ID相关

                {

                    if (((USB_STRING_DESCRIPTOR *)pD)->bLength != 0)

                    {

                        pD += ((USB_STRING_DESCRIPTOR *)pD)->bLength;

                    }

                }

                if (((USB_STRING_DESCRIPTOR *)pD)->bLength == 0)

                {

                    usb_debug_printf("获取字符串描述符不支持 ");

                    return (__FALSE);

                }

                EP0Data.pData = pD;

                len = ((USB_STRING_DESCRIPTOR *)pD)->bLength;

                usb_debug_printf("获取字符串描述符 %d ",n);

                break;

            default:

                usb_debug_printf("不支持的请求对象 ");

                return (__FALSE);

            }

            break;

        case REQUEST_TO_INTERFACE://请求接口

            switch (SetupPacket.wValue.WB.H)//接口请求类型

            {

                case HID_REPORT_DESCRIPTOR_TYPE://报告描述符

                    if (SetupPacket.wIndex.WB.L != USB_HID_IF_NUM)

                    {

                        return (__FALSE); /* Only Single HID Interface is supported */

                    }

                    EP0Data.pData = (U8 *)HID_ReportDescriptor;

                    len = HID_ReportDescSize;

                    usb_debug_printf("请求报告描述符 ");

                break;

               

                case HID_PHYSICAL_DESCRIPTOR_TYPE://端点物理特性描述符

                    usb_debug_printf("不支持的描述符 ");

                    return (__FALSE); /* 不支持*/

               

                default:

                    return (__FALSE);

            }

            break;

        default:

            usb_debug_printf("不支持的请求对象 ");

            return (__FALSE);

        }

     

        if (EP0Data.Count> len)//发送的数据不能比指定的数据多,多的截取掉

        {

            EP0Data.Count = len;

        }

        return (__TRUE);

    }

     

    //设置配置

    __inline BOOL USB_ReqSetConfiguration (void)

    {

        USB_COMMON_DESCRIPTOR *pD;//通配的描述符

        U32 n;

     

        switch (SetupPacket.bmRequestType.BM.Recipient)

        {

        case REQUEST_TO_DEVICE://设备设置配置

            if (SetupPacket.wValue.WB.L)//配置值大于0.进行配置

            {

                pD = (USB_COMMON_DESCRIPTOR *)USB_ConfigDescriptor;

                while (pD->bLength)

                {

                    switch (pD->bDescriptorType)//选择描述符类型

                    {

                    case USB_CONFIGURATION_DESCRIPTOR_TYPE://配置描述符类型

                        if (((USB_CONFIGURATION_DESCRIPTOR *)pD)->bConfigurationValue == SetupPacket.wValue.WB.L)

                        {

                            USB_Configuration = SetupPacket.wValue.WB.L;//保存主机发送来的配置号

                            USB_Configure(__TRUE);

                        }

                        else

                        {

                            (U8 *)pD += ((USB_CONFIGURATION_DESCRIPTOR *)pD)->wTotalLength;

                            usb_debug_printf("设置下一个配置 ");

                            continue;

                        }

                        break;

     

                    case USB_INTERFACE_DESCRIPTOR_TYPE:

                        break;

     

                    case USB_ENDPOINT_DESCRIPTOR_TYPE:

                        n = ((USB_ENDPOINT_DESCRIPTOR *)pD)->bEndpointAddress & 0x8F;

                        USB_ConfigEP((USB_ENDPOINT_DESCRIPTOR *)pD);

                        USB_EnableEP(n);

                        USB_ResetEP(n);

                        usb_debug_printf("设置端点配置 ");

                        break;

                    }

                    (U8 *)pD += pD->bLength;

                }

            }

            else

            {

                USB_Configuration = 0;

                USB_Configure(__FALSE);//禁止全部端点响应

            }

            if (USB_Configuration != SetupPacket.wValue.WB.L)//这一句是核心,在切换配置的时候尤其重要

            {

                return (__FALSE);

            }

            break;

     

        default:

            return (__FALSE);

        }

        return (__TRUE);

    }

     

    void usb_debug_printf_setup(void)

    {

        usb_debug_printf("读取   :  ");

        usb_debug_printf("0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x ",SetupPacket.bmRequestType.B,

            SetupPacket.bRequest,SetupPacket.wValue.WB.L,SetupPacket.wValue.WB.H,SetupPacket.wIndex.WB.L,

            (u8)SetupPacket.wIndex.WB.H,SetupPacket.wLength,(u8)((SetupPacket.wLength)>>8));

    }

     

    void USB_EndPoint0_setup_process(void)

    {

        USB_SetupStage();//获取setup数据包

        usb_debug_printf_setup();

        EP0Data.Count = SetupPacket.wLength; /* 获取可以发送的数据最大字节数量 */

        switch (SetupPacket.bmRequestType.BM.Type)

        {

        case REQUEST_STANDARD://标准请求

            switch (SetupPacket.bRequest)//识别标准请求类型

            {

            case USB_REQUEST_GET_STATUS://获取状态

                USB_SetStallEP(0x80);

                EP0Data.Count = 0;

                usb_debug_printf("获取状态,不支持 ");

                break;

            case USB_REQUEST_CLEAR_FEATURE://清除特性

                USB_SetStallEP(0x80);

                EP0Data.Count = 0;

                usb_debug_printf("清除特性,不支持 ");

                break;

            case USB_REQUEST_SET_FEATURE://设置特性

                USB_SetStallEP(0x80);

                EP0Data.Count = 0;

                usb_debug_printf("设置特性,不支持 ");

                break;

            case USB_REQUEST_SET_ADDRESS://设置地址

                USB_DeviceAddress = 0x80 | SetupPacket.wValue.WB.L;

                USB_StatusInStage();

                usb_debug_printf("设置地址 ");

                break;

            case USB_REQUEST_GET_DESCRIPTOR://获取描述符

                if (!USB_ReqGetDescriptor())

                {

                    USB_SetStallEP(0x80);

                    EP0Data.Count = 0;

                    return;

                }

                USB_DataInStage();

                break;

     

            case USB_REQUEST_SET_DESCRIPTOR://设置描述符

                USB_SetStallEP(0x00);

                EP0Data.Count = 0;

                usb_debug_printf("设置描述符,不支持 ");

                break;

     

            case USB_REQUEST_GET_CONFIGURATION://获取配置

                USB_SetStallEP(0x80);

                EP0Data.Count = 0;

                usb_debug_printf("获取配置,不支持 ");

                break;

     

            case USB_REQUEST_SET_CONFIGURATION://设置配置

                if (!USB_ReqSetConfiguration())

                {

                    USB_SetStallEP(0x80);EP0Data.Count = 0;return;

                }

                USB_StatusInStage();

    #if USB_CONFIGURE_EVENT

                USB_Configure_Event();

    #endif

                break;

     

            case USB_REQUEST_GET_INTERFACE://获取接口

                USB_SetStallEP(0x80);

                EP0Data.Count = 0;

                usb_debug_printf("获取接口,不支持 ");

                break;

     

            case USB_REQUEST_SET_INTERFACE://设置接口

                USB_SetStallEP(0x80);

                EP0Data.Count = 0;

                usb_debug_printf("设置接口,不支持 ");

                break;

     

            default:

                USB_SetStallEP(0x80);EP0Data.Count = 0;return;

            }

            break;

     

        case REQUEST_CLASS://类请求

            switch (SetupPacket.bmRequestType.BM.Recipient)

            {

     

            case REQUEST_TO_DEVICE://设备类请求

                USB_SetStallEP(0x80);

                EP0Data.Count = 0;

                usb_debug_printf("设备类请求不支持 ");

                return;

            case REQUEST_TO_INTERFACE://接口类请求

    //          if (SetupPacket.wIndex.WB.L == USB_HID_IF_NUM)

    //          {

    //              switch (SetupPacket.bRequest)

    //              {

    //              case HID_REQUEST_SET_IDLE://设置空闲

    //                  USB_StatusInStage(); //返回状态包

    //                  usb_debug_printf("设置空闲 ");

    //                  break;

    //              }

    //          }

                switch (SetupPacket.bRequest)

                {

                      case HID_REQUEST_SET_IDLE://设置空闲

                          USB_StatusInStage(); //返回状态包

                          usb_debug_printf("设置空闲 ");

                        break;

                      default:

                          USB_SetStallEP(0x80);

                          EP0Data.Count = 0;

                          usb_debug_printf("不支持的类请求 ");

                          break;

                    }          

                break;

            case REQUEST_TO_ENDPOINT://端点请求

                USB_SetStallEP(0x80);

                EP0Data.Count = 0;

                usb_debug_printf("不支持的端点类请求 ");

                return;

            default:

                USB_SetStallEP(0x80);

                EP0Data.Count = 0;

                usb_debug_printf("不支持的类请求 ");

                return;

            }

            break;

        default://不支持的标准请求

            USB_SetStallEP(0x80);

            EP0Data.Count = 0;

            break;

        }

    }

     

    void USB_EndPoint0_out_process(void)

    {

       

    }

    void USB_EndPoint0_in_process(void)

    {

        if (SetupPacket.bmRequestType.BM.Dir == REQUEST_DEVICE_TO_HOST)

        {

            USB_DataInStage();

        } else

        {

            if (USB_DeviceAddress & 0x80)

            {

                USB_DeviceAddress &= 0x7F;

                USB_SetAddress(USB_DeviceAddress);

            }

        }

    }

     

    //usb端点0相关事件处理

    void USB_EndPoint0(U32 event)

    {

        switch (event)

        {

        case USB_EVT_SETUP: //SETup事件处理

            USB_EndPoint0_setup_process();

            break;

        case USB_EVT_OUT:

            USB_EndPoint0_out_process();

            break;

        case USB_EVT_IN:

            USB_EndPoint0_in_process();

            break;

        }

    }

  • 相关阅读:
    jdk和jre有什么区别?
    Apache的作用及意义
    博客园新成员的第一天
    重构改善既有代码的设计--简化条件表达式
    SourceMonitor: 代码重构的小工具,大用场
    使用Eclipse中提供的Refactor(重构)工具
    极大提高Web开发效率的8个工具和建议(含教程)
    Hbase shell命令
    Java多线程-新特性-有返回值的线程
    Java多线程-新特征-条件变量
  • 原文地址:https://www.cnblogs.com/dengxiaojun/p/4338694.html
Copyright © 2020-2023  润新知