Developing a char driver

Driver implementation differs in how it handles hardware communication (as shown in the Stub io-char driver and Raspberry Pi 4 mini UART driver example), but integration with io-char follows the same steps:

  • Initialize the io-char library.

  • Initialize the TTYINIT struct.

  • Use the ttc() function to parse default devc-* and dev-ser* options.

  • Initialize one or more TTYDEV structures using data from TTYINIT structures.

  • Read data from hardware (e.g., using an interrupt handler) and push it into an input buffer using the tti() or tti2() functions.

  • Provide the tto() function implementation to set up hardware communication options and to write data to hardware.

  • Attach each hardware device to resource manager.

  • Run the driver.

When developing an io-char driver, you must implement the tto() function. io-char calls tto() when there's data to be transmitted or to perform out of band actions.

You must also declare values for:

  • TTYINIT - Use once per driver to initialize TTYDEV structures.
  • TTYDEV - Use once per device handled by the driver to hold buffer and control information.
  • TTYCTRL - Use once per driver to control information exchanged between the driver and library. The variable must be named ttyctrl.

During initialization, the driver can call the ttc() function as many times as necessary. When the driver receives data from hardware, it calls the tti() or tti2() function to add data to the incoming buffer. When the driver's client sends data, or the client calls devctl(), io-char calls the driver's tto() function. The driver then uses tto_getchar() and tto_write_block() to get data from the output buffer.

UART communication

You can configure UART communication by sending data to the device ports. For more information, refer to the hardware-specific device documentation. For example, refer to the "2. Auxilaries: UART1, SPI1 & SPI2 and 11. UART" chapters of the BCM2711 ARM Peripherals document for RPi4 UART documentation.

To create a serial driver for UART, you'd typically use io-char. Otherwise, follow the Writing a Resource Manager documentation to create your own resource manager to handle client-driver interaction.

The setup and details of the communication with the UART hardware is outside of the scope of this document, and should be defined by manufacturer; for example, the BCM2711 ARM Peripherals document for RPi4.

As another example, to interact with PL011 UART or RPi4 mini UART chips, you'd need to call mmap() function to access the device's I/O registers, and in8()/in16()/in32() and out8()/out16()/out32() functions to read and write 8/16/32-bit data from/to the port.

Page updated: