Adaptation/GUID-AB9175EB-1B61-5341-B6B9-5613A7862D74.dita
changeset 15 307f4279f433
equal deleted inserted replaced
14:578be2adaf3e 15:307f4279f433
       
     1 <?xml version="1.0" encoding="utf-8"?>
       
     2 <!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
       
     3 <!-- This component and the accompanying materials are made available under the terms of the License 
       
     4 "Eclipse Public License v1.0" which accompanies this distribution, 
       
     5 and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". -->
       
     6 <!-- Initial Contributors:
       
     7     Nokia Corporation - initial contribution.
       
     8 Contributors: 
       
     9 -->
       
    10 <!DOCTYPE concept
       
    11   PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
       
    12 <concept id="GUID-AB9175EB-1B61-5341-B6B9-5613A7862D74" xml:lang="en"><title>Channel
       
    13 Implementation</title><shortdesc>Describes how to implement <codeph>DComm</codeph> to drive a serial
       
    14 port hardware.</shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
       
    15 <p>A physical channel defines the interface between the logical device and
       
    16 the physical device. The Serial Port Driver physical channel interface is
       
    17 defined by the <codeph>DComm</codeph> class. </p>
       
    18 <p>The <codeph>DComm</codeph> class is defined in: <filepath>...\e32\include\drivers\comm.h</filepath>,
       
    19 which is exported to <filepath>epoc32\include\drivers</filepath>: </p>
       
    20 <codeblock id="GUID-F9E58262-51AA-5A58-A113-3FA994F00156" xml:space="preserve">class DComm : public DBase
       
    21     {
       
    22 public:
       
    23     virtual TInt Start() =0;
       
    24     virtual void Stop(TStopMode aMode) =0;
       
    25     virtual void Break(TBool aState) =0;
       
    26     virtual void EnableTransmit() =0;
       
    27     virtual TUint Signals() const =0;
       
    28     virtual void SetSignals(TUint aSetMask,TUint aClearMask) =0;
       
    29     virtual TInt ValidateConfig(const TCommConfigV01 &amp;aConfig) const =0;
       
    30     virtual void Configure(TCommConfigV01 &amp;aConfig) =0;
       
    31     virtual void Caps(TDes8 &amp;aCaps) const =0;
       
    32     virtual void CheckConfig(TCommConfigV01&amp; aConfig)=0;
       
    33     virtual TInt DisableIrqs()=0;
       
    34     virtual void RestoreIrqs(TInt aIrq)=0;
       
    35     virtual TDfcQue* DfcQ(TInt aUnit)=0;
       
    36     inline TBool PowerGood(); 
       
    37     inline void SetCurrent(TInt aCurrent);
       
    38     inline void ReceiveIsr(TUint* aChar, TInt aCount, TInt aXonXoff);
       
    39     inline TInt TransmitIsr();inline void CheckTxBuffer();
       
    40     inline void StateIsr(TUint aSignals);
       
    41     inline TBool Transmitting();
       
    42 public:
       
    43     DChannelComm *iLdd;
       
    44     TBool iTransmitting;
       
    45     };
       
    46 </codeblock>
       
    47 <p>Note that <codeph>DComm</codeph> defines the minimum set of functions to
       
    48 be used by the LDD. A real physical channel object, typically, requires the
       
    49 addition of an interrupt handler, some DFC callback routines (if these are
       
    50 not handled in the LDD itself) and various other state variables. </p>
       
    51 <section id="GUID-B0D61B54-EDF3-4804-9B1E-370C36E01708"><title>DCommVariant constructor</title> <p>Implement the constructor
       
    52 for the channel object. Since there is no unit number argument, the constructor
       
    53 is limited to initialising only those members that are common across all possible
       
    54 channels, with no access to any specific hardware. </p> </section>
       
    55 <section id="GUID-550681C3-F1A6-4298-BAA5-C6F2D9D61624"><title>DCommVariant destructor</title> <p>Implement the destructor
       
    56 for the channel object. It should release any hardware and Symbian platform
       
    57 resources that have been allocated to the driver, typically unbinding the
       
    58 UART interrupt ISR, and any private DFCs that are still in use. The destructor
       
    59 merely unbinds the interrupt as no channel specific DFCs are active at destructor
       
    60 invocation. </p> </section>
       
    61 <section id="GUID-8254536B-E938-4B86-A735-798DD03E3456"><title>DoCreate()</title> <p>Implement the <codeph>DoCreate()</codeph> channel
       
    62 initialisation function for the UART driver. In general, defining a <codeph>DoCreate()</codeph> function
       
    63 is not mandated by the device driver framework but is useful for drivers that
       
    64 make use of unit numbers. This is called by the factory object’s <xref href="GUID-6DE69F29-45B0-5E62-AA13-DA4041B1BC46.dita#GUID-6DE69F29-45B0-5E62-AA13-DA4041B1BC46/GUID-48EF94F9-ACBC-58DA-9F0E-4034E56C6C74">Create()</xref> function after the device object’s allocation has succeeded. </p> <p>Typical
       
    65 operations performed by this function are to setup any channel specific hardware
       
    66 states and bind the driver’s ISR to the (possibly channel specific) interrupt
       
    67 channel, as well as enabling the UART hardware itself. However, since the <xref href="GUID-AB9175EB-1B61-5341-B6B9-5613A7862D74.dita#GUID-AB9175EB-1B61-5341-B6B9-5613A7862D74/GUID-0CAA6D27-FE2E-5569-8747-EB3D4976E7FD">Start()</xref> function
       
    68 has not yet been called, it should not enable the UART interrupts/poll routines
       
    69 which would actively buffer incoming data; any data I/O requests should be
       
    70 discarded until the driver’s <xref href="GUID-AB9175EB-1B61-5341-B6B9-5613A7862D74.dita#GUID-AB9175EB-1B61-5341-B6B9-5613A7862D74/GUID-0CAA6D27-FE2E-5569-8747-EB3D4976E7FD">Start()</xref> routine
       
    71 has been called. </p> </section>
       
    72 <section id="GUID-0CAA6D27-FE2E-5569-8747-EB3D4976E7FD"><title>Start()</title> <p> Implement
       
    73 the <codeph>Start()</codeph> function. This should enable the driver’s receive
       
    74 path.</p><p> Received characters are placed in the LDD upstream buffer, either
       
    75 by the interrupt handler routine, or by a polling routine that tests for the
       
    76 existence of received characters (and their associated error state). This
       
    77 is done by calling the LDD’s <codeph>ReceiveIsr()</codeph> routine, with a
       
    78 pointer to the buffered characters, a count and a flag indicating whether
       
    79 the XON or XOFF flow control characters have been received.</p><p>The function
       
    80 is called by the LDD when the owning thread opens the device channel. It should
       
    81 complete any UART data I/O enabling that has not already been performed in
       
    82 the <codeph>DoCreate()</codeph> function, i.e. the enabling of UART receive
       
    83 interrupt processing as a minimum. After this function returns, it is expected
       
    84 that incoming data will be placed in a (local) buffer and passed upstream
       
    85 to the LDD, until <xref href="GUID-AB9175EB-1B61-5341-B6B9-5613A7862D74.dita#GUID-AB9175EB-1B61-5341-B6B9-5613A7862D74/GUID-9428082D-581D-530B-8838-1DBF6D0EB8E7">Stop()</xref> is
       
    86 invoked. Note that since there may have been line activity prior to this call,
       
    87 it may be necessary to reset the UART state, as we do not want to report errors/states
       
    88 that may have occurred before the UART was (logically) enabled.</p></section>
       
    89 <section id="GUID-9428082D-581D-530B-8838-1DBF6D0EB8E7"><title>Stop()</title><p>Implement
       
    90 the <codeph>Stop()</codeph> function. This should disable the driver’s transmit
       
    91 and receive paths. </p><p>Depending on the type of stop requested, i.e. emergency
       
    92 power down, or otherwise, <codeph>Stop()</codeph> may not wait for the UART
       
    93 to finish transmitting any characters stored in the transmit FIFO queue. All
       
    94 receive paths are stopped instantly and any characters that may be in the
       
    95 receive FIFO queue are ignored. </p><p>The function is called by the LDD when
       
    96 the owning thread closes the device channel. At this point, the UART device
       
    97 should revert to the state in which all data I/O requests are ignored or failed.
       
    98 To save OS resources the natural method to accomplish this is to disable the
       
    99 UART interrupt processing or disable the UART itself. It may also be necessary
       
   100 to cancel any DFCs queued, so that event notifications are not sent to the
       
   101 LDD after it has requested an end to I/O. </p></section>
       
   102 <section id="GUID-5E4B6533-75F5-47FB-A4DF-55FAA1E1B973"><title>DfcQ()</title><p>Implement the <codeph>DfcQ()</codeph> function.
       
   103 This should return the DFC queue on which the LDD will install its DFCs. Usually
       
   104 the standard low priority kernel DFC queue 0 is returned. </p></section>
       
   105 <section id="GUID-ADC89B5B-0E29-4723-92E6-A6F1A5604710"><title>Break()</title><p>Implement the <codeph>Break()</codeph> function.
       
   106 This starts or ends a BREAK condition on the wire. </p><p>This operation is
       
   107 explicitly requested by the owning thread through the LDD. A break state requires
       
   108 the forcing of the line into an abnormal state, which violates standard data
       
   109 format timings (a form of out of band signalling), and is detected by the
       
   110 remote device and is usually used to force it to cycle through its baud rate
       
   111 detection modes. Forcing a break state requires that the PDD explicitly set
       
   112 some state in the UART hardware. </p></section>
       
   113 <section id="GUID-82A259A7-54F7-536A-B829-31C0AF3C5C81"><title>Signals()</title><p>Implement
       
   114 the <codeph>Signals()</codeph> function. This returns the state of the flow
       
   115 and MODEM control inputs, ie. DCD, DSR, CTS and RI (if implemented on the
       
   116 device itself). This function is called by the LDD to return the state of
       
   117 all the handshaking lines so that it can decide whether further data I/O operations
       
   118 are allowed. </p></section>
       
   119 <section id="GUID-492D86E5-BEEF-4408-B6E0-6DDA1244CA74"><title>SetSignals()</title><p>Implement the <codeph>SetSignals()</codeph> function.
       
   120 This controls the state of the flow and MODEM control outputs. It is used
       
   121 by the LDD to control MODEM handshaking and line failure detection, and can
       
   122 be invoked in response to a specific user request to change the handshake
       
   123 signal’s state, or when the LDD itself decides that the output lines states
       
   124 should be changed in response to some transfer state (e.g. requesting no further
       
   125 transmissions if buffer availability runs low). </p></section>
       
   126 <section id="GUID-CB1FA26C-5D29-50ED-AF40-8CC579AF776F"><title>Caps()</title><p>Implement
       
   127 the <codeph>Caps()</codeph> function. This returns the driver supported configurations:
       
   128 speed, format, and handshaking. </p><p>It is called by the LDD in response
       
   129 to a user request for the device's capabilities. The PDD must fill a <xref href="GUID-98A18771-CA6D-3B68-8784-449CDBEC3D88.dita"><apiname>TCommCapsV02</apiname></xref> object,
       
   130 with the capabilities for that port. </p><p>The object is defined in <filepath>d32comm.h</filepath>: </p><codeblock id="GUID-A95D8753-E574-5C86-85DC-6AA10F635612" xml:space="preserve">class TCommCapsV01
       
   131     {
       
   132 public:
       
   133     TUint iRate;
       
   134     TUint iDataBits;
       
   135     TUint iStopBits;
       
   136     TUint iParity;
       
   137     TUint iHandshake;
       
   138     TUint iSignals;
       
   139     TUint iFifo;
       
   140     TUint iSIR;
       
   141     };
       
   142 
       
   143 class TCommCapsV02 : public TCommCapsV01
       
   144     {
       
   145 public:
       
   146     TUint iNotificationCaps;
       
   147     TUint iRoleCaps;
       
   148     TUint iFlowControlCaps;
       
   149     };</codeblock> <p>The base object, <xref href="GUID-BDBB61A7-18BC-3C85-A258-77D8B16621AD.dita"><apiname>TCommCapsV01</apiname></xref>, defines
       
   150 capabilities in terms of: </p> <ul>
       
   151 <li id="GUID-7AE03D23-1013-5522-B219-23153E1B7798"><p>data rate </p> </li>
       
   152 <li id="GUID-E2FBD4C1-B704-592A-B3A2-1BCFFC7E5451"><p>word format (i.e. parity,
       
   153 data bits, stop bits) </p> </li>
       
   154 <li id="GUID-525050DD-8ACE-5580-BDF7-3717295D704E"><p>flow control lines </p> </li>
       
   155 <li id="GUID-B5DBE4E6-8184-522A-856A-9BD17E76FF33"><p>MODEM control lines </p> </li>
       
   156 <li id="GUID-62ACC296-4B9B-59D3-8531-480E04264FE0"><p>IrDA support. </p> </li>
       
   157 </ul> <p>Each attribute range is passed as a bitfield of possible settings,
       
   158 all assumed to be orthogonal, i.e. each attribute can assume all the values
       
   159 independently of the other attributes. </p> <p>The attribute bitfields are
       
   160 defined in <filepath>d32comm.h</filepath>. </p> <p>The <codeph>iSIR</codeph> attribute
       
   161 in <xref href="GUID-BDBB61A7-18BC-3C85-A258-77D8B16621AD.dita"><apiname>TCommCapsV01</apiname></xref> indicates whether the port can support
       
   162 slow infrared protocol. </p> <p>The <codeph>iNotificationCaps</codeph> attribute
       
   163 in <xref href="GUID-98A18771-CA6D-3B68-8784-449CDBEC3D88.dita"><apiname>TCommCapsV02</apiname></xref> allows the driver to describe its ability
       
   164 to report asynchronous events, if requested to do so by the client thread.
       
   165 The only useful applications seem to be to report data arrival and handshake
       
   166 line status change, although fields exist for other capabilities. </p> <p>The <codeph>iRoleCaps</codeph> attribute
       
   167 in <xref href="GUID-98A18771-CA6D-3B68-8784-449CDBEC3D88.dita"><apiname>TCommCapsV02</apiname></xref> is intended to indicate that the device
       
   168 is capable of acting as a DCE as well as a DTE, i.e. that the port can be
       
   169 configured to act like a MODEM port. This essentially reverses the normal
       
   170 I/O of the status lines, and could add functionality such as ring indication.
       
   171 Normal UART devices will never need to change this field from the default,
       
   172 i.e. DTE device personality. </p> <p>The <codeph>iFlowControlCaps</codeph> field
       
   173 in <xref href="GUID-98A18771-CA6D-3B68-8784-449CDBEC3D88.dita"><apiname>TCommCapsV02</apiname></xref> is unused and should be set to 0. </p> <p>The <codeph>iHandshake</codeph> field
       
   174 in <xref href="GUID-BDBB61A7-18BC-3C85-A258-77D8B16621AD.dita"><apiname>TCommCapsV01</apiname></xref> describes the flow control signal support
       
   175 on the device. Input signals have attributes “Obey” and “Fail” e.g. ObeyCts,
       
   176 FailCts. Output signals have only the “Free” attribute, which indicates they
       
   177 can be driven (via a call to <xref href="GUID-AB9175EB-1B61-5341-B6B9-5613A7862D74.dita#GUID-AB9175EB-1B61-5341-B6B9-5613A7862D74/GUID-82A259A7-54F7-536A-B829-31C0AF3C5C81">Signals()</xref>)
       
   178 to any state, independent of the internal state of the UART, i.e. they are
       
   179 entirely under LDD control. The Fail attribute implies that the LDD will deem
       
   180 operations to have failed if an input line thus labelled becomes disasserted.
       
   181 This means that the PDD can report these signal states asynchronously. If,
       
   182 for example, a change in CTS state can generate an interrupt, then the PDD
       
   183 should report it as possessing both Obey and Fail attributes, whereas if the
       
   184 DCD line cannot generate an asynchronous event, it should merely present itself
       
   185 as “Obey”. If the line is unimplemented then neither attribute should be reported. </p> </section>
       
   186 <section id="GUID-DA860E4A-4240-4C16-B1C0-5E9B7C96F9E8"><title>Configure()</title> <p>Implement the <codeph>Configure()</codeph> function.
       
   187 This configures the UART device according to the configuration data passed
       
   188 into the function. </p> <p>Configuration data is encapsulated by a <xref href="GUID-0CBAE946-AB8E-3114-89FC-9591125C4BDC.dita"><apiname>TCommConfigV02</apiname></xref> object: </p> <codeblock id="GUID-275DAD25-9EF9-5084-A82B-8E2392CB14E8" xml:space="preserve">class TCommConfigV01
       
   189     {
       
   190 public:
       
   191     TBps iRate;
       
   192     TDataBits iDataBits;
       
   193     TStopBits iStopBits;
       
   194     TParity iParity;
       
   195     TUint iHandshake;
       
   196     TUint iParityError;
       
   197     TUint iFifo;
       
   198     TInt iSpecialRate;
       
   199     TInt iTerminatorCount;
       
   200     TText8 iTerminator[KConfigMaxTerminators];
       
   201     TText8 iXonChar;
       
   202     TText8 iXoffChar;
       
   203     TText8 iParityErrorChar;
       
   204     TSir iSIREnable;
       
   205     TUint iSIRSettings;
       
   206     };
       
   207 
       
   208 class TCommConfigV02: public TCommConfigV01
       
   209     {
       
   210 public:
       
   211     TInt iTxShutdownTimeout;
       
   212     };
       
   213 </codeblock> <p>This function is called by the LDD when the physical channel
       
   214 is opened. The default configuration is set by the LDD when the <codeph>Dcomm</codeph> object
       
   215 is constructed, but the user can override the configuration with a <codeph>SetConfig</codeph> request
       
   216 on the opened channel. The configuration is described by specifying a set
       
   217 of individual capability attributes from the supported ranges returned in
       
   218 the <xref href="GUID-AB9175EB-1B61-5341-B6B9-5613A7862D74.dita#GUID-AB9175EB-1B61-5341-B6B9-5613A7862D74/GUID-CB1FA26C-5D29-50ED-AF40-8CC579AF776F">Caps()</xref> call. </p> <p>Note
       
   219 that the <codeph>iTerminatorCount</codeph>, the <codeph>iTerminatorArray</codeph> and<codeph> iSpecialRate</codeph> are
       
   220 currently unused. The <codeph>iParityErrorChar</codeph> replaces the character
       
   221 that the UART determined had a parity violation. This can be used to send
       
   222 a prearranged escape character to the upstream LDD. </p> </section>
       
   223 <section id="GUID-509C63E0-09D9-48F1-8ECB-F18377B73E8A"><title>CheckConfig()</title> <p>Implement the <codeph>CheckConfig()</codeph> function.
       
   224 This is used by autosensing UARTs to pass detected configuration upstream
       
   225 to the LDD. This is called by the LDD when it creates the initial channel
       
   226 to allow the autosensed state to override any default it has set. If the UART
       
   227 device cannot perform autosensing, and most cannot, then the <codeph>CheckConfig()</codeph> function
       
   228 should leave the parameter buffer unchanged. </p> </section>
       
   229 <section id="GUID-6F26F95A-7115-4E07-BA72-7AEF75DC2912"><title>ValidateConfig()</title> <p>Implement the <codeph>ValidateConfig()</codeph> function.
       
   230 This returns true if the specified configuration is supported by the driver.
       
   231 This should never return false if the correct capabilities have been setup,
       
   232 but may be used to check for cases where, for example, a specific set of attributes
       
   233 cannot be applied together. As an example, a data format word size may not
       
   234 be generated for some specific baud rate. </p> </section>
       
   235 <section id="GUID-10FB213C-47B3-4CFF-AB2B-5868AE4531E0"><title>DisableIrqs()</title> <p>Implement the <codeph>DisableIrqs()</codeph> function.
       
   236 This is called by the LDD to disable (all) interrupts during critical sections,
       
   237 for example, during LDD buffer manipulation. It calls the kernel utility to
       
   238 perform the task. </p> </section>
       
   239 <section id="GUID-BFE0DF32-3D2A-4D86-8BEE-6EB5AF32C3BB"><title>RestoreIrqs()</title> <p>Implement the <codeph>RestoreIrqs()</codeph> function,
       
   240 called by the LDD to enable (all) interrupts after critical sections have
       
   241 completed. Calls the kernel utility to perform the task. </p> </section>
       
   242 <section id="GUID-96B9D6FE-1E2C-45C0-B7F4-E5CF9B5BD802"><title>EnableTransmit()</title> <p>Implement the <codeph>EnableTransmit()</codeph> function.
       
   243 This initialises the UART transmit hardware, and the transmit ISR code path.
       
   244 This function can be called from the ISR (on receipt of an unblocking XON
       
   245 character), or to start a transmission of a LDD originated data buffer. It
       
   246 causes the UART to generate Tx service interrupts as it finishes transmitting
       
   247 a FIFOs worth of data, so that the entire buffer (passed by the LDD) can be
       
   248 sent under interrupt control. </p> </section>
       
   249 <section id="GUID-593C5E94-A188-48C4-BB02-07268735270A"><title>Data handling routines</title> <p>Implement the main data
       
   250 handling routines. These are entirely dependent on the UART hardware interface
       
   251 and cannot therefore be described generally. They are typically driven by
       
   252 the interrupt service routine as asynchronous events from the UART (eg. data
       
   253 received, finished transmission of data, change in handshaking/flow control
       
   254 inputs) occur. </p> <p>The main ISR is typically driven by an interrupt multiplexed
       
   255 from all the sources in the UART. The ISR, therefore, needs to determine which
       
   256 of the interrupt sources requires attention. Since the most critical source
       
   257 is the data received state, as this requires that the data is processed before
       
   258 following data overwrites earlier data, then this is usually the signal to
       
   259 be checked first. To avoid wasting time, the error state of the data is also
       
   260 checked – data that has bad parity or framing must be noted as such. Typically
       
   261 the receive path will save the currently available data into a temporary buffer,
       
   262 and queue a DFC to process the data further at a later time, when more client
       
   263 thread context is available (though this is a function of the LDD). The receive
       
   264 ISRr just passes the location of the ISR buffer into an LDD function which
       
   265 queues a DFC to process it. </p> <p>The transmit path, called when the transmit
       
   266 FIFO contents drop below a programmable number, merely requests more data
       
   267 from the LDD. If there is none available it disables the transmit interrupt
       
   268 so as to prevent further requests when there is no data to be sent. Further
       
   269 data to transmit will cause the transmit FIFO empty interrupt to be re-enabled.
       
   270 Hence the start of any transmission is always performed on an explicit start
       
   271 request from the LDD and then continues under PDD interrupt control until
       
   272 the source data is exhausted. </p> <p>The status notification path is present
       
   273 to inform the upstream LDD of changes in the input status signals (MODEM and
       
   274 flow control status). The UART can generate interrupts when any input handshake
       
   275 line changes state – the ISR merely reads the current state and queues a handler
       
   276 DFC so that the LDD can be informed. The LDD is responsible for determining
       
   277 what status change has occurred and dealing with it. </p> </section>
       
   278 </conbody></concept>