I'm stuck and I need some help if anyone is willing.

I have a USB Missile Launcher that I'm trying to access in Delphi via 
HID. My goal was to create the application without using any third party 
software. I can access the launcher without any problems, getting the 
VID and PID data. This is where I get stuck as unfortunately I can't 
seem to get the Windows.WriteFile method to work. When I catch the error 
raised, it comes back as an error 87.

 From what I've read up on, the launcher requires two initiator packets 
to device endpoint 1, then a bronto 64 byte packet to endpoint 0. I'm 
still not sure how to implement this, as I've still been working on 
merely getting a message successfully sent to the thing.

I've been working on this for close to a year now, and I know it's a big 
ask to have anyone go over the code and provide any insight. If you 
could help me out I'd give you my kidney. I've removed as much of the 
code that doesn't directly relate to the problem as I could.

{----------------------------------- Summary of the Accessed Data 
Structures >>}
{
Human Interface Device (HID): This is an external device plugged into the
  system. The application is trying to connect with a USB device (a USB 
Missile
  Launcher).

Device Interface Class (DIC): This is a class used to categorise various 
HID's
  attached to the system. An example of this is the 
'GUID_DEVINTERFACE_MOUSE'
  class, used to encompass mouse devices.

Device Information Set (DIS): This is a list of Device Information Elements
  (DIE) for devices belonging to a DIC. Not all DIE's may be present in 
a DIS
  as when obtaining the DIS, filters can be set to omit certain elements.

Device Information Element (DIE): Each element contains a list of Device
  Interfaces (DI's) associated with the Human Interface Device (HID) 
that the
  element refers to.

Device Interface (DI): Based on the 'DeviceInterface' object type, this is a
  record of basic data pertaining to a HID. The 'ReservedXX' fields are 
not used
  in this application.

Device Details (DD): Based on the 'DeviceDetails' object type, this is a 
record
  of data pertaining to a HID. The 'Location' field of this record is 
used to
  directly speak with the HID in question.
}
{---------------------------------------------------------------------- 
code >>}


{declare the imported 'HidD_GetHidGuid' method used for getting a GUID that
  points to the DIC for all HID's}
procedure GetHIDGUID(var HIDGUID: TGUID) stdcall; external 'HID.dll' name
  'HidD_GetHidGuid';

{declare the imported 'SetupDiGetClassDevsA' method used for getting the
  pointer of the DIS for all HID's corresponding to the 'Flag' parameter}
function GetHIDDIS(var HIDGUID: TGUID; Enumerator: PChar; Parent: HWND;
  Filters: LongWord): Pointer; stdcall; external 'SetupAPI.dll'
  name 'SetupDiGetClassDevsA';

{declare the imported 'SetupDiEnumDeviceInterfaces' method used for 
enumerating
  through the DI's within the DIS}
function GetDI(DeviceInformationSet: Pointer; DeviceInformation: Pointer;
  var HIDGUID: TGUID; Index: LongWord; var DeviceInterface: 
TDeviceInterface):
  Boolean; stdcall; external 'SetupAPI.dll' name 
'SetupDiEnumDeviceInterfaces';

{declare the imported 'SetupDiGetDeviceInterfaceDetailA' method used for
  getting DD's on a DI}
function GetDIDetails(DeviceInformationSet: Pointer; DeviceInterface:
  PDeviceInterface; DeviceInterfaceDetails: Pointer; BufferSize: 
LongWord; var
  RequiredSize: LongWord; DataSummary: PDeviceInterface): Boolean; stdcall;
  external 'SetupAPI.dll' name 'SetupDiGetDeviceInterfaceDetailA';

{?}
function GetHIDAttributes(DeviceDetailsLocation: LongWord; var 
DeviceAttributes:
  TDeviceAttributes): Boolean; stdcall; external 'HID.dll' name
  'HidD_GetAttributes';

{?}
function GetHIDProductID(HidDeviceObject: THandle; Buffer: PWideChar;
  BufferLength: Integer): Boolean; stdcall; external 'HID.dll' name
  'HidD_GetProductString';

var
  Buffer: array [0..255] of WideChar;
  DataSummary: TDeviceInterface;
  DeviceAttributes: TDeviceAttributes;
  DeviceDetails: PDeviceDetails;
  DeviceDetailsFound: Boolean;
  DeviceInformationSet: Pointer;
  DeviceInterface: TDeviceInterface;
  DeviceInterfaceFound: Boolean;
  HIDFileHandle: THandle;
  HIDGUID: TGUID;
  Index: Integer;
  RequiredSize: LongWord;
  TemporaryString: String;

  Increment: Integer;
  Report: array[0..7] of Byte;
  BytesWritten: Cardinal;

begin
  {try the following}
  try
    {get the GUID pointing to the DIC for all HID's}
    GetHIDGUID(HIDGUID);
  end;
  {get the DIS for all 'active' HID's}
  DeviceInformationSet := GetHIDDIS(HIDGUID, nil, 0, FILTER_PRESENT or
    FILTER_DEVICEINTERFACE);
  {set the byte size for the DI type and reset the index value}
  DeviceInterface.ByteSize := SizeOf(TDeviceInterface);
  Index := -1;
  {repeat the following}
  repeat
    {increment the index value}
    Index := Index + 1;
    {try to locate the DI within the DIS that corresponds to the index 
value}
    DeviceInterfaceFound := GetDI(DeviceInformationSet, nil, HIDGUID, Index,
      DeviceInterface);
    {if a DI was found, continue}
    if DeviceInterfaceFound = True then
    begin
      {set the data summary's default values}
      DataSummary.ByteSize := SizeOf(TDeviceInterface);
      RequiredSize := 0;
      {attempt to get the required byte size for the DD}
      GetDIDetails(DeviceInformationSet, @DeviceInterface, nil, 0, 
RequiredSize,
        @DataSummary);
      {if the required byte size is passed back, continue}
      if (RequiredSize <> 0) and (GetLastError = 
ERROR_INSUFFICIENT_BUFFER) then
      begin
        {allocate memory for the DD}
        DeviceDetails := AllocMem(RequiredSize);
        DeviceDetails.ByteSize := SizeOf(TDeviceDetails);
        {get the DD for the DI}
        DeviceDetailsFound := GetDIDetails(DeviceInformationSet,
          @DeviceInterface, DeviceDetails, RequiredSize, RequiredSize,
          @DataSummary);
        {if the DD was obtained, continue}
        if DeviceDetailsFound = True then
        begin
          {open a handle to the current device being worked on}
          HIDFileHandle := CreateFile(DeviceDetails.Location,
            GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or 
FILE_SHARE_WRITE,
            nil, OPEN_EXISTING, 0, 0);
          {the the handle opened successfully, continue}
          if HIDFileHandle <> INVALID_HANDLE_VALUE then
          begin
            {get the device name and show it to the user}
            FillChar(Buffer, SizeOf(Buffer), 0);
            GetHIDProductID(HidFileHandle, Buffer, SizeOf(Buffer));
            {get the device attributes}
            DeviceAttributes.ByteSize := SizeOf(TDeviceAttributes);
            GetHIDAttributes(HIDFileHandle, DeviceAttributes);
            {if the device is the one we are looking for, continue}
            if (DeviceAttributes.VendorID = 4400) and
              (DeviceAttributes.ProductID = 514) then
            begin

              {?}
              for Increment := 0 to 7 do
                Report[Increment] := Byte(00);
              {?}
              Report[0] := Byte(85);
              Report[1] := Byte(83);
              Report[2] := Byte(66);
              Report[3] := Byte(67);
              Report[4] := Byte(00);
              Report[5] := Byte(00);
              Report[6] := Byte(04);
              Report[7] := Byte(00);
              {?}
              if Windows.WriteFile(HIDFileHandle, Report, Length(Report),
                BytesWritten, nil) = True then Self.Caption := 'Sent Data';

            end;
            {close the current device handle}
            CloseHandle(HIDFileHandle);
          end;
        end;
        {destroy the DD in memory}
        FreeMem(DeviceDetails);
      end;
    end;
  {until no more DI's are found}
  until DeviceInterfaceFound = False;
end;
_______________________________________________
Delphi mailing list -> Delphi@elists.org
http://lists.elists.org/cgi-bin/mailman/listinfo/delphi

Reply via email to