关于用scsi指令读写U盘的问题!

zxwitsme 2004-10-08 12:03:25
驱网上不去,在这里问个问题
驱网上面有这样一篇文章:
问题:
我用NTDDK下是spti例子程序和U盘通信,调用方法如下:
spti g:
(g:是U盘的盘符)但是调用第一个命令就返回错误,如下:
Error reading inquiry data information; error was 50
不支持网络请求。

但是CreateFile没返回错误,这说明创建句柄是对的,为什么一调用命令就出错。

还请高手解答,谢谢!

答案:
问题已经解决了,必须自己构造SCSI_PASS_THROUGH命令,标准的Windows提供的IOCTL不行,这是我的理解,不知高手有没有其它答案。希望别人不用走弯路。

有人知道他所说的构造SCSI_PASS_THROUGH命令是在驱动里面构造还是怎么构造呢?多谢!

...全文
1472 16 点赞 打赏 收藏 举报
写回复
16 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
zxwitsme 2004-10-11
这样就可以了,不过你用到的INQUIRY_BUFFER_LENGTH是在哪里定义的?我没找到
给分了,多谢!
  • 打赏
  • 举报
回复
roger_ding 2004-10-11
我的意思是换个inquiry的方法,用下面方法试试,

DWORD CFormatNT::InquiryDisk(HANDLE hDisk)
{
SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER sptdwb;
ZeroMemory(&sptdwb, sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER));

BYTE byBuffer[INQUIRY_BUFFER_LENGTH];
DWORD dwBufferBytes = sizeof(byBuffer);

sptdwb.sptd.Length = sizeof(SCSI_PASS_THROUGH_DIRECT);
sptdwb.sptd.PathId = 0;
sptdwb.sptd.TargetId = 1;
sptdwb.sptd.Lun = 0;
sptdwb.sptd.CdbLength = CDB6GENERIC_LENGTH;
sptdwb.sptd.SenseInfoLength = 24;
sptdwb.sptd.DataIn = SCSI_IOCTL_DATA_IN;
sptdwb.sptd.DataTransferLength = dwBufferBytes;
sptdwb.sptd.TimeOutValue = 2;
sptdwb.sptd.DataBuffer = byBuffer;
sptdwb.sptd.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, ucSenseBuf);
sptdwb.sptd.Cdb[0] = SCSI_INQUIRY;
sptdwb.sptd.Cdb[4] = (UCHAR) dwBufferBytes;

int iLength = sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER);
DWORD dwReturn = 0;
if (!DeviceIoControl(hDisk, IOCTL_SCSI_PASS_THROUGH_DIRECT,
&sptdwb, iLength, &sptdwb, iLength, &dwReturn, FALSE))
return -1;

return ERROR_SUCCESS;
}

  • 打赏
  • 举报
回复
zxwitsme 2004-10-08
你好,请仔细看我的问题,我想问的是
他所说的构造SCSI_PASS_THROUGH命令是在驱动里面构造还是怎么构造呢?
  • 打赏
  • 举报
回复
roger_ding 2004-10-08
不过使用sptdwb前需要初始化
参考 SCSI command, CDB
  • 打赏
  • 举报
回复
roger_ding 2004-10-08
DeviceIoControl可以传送SCSI命令的

建议使用
SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER sptdwb;
DeviceIoControl(hDisk, IOCTL_SCSI_PASS_THROUGH_DIRECT, &sptdwb, iLength, &sptdwb, iLength, &dwReturn, FALSE);
  • 打赏
  • 举报
回复
zxwitsme 2004-10-08
我就是参考的NTDDK\src\storage\class\spti\spti.c这个程序,要是
status = DeviceIoControl(fileHandle,
IOCTL_SCSI_GET_INQUIRY_DATA,
NULL,
0,
buffer,
sizeof(buffer),
&returned,
FALSE);
都不能成功的话,后面的操作还有可能成功吗?
谢谢你的帮助.
  • 打赏
  • 举报
回复
zxwitsme 2004-10-08
嗯,我知道,读写U盘,就想读写普通磁盘一样可以用createfile,writefile,readfile
可是我现在是想发送一些字符串到Usb,然后让固件程序接收并且返回一些字符串.
我看看啊,谢谢了
  • 打赏
  • 举报
回复
roger_ding 2004-10-08
再给你个,
NTDDK\src\storage\class\spti\spti.c

//
// Get the inquiry data.
//

status = DeviceIoControl(fileHandle,
IOCTL_SCSI_GET_INQUIRY_DATA,
NULL,
0,
buffer,
sizeof(buffer),
&returned,
FALSE);
这是它的例子,如果不成功的话,可以参考紧跟着它的代码,

ZeroMemory(&sptwb,sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS));

sptwb.spt.Length = sizeof(SCSI_PASS_THROUGH);
sptwb.spt.PathId = 0;
sptwb.spt.TargetId = 1;
sptwb.spt.Lun = 0;
sptwb.spt.CdbLength = CDB6GENERIC_LENGTH;
sptwb.spt.SenseInfoLength = 24;
sptwb.spt.DataIn = SCSI_IOCTL_DATA_IN;
sptwb.spt.DataTransferLength = 192;
sptwb.spt.TimeOutValue = 2;
sptwb.spt.DataBufferOffset =
offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf);
sptwb.spt.SenseInfoOffset =
offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucSenseBuf);
sptwb.spt.Cdb[0] = SCSIOP_MODE_SENSE;
sptwb.spt.Cdb[2] = MODE_SENSE_RETURN_ALL;
sptwb.spt.Cdb[4] = 192;
length = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf) +
sptwb.spt.DataTransferLength;

status = DeviceIoControl(fileHandle,
IOCTL_SCSI_PASS_THROUGH,
&sptwb,
sizeof(SCSI_PASS_THROUGH),
&sptwb,
length,
&returned,
FALSE);

把 SCSIOP_MODE_SENSE 换成 SCSI_INQUIRY
当然CDB的结构也要变,建议找个SCSI的定义看看
  • 打赏
  • 举报
回复
roger_ding 2004-10-08
其实读写U盘,可以通过ReadFile,WriteFile 不用SCSI的

98DDK\src\BLOCK\WNASPI32\SCSIDEFS.H 为SCSI命令的定义
  • 打赏
  • 举报
回复
zxwitsme 2004-10-08
http://community.csdn.net/Expert/topic/3418/3418169.xml?temp=.2060816
就是这个贴啦,你也有回答过的
我就是想通过scsi命令来和U盘通信,可是spti的源码根本就不能和U盘通信啊:(
  • 打赏
  • 举报
回复
zxwitsme 2004-10-08
帮我搞定了,这个帖子的80分还有另外一个类似帖子的100分马上就给你,谢谢
  • 打赏
  • 举报
回复
zxwitsme 2004-10-08
请问控制码是指哪个?命令结构不是在驱动里面就已经构造了吗?
构造的例子在spti里面吗?
我只是用
status = DeviceIoControl(fileHandle,
IOCTL_SCSI_GET_INQUIRY_DATA,
NULL,
0,
buffer,
sizeof(buffer),
&returned,
FALSE);
的时候都不能成功,也是因为没有构造命令结构的原因吗?
请帮帮忙,多谢了
  • 打赏
  • 举报
回复
roger_ding 2004-10-08
你贴的都是控制码,需要自己构造命令结构,windows ddk 里有构造的例子
  • 打赏
  • 举报
回复
zxwitsme 2004-10-08
如果有的话,为何DeviceIoControl的第二个参数使用这个ioctl不能成功呢?
而我的问题中提到的自己构造SCSI_PASS_THROUGH命令,又是怎么回事呢?
  • 打赏
  • 举报
回复
zxwitsme 2004-10-08
应该是在ddk的ntddscsi.h里面构造的吧,不知道在win2k的默认驱动usbstor.sys里面有没有对应

#define IOCTL_SCSI_PASS_THROUGH CTL_CODE(IOCTL_SCSI_BASE, 0x0401, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_SCSI_MINIPORT CTL_CODE(IOCTL_SCSI_BASE, 0x0402, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_SCSI_GET_INQUIRY_DATA CTL_CODE(IOCTL_SCSI_BASE, 0x0403, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_SCSI_GET_CAPABILITIES CTL_CODE(IOCTL_SCSI_BASE, 0x0404, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_SCSI_PASS_THROUGH_DIRECT CTL_CODE(IOCTL_SCSI_BASE, 0x0405, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_SCSI_GET_ADDRESS CTL_CODE(IOCTL_SCSI_BASE, 0x0406, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_SCSI_RESCAN_BUS CTL_CODE(IOCTL_SCSI_BASE, 0x0407, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_SCSI_GET_DUMP_POINTERS CTL_CODE(IOCTL_SCSI_BASE, 0x0408, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_SCSI_FREE_DUMP_POINTERS CTL_CODE(IOCTL_SCSI_BASE, 0x0409, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_IDE_PASS_THROUGH CTL_CODE(IOCTL_SCSI_BASE, 0x040a, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)

这些定义的操作?
  • 打赏
  • 举报
回复
roger_ding 2004-10-08
当然是在调用DeviceIoControl之前构造的
  • 打赏
  • 举报
回复
相关推荐
发帖
硬件/系统
加入

2603

社区成员

VC/MFC 硬件/系统
申请成为版主
帖子事件
创建了帖子
2004-10-08 12:03
社区公告
暂无公告