PDA

View Full Version : How to open a device for Asynchronous IO in QT4



WDT
28th July 2010, 19:16
Hi all

I'm new to Qt and an intermediate C++ (well I think so anyways) dev.
I'm trying to port some code over from C# to do with driver development for a HiD board and trying to use Qt and C++ data types as opposed to the MFC ones like, QFile instead of HANDLE and unsigned long instead of DWORD. So far so good I have managed to get to the point of opening the device which is where I've hit an impasse.

bool hid_device::init_device(QString devPathname)
{
QString errorMessage;
QMessageBox msgBox;
HIDD_ATTRIBUTES mDeviceAttribs;

qDebug() << devPathname;
//devicehandle is of type QFILE
deviceHandle.setFileName(devPathname);
if(!deviceHandle.open(QIODevice::ReadWrite))
{
unsigned long lastErr = GetLastError(); //ulong = DWORD
errorMessage = errorMessage.setNum(lastErr);

msgBox.setText("Unable to Open the Device for IO operations. Error code: " +QString::number(lastErr));
msgBox.exec();
return false;
}

HidD_GetAttributes(&deviceHandle, &mDeviceAttribs);
this->ProductID = mDeviceAttribs.ProductID;
this->VendorID = mDeviceAttribs.VendorID;
this->VersionNumber = mDeviceAttribs.VersionNumber;

deviceHandle.close();
return true;
}

Attempting to open the device always returns an error: ERROR_PATH_NOT_FOUND.
I know the QString I'm passing to the device is the one returned from the setupDi* DDK function so it's valid. (I have anyone done HiD dev in Qt and can point me anywhere? Please remember I'm new to Qt and I'm just porting some code over as a way of learning the framework. I'll tidy up my programming later when I start getting used to thinking in QT.

Thanks for your time.

ChrisW67
29th July 2010, 00:41
I'm not familiar with Windows device driver coding but since Windows does not abide the notion of device-as-file like UNIXes it may be that QFile cannot open the "file" returned. What does devPathName actually contain? Does that exist as a file?

Mixing the Windows API GetLastError() with the Qt QFile class does not strike me that it will be particularly reliable. Who knows what the last Windows API call that QFile made was. What does QFile::error() return.

simar0at
13th August 2010, 19:48
The problem here is that the QFile is based on C runtime low-level I/O file descriptors (just like on unix) and the HidD_* functions need a Windows API HANDLE (which QFile::handle() does not returns). There are two conversion functions between HANDLE and fd: _get_osfhandle (fd->HANDLE) and _open_osfhandle (HANDLE->fd). I didn't get the latter to do anything useful on my CreateFile(...) handles for HID devices.

chesterx
31st August 2011, 21:58
What simar0at said is what you should check out, WDT. If QFile uses the native c runtime file reading functions (instead of the CreateFile()/WriteFile()/ReadFile() Windows API functions) then, passing the file name (device path) of your HID device in the same way that CreateFile() expects, will not work at all.
Just as a coincidence I also have a user level HID program using Qt, but the whole HID part of it was done using the native Windows API functions.

Just to shower some light on the issue here are a couple things you could check:
1 - QSocketNotifier seems like a very nice solution for monitoring read and write operations over file descriptors. The problem is that (and the Qt documentation for the QSocketNotifier class slounds like that) is that, on Windows, it really works only for network socket descriptors (not handles returned by CreateFile()), but on *nix it works for network sockets, and maybe even for serial ports and file descriptors of any kind (maybe even a HID one). It's just my guess, but I will try answering this question soon.

2 - Second option is cumbersome, but it's a way and that's what I did here at work: Subclass QIODevice, then when using the CreateFile and Read/WriteFile functions with Overlapped IO, if you find yourself asking how you are going to mix the WaitForSingleObject (or multiple objects) with the main thread event loop (so you don't have to use a separated thread to avoid freezing the Ui) just look at the : <QtCore/private/qwineventnotifier_p.h>, it solves that problem.