基本固件框架的追踪研读之SETUP命令的处理2

书接上回


我在《 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做基本固件框架时考虑的问题, 为了简化开发者的代码,开发者做后续开发时,可以直接在这里添加代码。赞!!!
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值