Communication between a user-mode application and the driver that drives the hardware, is implemented differently for each operating system, using the custom OS Application Programming Interfaces (APIs).
On Windows, and Linux, the application can use the OS
file-access API to open a handle to the driver (e.g., using the Windows
CreateFile() function or using the Linux
function), and then read and write from/to the device by passing the handle to
the relevant OS file-access functions (e.g., the Windows
WriteFile() functions, or the Linux
The application sends requests to the driver via I/O control (IOCTL) calls,
using the custom OS APIs provided for this purpose (e.g., the Windows
DeviceIoControl() function, or the Linux
The data passed between the driver and the application via the IOCTL calls is encapsulated using custom OS mechanisms. For example, on Windows the data is passed via an I/O Request Packet (IRP) structure, and is encapsulated by the I/O Manager.