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