Serial Port Events

The hardware serial port will need to be configured to match the settings used by the device on the other end of the serial connection. Configurable settings include parameters such as the baud rate at which data is sent, the number of bits in a data character, whether parity bits are transmitted, and the number of stop bits that are sent at the end of each character.

These serial port settings are determined by the user space process that has opened the serial port and are configured through functions such as tcsetattr() and tcgetattr(). These functions enter the kernel through the I/O Kit's IOSerialBSDClient class, which passes the individual configuration options to the serial port driver through its executeEvent() method.

The executeEvent() method is paired with the method requestEvent(), which is used by the IOSerialBSDClient class to query the current configuration of the serial port. The prototypes for the executeEvent() and requestEvent() methods are as follows:

IOReturn          executeEvent(UInt32 event, UInt32 data, void* refCon);
IOReturn          requestEvent(UInt32 event, UInt32* data, void* refCon);

The parameter “event” is an enumeration from IOSerialStreamSync.h and identifies the property that is being configured or queried. The parameter “data” is used to pass the new value for the property that is being set through executeEvent(), or the current value of the property that is being queried through requestEvent(). Most drivers implement the executeEvent() and requestEvent() methods with a large switch statement on the value of the event parameter. A description of the possible event types is given below in Table 11-1.

images

images

images

In addition to the method executeEvent(), you will notice that the IOSerialDriverSync interface also defines a method named enqueueEvent() that is used for setting the properties of a serial port. There is a subtle difference between the two methods; a call to the executeEvent() method causes a change in the serial port's configuration to take effect as soon as the method is called, whereas a call to enqueueEvent() won't take effect until all of the characters that are currently in the serial driver's transmit buffer have been written to hardware.

Implementing the correct behavior of enqueueEvent() requires the serial driver to define a transmit buffer that consists of a queue of events and the data associated with each event. Then, each call to enqueueEvent() appends the pair of values {event, data} to the transmit queue. Similarly, character data for transmission also needs to be treated as an event and appended to the end of the transmit buffer. Whenever the transmit buffer is not empty, the serial driver pulls the next event off the queue, which is either an event that changes the configuration of the serial port or a character to be sent over the serial port.

A serial driver isn't required to adhere this closely to the correct implementation of enqueueEvent(). If you examine the source code for the AppleUSBCDCDMM driver, you will see that it implements enqueueEvent() by calling through to executeEvent(), which applies the requested change to the serial port's configuration immediately.

Similarly, the serial driver's receive buffer allows events to be inserted between data bytes read from the serial port. For the receive queue, events represent errors that have occurred while reading data from the serial port. Some of the errors that can be reported are described here:

  • PD_RS232_E_RX_LINE_BREAK indicates that a break condition was detected by the receiver.
  • PD_E_FRAMING_ERROR indicates that the character data was incorrectly framed. (The stop bit was not in the expected position.)
  • PD_E_INTEGRITY_ERROR indicates a parity error was detected.
  • PD_E_HW_OVERRUN_ERROR and PD_E_SW_OVERRUN_ERROR indicate that character data was not pulled from the hardware or the software buffers fast enough to prevent the buffer from filling and data being lost.

Before reading any data from the serial port, the IOSerialBSDClient class will make a call to the serial driver's nextEvent() method. If the next element in the serial driver's receive queue is an error event, nextEvent() will return the event type to the caller, and the caller will respond by calling the driver's dequeueEvent() method. Otherwise, if the next element in the serial driver's receive queue is a data byte that has been read from the serial port, it should return PD_E_EOQ.

As with the transmit side of the serial driver, it is not strictly necessary for a driver to fully implement the queuing of events in its receive queue. In fact, the implementation provided by the AppleUSBCDCDMM driver reports no events on its receive queue at all; its implementation of nextEvent() and dequeueEvent() will check that the serial port has been activated and, if so, will always return a value of kIOReturnSuccess. Note that kIOReturnSuccess has a value of 0, and therefore, corresponds to the event PD_E_EOQ, which also has a value of 0.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.206.244