none
Now how do I communicate with my driver from userspace? RRS feed

  • Question

  • I got my driver to initialize the hardware. The hardware dumps data into a DMA buffer. Some debugging reveiled that it's all working.

    Now I want to fetch that data into a user application so that it can be put to use. On a POSIX system, I'd write a C program to open() my /dev/ thing, and then read() or mmap() it.I found the IO queues that are the driver part of read/write calls.

    Now I'm kinda lost, as I have no clue what I have to pass to CreateFile to get to my driver.

    Wednesday, August 26, 2015 9:35 AM

Answers

  • you don't want SetupDiGetDeviceProperty , you want to enumerate the instnaces of your device interface. the enum.exe project in the toaster sample has copy/paste code that will do the iteration and give you a string to pass to CreateFile for you. After that, it is up to you. You can use read, write, or IOCTL requests to communicate with the driver. in the Windows world, you more often than not find read/write in FS drivers and IOCTLs elsewhere. IOCTLs have the flexibility of each being to encode buffering (mapped, double buffered, raw) as well as specify both input and output buffers in the same request. Read/Write have one shared buffering type and only one buffer.

    d -- This posting is provided "AS IS" with no warranties, and confers no rights.

    Wednesday, August 26, 2015 4:54 PM

All replies

  • What you pass to CreateFile depends on whether you created a symlink for the name or are depending on device interfaces.  Device interfaces are the recommended way look at https://msdn.microsoft.com/en-us/library/windows/hardware/ff551069(v=vs.85).aspx plus SetupDiGetDeviceProperty to get the name to pass into CreateFile.

    Symlink approach is the older mechanism, that looks more like Linux.  There you use a string such as \\.\XXX where XXX is the symlink name.  The IOCTL samples executable source is a good example of how this works, with the driver illustrating the creation of the symlink.


    Don Burn Windows Driver Consulting Website: http://www.windrvr.com

    Wednesday, August 26, 2015 11:47 AM
  • SetupDiGetDeviceProperty requires about a hundred lines of code to get at the device name. Now that I know its name, I can see that same code in various driver test code.

    The "echo" example uses CM_Get_Device_Interface_List to reach the same goal, at least that requires less code.

    The symlink approach looks a lot more user friendly compared to these. I guess I can let my driver provide both interfaces and let the user decide.

    Which now brings up the next problem: I'd want to deploy and run that test application along with the driver when I hit "debug". The MSDN documentation suggests that I could do "New Project > Visual C++ > Windows Driver > Tests." but that does not seem to exist at all:

    https://msdn.microsoft.com/en-us/library/windows/hardware/hh454838%28v=vs.85%29.aspx

    Lacking that, I just wrote a console application that talks to the driver, but I have no luck getting it installed onto the test target. I tried adding its output to the "extra files" in the Driver Install, but that didn't really happen apparently. Having to put it on a USB stick and walking to the test machine works but isn't quite the user experience I was looking forward to.

    Wednesday, August 26, 2015 12:53 PM
  • Well, since the "debug" step already sends a bunch of files to the other side over said network, I was kind of hoping to be able to let my files travel along with that. It would save me a few dozen mouseclicks too...

    Wednesday, August 26, 2015 1:34 PM
  • you don't want SetupDiGetDeviceProperty , you want to enumerate the instnaces of your device interface. the enum.exe project in the toaster sample has copy/paste code that will do the iteration and give you a string to pass to CreateFile for you. After that, it is up to you. You can use read, write, or IOCTL requests to communicate with the driver. in the Windows world, you more often than not find read/write in FS drivers and IOCTLs elsewhere. IOCTLs have the flexibility of each being to encode buffering (mapped, double buffered, raw) as well as specify both input and output buffers in the same request. Read/Write have one shared buffering type and only one buffer.

    d -- This posting is provided "AS IS" with no warranties, and confers no rights.

    Wednesday, August 26, 2015 4:54 PM
  • I found that toaster's enum uses a copy of the CM_Get_Device_Interface_List that the "echo" sample I mentioned also uses.

    (Might be an idea for the sample writing folks to create a library or so of this kind of  recommended practices. Having samples copy code around or doing the same thing in a different way isn't helping much.)

    Thursday, August 27, 2015 5:26 AM
  • Related question now that I found the way to open the driver:

    The hardware writes into the DMA buffer and then signals an IRQ. I would want to display the data in a GUI, and sync these.

    Currently, I just call ReadFile periodically from the GUI, and made the driver just copy whatever was in the DMA buffer without blocking, so the GUI thread isn't blocked waiting for data, but it will miss events or display the same data twice now. So the GUI needs a kind of "there's data" signal from the driver.

    The obvious thing to do here I think would be to use overlapped IO in the GUI, and make the driver wait for the IRQ before copying data to the user and signalling completion. The GUI can wait for completion by placing MsgWaitForObject() in its event loop. That's where things get tricky, as that's quite cumbersome to do, and not all GUI frameworks allow you to easily meddle so deep in their message handling.

    Is this a good way to go, or are there alternatives that would be much easier to implement, in particular where interfacing with the GUI (without blocking it) is concerned?

    Thursday, August 27, 2015 1:13 PM
  • There are a lot of approaches here.  You can create a second thread in the GUI app to collect the data from the driver, you can in the event loop check for the completion of the overlapped I/O, and many more ways.  It really depends on the design of your GUI app.

    One thing to consider is issuing more than one ReadFile and having them queued in the driver, then when a DMA comes there is likely a buffer to deliver it to immediately.


    Don Burn Windows Driver Consulting Website: http://www.windrvr.com

    Thursday, August 27, 2015 2:07 PM
  • you can send overlapped (async io) and use MsgWaitForMultipleObjectsEx to wait for the results to keep the UI going. A second thread can be used to wait for io and it posts custom windows messages to the ui thread to tell it to pick up data. as don said, there are many patterns

    d -- This posting is provided "AS IS" with no warranties, and confers no rights.

    Thursday, August 27, 2015 5:43 PM