Hi,
We are using our own usb driver for our device transmitting analog data 2bytes per 1ms via iso pipe.
Driver written 15 years ago and in some PC’s do not work properly.
I wanted to check possibility to work with winusb.sys driver.
I installed it OK, Can send commands via control pipes but when i start isochronous pipe stream i get USBD_STATUS_ISO_NOT_ACCESSED_BY_HW
error in “isochPacketDescriptors[j].Status” for all transfers exept the first one…
Here is a code
define ISOCH_DATA_SIZE_MS 10
define ISOCH_TRANSFER_COUNT 2 //will need to be at least 2
/
My device sends one sample of 2 bytes every 1ms … => data sample rate = 1000s/s
Problem !!
Only Transfer 1 has the data all next (ISOCH_TRANSFER_COUNT) are empty
As a result i see data arriving at sample rate of 1000 / ISOCH_TRANSFER_COUNT in Read application
Why ???
nvUSB.lib: Current Frame number=261744397
nvUSB.lib: bRead() Requested 1200 bytes in 50 packets per transfer.
nvUSB.lib: bRead() Transfer 1 completed. Read 100 bytes.
nvUSB.lib: Current Frame number=261744447
nvUSB.lib: bRead() Requested 1200 bytes in 50 packets per transfer.
nvUSB.lib: bRead() Transfer 2 completed. Read 0 bytes. ← return with error USBD_STATUS_ISO_NOT_ACCESSED_BY_HW , why??
nvUSB.lib: Current Frame number=261744497
nvUSB.lib: bRead() Requested 1200 bytes in 50 packets per transfer.
nvUSB.lib: bRead() Transfer 1 completed. Read 100 bytes.
nvUSB.lib: Current Frame number=261744547
nvUSB.lib: bRead() Requested 1200 bytes in 50 packets per transfer.
nvUSB.lib: bRead() Transfer 2 completed. Read 0 bytes. ← return with error USBD_STATUS_ISO_NOT_ACCESSED_BY_HW , why??
nvUSB.lib: Current Frame number=261744597
nvUSB.lib: bRead() Requested 1200 bytes in 50 packets per transfer.
nvUSB.lib: bRead() Transfer 1 completed. Read 100 bytes.
nvUSB.lib: Current Frame number=261744647
nvUSB.lib: bRead() Requested 1200 bytes in 50 packets per transfer.
nvUSB.lib: bRead() Transfer 2 completed. Read 0 bytes.
nvUSB.lib: Current Frame number=261744697
*/
Start this thread when user wants start the data stream…
DWORD WINAPI CUsbPCECGHelper::AsyncReadThreadProc(__in LPVOID pvData)
{
if(1)
//--------------
HANDLE hEvents[ISOCH_TRANSFER_COUNT+1];
DWORD dwWait = 0;
DWORD dwNum = 0;
USHORT headerSize = 3;
ULONG bytesRead = 0;
BOOL b = FALSE;
ULONG i;
BOOL result = FALSE;
// Cast the argument to the correct type
CUsbPCECGHelper* pThis = static_cast<CUsbPCECGHelper*>(pvData);
// New threads must always CoInitialize
HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
ULONG totalTransferSize = pThis->IsochInTransferSize * ISOCH_TRANSFER_COUNT;
pThis->readBuffer = new UCHAR[totalTransferSize];
if (pThis->readBuffer == NULL)
{
//sprintf_s(s, sizeof(s), “nvUSB.lib: bStart() Unable to allocate memory\n”);
//OutputDebugString((LPCSTR)s);
hr = E_UNEXPECTED;
}
else
{
ZeroMemory(pThis->readBuffer, totalTransferSize);
}
hEvents[0] = pThis->m_hCloseThread;
for (i = 0; i < ISOCH_TRANSFER_COUNT; i++)
{
pThis->m_hReadAsync[i] = CreateEvent(
NULL, // default security attribute
TRUE, // manual-reset event
FALSE, // initial state = not signaled
NULL); // unnamed event object
}
for (i = 1; i < (ISOCH_TRANSFER_COUNT+1); i++)
hEvents[i] = pThis->m_hReadAsync[i-1];
if (SUCCEEDED(hr))
{
pThis->overlapped = new OVERLAPPED[ISOCH_TRANSFER_COUNT];
ZeroMemory(pThis->overlapped, (sizeof(OVERLAPPED) * ISOCH_TRANSFER_COUNT));
for (i = 0; i < ISOCH_TRANSFER_COUNT; i++)
{
// pThis->overlapped[i].hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
pThis->overlapped[i].hEvent = pThis->m_hReadAsync[i];
// Initialize the rest of the OVERLAPPED structure to zero.
pThis->overlapped[i].Internal = 0;
pThis->overlapped[i].InternalHigh = 0;
pThis->overlapped[i].Offset = 0;
pThis->overlapped[i].OffsetHigh = 0;
if (pThis->overlapped[i].hEvent == NULL)
{
//sprintf_s(s, sizeof(s), "nvUSB.lib: bStart() Unable to set event for overlapped operation\n");
//OutputDebugString((LPCSTR)s);
hr = E_UNEXPECTED;
}
}
}
if (SUCCEEDED(hr))
{
result = WinUsb_RegisterIsochBuffer(
pThis->m_hWinUSBHandle[0], // An opaque handle to an interface in the selected configuration. That handle must be created by a previous call to WinUsb_Initialize or WinUsb_GetAssociatedInterface.
pThis->PipeID.Iso_Pipe[0].PipeId, // Derived from Bit 3…0 of the bEndpointAddress field in the endpoint descriptor.
pThis->readBuffer, // Pointer to the transfer buffer to be registered.
totalTransferSize, // Length, in bytes, of the transfer buffer pointed to by Buffer.
&pThis->isochReadBufferHandle); // Receives an opaque handle to the registered buffer. This handle is required by other WinUSB functions that perform isochronous transfers. To release the handle, call the WinUsb_UnregisterIsochBuffer function.
if (!result)
{
//sprintf_s(s, sizeof(s), “nvUSB.lib: bStart() Isoch buffer registration failed.\n”);
//OutputDebugString((LPCSTR)s);
hr = E_UNEXPECTED;
}
}
if (SUCCEEDED(hr))
{
pThis->isochPacketDescriptors = new USBD_ISO_PACKET_DESCRIPTOR[pThis->IsochInPacketCount * ISOCH_TRANSFER_COUNT];
ZeroMemory(pThis->isochPacketDescriptors, pThis->IsochInPacketCount * ISOCH_TRANSFER_COUNT);
//for iso endpoints read this
//https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/getting-set-up-to-use-windows-devices-usb
//
for (i = 0; i < ISOCH_TRANSFER_COUNT; i++)
{
result = WinUsb_ReadIsochPipeAsap(
pThis->isochReadBufferHandle, // An opaque handle to the transfer buffer that was registered by a previous call to WinUsb_RegisterIsochBuffer.
pThis->IsochInTransferSize * i, // Offset into the buffer relative to the start the transfer.
pThis->IsochInTransferSize, // Length in bytes of the transfer buffer.
(i == 0) ? FALSE : TRUE, // Indicates that the transfer should only be submitted if it can be scheduled in the first frame after the last pending transfer.
pThis->IsochInPacketCount, // Total number of isochronous packets required to hold the transfer buffer.Also indicates the number of elements in the array pointed to by IsoPacketDescriptors.
&pThis->isochPacketDescriptors[i * pThis->IsochInPacketCount], //An array of USBD_ISO_PACKET_DESCRIPTOR that receives the details of each isochronous packet in the transfer.
&pThis->overlapped[i]); // Pointer to an OVERLAPPED structure used for asynchronous operations.
if (!result)
{
DWORD lastError = GetLastError();
if (lastError != ERROR_IO_PENDING)
{
//sprintf_s(s, sizeof(s), “nvUSB.lib: bStart() Failed to start a read operation with error %x\n”, lastError);
//OutputDebugString((LPCSTR)s);
hr = E_UNEXPECTED;
}
}
}
}
//--------------
if (SUCCEEDED(hr))
{
while (true)
{
for (i = 0; i < ISOCH_TRANSFER_COUNT; i++)
pThis->m_bResult = ResetEvent(pThis->m_hReadAsync[i]);
dwWait = WaitForMultipleObjects(ISOCH_TRANSFER_COUNT+1, // number of event objects
hEvents, // array of event objects
FALSE, // does not wait for all
INFINITE // waits indefinitely
);
if (dwWait == WAIT_OBJECT_0) //STOP_THREAD
{
CoUninitialize();
for (i = 0; i < ISOCH_TRANSFER_COUNT; i++)
CloseHandle(pThis->m_hReadAsync[i]);
return 0;
}
else
{
for (i = 1; i < (ISOCH_TRANSFER_COUNT + 1); i++)
{
if (dwWait == (WAIT_OBJECT_0 + i))
{
pThis->ReadIsoBuffer((i-1));
}
}
}
}
}
endif