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("获取设备描述符\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使用-枚举过程的更多相关文章
- usb设备枚举过程
USB主机在检测到USB设备插入后,就要对设备进行枚举了.为什么要枚举呢?枚举就是从设备读取一些信息,知道设备是什么样的设备,如何进行通信,这样主机就可以根据这些信息来加载合适的驱动程序.调试USB设 ...
- USB协议枚举过程详解
一 枚举过程之文字描述 ?主机集线器监视着每个端口的信号电压,当有新设备接入时便可觉察.(集线器端口的两根信号线的每一根都有15kΩ的下拉电阻,而每一个设备在D+都有一个1.5kΩ的上拉电阻.当用US ...
- 不错的usb分析工具!!!---用bus hound分析usb的枚举过程【转】
转自:http://blog.chinaunix.net/uid-25909619-id-3335199.html 说明:由于分析时是在记事本上分析的,贴到这里出现了格式有点乱,看时请复制到记事本中, ...
- USB枚举过程
1. 枚举是什么? 枚举就是从设备读取一些信息,知道设备是什么样的设备,如何进行通信,这样主机就可以根据这些信息来加载合适的驱动程序.调试USB设备,很重要的一点就是USB的枚举过程,只 ...
- USB枚举过程【转】
转自:http://blog.csdn.net/myarrow/article/details/8270029 1. 枚举是什么? 枚举就是从设备读取一些信息,知道设备是什么样的设备,如 ...
- USB 枚举过程详解
Windows 对USB设备的枚举过程流程图如图1所示: 图1 WP8的USB功能只支持一个配置,三个接口,也就是分别有如下的字段: 设备描述符的bNumConfigurations=1, 配置描述符 ...
- USB枚举过程的详细流程
USB枚举过程的详细流程 用户将一个USB设备插入USB端口,主机为端口供电,设备此时处于上电状态.主机检测设备.1>Hub使用中断通道将事件报告给Host.2>Host发送Get_Por ...
- 基于STM32的USB枚举过程学习笔记
源:基于STM32的USB枚举过程学习笔记 基于STM32的USB枚举过程学习笔记(一) 基于STM32的USB枚举过程学习笔记(二) 基于STM32的USB枚举过程学习笔记(三) 基于STM32的U ...
- 基于STM32的USB枚举过程学习笔记(转)
之前使用ST官方的库以及网络的资料,完成了使用USB HID类进行STM32和PC机的通讯.由于其他原因并没有深入的分析,虽然实现了功能,但是关于USB设备的枚举,以及具体的通讯方式都没有清晰的概念, ...
随机推荐
- Loadrunner之文件的上传(八)
老猪提供: https://mp.weixin.qq.com/s?__biz=MzIwOTMzNDEwNw==&mid=100000013&idx=1&sn=624f5bc74 ...
- 2015年4月27日---C语言:输出特殊图案,请在c环境中运行,看一看,Very Beautiful!
---恢复内容开始--- 题目:输出特殊图案,请在c环境中运行,看一看,Very Beautiful! 1.程序分析:字符共有256个.不同字符,图形不一样. 2.程序源代码: [code=c] #i ...
- FOJ 2203 单纵大法好
二分答案+验证 #include<cstdio> #include<cstring> #include<cmath> #include<algorithm&g ...
- Discuz登录慢、退出也慢的原因?
Discuz登录慢.退出也慢的原因? 2009-02-21 12:50:11 分类: 转载自:http://www.aiseminar.cn/bbs/thread-201-1-1.html 由于服务 ...
- FileReader和BufferedReader的区别
1.FileReader不能一行行读 FileReader fr = null; try { fr = new FileReader(new File(path)); StringBuffer str ...
- centos和ubuntu下使用cron设置定时任务
1.启动cron工具[ps:使用root权限] centos启动cron两种方式 a) /etc/init.d/crond start b) service crond start ubuntu启动c ...
- jquery页面滑到底部加载更多
$(window).scroll(function(){ var _scrolltop = $('body').scrollTop();if(_scrolltop+_winHeight>_doc ...
- 转 Android HTTPS详解
目录(?)[-] 前言 HTTPS原理 SSLTLS协议作用 基本的运行过程 握手阶段的详细过程 客户端发出请求ClientHello 服务器回应ServerHello 客户端回应 服务器的最后回应 ...
- jsp自动刷新(转)
1.页面自动刷新:把如下代码加入<head>区域中<meta http-equiv="refresh" content="20">,其中 ...
- 有向图强连通分支的Tarjan算法讲解 + HDU 1269 连通图 Tarjan 结题报告
题目很简单就拿着这道题简单说说 有向图强连通分支的Tarjan算法 有向图强连通分支的Tarjan算法伪代码如下:void Tarjan(u) {dfn[u]=low[u]=++index//进行DF ...