打印

菜鸟初学USB之一:数据包分析,请各位DX赐教

[复制链接]
6447|9
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
sxcjsnj|  楼主 | 2010-8-25 09:01 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 sxcjsnj 于 2010-8-25 09:20 编辑

下位机:U盘例程@圈圈教你玩USB小板
  修改例程,只打印收到的数据(全部打印会有问题,有可能是来不及响应)

上位机:WinXP
  使用标准Mass Storage驱动,调用DeviceIoControl向下位机发送数据

学习目的:
  分析上位机发送数据格式与发送方法,分析下位机收到的数据格式

方法:
  上位机向下位机发四次数据,分别是
  0x12,0x34
  0x12,0x34,0x56,0x78
  0x12,0x34,0x56,0x78,0x90
  0x12,0x34,0x56,0x78,0x90
  
  下位机输出结果如下:

   上位机发送:0x12,0x34
   下位机输出:
        读端点2缓冲区31字节。
        0x55 0x53 0x42 0x43 0x08 0x30 0x4A 0x88 0x02 0x00 0x00 0x00 0x00 0x00 0x06 0xFF
        0x54 0x59 0x43 0x4F 0x53 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
        读端点2缓冲区2字节。
        0x12 0x34

   上位机发送:0x12 0x34 0x56 0x78
   下位机输出:
        读端点2缓冲区31字节。
        0x55 0x53 0x42 0x43 0x08 0x90 0xAA 0x89 0x04 0x00 0x00 0x00 0x00 0x00 0x06 0xFF
        0x54 0x59 0x43 0x4F 0x53 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
        读端点2缓冲区4字节。
        0x12 0x34 0x56 0x78

   上位机发送:0x12 0x34 0x56 0x78 0x90
   下位机输出:
        读端点2缓冲区31字节。
        0x55 0x53 0x42 0x43 0x28 0xFE 0xAE 0x87 0x05 0x00 0x00 0x00 0x00 0x00 0x06 0xFF
        0x54 0x59 0x43 0x4F 0x53 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
        读端点2缓冲区5字节。
        0x12 0x34 0x56 0x78 0x90

   上位机发送:0x12 0x34 0x56 0x78 0x90
   下位机输出:
        读端点2缓冲区31字节。
        0x55 0x53 0x42 0x43 0x08 0x50 0xAB 0x87 0x05 0x00 0x00 0x00 0x00 0x00 0x06 0xFF
        0x54 0x59 0x43 0x4F 0x53 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
        读端点2缓冲区5字节。
        0x12 0x34 0x56 0x78 0x90

相关帖子

沙发
sxcjsnj|  楼主 | 2010-8-25 09:14 | 只看该作者
上位机函数调用:
DeviceIoControl(hHandle,
        IOCTL_SCSI_PASS_THROUGH_DIRECT,        
        &TransStruct, //定义见下
        cbDataLen,  //0x2e
        &TransStruct, //定义见下
        cbDataLen, //0x2e
        &cbRetValSize,
        FALSE)

其中:TransStruct定义如下:
SCSI_PASS_THROUGH_DIRECT TransStruct;
ZeroMemory(&TransStruct, sizeof(SCSI_PASS_THROUGH_DIRECT));
TransStruct.Length = sizeof(SCSI_PASS_THROUGH_DIRECT); //0x2C
TransStruct.PathId = 0;
TransStruct.TargetId = 1;
TransStruct.Lun = 0;
TransStruct.CdbLength = cCBDLen;//0x06
TransStruct.DataIn = SCSI_IOCTL_DATA_OUT;//0x00
TransStruct.DataTransferLength = ulDataTransferLength;//0x02
TransStruct.TimeOutValue = 3;
TransStruct.DataBuffer = abIOBuffer;
TransStruct.SenseInfoLength = 0;
TransStruct.SenseInfoOffset = sizeof(SCSI_PASS_THROUGH_DIRECT);//0x2C
memcpy(TransStruct.Cdb, pbCBD, cCBDLen);//0xff,0x54,0x59,0x43,0x4f,0x53

使用特权

评论回复
板凳
sxcjsnj|  楼主 | 2010-8-25 09:19 | 只看该作者
现在的问题有两个:
1、如何分析下位机收到的数据包?比如:
        读端点2缓冲区31字节。
        0x55 0x53 0x42 0x43 0x08 0x50 0xAB 0x87 0x05 0x00 0x00 0x00 0x00 0x00 0x06 0xFF
        0x54 0x59 0x43 0x4F 0x53 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
        读端点2缓冲区5字节。
        0x12 0x34 0x56 0x78 0x90

2、下位机现在可以收到数据包,但是上位机DeviceIoControl函数返回了一个非零值,调用GetLastErr得到错误代码为0x0000045d,查阅手册,这个错误表示Device_IO_Error。是不是因为下位机响应不正确导致?如果是,应该如何响应这个上位机输出?

刚开始看USB,问题比较白痴...请各位DX不吝赐教,先行谢过~~~

使用特权

评论回复
地板
飞翔的猪| | 2010-8-25 11:39 | 只看该作者
话说我比你都菜,纯路过支持下,等待高人

使用特权

评论回复
5
sxcjsnj|  楼主 | 2010-8-26 11:03 | 只看该作者
高人还没有出现,自已根据这两天看的资料大概分析一下,第一个数据报一个CBW包(包结构可以查阅相关资料或00的书):
0x55 0x53 0x42 0x43 //CBW标志,即字符串“USBC”,固定不变
0x08 0x50 0xAB 0x87 //CBW标签,从机在状态阶段要返回给主机,暂时不理解,先放一下(难道是ID?)
0x05 0x00 0x00 0x00 //需要在数据传输阶段传输的字节数
0x00 //CBW的标志,0x00表示从主机到设备,0x80代表从设备到主机
0x00 //目标逻辑单元的编号,仅使用低四位,即最多有16个逻辑单元
0x06 //CBWCB的长度,即下面这个域的长度,仅使用5位,有效范围为1~16,0x06表示CBWCB的长度为6个字节
0xFF 0x54 0x59 0x43 0x4F 0x53 //需要执行的命令,长度正好为6
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00  //填充,如果命令的长度不足16字节,用0填充

批量传输分为三个阶段:
命令阶段(主机到设备)-数据阶段(方向根据命令决定)-状态阶段(设备到主机)

以本帖的例子来说,上面分析的就是命令阶段由主机发给设备的命令,表示主机发给设备一个5字节的命令“0xFF 0x54 0x59 0x43 0x4F 0x53”,另外主机告诉设备:在接下来的数据阶段,我要发送给你6个字节的数据(就是后面打印出来的“0x12 0x34 0x56 0x78 0x90”)。当然本例中举的是主机到设备的数据传输,也可以是设备到主机的数据传输。
最后一个阶段是状态阶段,命令状态封包叫CSW,包结构如下:
0-3:CSW标志,固定为USBS,即0x55,0x53,0x42,0x53
4-7:CSW封包的标签,把响应的CBW的标签拷贝出来放这里就OK了
8-11:命令完成时剩余的字节数,需要收取的字节数在CBW中规定了,实际收到的如果正好,就回个0,如果少了,还差多少告诉主机就OK,实际收取的会多不?
12:命令的执行状态,00:成功,01:失败,02:阶段错误

上面提到主机报错,估计有可能是CSW回得不对,修改一下代码再试试~~~

参考资料:圈圈教你玩USB第8章

使用特权

评论回复
6
sxcjsnj|  楼主 | 2010-8-26 11:15 | 只看该作者
本帖最后由 sxcjsnj 于 2010-8-26 13:21 编辑

修改00第8章的例子中的SCSI.c的ProcScsiCommand函数
添加用户自定义SCSI指令:
  case USER_COMMAND:
   Ep2DataLength=GetDataTransferLength(); //获取需要返回的长度
   SetCsw(0,0); //设置剩余字节数为0,状态成功
   break;
上位机发送函数返回正常~~~

使用特权

评论回复
7
sxcjsnj|  楼主 | 2010-8-26 13:36 | 只看该作者
简单地修改了一下,现在上位机和下位机都通了:
  case USER_COMMAND:
  if(CBW[12]&0x80)
  {
          pEp2SendData=pUserData;
        Ep2DataLength=2;
        SetCsw(0,0);
        Ep2SendData();               
  }
  else
  {
           Ep2DataLength=GetDataTransferLength(); //获取需要返回的长度
           SetCsw(0,0); //设置剩余字节数为0,状态成功
   }
   break;

使用特权

评论回复
8
yufengzungzhe| | 2010-11-1 15:14 | 只看该作者
大哥,能不能加你QQ好友啊,,我也 正在做这方面的工作 。想向你请教 我的QQ281273905

使用特权

评论回复
9
xty_seven| | 2010-11-3 19:50 | 只看该作者
我也有这块板子,但不知道怎么做! 向楼主学习

使用特权

评论回复
10
kaixin_0007| | 2010-12-16 13:25 | 只看该作者
请问SCSI_PASS_THROUGH_DIRECT中的变量SenseInfoLength 表示什么意思啊?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

9

帖子

1

粉丝