Windows System Software -- Consulting, Training, Development -- Unique Expertise, Guaranteed Results

Home NTDEV

Before Posting...

Please check out the Community Guidelines in the Announcements and Administration Category.

More Info on Driver Writing and Debugging


The free OSR Learning Library has more than 50 articles on a wide variety of topics about writing and debugging device drivers and Minifilters. From introductory level to advanced. All the articles have been recently reviewed and updated, and are written using the clear and definitive style you've come to expect from OSR over the years.


Check out The OSR Learning Library at: https://www.osr.com/osr-learning-library/


Writing to serial port from KMDF driver

LeHackermanLeHackerman Member Posts: 12

I'm trying to write to a serial port from a KMDF driver as a logging mechanism. I'm using the WdfIoxxx APIs as I'm planning to use this same functionality in a minifilter later. My problem is that WdfIoTargetOpen is failing with STATUS_OBJECT_NAME_NOT_FOUND status. I tried all kinds of symbolic links and object names to reference the COM port but the result is the same. Here's a snippet of how I'm trying to open the port :

        DECLARE_CONST_UNICODE_STRING(portName, L"\\Device\\COM4");
        WDF_IO_TARGET_OPEN_PARAMS_INIT_OPEN_BY_NAME(
            &params,
            &portName,
            MAXIMUM_ALLOWED);  
        status = WdfIoTargetOpen(m_ioTarget, &params);

PS: To conform to the rules, I'm a student and this is for an academic project.

Comments

  • Doron_HolanDoron_Holan Member - All Emails Posts: 10,795
    !object in the debugger can be very helpful. Does !object \Device\COM4 report that the device exists?

    Specifically for serial ports, the convention is that the symbolic link name is COMX and it points to \Device\SerialX or something similar. So you would need to open L"\\??\\COM4" to open via the symbolic link name.
    d
  • LeHackermanLeHackerman Member Posts: 12

    Yeah I also tried that and it failed. Enumerating \Device objects in windbg shows Serial0 and using winobj I could find \Global??\COM4 which is a symlink to \Device\Serial0.

  • Doron_HolanDoron_Holan Member - All Emails Posts: 10,795
    This usually comes down to a typo and getting the double \\ just a little bit wrong. What string literal are you using for the symbolic link name?
    d
  • Tim_RobertsTim_Roberts Member - All Emails Posts: 14,718
    edited July 5

    Theoretically, L"\\DosDevices\\COM4" should also work. Any special name that works at a command prompt should be available in \DosDevices.

    https://learn.microsoft.com/en-us/windows-hardware/drivers/kernel/introduction-to-ms-dos-device-names

    Tim Roberts, [email protected]
    Providenza & Boekelheide, Inc.

  • LeHackermanLeHackerman Member Posts: 12
    edited July 5

    This finally worked. I'm not sure what I was doing wrong but I turned back to using ZwCreateFile, had some errors with it, debugged it, figured out my driver is being loaded before serial.sys so that's a problem set aside. Some more tweaks later ZwCreateFile worked and I decided to go back to WdfIoTargetOpen and it miraculously worked. I'm sorry if I can't say for sure what the problem was besides my driver being loaded before serial.sys. For reference, I ended up using L"\\device\\Serial0"

  • Doron_HolanDoron_Holan Member - All Emails Posts: 10,795
    edited July 5

    For a production quality driver, \Device\Serial0 is a pretty fragile name. For a student experiment, it is OK (but not great).

    For the load order issue where you are loading before the serial driver, you can register for device interface arrival notifications with IoRegisterPlugPlayNotification(EventCategoryDeviceInterfaceChange, PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES, &GUID_DEVINTERFACE_COMPORT, ...). You can then use the provided symbolic link name(s) (they look like gibberish) to open the com port.

    Post edited by Doron_Holan on
    d
  • LeHackermanLeHackerman Member Posts: 12

    Okay great, since I've successfully written to the serial port I'll try your method to solve the load order issue. One other thing, I read somewhere that a serial port could not be concurrently open, is that true ? If so, that would be a problem for me because various drivers would be logging to it at the same time.

  • Doron_HolanDoron_Holan Member - All Emails Posts: 10,795
    Correct. Serial ports are opened with exclusive access, enforced by the serial driver. If you need multiple drivers writing to the serial port then you should have one driver open the serial port, create a device object in which your other drivers can open, and pass through the logging requests from your driver through to the serial port.
    d
  • LeHackermanLeHackerman Member Posts: 12

    Yeah that's what I decided to do. I found a close enough open-source driver project that I'm going to port for my needs. It has buffering capabilities and flushes data to the COM port with spinlock synchronisation. But I'm still not sure If building it as an export driver and export a logging function or as a device driver and send manually built IRPs ?

  • Doron_HolanDoron_Holan Member - All Emails Posts: 10,795

    if it matters, you can't implement an export driver with KMDF. since this is a time bound project, go with the simplest path forward that makes it work. that is probably an export driver with a bunch of global state (since it can't have a device object of its own), but it is your judgement call at the end of the day

    d
  • LeHackermanLeHackerman Member Posts: 12

    Okay then, I'll find out what works well for me and report it back here for future reference. Thank you for all the help !

  • LeHackermanLeHackerman Member Posts: 12

    But wait, if a KMDF driver can't be an export driver, that means I can't use the WdfIoXXX functions to write to the COM port. What should I do then ? the ZwXXX functions have an IRQL constraint and you advice people not to use the WDM in your faq ?

  • Peter_Viscarola_(OSR)Peter_Viscarola_(OSR) Administrator Posts: 9,131

    if a KMDF driver can't be an export driver, that means I can't use the WdfIoXXX functions to write to the COM port. What should I do then ?

    As a wise man once wrote: "it is your judgement call at the end of the day" -- If you prefer to do this in WDF, then write a WDF driver that implements the functionality you want. You can communicate to that WDF driver any way you want: Irps, Bus Interface, whatever...

    Peter

    Peter Viscarola
    OSR
    @OSRDrivers

  • Tim_RobertsTim_Roberts Member - All Emails Posts: 14,718

    you advice people not to use the WDM in your faq

    You do what you have to do. KMDF is a HUGE leap forward if you're doing dispatching, PnP, and power management, and it's foolish to attempt a full driver without it. However, an export driver doesn't do ANY of those things. It's just a repository of code snippets. Most of the WdfIoXxx functions are rather thin wrappers around their WDM analogs.

    Tim Roberts, [email protected]
    Providenza & Boekelheide, Inc.

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. Sign in or register to get started.

Upcoming OSR Seminars
OSR has suspended in-person seminars due to the Covid-19 outbreak. But, don't miss your training! Attend via the internet instead!
Kernel Debugging 13-17 May 2024 Live, Online
Developing Minifilters 1-5 Apr 2024 Live, Online
Internals & Software Drivers 11-15 Mar 2024 Live, Online
Writing WDF Drivers 26 Feb - 1 Mar 2024 Live, Online