2011-11-08 31 views
5

Tôi đang sử dụng Delphi XE2 và cố gắng nâng cấp dll usb của chúng tôi lên 64 bit. Chúng tôi đang sử dụng các thiết bị JVCL SetupAPI và Hid. Tất cả các công trình hoàn hảo bằng cách sử dụng trình biên dịch 32 bit và có thể nhìn thấy thiết bị HID kèm theo của tôi. Tôi chuyển sang 64 bit và tôi không thể nhìn thấy bất kỳ thiết bị HID nào mà tôi biết được đính kèm.Liệt kê các thiết bị USB HID bằng SetupAPI trong ứng dụng 64 bit

Tôi đã bắt gặp mọi người đề cập đến sự cần thiết phải thay đổi kích thước một số cấu trúc dữ liệu khác nhau cho 64 bit (xem https://forums.embarcadero.com/thread.jspa?messageID=408473#408473) và điều này đã giúp nhưng tôi bây giờ chính thức stumped.

Hiện tại mã của tôi đang trả về 0 byte được đọc từ hàm SetupDiGetDeviceInterfaceDetail. Các nhận xét ra SizeOf() đã làm việc cho 32 bit nhưng không cho 64 bit.

Mọi trợ giúp sẽ được đánh giá cao.

repeat 
    TmpDeviceInterfaceData.cbSize := SizeOf(TSPDeviceInterfaceData); 
    TmpDeviceInterfaceData.cbSize := 32; // SizeOf(TmpDeviceInterfaceData); 
    TmpSuccess := SetupDiEnumDeviceInterfaces(TmpDevInfo, nil, TmpDevHidGuid, TmpDevn, TmpDeviceInterfaceData); 
    if TmpSuccess then 
    begin 
    TmpDevData.cbSize := 32; //SizeOf(TmpDevData); 
    showmessage(inttostr(tmpdevdata.cbsize)); 
    TmpBytesReturned := 0; 
    SetupDiGetDeviceInterfaceDetail(TmpDevInfo, @TmpDeviceInterfaceData, nil, 0, TmpBytesReturned, @TmpDevData); 
    showmessage('bytes returned = ' + inttostr(TmpBytesReturned)); 
    if (TmpBytesReturned <> 0) and (GetLastError = ERROR_INSUFFICIENT_BUFFER) then 
    begin 
     // showmessage('hello'); 
     TmpFunctionClassDeviceData := AllocMem(TmpBytesReturned); 
     TmpFunctionClassDeviceData.cbSize := sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A); 

     TmpFunctionClassDeviceData.cbSize := 8; 
     // showmessage(inttostr(TmpFunctionClassDeviceData.cbSize)); 
     if SetupDiGetDeviceInterfaceDetail(TmpDevInfo, @TmpDeviceInterfaceData, TmpFunctionClassDeviceData, TmpBytesReturned, TmpBytesReturned, @TmpDevData) then 
     begin 
     // showmessage('here'); 
     try 
      begin 
      //try to obtain PID and VID information about the HID devices 
      TmpDeviceHandle := CreateFile(@TmpFunctionClassDeviceData.DevicePath, 
          GENERIC_READ OR GENERIC_WRITE, 
          FILE_SHARE_READ OR FILE_SHARE_WRITE, 
          NIL, OPEN_EXISTING, 0 , 0); 
      TmpAttributes.Size := Sizeof(TmpAttributes); 
      HidD_GetAttributes(TmpDeviceHandle, TmpAttributes); 
      If (vid = TmpAttributes.VendorID) then 
      begin 
      PIDlistStr := PIDlistStr + Inttostr(TmpAttributes.ProductID) + ','; 
      end ; 


      if TmpDeviceHandle <> INVALID_HANDLE_VALUE then 
      begin 
      CloseHandle(TmpDeviceHandle); 
      TmpAttributes.ProductID := 0; 
      TmpAttributes.VendorID := 0; 
      end; 
      TmpDeviceHandle := INVALID_HANDLE_VALUE; 
      end 
     except 
      // ignore device if unreadable 
     end; 
     Inc(TmpDevn); 
     end 
    else 
     showmessage('error in SetupDiGetDeviceInterfaceDetails'); 
     FreeMem(TmpFunctionClassDeviceData); 
    end; 
    end; 
until not TmpSuccess; 

Trả lời

0

Các thay đổi hiện có trong JVCL, vui lòng sử dụng nội dung SVN mới nhất.

Về cơ bản, cần phải sửa SetupApi để nó sử dụng "phụ" trong x64 để căn chỉnh.

Điều này đã được kiểm tra và hoạt động tốt ở đây.

0

Vì vậy, sau nhiều khó khăn, tôi đã làm việc này. Việc sửa chữa cuối cùng không quá phức tạp, mặc dù tôi đã phải nghiên cứu kỹ vào đơn vị JVCL SetupApi và thay đổi một số loại biến của cấu trúc.

repeat 
    TmpDeviceInterfaceData.cbSize := SizeOf(TSPDeviceInterfaceData); 
    // showmessage('TSPDeviceInterfaceData: ' + inttostr(SizeOf(TSPDeviceInterfaceData))); 
    TmpSuccess := SetupDiEnumDeviceInterfaces(TmpDevInfo, nil, TmpDevHidGuid, TmpDevn, TmpDeviceInterfaceData); 
    if TmpSuccess then 
    begin 
    TmpDevData.cbSize := SizeOf(TmpDevData); 
    // showmessage('TmpDevData: ' + inttostr(tmpdevdata.cbsize)); 
    TmpBytesReturned := 0; 
    SetupDiGetDeviceInterfaceDetail(TmpDevInfo, @TmpDeviceInterfaceData, nil, 0, TmpBytesReturned, @TmpDevData); 
    //showmessage('bytes returned = ' + inttostr(TmpBytesReturned)); // = 170 in 32 bit app 
    inc(i); 
    if (TmpBytesReturned <> 0) and (GetLastError = ERROR_INSUFFICIENT_BUFFER) then 
    begin 
     // showmessage('i did this ' + inttostr(i) + ' times'); 
     TmpFunctionClassDeviceData := AllocMem(TmpBytesReturned); 

     {$ifdef CPUX64} 
     TmpFunctionClassDeviceData.cbSize := 8; 
     // showmessage('64 bit compiler used'); 
     {$else} 
     TmpFunctionClassDeviceData.cbSize := 6; 
     // showmessage('32 bit compiler used'); 
     {$endif} 

     // showmessage('TmpFunctionClassDeviceData:' + inttostr(sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A))); 
     if SetupDiGetDeviceInterfaceDetail(TmpDevInfo, @TmpDeviceInterfaceData, TmpFunctionClassDeviceData, TmpBytesReturned, TmpBytesReturned, @TmpDevData) then 
     begin 
     try 
      begin 
      //try to obtain PID and VID information about the HID devices 

      s := ''; 
      for i := 0 to 999 do 
      begin 
      s := s + TmpFunctionClassDeviceData.DevicePath[i]; 
      end; 

      TmpDeviceHandle := CreateFile(PChar(s), 
          GENERIC_READ OR GENERIC_WRITE, 
          FILE_SHARE_READ OR FILE_SHARE_WRITE, 
          0, OPEN_EXISTING, 0 , 0); 

      TmpAttributes.Size := Sizeof(TmpAttributes); 
      // showmessage('TmpAttributes: ' + inttostr(Sizeof(TmpAttributes))); 

      HidD_GetAttributes(TmpDeviceHandle, TmpAttributes); 

      // showmessage(inttostr(TmpAttributes.VendorID) + ' ; ' + inttostr(TmpAttributes.ProductID)); 

      If (vid = TmpAttributes.VendorID) then 
      begin 
      PIDlistStr := PIDlistStr + Inttostr(TmpAttributes.ProductID) + ','; 
      end ; 

      if TmpDeviceHandle <> INVALID_HANDLE_VALUE then 
      begin 
      CloseHandle(TmpDeviceHandle); 
      TmpAttributes.ProductID := 0; 
      TmpAttributes.VendorID := 0; 
      end; 
      TmpDeviceHandle := INVALID_HANDLE_VALUE; 
      end 
     except 
      // ignore device if unreadable 
     end; 
     Inc(TmpDevn); 
     end; 
    //else 
     //showmessage('bob ' + inttostr(GetLastError)); 
     FreeMem(TmpFunctionClassDeviceData); 
    end; 
    end; 
until not TmpSuccess; 

Đối với những thay đổi SetupAPI.pas xem mục theo dõi vấn đề Jedi tôi ở đây: http://issuetracker.delphi-jedi.org/view.php?id=5706

Nếu bất cứ ai có thể cho tôi biết tại sao DevicePath cần phải được sao chép một cách rõ ràng trong một chuỗi địa phương trước khi được thông qua để CreateFile , hoặc tại sao tôi không thể sử dụng SizeOf cho TmpFunctionClassDeviceData.cbSize, tôi sẽ có nhiều nghĩa vụ.

+0

> tại sao DevicePath cần phải được sao chép một cách rõ ràng như ms nói ở đây: http://msdn.microsoft.com/en-us/library/windows/hardware/ff552343%28v=vs.85%29 .aspx > DevicePath > Chuỗi bị chấm dứt NULL chứa đường dẫn giao diện thiết bị. Đường dẫn này có thể được chuyển tới các hàm Win32 như CreateFile. szDevicePath: = PChar (@ TmpFunctionClassDeviceData.DevicePath [0]); sử dụng giá trị đó để chuyển đến CreateFile. –

Các vấn đề liên quan