基本固件框架的追踪研读之SETUP命令的处理2
来源:互联网 发布:单片机堆栈是什么意思 编辑:程序博客网 时间:2024/06/10 22:30
书接上回
我在《 DvkUsersGuide.pdf》文档里面找到了库文件EZUSB.LIB的说明:
说的是,这个函数根据常量“StrIdx”返回返回一个字符串描述符的指针,如果字符串描述符表中不包含这个常量,则函数返回NULL。
我决定先不看这个函数的源代码,但是还是先把源代码贴出来,以备以后查看,在我电脑的C:\Cypress\USB\Target\Lib\LP目录下的get_strd.c文件里:
#include <stdio.h>#include <fx2.h>STRINGDSCR xdata * EZUSB_GetStringDscr(BYTE StrIdx){ STRINGDSCR xdata * dscr; dscr = (STRINGDSCR xdata *) pStringDscr; while(dscr->type == STRING_DSCR) { if(!StrIdx--) return(dscr); dscr = (STRINGDSCR xdata *)((WORD)dscr + dscr->length); } return(NULL);}
再来看一下“SETUPDAT[2]”
在lpregs.h里找到了SETUPDAT的声明:
EXTERN xdata volatile BYTE SETUPDAT[8] _AT_ 0xE6B8; // 8 bytes of SETUP data
是一个8字节的数组,用于保存SETUP数据,在文档里找到:
可以看出SETUPDAT[2]是wValueL,而在文档《EZ-USB(R) Technical Reference Manual.pdf》的2.3.4节,可以得出wValueL用于表明Host所请求的字符串描述符的String Number,鉴于这个函数的名字是EZUSB_GetStringDscr,推断是用于获取固件中字符串描述符的首地址,所以这里先将文档中,Cypress推荐的固件应对Host发来的Get Descriptor-String请求应该做出的响应贴出来:
现在,指针dscr_ptr指向的正式字符串描述符的地址,在LP.h文件中搜索到:
#define MSB(word) (BYTE)(((WORD)(word) >> 8) & 0xff)#define LSB(word) (BYTE)((WORD)(word) & 0xff)
可见,MSB和LSB分别用于提取提取“字符串描述符”的地址高八位和低八位,再分别赋给SUDPTRH和SUDPTRL:
{ SUDPTRH = MSB(dscr_ptr); SUDPTRL = LSB(dscr_ptr); }
这符合文档里的描述:
文档上写着:The EZ-USB dose the rest !!!哈哈哈
如果if语句的条件不成立,使EndPoint0进入Stall状态:
else EZUSB_STALL_EP0(); // Stall End Point 0
而文档里说:
STALL说明“发生了一些没有料到的事情”。再来看EZUSB_STALL_EP0(),在LP.H文件中找到:
#define EZUSB_STALL_EP0() EP0CS |= bmEPSTALL
找到:
#define bmEPSTALL bmBIT0#define bmBIT0 0x01
还有:
EXTERN xdata volatile BYTE EP0CS _AT_ 0xE6A0; // Endpoint Control and Status
可以看出函数EZUSB_STALL_EP0()是将寄存器EP0CS的BIT0位置1,再来看文档中寄存器EP0CS的描述:
不过这里说,需要将STALL and HSNAK两位都置1,难道这里有坑??先忽略了
回过头来,继续看SetupCommand函数,可以看到其实剩下的就是一条switch语句:
switch(SETUPDAT[1])
那么SETUPDAT[1]又是啥呢?为啥他这么重要呢?追踪一下,哈哈可以看到,它指明了控制请求的请求号:
请求号有以下几种:
所以,这个switch语句的所有case语句所指的就是这些设备请求。先来看第一个case语句:
case SC_GET_DESCRIPTOR: // *** Get Descriptor if(DR_GetDescriptor()) switch(SETUPDAT[3]) { case GD_DEVICE: // Device SUDPTRH = MSB(pDeviceDscr); SUDPTRL = LSB(pDeviceDscr); break; case GD_DEVICE_QUALIFIER: // Device Qualifier // only retuen a device qualifier if this is a high speed // capable chip. if (HighSpeedCapable()) { SUDPTRH = MSB(pDeviceQualDscr); SUDPTRL = LSB(pDeviceQualDscr); } else { EZUSB_STALL_EP0(); } break; case GD_CONFIGURATION: // Configuration SUDPTRH = MSB(pConfigDscr); SUDPTRL = LSB(pConfigDscr); break; case GD_OTHER_SPEED_CONFIGURATION: // Other Speed Configuration SUDPTRH = MSB(pOtherConfigDscr); SUDPTRL = LSB(pOtherConfigDscr); break; case GD_STRING: // String if(dscr_ptr = (void *)EZUSB_GetStringDscr(SETUPDAT[2])) { SUDPTRH = MSB(dscr_ptr); SUDPTRL = LSB(dscr_ptr); } else EZUSB_STALL_EP0(); // Stall End Point 0 break; default: // Invalid request EZUSB_STALL_EP0(); // Stall End Point 0 } break;
这个case对应的是Get Descriptor设备请求,查看文档可知,Get Descriptor的请求号是0x06,所以猜测SC_GET_DESCRIPTOR就应该是0x06,追踪验证一下:
#define SC_GET_DESCRIPTOR 0x06 // Setup command: Get Descriptor
猜测正确!!!而Get Descriptor设备请求又细分成五个子类:
所以,固件中也会有对应的5个case语句。
switch(SETUPDAT[3])
SETUPDAT[3]就是wValueH,所代表的就是这五种Descriptor Type。
可是这里为啥要有这么一条if语句呢?
if(DR_GetDescriptor())
我追踪到了DR_GetDescriptor()这个函数的定义:
//-----------------------------------------------------------------------------// Device Request hooks// The following hooks are called by the end point 0 device request parser.//-----------------------------------------------------------------------------BOOL DR_GetDescriptor(void){ return(TRUE);}
其实,这相当于说这个if语句没有起作用,不过我注意到了“hooks”这个词,汉语的意思是“钩子”,又好像在《DvkUsersGuide.pdf》这份文档里看到过它的踪影,于是接着追踪:
大意是说,这是Cypress做基本固件框架时考虑的问题, 为了简化开发者的代码,开发者做后续开发时,可以直接在这里添加代码。赞!!!
1 0
- 基本固件框架的追踪研读之SETUP命令的处理2
- 基本固件框架的追踪研读之SETUP命令的处理1
- 基本固件框架的追踪研读之SETUP命令的处理3
- 基本固件框架的追踪研读之SETUP命令的处理4
- 基本固件框架的追踪研读之SETUP命令的处理5
- 基本固件框架的追踪研读之SETUP命令的处理6
- 基本固件框架的追踪研读之SETUP命令的处理7
- 基本固件框架的追踪研读之USB事务处理
- 基本固件框架的追踪研读之描述符1
- 基本固件框架的追踪研读之USB控制传输
- EZ-USB固件框架的追踪研读之main函数2
- EZ-USB固件框架的追踪研读之main函数1
- EZ-USB固件框架的追踪研读之main函数3
- 追踪研读法破解EZ-USB的“远程唤醒”
- GDI对位图文件的基本处理
- 用Source Insight追踪Arduino的setup和loop
- 【Darwin学习笔记】之QTSSReflectorModule的Setup消息处理
- 【Darwin学习笔记】之QTSSReflectorModule的Setup消息处理
- Android 命名规范 (提高代码可以读性)
- 关于利用url动态获取天气的信息以及各个城市天气的id代码
- 读书笔记22:职责链模式
- == 和 equal的区别
- 【暑期基础】R HDU 2017 字符串统计
- 基本固件框架的追踪研读之SETUP命令的处理2
- Android获取手机配置信息
- 算法题:链表的递归逆序
- 继承、实现、依赖、关联、聚合、组合的联系与区别
- nyoj-2括号匹配
- 为什么后面加了个eq(0).mouseover(),该怎么解决
- FreeMarker初级攻略
- SDWebImage 报错:Use of undeclared identifier _executing/_finished
- freemarker常见语法大全