jinghuiren
驱动巨牛
驱动巨牛
  • 注册日期2002-06-01
  • 最后登录2008-10-27
  • 粉丝0
  • 关注0
  • 积分291分
  • 威望460点
  • 贡献值0点
  • 好评度428点
  • 原创分0分
  • 专家分0分
阅读:1595回复:10

nter0及已经完成枚举的同仁请进,300分解决枚举问题!

楼主#
更多 发布于:2003-02-13 16:18
1,那位仁兄能把枚举阶段收到的命令及相应的应答贴出来,我收到的是:
(1)80 06 00 01 00 00 40 00  GetDescriptor
(2)00 05 02 00 00 00 00 00  SetAddress
(3)80 06 00 01 00 00 12 00   GetDescriptor
其余的我还没收到,不知道是那里除了问题,据我所知下面应该还有:
(4)80 06 00 02 00 00 09 00  GetDescriptor
(5)80 06 00 02 00 00 ? 00  GetDescriptor
第(5)步里那个问号表示那个值那可能不是个完全固定的,余下的我就不知道了,还望做过的大侠把剩下的补充完全!

2,如果我用操作系统自带的驱动能做到那一步,如果vid和pid和操作系统缺省列表中的一样是不是可以完成整个枚举?如果不是能做到那一步呢?

3,如果我用ds里的drivermonitor监测驱动的事件,怎么才能看到设备返回的数据,是不是必须用softice来跟踪驱动的整个运行过程才能看到全部的数据?

目前就这几个问题,还望知道的不吝赐教呀,如果能留下你们的宝贵意见,在下将不胜感激!


[编辑 -  2/13/03 by  jinghuiren]

最新喜欢:

lhaihlhaih
iamchine
驱动小牛
驱动小牛
  • 注册日期2002-11-18
  • 最后登录2005-11-23
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2003-02-13 17:08
1)
首先4中有点小错,09是倒数第二的位置,不是最后
如果你在3之后主机不发4,应该是你返回的设备描述符表主机不认,一般可能性在Vid和Pid不正确,我昨天给的那个不行吗?
我返回给主机的描述符
12 01 00 02 - 00 00 00 40 - d1 0e 20 66 - 00 01 00 00 - 00 01
就收到主机的4和5,你需返回正确的配置描述符表
其实到这里枚举可以认为结束了,因为接下来是BulkOnly和UFI的东东了.到这步W2K可以显示找到Mass Storage设备
(6)00 09 01 00 - 00 00 00 00  Set Config (Endpoint 0)
(7)55 53 42 43 - 48 f3 2e ff - 24 00 00 00 - 80 00 0c 12
   00 00 00 24 - 00 00 00 00 - 00 00 00 00 - 00 00 00 Inquiry (Bulk Out Endpoint)
后面的就不写了
2)如果Vid和Pid正确,你的固件也没错,应该是可以的
puppypyb
驱动牛犊
驱动牛犊
  • 注册日期2003-01-14
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分52分
  • 威望10点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2003-02-13 17:21
我枚举没作出来, 但是有同志作出来过,贴给你,或许有用

发表于: 2002/12/3 - 16:26
呵呵,你真走运,我正好这几天在做枚举这部分,并且已经成功了。下面告诉你我的过程:
根集线器检查到设备连接后,激活主机USB总线驱动程序,USBD发出一系列的SETUP包。这过程中并不要用到你自己编的驱动,会由系统的总线驱动来自动处理,所以你要自己还没编主机那的驱动,也能调枚举过程。
主机的第一个命令要求得到设备描述符,此SETUP包为8个字节数据(80,06,00,01,00,00,40,00),其具体含义自己看资料。40表示返回数据长度最大为40H个字节。实际上,你只只返回一个包,即数组DEV_DESC[]中的前8个字节。用于说明设备的描述符的真实长度和设备的类型。
接着是设置设备地址处理事件,主机发送一个含有指定地址的数据包(00,05,02,00,00,00,00,00),设备需返回一个0数据包(这一步一定要做)。在主机只有一个USB设备的时候,这个地址一般会是2。设置地址事件处理结束后,设备进入地址状态,主机会在指定地址处访问设备。
主机再次发送得到设备描述符的数据包(80,06,00,01,00,00,12,00),与上次不同的是,要求的数据的长度是实际的数据长度。因为设备每次只能发送16字节,因此它会分两次(18字节)完成此要求。
接着主机要求得到设备的配置描述符(80,06,00,02,00,00,09,00),包中数据“09”指定设备发送9个字节,这正是设备配置描述符的长度。
接着主机要求得到设备的配置描述符、接口描述符和节点描述符(80,06,00,02,00,00,FF,00),由于不知道设备描述符的真实长度,因此它要求得到256个字节,
以上过程主机都是总线驱动层在处理,你用USBVIEW能看到你发出的东西,下面的一步(最后一步)就需要你的设备驱动来做了:
最后主机发送设置设备配置SETUP包(00,09,01,00,00,00,00,00),设备处理此事件,将允许所有节点进入工作状态。
如果D12固件没问题,则只收到:
1,get_descriptor;d12发送8字节的设备描述符信息
2.set_address;
3,get_descriptor;获取全部设备描述符
4,get_decriptor:9byte配置描述符
5,get_decriptor:整个配置描述符,包括interface,endpoit
6,找驱动程序->终止,d12灯灭
 
jinghuiren
驱动巨牛
驱动巨牛
  • 注册日期2002-06-01
  • 最后登录2008-10-27
  • 粉丝0
  • 关注0
  • 积分291分
  • 威望460点
  • 贡献值0点
  • 好评度428点
  • 原创分0分
  • 专家分0分
地板#
发布于:2003-02-13 17:31
  我现在正在对我的程序进行大的修改,包括描述符,我也觉得可能是描述符的问题,可是经过多次尝试还是无法收到第四个请求,所以我决定在从头找一遍原因。
  另外我的操作系统是98,所以iamchine给我的vid和pid可能不能用,不过我在注册表中找到了一个跟你的相似的,是0ed1和6630,我想马上再试一下。

对于楼上两位仁兄的回答,我在此先表示感谢了,你们每人将得到100分以示我的感激!为了鼓励大家多提意见,暂时留100分给后来者
puppypyb
驱动牛犊
驱动牛犊
  • 注册日期2003-01-14
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分52分
  • 威望10点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2003-02-13 17:35
还有我的问题呢!
帮我解决了 回一百分给你!
谢谢了先
yalong
驱动牛犊
驱动牛犊
  • 注册日期2001-08-27
  • 最后登录2011-07-24
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望2点
  • 贡献值0点
  • 好评度2点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2003-02-13 17:56
你没有收到第四步的最大可能就是第三步时你回给主机的描述符有问题,第二种情况是,你返回的18个设备描述符不能在一包中返回,需要多次返回,那么第二次时需要修改PID(非VID、PID中的PID),一般对于多包数据,PID要进行0、1切换才能被正常发回主机的,这个问题我在调1。1的时候遇到过。如果你是做2。0,好象是可以让芯片自动进行枚举,而你只需要提供VID、PID、DID的值。另外,在你完成枚举之前,主机端的设备驱动是没有用的,只有HOST的驱动起作用。
iamchine
驱动小牛
驱动小牛
  • 注册日期2002-11-18
  • 最后登录2005-11-23
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2003-02-13 18:00
不是很明白yalong说的pid,如果是指data toggle标记的话,这个硬件(芯片)应该处理的啊
nter0
驱动牛犊
驱动牛犊
  • 注册日期2002-12-10
  • 最后登录2008-11-17
  • 粉丝0
  • 关注0
  • 积分10分
  • 威望2点
  • 贡献值0点
  • 好评度2点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2003-02-14 05:00
#include <reg51.h>
#include <usbtest.h>

char ii[5];
void main()
{
    P1=0xff;
    XmtBuff.out = 0x00;
    XmtBuff.in = 0x01;
    D12_COMMAND = 0xf3;D12_DATA = 0x06;D12_DATA = 0x03;//初始化频率 12MHz
    D12_COMMAND = 0xd0;D12_DATA = 0x80;//设置地址 0 使能
    D12_COMMAND = 0xf3;D12_DATA = 0x16;//连接主机
    while(1)
    {
        if(!D12_int_n)
        {
            D12_COMMAND = 0xf4;// 读中断寄存器
            XmtBuff.b[0] = D12_DATA;
            if(XmtBuff.b[0] & 0x80)
            {
              if(D12_suspend == 1)
              {   /** /
                  D12_suspend=0;//处理挂起事务
                  D12_COMMAND = 0xf6;//发送恢复命令
                  D12_suspend = 1;
                  /**/
              }
            }
            else
            {
              if(XmtBuff.b[0] & 0x15)// 收到 OUT 包
              {
                  if(ii[0]==12)
                  ii[0]=ii[0];
                  if(XmtBuff.b[0] & 0x01)
                  {
                      D12_COMMAND = 0x40;//读 OUT 最后状态
                      if(D12_DATA & 0x20)// 收到 SETUP 包
                      {
                          SETUP_read();
                          HandleSetup();
                      }
                  }else if(XmtBuff.b[0] & 0x04)
                  {
                      D12_COMMAND = 0x42;//读 OUT 最后状态
                  }else if(XmtBuff.b[0] & 0x10)
                  {
                      D12_COMMAND = 0x44;//读 OUT 最后状态
                  }
              } else if(XmtBuff.b[0] & 0x2a)// 收到 IN 包
              {
                  if(ii[1]==18)
                  ii[0]=ii[0];
                  if(XmtBuff.b[0] & 0x02)XmtBuff.in = 1;
                  else if(XmtBuff.b[0] & 0x08)XmtBuff.in = 3;
                  else if(XmtBuff.b[0] & 0x20)XmtBuff.in = 5;
                      D12_COMMAND = (XmtBuff.in | 0x40);// 读 IN 最后状态
                  XmtBuff.b[1] = D12_DATA;
                  //if(D12_DATA & 0x01)
                  {
                      ii[1]++;
                      //if(ii[1]==4)
                      //ii[0]=ii[0];
                      USB_submit();
                  }
              }
            }
        }
    }
}

void HandleSetup(void)
{
    if(ii[0]==10)
    ii[0]=ii[0];
    ii[0]++;
    if(XmtBuff.b[0] & 0x20)//类请求跳转表
    {
       if (XmtBuff.b[1] <= 0x0B)
       {
          //(*ClassFunctionTable[XmtBuff.b[1]])();
          return;
       }
    }
    else
    {
       if (XmtBuff.b[1] <= 0x0B)//标准请求跳转表
       {
          if (XmtBuff.b[1] == 15)
          {
              SetConfiguration();
          }else
          {
              (*StandardFunctionTable[XmtBuff.b[1]])();
          }
       }
       return;
    }
}

void SETUP_read(void)
{
    char i;
    D12_COMMAND = 0x00;// 选择端点0(指针指向0位置)
    D12_COMMAND = 0xf0;// 读标准控制码
    XmtBuff.b[0] = D12_DATA;
    XmtBuff.b[1] = D12_DATA;
    for(i=0;i<8;i++)
    {
       XmtBuff.b = D12_DATA;
    }
    D12_COMMAND = 0xf1;// 应答SETUP包,使能(清 OUT 缓冲区、使能 IN 缓冲区)命令
    D12_COMMAND = 0xf2;// 清 OUT 缓冲区
}

void USB_submit(void)
{
    ii[3]++;

    if(XmtBuff.rLength>XmtBuff.pNum)XmtBuff.rLength = XmtBuff.pNum;

    D12_COMMAND = XmtBuff.in;// 选择 IN 端点(指针指向0位置)
    D12_COMMAND = 0xf0;// 写缓冲区
    D12_DATA = 0x00;
    D12_DATA = XmtBuff.rLength;

    for(XmtBuff.b[7]=0;XmtBuff.b[7]<XmtBuff.rLength ;XmtBuff.b[7]++)
    {
        D12_DATA = *(XmtBuff.p++);
    }
    XmtBuff.pNum-=XmtBuff.rLength;

    if(XmtBuff.in == 1)D12_COMMAND = 0xf1;// 应答SETUP包,使能(清 OUT 缓冲区、使能 IN 缓冲区)命令
    D12_COMMAND = 0xfa;// 设置 IN 缓冲区有效(满标志)
}

void voidfunction(void)
{
    D12_COMMAND = 0x40;// 0 端点停止(用于发送Stall包)
    D12_DATA = 0x01;
    D12_COMMAND = 0x41;// 1 端点停止(用于发送Stall包)
    D12_DATA = 0x01;
    D12_COMMAND = 0xf1;// 应答SETUP包,使能(清 OUT 缓冲区、使能 IN 缓冲区)命令
}

void SetAddress(void)
{
    ii[4]++;
    D12_COMMAND = 0xd0;//设置新地址使能
    D12_DATA = 0x80 | XmtBuff.b[2];
    XmtBuff.rLength = 0;
    USB_submit();
}

void GetDescriptor(void)
{
     ii[2]++;
    XmtBuff.rLength=16;
    switch (XmtBuff.b[3])
    {
        case 0x01: //USB_DEVICE
            XmtBuff.pNum = sizeof(device_descriptor);
            XmtBuff.p = device_descriptor;
            break;
        case 0x02:// USB_CONFIGURATION
            XmtBuff.pNum = Configuration_Descriptor[2];
            XmtBuff.p = Configuration_Descriptor;
            if(XmtBuff.b[6]<16)XmtBuff.pNum = XmtBuff.b[6];
            break;
        case 0x03: //USB_STRING
            switch(XmtBuff.b[2])
            {
            case 0x00 :
                XmtBuff.pNum = sizeof(USBStringLanguageDescription);
                XmtBuff.p = USBStringLanguageDescription;
                break;
            case 0x01 :
                XmtBuff.pNum = sizeof(USBStringDescription1);
                XmtBuff.p = USBStringDescription1;
               break;
            case 0x02 :
                XmtBuff.pNum = sizeof(USBStringDescription2);
                XmtBuff.p = USBStringDescription2;
               break;
            default   :
                voidfunction();
                return;
            }
            break;
        default :
            voidfunction();
            return;
    }
    USB_submit();
}

void SetConfiguration(void)
{
    if (XmtBuff.b[0] == 0x00)
    {
        XmtBuff.rLength = 0;
        USB_submit();
        D12_COMMAND = 0xd8;
        if(XmtBuff.b[2] == 0x00)
        {
            D12_DATA = 0x00;  // 使用端点0
        }else if(XmtBuff.b[2] == 0x01)
        {
            D12_DATA = 0x01;  // 使用端点1
        }
   }
    else
    voidfunction();
}

void GetStatus(void)
{
    switch (XmtBuff.b[0])
    {
    case 0x80://返回设备状态
              //发送两个字节数据:第一字节D1为1支持远程唤醒,D0为0是总线供电,其它位为0;第二字节为0。
        XmtBuff.b[0] = 0x03;
        XmtBuff.b[1] = 0x00;
        break;
    case 0x81://返回接口状态
        //发送两个字节数据:第一字节为0;第二字节为0。
        //XmtBuff.b[5] 为接口号
        XmtBuff.b[0] = 0x00;
        XmtBuff.b[1] = 0x00;
        break;
    case 0x82://返回端点状态
        //发送两个字节数据:第一字节D0为1端点处于暂停,否则D0为0,其它位为0;第二字节为0。
        //XmtBuff.b[5] D7为方向,D3~0为端点号
        XmtBuff.b[0] = 0x00;
        XmtBuff.b[1] = 0x00;
        break;
    }
    XmtBuff.rLength = 2;
    XmtBuff.pNum = 2;
    XmtBuff.p = XmtBuff.b;
    USB_submit();
}
nter0
驱动牛犊
驱动牛犊
  • 注册日期2002-12-10
  • 最后登录2008-11-17
  • 粉丝0
  • 关注0
  • 积分10分
  • 威望2点
  • 贡献值0点
  • 好评度2点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2003-02-14 05:01
//自定义头文件 usbtest.h

sbit D12_suspend=P1^0;
sbit D12_int_n=P1^1;
sbit D12_eot_n=P1^2;
sbit D12_DMAck_n=P1^3;
sbit D12_DMAreq=P1^4;
sbit p15=P1^5;
sbit p16=P1^6;
sbit p17=P1^7;

#define D12_COMMAND (*(unsigned char xdata *)0x8000)
#define D12_DATA    (*(unsigned char xdata *)0x0000)

void HandleSetup(void);
void SETUP_read(void);
void USB_submit(void);

void GetStatus(void);
void ClearFeature(void);
void SetFeature(void);
void SetAddress(void);
void GetDescriptor(void);
void SetDescriptor(void);
void GetConfiguration(void);
void SetConfiguration(void);
void GetInterface(void);
void SetInterface(void);

void voidfunction(void);

code void (* StandardFunctionTable[])(void)=
{
   GetStatus,voidfunction,voidfunction,voidfunction,
   voidfunction,SetAddress,GetDescriptor,voidfunction,
   voidfunction,SetConfiguration,voidfunction,voidfunction
};
/**/
void GetReport(void);
void GetIdle(void);
void GetProtocol(void);
void SetIdle(void);
void SetProtocol(void);

code void (* ClassFunctionTable[])(void)=
{
  voidfunction, GetReport, GetIdle,GetProtocol,
  voidfunction, voidfunction, voidfunction,voidfunction,
  voidfunction, voidfunction, SetIdle,SetProtocol
};
/**/

typedef struct
{
    unsigned char b[8];
    unsigned char out;
    unsigned char in;
    unsigned char rLength;
    unsigned char pNum;
    unsigned char *p;
}TRANSMIT_STRUCT;
TRANSMIT_STRUCT XmtBuff;

code char device_descriptor[] =
{
0x12, // 描述表大小 (18 bytes)
0x01, // 设备描述表类型
0x10, 0x01,    // 兼容设备版本号(BCD码)
0x00, // 设备类码
0x00, // 子类码
0x00, // 协议码
0x10,          // 端点0最大包大小(8,16,32,64)
0x71, 0x04,    // 厂商ID
0x11, 0x11,    // 产品ID
0x01, 0x00,    // 设备发行号(BCD码)
0x01, // 厂商信息字符串索引
0x02, // 产品信息字符串索引
0x00, // 设备序列号字符串索引(不支持设为0)
0x01 // 配置数
};

code char Configuration_Descriptor[] =
{
0x09,          // 配置描述表长度
0x02,          // 配置描述表类型
0x20,0x00,     // 配置描述表及附带表长度
0x01,          // 接口配置数
0x01,          // 配置描述表标识
0x00,          // 配置描述表字符串描述表索引
0xa0,          // 配置属性
0x64           // 总线供电最大值(*2mA)
};

code char Interface_Descriptor[] =
{
0x09, // 接口描述表长度(9)
0x04, // 接口描述表类型
0x00, // 接口数(0)
0x00, // 轮寻设置(0 号端点)
0x02, // 端点数 (4)
0x03, // 接口类属
0x01, // 子类码
0x02, // 协议码
0x00  // 接口字符串描述表索引(不支持)
};

code char Endpoint_Descriptor_t[] =
{
0x07, // 端点描述表长度(7)
0x05, // 端点描述表类型
0x81, // IN 端点(1)
0x02, // 传输模式(0 控制、1 同步、2 批、3 中断传输)
0x10, 0x00,    // 最大包大小(16)
0x0A  // 轮寻时间 (10ms)
};

code char Endpoint_Descriptor_r[] =
{
0x07, // 端点描述表长度(7)
0x05, // 端点描述表类型
0x01, // OUT 端点(1)
0x02, // 传输模式(0 控制、1 同步、2 批、3 中断传输)
0x10, 0x00,    // 最大包大小(16)
0x0A  // 轮寻时间 (10ms)
};

code char USBStringLanguageDescription[] =
{
sizeof(USBStringLanguageDescription), // 字符串描述表长度
0x03, // 字符串描述表类型
0x09, // 语言标识(9 英语)
0x04 // 子语言标识: Default
};

code char USBStringDescription1[] =
{
sizeof(USBStringDescription1),
        0x03,
        \'C\',0,\'y\',0,\'p\',0,\'r\',0,\'e\',0,\'s\',0,\'s\',0,\' \'
};

code char USBStringDescription2[] =
{
sizeof(USBStringDescription2),
        0x03,
        \'C\',0,\'y\',0,\'p\',0,\'r\',0,\'e\',0,\'s\',0,\'s\',0,\' \'
};

你觉得这样怎样,不用我罗嗦了  :D
nter0
驱动牛犊
驱动牛犊
  • 注册日期2002-12-10
  • 最后登录2008-11-17
  • 粉丝0
  • 关注0
  • 积分10分
  • 威望2点
  • 贡献值0点
  • 好评度2点
  • 原创分0分
  • 专家分0分
9楼#
发布于:2003-02-14 05:11
 下面也是我的,不过这是完成后程序的派举结果

OUT:80 06 00 02 - 00 00 ff 00  GET DESCRIPTR
IN: 09 02 27 00 - 01 01 00 80  ..\'.....      
     32 09 04 00 - 00 03 08 06  2.......    
     50 00 07 05 - 81 02 40 00  P.....@.    
     00 07 05 02 - 02 40 00 00  .....@..    
OUT:80 06 00 01 - 00 00 12 00  GET DESCRIPTR
IN: 12 01 10 01 - 00 00 00 08  ........      
     76 0c 05 00 - 00 01 00 00  v.......    
     00 01                      ..            
OUT:80 06 00 02 - 00 00 09 00  GET DESCRIPTR
IN: 09 02 27 00 - 01 01 00 80  ..\'.....      
     32                      
OUT:80 06 00 02 - 00 00 27 00  GET DESCRIPTR
IN: 09 02 27 00 - 01 01 00 80  ..\'.....      
     32 09 04 00 - 00 03 08 06  2.......      
     50 00 07 05 - 81 02 40 00  P.....@.      
     00 07 05 02 - 02 40 00 00  .....@..    
OUT:00 09 01 00 - 00 00 00 00  SET CONFIG  
OUT:01 0b 00 00 - 00 00 00 00  SET INTERFACE
OUT:21 00 00 00 - 00 00 01 00  CLASS  
IN: 00

朋友 仁至义尽了,给分吧
jinghuiren
驱动巨牛
驱动巨牛
  • 注册日期2002-06-01
  • 最后登录2008-10-27
  • 粉丝0
  • 关注0
  • 积分291分
  • 威望460点
  • 贡献值0点
  • 好评度428点
  • 原创分0分
  • 专家分0分
10楼#
发布于:2003-02-14 10:54
老兄,想要分还不简单,我有的是!只要问题解决了,放1000分都行!

多谢诸位了,你们都说的这么清楚了,我看我必须详细检查一下我的程序了,在下感激万分!
游客

返回顶部