diff -r 578be2adaf3e -r 307f4279f433 Adaptation/GUID-AB9175EB-1B61-5341-B6B9-5613A7862D74.dita --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Adaptation/GUID-AB9175EB-1B61-5341-B6B9-5613A7862D74.dita Fri Oct 15 14:32:18 2010 +0100 @@ -0,0 +1,278 @@ + + + + + +Channel +ImplementationDescribes how to implement DComm to drive a serial +port hardware. +

A physical channel defines the interface between the logical device and +the physical device. The Serial Port Driver physical channel interface is +defined by the DComm class.

+

The DComm class is defined in: ...\e32\include\drivers\comm.h, +which is exported to epoc32\include\drivers:

+class DComm : public DBase + { +public: + virtual TInt Start() =0; + virtual void Stop(TStopMode aMode) =0; + virtual void Break(TBool aState) =0; + virtual void EnableTransmit() =0; + virtual TUint Signals() const =0; + virtual void SetSignals(TUint aSetMask,TUint aClearMask) =0; + virtual TInt ValidateConfig(const TCommConfigV01 &aConfig) const =0; + virtual void Configure(TCommConfigV01 &aConfig) =0; + virtual void Caps(TDes8 &aCaps) const =0; + virtual void CheckConfig(TCommConfigV01& aConfig)=0; + virtual TInt DisableIrqs()=0; + virtual void RestoreIrqs(TInt aIrq)=0; + virtual TDfcQue* DfcQ(TInt aUnit)=0; + inline TBool PowerGood(); + inline void SetCurrent(TInt aCurrent); + inline void ReceiveIsr(TUint* aChar, TInt aCount, TInt aXonXoff); + inline TInt TransmitIsr();inline void CheckTxBuffer(); + inline void StateIsr(TUint aSignals); + inline TBool Transmitting(); +public: + DChannelComm *iLdd; + TBool iTransmitting; + }; + +

Note that DComm defines the minimum set of functions to +be used by the LDD. A real physical channel object, typically, requires the +addition of an interrupt handler, some DFC callback routines (if these are +not handled in the LDD itself) and various other state variables.

+
DCommVariant constructor

Implement the constructor +for the channel object. Since there is no unit number argument, the constructor +is limited to initialising only those members that are common across all possible +channels, with no access to any specific hardware.

+
DCommVariant destructor

Implement the destructor +for the channel object. It should release any hardware and Symbian platform +resources that have been allocated to the driver, typically unbinding the +UART interrupt ISR, and any private DFCs that are still in use. The destructor +merely unbinds the interrupt as no channel specific DFCs are active at destructor +invocation.

+
DoCreate()

Implement the DoCreate() channel +initialisation function for the UART driver. In general, defining a DoCreate() function +is not mandated by the device driver framework but is useful for drivers that +make use of unit numbers. This is called by the factory object’s Create() function after the device object’s allocation has succeeded.

Typical +operations performed by this function are to setup any channel specific hardware +states and bind the driver’s ISR to the (possibly channel specific) interrupt +channel, as well as enabling the UART hardware itself. However, since the Start() function +has not yet been called, it should not enable the UART interrupts/poll routines +which would actively buffer incoming data; any data I/O requests should be +discarded until the driver’s Start() routine +has been called.

+
Start()

Implement +the Start() function. This should enable the driver’s receive +path.

Received characters are placed in the LDD upstream buffer, either +by the interrupt handler routine, or by a polling routine that tests for the +existence of received characters (and their associated error state). This +is done by calling the LDD’s ReceiveIsr() routine, with a +pointer to the buffered characters, a count and a flag indicating whether +the XON or XOFF flow control characters have been received.

The function +is called by the LDD when the owning thread opens the device channel. It should +complete any UART data I/O enabling that has not already been performed in +the DoCreate() function, i.e. the enabling of UART receive +interrupt processing as a minimum. After this function returns, it is expected +that incoming data will be placed in a (local) buffer and passed upstream +to the LDD, until Stop() is +invoked. Note that since there may have been line activity prior to this call, +it may be necessary to reset the UART state, as we do not want to report errors/states +that may have occurred before the UART was (logically) enabled.

+
Stop()

Implement +the Stop() function. This should disable the driver’s transmit +and receive paths.

Depending on the type of stop requested, i.e. emergency +power down, or otherwise, Stop() may not wait for the UART +to finish transmitting any characters stored in the transmit FIFO queue. All +receive paths are stopped instantly and any characters that may be in the +receive FIFO queue are ignored.

The function is called by the LDD when +the owning thread closes the device channel. At this point, the UART device +should revert to the state in which all data I/O requests are ignored or failed. +To save OS resources the natural method to accomplish this is to disable the +UART interrupt processing or disable the UART itself. It may also be necessary +to cancel any DFCs queued, so that event notifications are not sent to the +LDD after it has requested an end to I/O.

+
DfcQ()

Implement the DfcQ() function. +This should return the DFC queue on which the LDD will install its DFCs. Usually +the standard low priority kernel DFC queue 0 is returned.

+
Break()

Implement the Break() function. +This starts or ends a BREAK condition on the wire.

This operation is +explicitly requested by the owning thread through the LDD. A break state requires +the forcing of the line into an abnormal state, which violates standard data +format timings (a form of out of band signalling), and is detected by the +remote device and is usually used to force it to cycle through its baud rate +detection modes. Forcing a break state requires that the PDD explicitly set +some state in the UART hardware.

+
Signals()

Implement +the Signals() function. This returns the state of the flow +and MODEM control inputs, ie. DCD, DSR, CTS and RI (if implemented on the +device itself). This function is called by the LDD to return the state of +all the handshaking lines so that it can decide whether further data I/O operations +are allowed.

+
SetSignals()

Implement the SetSignals() function. +This controls the state of the flow and MODEM control outputs. It is used +by the LDD to control MODEM handshaking and line failure detection, and can +be invoked in response to a specific user request to change the handshake +signal’s state, or when the LDD itself decides that the output lines states +should be changed in response to some transfer state (e.g. requesting no further +transmissions if buffer availability runs low).

+
Caps()

Implement +the Caps() function. This returns the driver supported configurations: +speed, format, and handshaking.

It is called by the LDD in response +to a user request for the device's capabilities. The PDD must fill a TCommCapsV02 object, +with the capabilities for that port.

The object is defined in d32comm.h:

class TCommCapsV01 + { +public: + TUint iRate; + TUint iDataBits; + TUint iStopBits; + TUint iParity; + TUint iHandshake; + TUint iSignals; + TUint iFifo; + TUint iSIR; + }; + +class TCommCapsV02 : public TCommCapsV01 + { +public: + TUint iNotificationCaps; + TUint iRoleCaps; + TUint iFlowControlCaps; + };

The base object, TCommCapsV01, defines +capabilities in terms of:

    +
  • data rate

  • +
  • word format (i.e. parity, +data bits, stop bits)

  • +
  • flow control lines

  • +
  • MODEM control lines

  • +
  • IrDA support.

  • +

Each attribute range is passed as a bitfield of possible settings, +all assumed to be orthogonal, i.e. each attribute can assume all the values +independently of the other attributes.

The attribute bitfields are +defined in d32comm.h.

The iSIR attribute +in TCommCapsV01 indicates whether the port can support +slow infrared protocol.

The iNotificationCaps attribute +in TCommCapsV02 allows the driver to describe its ability +to report asynchronous events, if requested to do so by the client thread. +The only useful applications seem to be to report data arrival and handshake +line status change, although fields exist for other capabilities.

The iRoleCaps attribute +in TCommCapsV02 is intended to indicate that the device +is capable of acting as a DCE as well as a DTE, i.e. that the port can be +configured to act like a MODEM port. This essentially reverses the normal +I/O of the status lines, and could add functionality such as ring indication. +Normal UART devices will never need to change this field from the default, +i.e. DTE device personality.

The iFlowControlCaps field +in TCommCapsV02 is unused and should be set to 0.

The iHandshake field +in TCommCapsV01 describes the flow control signal support +on the device. Input signals have attributes “Obey” and “Fail” e.g. ObeyCts, +FailCts. Output signals have only the “Free” attribute, which indicates they +can be driven (via a call to Signals()) +to any state, independent of the internal state of the UART, i.e. they are +entirely under LDD control. The Fail attribute implies that the LDD will deem +operations to have failed if an input line thus labelled becomes disasserted. +This means that the PDD can report these signal states asynchronously. If, +for example, a change in CTS state can generate an interrupt, then the PDD +should report it as possessing both Obey and Fail attributes, whereas if the +DCD line cannot generate an asynchronous event, it should merely present itself +as “Obey”. If the line is unimplemented then neither attribute should be reported.

+
Configure()

Implement the Configure() function. +This configures the UART device according to the configuration data passed +into the function.

Configuration data is encapsulated by a TCommConfigV02 object:

class TCommConfigV01 + { +public: + TBps iRate; + TDataBits iDataBits; + TStopBits iStopBits; + TParity iParity; + TUint iHandshake; + TUint iParityError; + TUint iFifo; + TInt iSpecialRate; + TInt iTerminatorCount; + TText8 iTerminator[KConfigMaxTerminators]; + TText8 iXonChar; + TText8 iXoffChar; + TText8 iParityErrorChar; + TSir iSIREnable; + TUint iSIRSettings; + }; + +class TCommConfigV02: public TCommConfigV01 + { +public: + TInt iTxShutdownTimeout; + }; +

This function is called by the LDD when the physical channel +is opened. The default configuration is set by the LDD when the Dcomm object +is constructed, but the user can override the configuration with a SetConfig request +on the opened channel. The configuration is described by specifying a set +of individual capability attributes from the supported ranges returned in +the Caps() call.

Note +that the iTerminatorCount, the iTerminatorArray and iSpecialRate are +currently unused. The iParityErrorChar replaces the character +that the UART determined had a parity violation. This can be used to send +a prearranged escape character to the upstream LDD.

+
CheckConfig()

Implement the CheckConfig() function. +This is used by autosensing UARTs to pass detected configuration upstream +to the LDD. This is called by the LDD when it creates the initial channel +to allow the autosensed state to override any default it has set. If the UART +device cannot perform autosensing, and most cannot, then the CheckConfig() function +should leave the parameter buffer unchanged.

+
ValidateConfig()

Implement the ValidateConfig() function. +This returns true if the specified configuration is supported by the driver. +This should never return false if the correct capabilities have been setup, +but may be used to check for cases where, for example, a specific set of attributes +cannot be applied together. As an example, a data format word size may not +be generated for some specific baud rate.

+
DisableIrqs()

Implement the DisableIrqs() function. +This is called by the LDD to disable (all) interrupts during critical sections, +for example, during LDD buffer manipulation. It calls the kernel utility to +perform the task.

+
RestoreIrqs()

Implement the RestoreIrqs() function, +called by the LDD to enable (all) interrupts after critical sections have +completed. Calls the kernel utility to perform the task.

+
EnableTransmit()

Implement the EnableTransmit() function. +This initialises the UART transmit hardware, and the transmit ISR code path. +This function can be called from the ISR (on receipt of an unblocking XON +character), or to start a transmission of a LDD originated data buffer. It +causes the UART to generate Tx service interrupts as it finishes transmitting +a FIFOs worth of data, so that the entire buffer (passed by the LDD) can be +sent under interrupt control.

+
Data handling routines

Implement the main data +handling routines. These are entirely dependent on the UART hardware interface +and cannot therefore be described generally. They are typically driven by +the interrupt service routine as asynchronous events from the UART (eg. data +received, finished transmission of data, change in handshaking/flow control +inputs) occur.

The main ISR is typically driven by an interrupt multiplexed +from all the sources in the UART. The ISR, therefore, needs to determine which +of the interrupt sources requires attention. Since the most critical source +is the data received state, as this requires that the data is processed before +following data overwrites earlier data, then this is usually the signal to +be checked first. To avoid wasting time, the error state of the data is also +checked – data that has bad parity or framing must be noted as such. Typically +the receive path will save the currently available data into a temporary buffer, +and queue a DFC to process the data further at a later time, when more client +thread context is available (though this is a function of the LDD). The receive +ISRr just passes the location of the ISR buffer into an LDD function which +queues a DFC to process it.

The transmit path, called when the transmit +FIFO contents drop below a programmable number, merely requests more data +from the LDD. If there is none available it disables the transmit interrupt +so as to prevent further requests when there is no data to be sent. Further +data to transmit will cause the transmit FIFO empty interrupt to be re-enabled. +Hence the start of any transmission is always performed on an explicit start +request from the LDD and then continues under PDD interrupt control until +the source data is exhausted.

The status notification path is present +to inform the upstream LDD of changes in the input status signals (MODEM and +flow control status). The UART can generate interrupts when any input handshake +line changes state – the ISR merely reads the current state and queues a handler +DFC so that the LDD can be informed. The LDD is responsible for determining +what status change has occurred and dealing with it.

+
\ No newline at end of file