枚举过程如下

#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("获取设备描述符\r\n");

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("没有指定的配置描述符\r\n");

return (__FALSE);

}

EP0Data.pData = pD;

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

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

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("获取字符串描述符不支持\r\n");

return (__FALSE);

}

EP0Data.pData = pD;

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

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

break;

default:

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

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("请求报告描述符\r\n");

break;

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

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

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

default:

return (__FALSE);

}

break;

default:

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

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("设置下一个配置\r\n");

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("设置端点配置\r\n");

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\r\n",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("获取状态,不支持\r\n");

break;

case USB_REQUEST_CLEAR_FEATURE://清除特性

USB_SetStallEP(0x80);

EP0Data.Count = 0;

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

break;

case USB_REQUEST_SET_FEATURE://设置特性

USB_SetStallEP(0x80);

EP0Data.Count = 0;

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

break;

case USB_REQUEST_SET_ADDRESS://设置地址

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

USB_StatusInStage();

usb_debug_printf("设置地址\r\n");

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("设置描述符,不支持\r\n");

break;

case USB_REQUEST_GET_CONFIGURATION://获取配置

USB_SetStallEP(0x80);

EP0Data.Count = 0;

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

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("获取接口,不支持\r\n");

break;

case USB_REQUEST_SET_INTERFACE://设置接口

USB_SetStallEP(0x80);

EP0Data.Count = 0;

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

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("设备类请求不支持\r\n");

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("设置空闲\r\n");

//                  break;

//              }

//          }

switch (SetupPacket.bRequest)

{

case HID_REQUEST_SET_IDLE://设置空闲

USB_StatusInStage(); //返回状态包

usb_debug_printf("设置空闲\r\n");

break;

default:

USB_SetStallEP(0x80);

EP0Data.Count = 0;

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

break;

}

break;

case REQUEST_TO_ENDPOINT://端点请求

USB_SetStallEP(0x80);

EP0Data.Count = 0;

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

return;

default:

USB_SetStallEP(0x80);

EP0Data.Count = 0;

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

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;

}

}

LPC1768的USB使用-枚举过程的更多相关文章

  1. usb设备枚举过程

    USB主机在检测到USB设备插入后,就要对设备进行枚举了.为什么要枚举呢?枚举就是从设备读取一些信息,知道设备是什么样的设备,如何进行通信,这样主机就可以根据这些信息来加载合适的驱动程序.调试USB设 ...

  2. USB协议枚举过程详解

    一 枚举过程之文字描述 ?主机集线器监视着每个端口的信号电压,当有新设备接入时便可觉察.(集线器端口的两根信号线的每一根都有15kΩ的下拉电阻,而每一个设备在D+都有一个1.5kΩ的上拉电阻.当用US ...

  3. 不错的usb分析工具!!!---用bus hound分析usb的枚举过程【转】

    转自:http://blog.chinaunix.net/uid-25909619-id-3335199.html 说明:由于分析时是在记事本上分析的,贴到这里出现了格式有点乱,看时请复制到记事本中, ...

  4. USB枚举过程

    1. 枚举是什么?        枚举就是从设备读取一些信息,知道设备是什么样的设备,如何进行通信,这样主机就可以根据这些信息来加载合适的驱动程序.调试USB设备,很重要的一点就是USB的枚举过程,只 ...

  5. USB枚举过程【转】

    转自:http://blog.csdn.net/myarrow/article/details/8270029 1. 枚举是什么?        枚举就是从设备读取一些信息,知道设备是什么样的设备,如 ...

  6. USB 枚举过程详解

    Windows 对USB设备的枚举过程流程图如图1所示: 图1 WP8的USB功能只支持一个配置,三个接口,也就是分别有如下的字段: 设备描述符的bNumConfigurations=1, 配置描述符 ...

  7. USB枚举过程的详细流程

    USB枚举过程的详细流程 用户将一个USB设备插入USB端口,主机为端口供电,设备此时处于上电状态.主机检测设备.1>Hub使用中断通道将事件报告给Host.2>Host发送Get_Por ...

  8. 基于STM32的USB枚举过程学习笔记

    源:基于STM32的USB枚举过程学习笔记 基于STM32的USB枚举过程学习笔记(一) 基于STM32的USB枚举过程学习笔记(二) 基于STM32的USB枚举过程学习笔记(三) 基于STM32的U ...

  9. 基于STM32的USB枚举过程学习笔记(转)

    之前使用ST官方的库以及网络的资料,完成了使用USB HID类进行STM32和PC机的通讯.由于其他原因并没有深入的分析,虽然实现了功能,但是关于USB设备的枚举,以及具体的通讯方式都没有清晰的概念, ...

随机推荐

  1. Login 和 Logout

    inux下Login和Logout详解                Login 是你用Linux系统工作时面对的第一个进程,这对于使用终端以及通过网络使用Linux都是正确的.但是login进程本身 ...

  2. jquery 限制字数 显示输入字数 插件

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  3. 多线程进阶之并发工具类:CountDownLatch、CyclicBarrier

    并发工具类在java.util.concurrent包下.常用的有CountDownLatch.CyclicBarrier,用它们可以控制并发流程. 1.CountDownLatch探究: 主要用到其 ...

  4. IPSEC VPN配置实例

    TL-R400VPN应用——IPSEC VPN配置实例 TL-ER6120是TP-LINK专为企业应用而开发的VPN路由器,具备强大的数据处理能力,并且支持丰富的软件功能,包括VPN.IP/MAC 地 ...

  5. 基础-Servlet

    Servlet是运行在web服务器上的一个java类. 它的作用是将http请求和http相应进行操作完成我们的业务逻辑. servlet创建: 1.创建一个类extends HttpServlet ...

  6. POJ 3419 Difference Is Beautiful(RMQ+二分 或者 模拟)

    Difference Is Beautiful Time Limit:5000MS     Memory Limit:65536KB     64bit IO Format:%lld & %l ...

  7. World Finals 2003 UVA - 1025 A Spy in the Metro(动态规划)

    分析:时间是一个天然的序,这个题目中应该决策的只有时间和车站,使用dp[i][j]表示到达i时间,j车站在地上已经等待的最小时间,决策方式有三种,第一种:等待一秒钟转移到dp[i+1][j]的状态,代 ...

  8. 多校 Cow Bowling

    题目链接:http://acm.hust.edu.cn/vjudge/contest/124435#problem/I 密码:acm Sample Input Sample Output 分析: #i ...

  9. windows加固方案

    1     账号管理.认证授权.... 1 1.1      账号... 1 1.2      口令... 1 1.3      授权... 2 2     日志配置操作.... 3 3     IP ...

  10. zf-关于分页的行数如何配置

    公司的项目分页显示行数是在web.xml里配置的 对应的java 文件是 BaseAction 这个文件里面写的就是分页的代码