全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:19566
推到 Plurk!
推到 Facebook!

請教關於USB & DeviceIoControl的問題

尚未結案
發呆
一般會員


發表:5
回覆:8
積分:2
註冊:2005-08-08

發送簡訊給我
#1 引用回覆 回覆 發表時間:2005-09-07 18:57:39 IP:211.21.xxx.xxx 未訂閱
請教各位大大們 /* A5DCBF10-6530-11D2-901F-00C04FB951ED */ DEFINE_GUID(GUID_DEVINTERFACE_USB_DEVICE, 0xA5DCBF10L, 0x6530, 0x11D2, 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED); 上述是我使用的guid,driver是xp內建的公用USB driver 我使用的方法是透過 SetupDiGetClassDevs SetupDiEnumDeviceInterfaces SetupDiGetInterfaceDeviceDetail 可得到DvicePath,將它傳入 CreateFile 可得到DeviceHandle 可是問題來了, 當我把DeviceHandle傳入DeviceIoControl後, 發現,回傳都是失敗 (error code is 50. The network request is not supported. ERROR_NOT_SUPPORTED) 我試過許多種的IoControlCode,如下 IOCTL_DISK_GET_DRIVE_GEOMETRY IOCTL_INTERNAL_USB_SUBMIT_URB IOCTL_USB_GET_NODE_INFORMATION IOCTL_GET_DEVICE_DESCRIPTOR IOCTL_READ_REGISTERS IOCTL_SCSI_PASS_THROUGH_DIRECT IOCTL_BULKUSB_GET_CONFIG_DESCRIPTOR 都是一樣的結果(ERROR_NOT_SUPPORTED), 難道,透過SetupDiXXX所得到的DeviceHandle, 在xp公用driver下,是沒有IoControlCode可用? 還是我有漏掉什麼的步驟嗎? 另外,ReadFile and WriteFile也無法正常使用, 回傳的都是(87, The parameter is incorrect. ERROR_INVALID_PARAMETER) 有沒有哪位大大可以幫忙解答一下, 或是提供個解決的方向, 或是DEBUG的方法。 感謝各位大大 ----------------------- 好心的大爺啊! 賞口飯吃好嗎!
------
春秋兩不沾
夏 下
日 雨
炎 不
炎 是
正 讀
好 書
眠 天
taishyang
站務副站長


發表:377
回覆:5490
積分:4563
註冊:2002-10-08

發送簡訊給我
#2 引用回覆 回覆 發表時間:2005-09-08 09:57:00 IP:210.68.xxx.xxx 未訂閱
發呆
一般會員


發表:5
回覆:8
積分:2
註冊:2005-08-08

發送簡訊給我
#3 引用回覆 回覆 發表時間:2005-09-08 19:36:34 IP:211.21.xxx.xxx 未訂閱
taishyang 大大 那篇文章我已有看過, 我的程式也跟他的差不多, 不過就是不能正常run, 可否請教幾個問題? 1. 透過SetupDixxx得到的DeviceHandle, 有哪些的IoControlCode可使用呢? 可否列幾個讓我試一下。 2. 在那篇文章中有提到Pipe Name, 要怎麼找到Pipe Name (在Windows內建的USB Driver)? 它這裡指的是USB內的Pipe(Endpoint),沒錯吧? 3. 從回傳的Error code中可看出是哪裡出錯嗎? DevicePath出錯? 還是DeviceHandle=Createfile(...)的DeviceHandle出錯? 還是傳入DeviceIoControl(...)的IoControlCode有錯? 不過我trace的結果,DevicePath="\\\\.\\usb#vid_xxxx&pid_xxxx#_#{GUID} 感覺好像沒有錯咩!? 不好意思,一次問了一堆問題, 希望taishyang 大大,或是其它大大可以解答一下, 感謝~~感謝~~再感謝
------
春秋兩不沾
夏 下
日 雨
炎 不
炎 是
正 讀
好 書
眠 天
taishyang
站務副站長


發表:377
回覆:5490
積分:4563
註冊:2002-10-08

發送簡訊給我
#4 引用回覆 回覆 發表時間:2005-09-09 00:01:46 IP:218.168.xxx.xxx 未訂閱
您好: 您的Device是什麼?
發呆
一般會員


發表:5
回覆:8
積分:2
註冊:2005-08-08

發送簡訊給我
#5 引用回覆 回覆 發表時間:2005-09-09 09:10:56 IP:211.21.xxx.xxx 未訂閱
taishyang 大大    我的device是MP3 player, MASS STORAGE CLASS    本來是想把程式PO上來, 希望有好心的大大可以幫忙看一下, 可是預視時,都只有看到1/3的程式, 後面就沒不見了,而且用
,
程式也不會縮排,滿怪地。
------
春秋兩不沾
夏 下
日 雨
炎 不
炎 是
正 讀
好 書
眠 天
發呆
一般會員


發表:5
回覆:8
積分:2
註冊:2005-08-08

發送簡訊給我
#6 引用回覆 回覆 發表時間:2005-09-09 09:25:51 IP:211.21.xxx.xxx 未訂閱
taishyang 大大 其實我的最終目的, 只是要對我的device發SCSI command, 和做一些簡單的Read, Write。 如此而已。 感謝您, 凌晨12點還在幫忙看問題
------
春秋兩不沾
夏 下
日 雨
炎 不
炎 是
正 讀
好 書
眠 天
taishyang
站務副站長


發表:377
回覆:5490
積分:4563
註冊:2002-10-08

發送簡訊給我
#7 引用回覆 回覆 發表時間:2005-09-09 10:00:17 IP:210.68.xxx.xxx 未訂閱
您好: 那您還是把程式碼po上來好了,讓前輩?幫您看看問題在哪邊
發呆
一般會員


發表:5
回覆:8
積分:2
註冊:2005-08-08

發送簡訊給我
#8 引用回覆 回覆 發表時間:2005-09-09 12:24:06 IP:211.21.xxx.xxx 未訂閱
麻煩前輩了        char *RPipeName="PIPE01";     char *WPipeName="PIPE02"; 上面兩個PipeName是亂猜的, 所以對應的ReadFile(RDevicePipeName[1],....) 跟WriteFile(WDevicePipeName[2],....) 應該是不會動才是    
//---------------------------------------------------------------------------    #include 
#include 
#include 
#include 
#include 
#include 
#include "C:\WINDDK\2600.1106\inc\wxp\usbioctl.h"    #pragma hdrstop    //---------------------------------------------------------------------------    #pragma argsused
DEFINE_GUID(USB_DRIVER_GUID,
        0x36FC9E60L,0xC465,0x11CF,0x80,0x56,0x44,0x45,0x53,0x54,0x00,0x00);    //DEFINE_GUID(USB_DRIVER_GUID,
//        0x4D36E967L,0xE325,0x11CE,0xBF,0xC1,0x08,0x00,0x2B,0xE1,0x03,0x18);    unsigned char SCSI0x12[31]={0x55, 0x53, 0x42, 0x43,
                                                        0xB0, 0x96, 0x57, 0x81,
                                                        0x24, 0x00, 0x00, 0x00,
                                                        0x80,
                                                        0x00,
                                                        0x06,
                                                        0x12,
                                                        0x00, 0x00, 0x00, 0x24,
                                                        0x00, 0x00, 0x00, 0x00,
                                                        0x00, 0x00, 0x00, 0x00,
                                                        0x00, 0x00, 0x00};    unsigned char *RWBuffer = NULL;
unsigned char RWBuffer2[512] = {0};
unsigned char CSW[13]={0};    int main(int argc, char* argv[])
{
    char DevicePipeName[3][256] = {"", "", ""};
    char *RPipeName="PIPE01";
    char *WPipeName="PIPE02";        bool bResult;
    bool bEnumFinish;
    int  iResult;
    DWORD ErrorCode;
    
//    const GUID *pGuid = &USB_DRIVER_GUID;
    const GUID *pGuid = &GUID_DEVINTERFACE_USB_DEVICE;
    ULONG iDevIndex = 0;
    ULONG  iReqLen = 0;
    SP_DEVICE_INTERFACE_DATA deviceInfoData;
    PSP_INTERFACE_DEVICE_DATA DvcInfoData;
    PSP_DEVICE_INTERFACE_DATA  DeviceInterfaceData;
    HDEVINFO hDevInfo;        HANDLE hDeviceRW = INVALID_HANDLE_VALUE;
    HANDLE hDeviceR = INVALID_HANDLE_VALUE;
    HANDLE hDeviceW = INVALID_HANDLE_VALUE;
    DWORD dwBytesTransferred;
    DISK_GEOMETRY pdg;        ErrorCode = 0;
    iDevIndex = 0;
    bEnumFinish = FALSE;            hDevInfo = SetupDiGetClassDevs(pGuid, NULL, NULL, DIGCF_PRESENT|DIGCF_INTERFACEDEVICE);
        if(INVALID_HANDLE_VALUE == hDevInfo)
        {
                printf("\nGet Class Device fail");
                printf("\nerror code is %d", GetLastError());
        }
        do{//find all device
            deviceInfoData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
            bResult = SetupDiEnumDeviceInterfaces(hDevInfo, NULL, pGuid, iDevIndex, &deviceInfoData);
            if(TRUE == bResult)
            {
                SetupDiGetInterfaceDeviceDetail(hDevInfo, &deviceInfoData, NULL, 0, &iReqLen, NULL);                    ULONG iDevDataLen = iReqLen; //sizeof(SP_FNCLASS_DEVICE_DATA)   512;
                PSP_INTERFACE_DEVICE_DETAIL_DATA pDevData = (PSP_INTERFACE_DEVICE_DETAIL_DATA)malloc(iDevDataLen);
                if(NULL == pDevData) {
                        printf("no assign memory for pDevData");
                }
                else {
                        pDevData->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA);
                        SetupDiGetInterfaceDeviceDetail(hDevInfo, &deviceInfoData, pDevData, iDevDataLen, &iReqLen, NULL);                            strcpy(DevicePipeName[0], pDevData->DevicePath);
                        strcpy(DevicePipeName[1], pDevData->DevicePath);
                        strcpy(DevicePipeName[2], pDevData->DevicePath);
                        strcat(DevicePipeName[1],"\\");
                        strcat(DevicePipeName[2],"\\");
                        strcat(DevicePipeName[1],RPipeName);
                        strcat(DevicePipeName[2],WPipeName);
                        //###########################
                        hDeviceRW = CreateFile(
                                DevicePipeName[0],
                                GENERIC_WRITE|GENERIC_READ,
                                FILE_SHARE_READ|FILE_SHARE_WRITE,
                                NULL, OPEN_EXISTING,
                                0, NULL);
                        if(INVALID_HANDLE_VALUE == hDeviceRW)
                            ErrorCode = GetLastError();                            //###########################
                        hDeviceR = CreateFile(
                                            DevicePipeName[1],
                                            GENERIC_WRITE|GENERIC_READ,
                                            FILE_SHARE_READ|FILE_SHARE_WRITE,
                                            NULL,
                                            OPEN_EXISTING,
                                            0, NULL);
                        if(INVALID_HANDLE_VALUE == hDeviceR)
                            ErrorCode = GetLastError();                            //###########################
                        hDeviceW = CreateFile(
                                            DevicePipeName[2],
                                            GENERIC_WRITE|GENERIC_READ,
                                            FILE_SHARE_READ|FILE_SHARE_WRITE,
                                            NULL,
                                            OPEN_EXISTING,
                                            0, NULL);
                        if(INVALID_HANDLE_VALUE == hDeviceW)
                            ErrorCode = GetLastError();                            //###########################
                                iResult = DeviceIoControl(hDeviceRW,
                                IOCTL_DISK_GET_DRIVE_GEOMETRY,
                                NULL, 0,
                                &pdg, sizeof(pdg),
                                &dwBytesTransferred,
                                NULL);
                        if(iResult == 0)
                            ErrorCode = GetLastError();                            //###########################
                            iResult = WriteFile(hDeviceW,
                                                                    SCSI0x12,
                                                                    31,
                                                                    &dwBytesTransferred,
                                                                    NULL);
                        if(iResult == 0)
                            ErrorCode = GetLastError();                            //###########################
                        RWBuffer = (unsigned char *)malloc(512);
                        if(NULL ==  RWBuffer)
                            printf("no memory of buffer");
                            iResult = ReadFile(hDeviceR,
                                                                    RWBuffer,
                                                                    512,
                                                                    &dwBytesTransferred,
                                                                    NULL);
                        if(iResult == 0)
                            ErrorCode = GetLastError();                            //###########################
                        free(pDevData);
                }
                iDevIndex  ;
            }
            else {
                ErrorCode = GetLastError();
                if(ERROR_NO_MORE_ITEMS == ErrorCode)
                    bEnumFinish = TRUE;
            }
        }while(bEnumFinish == FALSE);
    if(hDeviceRW != INVALID_HANDLE_VALUE)
        CloseHandle(hDeviceRW);
    if(hDeviceR != INVALID_HANDLE_VALUE)
        CloseHandle(hDeviceR);
    if(hDeviceW != INVALID_HANDLE_VALUE)
        CloseHandle(hDeviceW);
    SetupDiDestroyDeviceInfoList(hDevInfo);
    return 0;
}
//---------------------------------------------------------------------------    
------
春秋兩不沾
夏 下
日 雨
炎 不
炎 是
正 讀
好 書
眠 天
derrenbol1
中階會員


發表:5
回覆:113
積分:93
註冊:2004-12-09

發送簡訊給我
#9 引用回覆 回覆 發表時間:2005-09-09 19:52:16 IP:210.202.xxx.xxx 未訂閱
To 發呆: 想要對Usb Mass Stroge裝置下CWB啊!您辛苦了; Pipe Name確實指的是USB規格上的PIPE沒錯, 得 視當該裝置設計者所使用的Pipe編號; 我相信你應 該有看RBC文件, 反正符合Mass Stroge中Bulk Only 的裝置一定是1 In 1 Out, 可使用USBview.exe去得 知你電腦中各個USB埠上裝置的資訊及所使用的Pipe 號碼, 不須要用猜的. 該應用程式在WINDDK中找得到 .
發呆
一般會員


發表:5
回覆:8
積分:2
註冊:2005-08-08

發送簡訊給我
#10 引用回覆 回覆 發表時間:2005-09-09 23:46:25 IP:203.67.xxx.xxx 未訂閱
Derrenbol1 大大    不知我這樣的解讀對不對? 利用USBView的方法, 我可以得到Endpoint desc., 那我就可以知道哪個是BULK-IN,哪個是BULK-OUT, 但是,pipe number呢?(Endpoint desc.中沒有這項), 難道是,自己列舉, 假如,EP1是BULK-IN, EP2是BULK-OUT, 所以我的pipe name就會這樣嗎? char *RPipeName="PIPE01"; char *WPipeName="PIPE02"; 如果是這樣,"PIPExx"有大小寫之分嗎?(xx is pipe number)    如果,上述的想法是正確地, 那我是否就可以利用writefile and readfile, 去實現BULK TRANSFER FlOW (CBW --> DATA IN or OUT --> CSW)    另外,在本論壇裡有看到另一個方法, 可以利用APTI的方法去對USB Mass Stroage Device下SCSI command, 不過,我的功力太差,到現在還沒試出來。 對於APTI的方式,有個疑問, Device Handle是要用那種方式取得, 1. SetupDixxx function 2. "\\\\.\\x:" 3. "\\\\.\\PHYSICALDRIVEn" 可否請大大細說一下 感謝
------
春秋兩不沾
夏 下
日 雨
炎 不
炎 是
正 讀
好 書
眠 天
derrenbol1
中階會員


發表:5
回覆:113
積分:93
註冊:2004-12-09

發送簡訊給我
#11 引用回覆 回覆 發表時間:2005-09-10 01:34:30 IP:210.202.xxx.xxx 未訂閱
To 發呆 :      請參閱USB1.1 or 2.0第九章, 關於Endpoint Descriptor各欄位的說明, 其中Endpoint Number 的第7個位元即在說明此Endpoint是IN or OUT,  而後七個位元即是它的號碼.   我記得我開Endpoint Pipe時是用大寫, 大小寫 限制我就不太清楚了.   若是透過ReadFile及WriteFile的話, 那就輪不 不到你去下CBW或是CSW, 那個應該由MassStorage 的驅動程式去下.    USB驅動程式這一層, 小弟就無法幫忙了, 小弟 是寫USB實際裝置上的軔體, 所以我知道你所寫的 CBW及CSW是啥碗糕; 在微軟上只要對我的裝置可 讀寫, 那我就算下班了. 
發呆
一般會員


發表:5
回覆:8
積分:2
註冊:2005-08-08

發送簡訊給我
#12 引用回覆 回覆 發表時間:2005-09-10 09:52:50 IP:203.70.xxx.xxx 未訂閱
Derrenbol1 大大 感謝您的解說, 不知為什麼腦筋一時短路, 一直把那個欄位當做address, 忘了內含有endpoint number在bit0~3, 好在大大的解說,要不然... 可能又會呆很久囉! 另外,我又有一個疑問了, 您指的read, write是指 可以讀寫裝置中sector的資料嗎? 可是我都已經開到了endpoint handle了, 卻只能做read, write, 感覺怪怪地。 另外,再來再請看看我的解讀對不對, 一開始我會使用SetupDixxx得到DevicePath, 假設 DevicePath="\\\\.\\usb#vid_xxxx&pid_xxxx#_#{GUID}" EP1 is BULK-IN EP2 is BULK-OUT 那我的 Pipe1Path="\\\\.\\usb#vid_xxxx&pid_xxxx#_#{GUID}\\PIPE01" Pipe2Path="\\\\.\\usb#vid_xxxx&pid_xxxx#_#{GUID}\\PIPE02" 那就可以用 hDevice = CreateFile(DevicePth,...)去做DeviceIoControl(hDevice,...) hDeviceR = CreateFile(Pipe1Pth,...)去做Readfile(hDeviceR,...) hDeviceW = CreateFile(Pipe2Pth,...)去做Writefile(hDeviceW,...) 是這樣的嗎? (不好意思,會這樣問並不是沒有去試著做, 而是,我這樣做都會一直得到ErrorCode=50, 所以,想問看看這樣的想法對嗎?) 新手上路 總是疑問
------
春秋兩不沾
夏 下
日 雨
炎 不
炎 是
正 讀
好 書
眠 天
derrenbol1
中階會員


發表:5
回覆:113
積分:93
註冊:2004-12-09

發送簡訊給我
#13 引用回覆 回覆 發表時間:2005-09-12 13:44:39 IP:210.202.xxx.xxx 未訂閱
To 發呆 :      歹勢, 最近有點忙; 用ReadFile及WriteFile想直接對"Sector" 做讀寫, 我想這是很難的; 如果這種都可以的話, 那這樣子對系 統不太好吧? , 而且
發呆
一般會員


發表:5
回覆:8
積分:2
註冊:2005-08-08

發送簡訊給我
#14 引用回覆 回覆 發表時間:2005-09-12 18:04:45 IP:211.21.xxx.xxx 未訂閱
感謝 derrenbol 大大的回應    雖然,我還沒找到實現BULK TRANSFER FlOW的方法, (CBW --> DATA IN or OUT --> CSW) 也搞不好根本就不可能單用api及win內建的USB driver來實現!?    不過,我己經試出如何使用DeviceIoControl(...) 配合參數IOCTL_SCSI_PASS_THROUGH_DIRECT 或是參數IOCTL_SCSI_PASS_THROUGH (兩個參數都可以做的到,擇一用就行了) 去下SCSI command or vendor command給device。    我會繼續朝這個方向下手, 等有空再來找實現BULK TRANSFER FlOW的方法。 另外,如果要設定
------
春秋兩不沾
夏 下
日 雨
炎 不
炎 是
正 讀
好 書
眠 天
harrypp
中階會員


發表:7
回覆:124
積分:61
註冊:2006-08-31

發送簡訊給我
#15 引用回覆 回覆 發表時間:2006-08-31 13:05:29 IP:210.202.xxx.xxx 未訂閱
用DeviceIOControl可以實現!!
不過你得先去找SCSI command的規格書,每個cmd有每個cmd的格式,
比如Read 是 cmd 28, write 是cmd 2A,
填入下面SCSI_PASS_THROUGH的CDB欄位,
再使用DeviceIoControl並用IOCTL_SCSI_PASS_THROUGH即可,

typedef struct _SCSI_PASS_THROUGH {
USHORT Length;
UCHAR ScsiStatus;
UCHAR PathId;
UCHAR TargetId;
UCHAR Lun;
UCHAR CdbLength;
UCHAR SenseInfoLength;
UCHAR DataIn=SCSI_IOCTL_DATA_IN;
ULONG DataTransferLength;
ULONG TimeOutValue;
ULONG_PTR DataBufferOffset;
ULONG SenseInfoOffset;
UCHAR Cdb[16]="\x28\0\A\A\A\A\0\B\B\0\0\0\0";
}SCSI_PASS_THROUGH, *PSCSI_PASS_THROUGH;

AAAA :LBA位置
BB:transfer長度


===================引 用 文 章===================
感謝 derrenbol 大大的回應 雖然,我還沒找到實現BULK TRANSFER FlOW的方法, (CBW --> DATA IN or OUT --> CSW) 也搞不好根本就不可能單用api及win內建的USB driver來實現!? 不過,我己經試出如何使用DeviceIoControl(...) 配合參數IOCTL_SCSI_PASS_THROUGH_DIRECT 或是參數IOCTL_SCSI_PASS_THROUGH (兩個參數都可以做的到,擇一用就行了) 去下SCSI command or vendor command給device。 我會繼續朝這個方向下手, 等有空再來找實現BULK TRANSFER FlOW的方法。 另外,如果要設定sector的位置, 可用SetFilePointer()去做。 再配合ReadFile & WriteFile就可以讀寫device任一個sector。
系統時間:2024-04-20 4:31:27
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!