Solution was here: File Buffering https://msdn.microsoft.com/en-us/library/windows/desktop/cc644950%28v=vs.85%29.aspx
Working code:
#include "stdafx.h"
#include "assert.h"
#include <iostream>
#include <Windows.h>
#include <comutil.h>
using namespace std;
namespace{
unsigned long tempBytesWritten = 0;
HANDLE m_fileHandle;
char m_pszFilename[_MAX_PATH] = "";
// Create a temporary file for benchmark
int createFile()
{
WCHAR tempPath[MAX_PATH];
GetTempPath(_countof(tempPath), tempPath);
_bstr_t p(tempPath);
const char* c = p;
strcpy(m_pszFilename, c);
strcat(m_pszFilename, "testRawFile.raw");
cout << "Writing to " << m_pszFilename << endl;
m_fileHandle = CreateFileA(
m_pszFilename,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH,
NULL);
if (m_fileHandle == INVALID_HANDLE_VALUE)
{
assert( false );
}
return 0;
}
}
DWORD DetectSectorSize( WCHAR * devName, PSTORAGE_ACCESS_ALIGNMENT_DESCRIPTOR pAlignmentDescriptor)
{
DWORD Bytes = 0;
BOOL bReturn = FALSE;
DWORD Error = NO_ERROR;
STORAGE_PROPERTY_QUERY Query;
ZeroMemory(&Query, sizeof(Query));
HANDLE hFile = CreateFileW( devName,
STANDARD_RIGHTS_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile==INVALID_HANDLE_VALUE) {
wprintf(L" hFile==INVALID_HANDLE_VALUE. GetLastError() returns %lu.n", Error=GetLastError());
return Error;
}
Query.QueryType = PropertyStandardQuery;
Query.PropertyId = StorageAccessAlignmentProperty;
bReturn = DeviceIoControl( hFile,
IOCTL_STORAGE_QUERY_PROPERTY,
&Query,
sizeof(STORAGE_PROPERTY_QUERY),
pAlignmentDescriptor,
sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR),
&Bytes,
NULL);
if (bReturn == FALSE) {
wprintf(L" bReturn==FALSE. GetLastError() returns %lu.n", Error=GetLastError());
}
CloseHandle(hFile);
return Error;
}
int main()
{
unsigned int dataSize = 2000;
DWORD Error = NO_ERROR;
STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR Alignment = {0};
// WCHAR szDisk[] = L"\\.\PhysicalDrive0";
WCHAR szDisk[] = L"\\.\C:";
Error = DetectSectorSize(szDisk, &Alignment);
if (Error) {
wprintf(L"Error %lu encountered while querying alignment.n", Error);
return Error;
}
wprintf(L"Disk %s Propertiesn", (WCHAR*) szDisk);
if (Alignment.BytesPerLogicalSector < Alignment.BytesPerPhysicalSector) {
wprintf(L" Emulated sector size is %lu bytes.n", Alignment.BytesPerLogicalSector);
}
wprintf(L" Physical sector size is %lu bytes.n", Alignment.BytesPerPhysicalSector);
dataSize = ((unsigned int)(dataSize + Alignment.BytesPerPhysicalSector - 1)/Alignment.BytesPerPhysicalSector) * Alignment.BytesPerPhysicalSector;
// Allocate buffer for file
unsigned char *buffer = new unsigned char[dataSize];
// Create file to write to
if ( createFile() != 0 )
{
printf("There was error creating the files... press Enter to exit.");
getchar();
return -1;
}
const BOOL bSuccess = WriteFile(m_fileHandle, buffer, dataSize, &tempBytesWritten, NULL );
if (!bSuccess)
{
cout << "Write failed with error " << GetLastError() << endl;
}
// clean up and remove file
CloseHandle(m_fileHandle);
wchar_t wtext[_MAX_PATH];
mbstowcs(wtext, m_pszFilename, strlen(m_pszFilename)+1);
DeleteFile(wtext);
return 0;
}
- Remove From My Forums
-
Question
-
Windows XP SP3
Visual Studio 2008
.Net 3.5When accessing an HID, I am receiving the error code 87 (The parameter is incorrect) when calling WriteFile.
I am able to successfully open a handle to the device and read from it.Here are the relevant portions of the code that I am using:
IntPtr dHandle = CreateFile(DevicePath, GENERIC_READ | GENERIC_WRITE, 0, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero); [DllImport("kernel32.dll", SetLastError = true)] public static extern bool WriteFile(IntPtr hFile, ref byte[] lpBuffer, uint nNumberOfBytesToWrite, ref uint lpNumberOfBytesWritten, IntPtr ipOverlapped); uint bytesWritten = 0; byte[] buffer = new byte[] { 0x5a, 0x0a }; WriteFile(dHandle, ref buffer, outputReportLength, ref bytesWritten, IntPtr.Zero);
The output report length specified by the call to HidP_GetCaps is 2.
If I change the DevicePath specified in CreateFile to a file, the file is written to.
This is leading me to believe that the byte array being sent in WriteFile is the parameter being rejected.
Many of the examples I have seen online pass byte arrays to the function.I am unsure as to what should be passed in.
The ddk documentation discusses using an output report, but the examples I have seen of those are byte arrays as well.
I have tried this on two different systems with two different usb devices.
Answers
-
Ah, one of those devices.
The arguments you pass in CreateFile seem OK, I have an application which communicates with a HID microchip programmer and I use exactly the same arguments. My WriteFile routine is no different to yours — other than mine works. I guess the only thing it
can be is the format of the packet you are sending to the device.Are you certain you have a valid handle?
K
-
Marked as answer by
Tuesday, October 12, 2010 8:01 AM
-
Marked as answer by
-
Try using HHD software’s USB monitor to find out what packets are being sent/received by application. Here’s a link…
http://www.hhdsoftware.com/usb-monitor
K
Thank you for supplying the link to the monitor app. I was able to determine what was being sent to the scale using it.
It turns out that the 87 error code was resulting from an incorrect report id.
The report id the scale expected was 4.
-
Marked as answer by
Guang-Ming Bian — MSFT
Tuesday, October 12, 2010 8:01 AM
-
Marked as answer by
WriteFile() Win32 call with input buffer size = 512 Fails., when i try to write to the disk that has bytes per sector = 4096.[3 TB disk]. Same WriteFile with input buffer size = 4096 works fine.,
Can any body explain this behavior.
svick
235k50 gold badges384 silver badges513 bronze badges
asked Mar 5, 2013 at 5:18
4
For low-level I/O operations, your buffer must be an integer multiple of the sector size. In your case, k*4096
. Most likely your hard drive wasn’t manufactured a long time ago. They are called «Advanced Format» and have 4096 bytes per sector. Mine doesn’t mind if I set it to 512 because it’s old. Try using the GetDiskFreeSpace
function to learn more about your hard-drive.
answered Mar 9, 2013 at 7:10
ValentinValentin
6541 gold badge7 silver badges15 bronze badges
Я работаю над программой, которая пишет на устройство HID, и получаю ошибку 87, Недопустимый параметр в функции WriteFile. Я получил функции от USB Complete Яна Аксельсона, поэтому я не уверен, почему я получаю ошибку. Я использую это, чтобы найти мое устройство:
private void USBInit()
{
IntPtr deviceInfoSet;
Int32 memberIndex = 0;
SP_DEVICE_INTERFACE_DATA MyDeviceInterfaceData = new SP_DEVICE_INTERFACE_DATA();
Int32 bufferSize = 0;
IntPtr detailDataBuffer;
Boolean success = false;
deviceFound = false;
HidD_GetHidGuid(ref hidGuid); // Get the GUID
deviceInfoSet = SetupDiGetClassDevs // Get pointer to a device info set
(ref hidGuid,
IntPtr.Zero,
IntPtr.Zero,
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
do
{
MyDeviceInterfaceData.cbSize = Marshal.SizeOf(MyDeviceInterfaceData); // Identify Device Interface
success = SetupDiEnumDeviceInterfaces
(deviceInfoSet,
IntPtr.Zero,
ref hidGuid,
memberIndex,
ref MyDeviceInterfaceData);
success = SetupDiGetDeviceInterfaceDetail // Request Structure with Device Path Name
(deviceInfoSet,
ref MyDeviceInterfaceData,
IntPtr.Zero,
0,
ref bufferSize,
IntPtr.Zero);
detailDataBuffer = Marshal.AllocHGlobal(bufferSize);
Marshal.WriteInt32(detailDataBuffer, (IntPtr.Size == 4) ? (4 + Marshal.SystemDefaultCharSize) : 8);
success = SetupDiGetDeviceInterfaceDetail
(deviceInfoSet,
ref MyDeviceInterfaceData,
detailDataBuffer,
bufferSize,
ref bufferSize,
IntPtr.Zero);
IntPtr pDevicePathName = new IntPtr(detailDataBuffer.ToInt32() + 4);
devicePathName = Marshal.PtrToStringAuto(pDevicePathName);
Marshal.FreeHGlobal(detailDataBuffer);
/* Request Communications Handle */
deviceHandle = CreateFile
(devicePathName,
(GENERIC_WRITE | GENERIC_READ),
FILE_SHARE_READ | FILE_SHARE_WRITE,
IntPtr.Zero,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
0);
/* Get Vendor ID and Product ID */
DeviceAttributes.Size = Marshal.SizeOf(DeviceAttributes);
success = HidD_GetAttributes(deviceHandle, ref DeviceAttributes);
// Compare Vendor ID and Product ID.
if ((DeviceAttributes.VendorID == myVendorID) && (DeviceAttributes.ProductID == myProductID))
{
MessageBoxResult res = System.Windows.MessageBox.Show("Device Found", "K-IX", MessageBoxButton.OK);
deviceFound = true;
/* Get pointer to capabilities */
success = HidD_GetPreparsedData(deviceHandle, ref preparsedData);
/* Get Device Capabilities */
Int32 result = 0;
result = HidP_GetCaps(preparsedData, ref Capabilities);
return;
}
else
{
// Not my device
memberIndex++;
deviceHandle.Close();
if (memberIndex == 128)
{ break; }
}
} while (!deviceFound);
}
И вот код, который я использую, чтобы попытаться отправить на устройство:
private void SendUSB()
{
Int32 numberOfBytesWritten = 0;
Byte[] outputReportBuffer = null;
Boolean success;
Boolean success2;
// Set size of the Output report buffer.
Array.Resize(ref outputReportBuffer, Capabilities.InputReportByteLength);
// Store Report ID in first byte of header.
outputReportBuffer[0] = 0;
// Store report data following the Report ID.
outputReportBuffer[1] = 0x01;
//outputReportBuffer[2] = 0x02;
// outputReportBuffer[3] = 0x03;
// Send Report
success = WriteFile
(deviceHandle,
outputReportBuffer,
outputReportBuffer.Length,
ref numberOfBytesWritten,
IntPtr.Zero);
if (!success)
{
Int32 lastError = Marshal.GetLastWin32Error();
}
success2 = HidD_FreePreparsedData(preparsedData);
}
Я подтвердил, что ожидаемая длина моего отчета для устройства равна 2, но я не уверен, куда идти, поскольку USB и HID программирование являются новыми для меня.
Topic: Sending report to a HID-dev via WriteFile failed with 87 errorcode (Read 19238 times)
Hi,
I’m a new to USB/HID development.
I need to interact with a HID-device.
I’ve followed the way decribed in «USB Complete» book (ch.11) for finding my device and getting a handler for him.
The handler is good as I can use it with HidP_GetCaps function.
But when I try to send some bytes with calling WriteFile to my device I get 87 error (parameter is incorrect).
Frankly I don’t fully understand all this concepts of report id/report types/pipes/collections etc. But I used a sniffer tool to get interaction log with my device (when it’s used from some proprietary software). This tool is BusDog. I also tried USB Monitor (Device Monitoring Studio) but it’s more complex.
I can see in the BusDog’s log the following bytes when the device is used from proprietary software:
0b 04… and some vendor specific payload
Then tried to send exactly such bytes from my program:
var bytes = new byte[] { 0x0b, 0x04, 0x2f, 0x7a, 0x77, 0x0d, 0, 0 };
bool success = NativeMethods.WriteFile(m_hDevice, bytes,
bytes.Length,
ref numberOfBytesWritten,
IntPtr.Zero);
I tried adding 0x00 byte at the begging.
I tried allocate 64-bytes array. Tried to get OutputReportByteLength from HidP_GetCaps (it equals .
But in all cases WriteFile fails with 87 error.
Any ideas?
update: I also tried allocate 65 byte length buffer and first zero.
« Last Edit: December 17, 2010, 12:07:00 pm by Shrike »
Logged
What is OutputReportByteLength? How about FeatureReportByteLength? (It might be a Feature report.) The WriteFile buffer definitely needs a zero or other report ID in the first byte.
Jan
Logged
FeatureReportByteLength=8
OutputReportByteLength=8
InputReportByteLength=8
Usage=1
UsagePage=64K
But inspite of GetCaps reports OutputReportByteLength=8 in sniffer I can see a report of 64 byte length.
I try both 8+1 (first zero) and 64+1 (first zero)
var data = new byte[65];
var bytes = new byte[] { 0, 0x0b, 0x04, 0x2f, 0x7a, 0x77, 0x0d, 0, 0 };
Array.Copy(bytes, data, bytes.Length);
Int32 numberOfBytesWritten = 0;
WriteFile(m_hDevice, data, data.Length, ref numberOfBytesWritten, IntPtr.Zero);
How to find out required report id for sure? I suspect BusDog tool to not show it.
UPDATE: here’s the BusDog tool — http://code.google.com/p/busdog/
UPDATE2: I’ve attached HID descriptor
[attachment deleted by admin]
« Last Edit: December 17, 2010, 02:21:36 pm by Shrike »
Logged
The report descriptor you posted shows 28 report IDs. Report ID zero is used only by devices that have at most one of each report type (Input, Output, Feature).
To send a report to your device, pick a report ID and send that report’s quantity of data. For example, Output Report ID 2 has 7 bytes, so you would send 02h followed by seven data bytes.
Make the WriteFile buffer = the largest report size + 1.
Jan
Logged
Jan, thanks for your help!
But I can’t get the point why I’m getting «parameter is incorrect» from WriteFile while I’m sending exactly the same sequence of data as I catch in the sniffer.
In BusDog tool (sniffer) I catch such report data: 0x0b, 0x04, 0x2f, 0x7a, 0x77, 0x0d. Ok, the first byte is report id = 0x0b. There’s such report type in HID descriptor I attached ealier. Then the rest bytes is payload. In the sniffer I can see sending of 64 bytes, but HID descriptor for 0x0b report type says «report size=8, report count 63».
Actualy the device I’m trying to work with is a custom solution (it’s a device with rs232 interface connected via custom controller which emulates HID interfaces to the OS), I just need to send them some commands and not very care about its descriptors (if it’s not required to work with it of cause!).
I’m calling WriteFile with the showed above sequence in the buffer of size 64 and get «parameter is incorrent» without touching the bus (there’s no any activity in the sniffer I mean).
In another sniffer (HHD Software Device Monitoring Studio) I catched more info with «Packet view» tool. The command I see in BusDog («/zw») is sending to «USB_FUNCTION_BULK_OR_INTERUPT_TRANSFER» function, but before I can see other output packets with function «USB_FUNCTION_CLASS_INTERFACE». I’ve attached log with all data.
Should I do something to reproduce these comunications with function «USB_FUNCTION_CLASS_INTERFACE» in my application (or this’s just OS HID driver’s activity)?
[attachment deleted by admin]
Logged
Ok, I’ve sorted out with «parameter is incorrect». The error was caused by the fact how I opened the handle to device. I opened it with FILE_FLAG_OVERLAPPED flag but tried to write synchronously.
So my question now is only about USB_FUNCTION_CLASS_INTERFACE: should (and how) I reproduce these kind communication in my program?
Thanks.
Logged
Hi
How exactly did you change from «write synchronously» to a synchronously?
Do you have an example of what you did wrong and then how you did it right?
Thanks
David
Logged
Logged