Home | History | Annotate | Download | only in trusty
      1 <html devsite>
      2   <head>
      3     <title>Trusty API Reference</title>
      4     <meta name="project_path" value="/_project.yaml" />
      5     <meta name="book_path" value="/_book.yaml" />
      6   </head>
      7   <body>
      8   <!--
      9       Copyright 2017 The Android Open Source Project
     10 
     11       Licensed under the Apache License, Version 2.0 (the "License");
     12       you may not use this file except in compliance with the License.
     13       You may obtain a copy of the License at
     14 
     15           http://www.apache.org/licenses/LICENSE-2.0
     16 
     17       Unless required by applicable law or agreed to in writing, software
     18       distributed under the License is distributed on an "AS IS" BASIS,
     19       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     20       See the License for the specific language governing permissions and
     21       limitations under the License.
     22   -->
     23 
     24 
     25 
     26 <p>The <a href="index.html">Trusty</a> API generally describes the
     27 Trusty inter-process communication (IPC)
     28 system, including communications with the non-secure world. This page defines the
     29 relevant terms and provides a reference for the API
     30 calls.</p>
     31 
     32 <h2 id=ports_and_channels>Ports and channels</h2>
     33 
     34 <p>Ports are used by Trusty applications to expose service end-points in the form
     35 of a named path to which clients connect. This gives a simple, string-based
     36 service ID for clients to use. The naming convention is reverse-DNS-style
     37 naming, e.g. <code>com.google.servicename</code>.</p>
     38 
     39 <p>When a client connects to a port, the client receives a channel for interacting
     40 with a service. The service must accept an incoming connection, and when it
     41 does, it too receives a channel. In essence, ports are used to look up services
     42 and then communication occurs over a pair of connected channels (i.e.,
     43 connection instances on a port). When a client connects to a port, a symmetric,
     44 bi-directional connection is established. Using this full-duplex path, clients
     45 and servers can exchange arbitrary messages until either side decides to tear
     46 down the connection.</p>
     47 
     48 <p>Only secure-side trusted applications or Trusty kernel modules can create
     49 ports. Applications running on the non-secure side (in the normal world) can
     50 only connect to services published by the secure side.</p>
     51 
     52 <p>Depending on requirements, a trusted application can be both a client and a
     53 server at the same time. A trusted application that publishes a service (as a
     54 server) might need to connect to other services (as a client).</p>
     55 
     56 <h2 id=handle_api>Handle API</h2>
     57 
     58 <p>Handles are unsigned integers representing resources such as ports and
     59 channels, similar to file descriptors in UNIX. After handles are created, they
     60 are placed into an application-specific handle table and can be referenced
     61 later.</p>
     62 
     63 <p>A caller can associate private data with a handle by using
     64 the <code>set_cookie()</code> method.</p>
     65 
     66 <h3 id=methods_handle_api>Methods in the Handle API</h3>
     67 
     68 <p>Handles are only valid in the context of an application. An application should
     69 not pass the value of a handle to other applications unless explicitly
     70 specified. A handle value only should be interpreted by comparing it with
     71 the <code>INVALID_IPC_HANDLE #define,</code> which an application can use as an
     72 indication that a handle is invalid or unset.</p>
     73 
     74 <h4 id=set_cookie>set_cookie()</h4>
     75 
     76 <p>Associates the caller-provided private data with a specified handle.</p>
     77 
     78 <pre class="prettyprint">
     79 long set_cookie(uint32_t handle, void *cookie)
     80 </pre>
     81 
     82 <p>[in] <code>handle</code>: Any handle returned by one of the API calls</p>
     83 
     84 <p>[in] <code>cookie</code>: Pointer to arbitrary user-space data in the Trusty application</p>
     85 
     86 <p>[retval]: <code>NO_ERROR</code> on success, <code>&lt; 0</code> error code otherwise</p>
     87 
     88 <p>This call is useful for handling events when they occur at a later time after
     89 the handle has been created. The event-handling mechanism supplies the handle
     90 and its cookie back to the event handler.</p>
     91 
     92 <p>Handles can be waited upon for events by using the <code>wait()</code>
     93 or <code>wait_any()</code> calls.</p>
     94 
     95 <h4 id=wait>wait()</h4>
     96 
     97 <p>Waits for an event to occur on a given handle for specified period of time.</p>
     98 
     99 <pre class="prettyprint">
    100 long wait(uint32_t handle_id, uevent_t *event, unsigned long timeout_msecs)
    101 </pre>
    102 
    103 <p>[in] <code>handle_id</code>: Any handle returned by one of the API calls</p>
    104 
    105 <p>[out] <code>event</code>: A pointer to the structure representing
    106 an event that occurred on this handle</p>
    107 
    108 <p>[in] <code>timeout_msecs</code>: A timeout value in milliseconds; a
    109 value of -1 is an infinite timeout</p>
    110 
    111 <p>[retval]: <code>NO_ERROR</code> if a valid event occurred within a
    112 specified timeout interval; <code>ERR_TIMED_OUT</code> if a specified timeout elapsed but no
    113 event has occurred; <code>&lt; 0</code> for other errors</p>
    114 
    115 <h4 id=wait_any>wait_any()</h4>
    116 
    117 <p>Waits for any event to occur on any handle in the application handle table for
    118 the specified period of time.</p>
    119 
    120 <pre class="prettyprint">
    121 long wait_any(uevent_t *event, unsigned long timeout_msecs);
    122 </pre>
    123 
    124 <p>[out] <code>event</code>: A pointer to the structure representing an
    125 event that occurred on this handle</p>
    126 
    127 <p>[in] <code>timeout_msecs</code>: A timeout value in milliseconds.
    128 A value of -1 is an infinite timeout</p>
    129 
    130 <p>[retval]: <code>NO_ERROR</code> if a valid event occurred within a
    131 specified timeout interval; <code>ERR_TIMED_OUT</code> if a specified timeout elapsed but no
    132 event has occurred; <code>&lt; 0</code> for other errors</p>
    133 
    134 <p>Upon success (<code>retval == NO_ERROR</code>), the <code>wait()</code>
    135 and <code>wait_any()</code> calls
    136 fill a specified <code>uevent_t</code> structure with information about
    137 the event that occurred.</p>
    138 
    139 <pre class="prettyprint">
    140 typedef struct uevent {
    141     uint32_t handle; /* handle this event is related to */
    142     uint32_t event;  /* combination of IPC_HANDLE_POLL_XXX flags */
    143     void    *cookie; /* cookie associated with this handle */
    144 } uevent_t;
    145 </pre>
    146 
    147 <p>The <code>event</code> field contains a combination of the following values:</p>
    148 
    149 <pre class="prettyprint">
    150 enum {
    151   IPC_HANDLE_POLL_NONE    = 0x0,
    152   IPC_HANDLE_POLL_READY   = 0x1,
    153   IPC_HANDLE_POLL_ERROR   = 0x2,
    154   IPC_HANDLE_POLL_HUP     = 0x4,
    155   IPC_HANDLE_POLL_MSG     = 0x8,
    156   IPC_HANDLE_POLL_SEND_UNBLOCKED = 0x10,
    157    more values[TBD]
    158 };
    159 </pre>
    160 
    161 <p><code>IPC_HANDLE_POLL_NONE</code> - no events are actually pending,
    162 caller should restart the wait</p>
    163 
    164 <p><code>IPC_HANDLE_POLL_ERROR</code> - an unspecified internal error has occurred</p>
    165 
    166 <p><code>IPC_HANDLE_POLL_READY</code> - depends on the handle type, as follows:</p>
    167 
    168 <ul>
    169   <li>For ports, this value indicates that there is a pending connection
    170   <li>For channels, this value indicates that an asynchronous connection
    171   (see <code>connect()</code>) was established
    172 </ul>
    173 
    174 <p>The following events are only relevant for channels:</p>
    175 
    176 <ul>
    177   <li><code>IPC_HANDLE_POLL_HUP</code> - indicates that a channel has been closed by a peer
    178   <li><code>IPC_HANDLE_POLL_MSG</code> - indicates that there is a pending message for this channel
    179   <li><code>IPC_HANDLE_POLL_SEND_UNBLOCKED</code> - indicates that a previously
    180   send-blocked caller may attempt to send a
    181   message again (see the description of <code>send_msg()</code> for details)
    182 </ul>
    183 
    184 <p>An event handler should be prepared to handle a combination of specified
    185 events, as multiple bits might be set at the same time. For example, for a
    186 channel, it is possible to have pending messages, and a connection closed by a
    187 peer at the same time.</p>
    188 
    189 <p>Most events are sticky. They persist as long as the underlying condition
    190 persists (for example all pending messages are received and pending connection
    191 requests are handled). The exception is the case of
    192 the <code>IPC_HANDLE_POLL_SEND_UNBLOCKED</code> event, which
    193 is cleared upon a read and the application has only one chance to
    194 handle it.</p>
    195 
    196 <p>Handles can be destroyed by calling the <code>close()</code> method.</p>
    197 
    198 <h4 id=close>close()</h4>
    199 
    200 <p>Destroys the resource associated with the specified handle and removes it from
    201 the handle table.</p>
    202 
    203 <pre class="prettyprint">
    204 long close(uint32_t handle_id);
    205 </pre>
    206 
    207 <p>[in] <code>handle_id</code>: Handle to destroy</p>
    208 
    209 <p>[retval]: 0 if success; a negative error otherwise</p>
    210 
    211 <h2 id=server_api>Server API</h2>
    212 
    213 <p>A server begins by creating one or more <strong>named ports</strong> representing
    214 its service end-points. Each port is represented by a handle.</p>
    215 
    216 <h3 id=methods_server_api>Methods in the Server API</h3>
    217 
    218 <h4 id=port_create>port_create()</h4>
    219 
    220 <p>Creates a named service port.</p>
    221 
    222 <pre class="prettyprint">
    223 long port_create (const char *path, uint num_recv_bufs, size_t recv_buf_size,
    224 uint32_t flags)
    225 </pre>
    226 
    227 <p>[in] <code>path</code>: The string name of the port (as described above). This
    228 name should be unique across the system; attempts to create a duplicate will fail.</p>
    229 
    230 <p>[in] <code>num_recv_bufs</code>: The maximum number of buffers that a channel on
    231 this port can pre-allocate to facilitate the exchange of data with the client. Buffers are counted
    232 separately for data going in both directions, so specifying 1 here would mean 1
    233 send and 1 receive buffer are preallocated. In general, the number of buffers
    234 required depends on the higher-level protocol agreement between the client and
    235 server. The number can be as little as 1 in case of a very synchronous protocol
    236 (send message, receive reply before sending another). But the number can be
    237 more if the client expects to send more than one message before a reply can
    238 appear (e.g, one message as a prologue and another as the actual command). The
    239 allocated buffer sets are per channel, so two separate connections (channels)
    240 would have separate buffer sets.</p>
    241 
    242 <p>[in] <code>recv_buf_size</code>: Maximum size of each individual buffer in the
    243 above buffer set. This value is
    244 protocol-dependent and effectively limits maximum message size you can exchange
    245 with peer</p>
    246 
    247 <p>[in] <code>flags</code>: A combination of flags that specifies additional port behavior</p>
    248 
    249 <p>This value should be a combination of the following values:</p>
    250 
    251 <p><code>IPC_PORT_ALLOW_TA_CONNECT</code> - allows a connection from other secure apps</p>
    252 
    253 <p><code>IPC_PORT_ALLOW_NS_CONNECT</code> - allows a connection from the non-secure world</p>
    254 
    255 <p>[retval]: Handle to the port created if non-negative or a specific error if
    256 negative</p>
    257 
    258 <p>The server then polls the list of port handles for incoming connections
    259 using <code>wait()</code> or <code>wait_any()</code> calls. Upon receiving a connection
    260 request indicated by the <code>IPC_HANDLE_POLL_READY</code> bit set in
    261 the <code>event</code> field of the <code>uevent_t</code> structure, the
    262 server should call <code>accept()</code> to finish establishing a connection and create a
    263 channel (represented by
    264 another handle) that can then be polled for incoming messages.</p>
    265 
    266 <h4 id=accept>accept()</h4>
    267 
    268 <p>Accepts an incoming connection and gets a handle to a channel.</p>
    269 
    270 <pre class="prettyprint">
    271 long accept(uint32_t handle_id, uuid_t *peer_uuid);
    272 </pre>
    273 
    274 <p>[in] <code>handle_id</code>: Handle representing the port to which a client has connected</p>
    275 
    276 <p>[out] <code>peer_uuid</code>: Pointer to a <code>uuud_t</code> structure to be
    277 filled with the UUID of the connecting client application. It
    278 will be set to all zeros if the connection originated from the non-secure world</p>
    279 
    280 <p>[retval]: Handle to a channel (if non-negative) on which the server can
    281 exchange messages with the client (or an error code otherwise)</p>
    282 
    283 <h2 id=client_api>Client API</h2>
    284 
    285 <p>This section contains the methods in the Client API.</p>
    286 
    287 <h3 id=methods_client_api>Methods in the Client API</h3>
    288 
    289 <h4 id=connect>connect()</h4>
    290 
    291 <p>Initiates a connection to a port specified by name.</p>
    292 
    293 <pre class="prettyprint">
    294 long connect(const char *path, uint flags);
    295 </pre>
    296 
    297 <p>[in] <code>path</code>: Name of a port published by a Trusty application</p>
    298 
    299 <p>[in] <code>flags</code>: Specifies additional, optional behavior</p>
    300 
    301 <p>[retval]: Handle to a channel over which messages can be exchanged with the
    302 server; error if negative</p>
    303 
    304 <p>If no <code>flags</code> are specified (the <code>flags</code> parameter
    305 is set to 0), calling <code>connect()</code> initiates a synchronous connection
    306 to a specified port that immediately
    307 returns an error if the port does not exist, and creates a block until the
    308 server otherwise accepts a connection.</p>
    309 
    310 <p>This behavior can be altered by specifying a combination of two values,
    311 described below:</p>
    312 
    313 <pre class="prettyprint">
    314 enum {
    315 IPC_CONNECT_WAIT_FOR_PORT = 0x1,
    316 IPC_CONNECT_ASYNC = 0x2,
    317 };
    318 </pre>
    319 
    320 <p><code>IPC_CONNECT_WAIT_FOR_PORT</code> - forces a <code>connect()</code>
    321 call to wait if the specified port does not immediately exist at execution,
    322 instead of failing immediately.</p>
    323 
    324 <p><code>IPC_CONNECT_ASYNC</code> - if set, initiates an asynchronous connection. An
    325 application has to poll for
    326 the returned handle (by calling <code>wait()</code> or <code>wait_any()</code>) for
    327 a connection completion event indicated by the <code>IPC_HANDLE_POLL_READY</code>
    328 bit set in the event field of the <code>uevent_t</code> structure before starting
    329 normal operation.</p>
    330 
    331 <h2 id=messaging_api>Messaging API</h2>
    332 
    333 <p>The Messaging API calls enable the sending and reading of messages over a
    334 previously established connection (channel). The Messaging API calls are the
    335 same for servers and clients.</p>
    336 
    337 <p>A client receives a handle to a channel by issuing a <code>connect()</code>
    338 call, and a server gets a channel handle from an <code>accept()</code> call,
    339 described above.</p>
    340 
    341 <h4 id=structure_of_a_trusty_message>Structure of a Trusty message</h4>
    342 
    343 <p>As shown in the following, messages exchanged by the Trusty API have a minimal
    344 structure, leaving it to the server and client to agree on the semantics of the
    345 actual contents:</p>
    346 
    347 <pre class="prettyprint">
    348 /*
    349  *  IPC message
    350  */
    351 typedef struct iovec {
    352         void   *base;
    353         size_t  len;
    354 } iovec_t;
    355 
    356 typedef struct ipc_msg {
    357         uint     num_iov; /* number of iovs in this message */
    358         iovec_t  *iov;    /* pointer to iov array */
    359 
    360         uint     num_handles; /* reserved, currently not supported */
    361         handle_t *handles;    /* reserved, currently not supported */
    362 } ipc_msg_t;
    363 </pre>
    364 
    365 <p>A message can be composed of one or more non-contiguous buffers represented by
    366 an array of <code>iovec_t</code> structures. Trusty performs scatter-gather
    367 reads and writes to these blocks
    368 using the <code>iov</code> array. The content of buffers that can be described
    369 by the <code>iov</code> array is completely arbitrary.</p>
    370 
    371 <h3 id=methods_messaging_api>Methods in the Messaging API</h3>
    372 
    373 <h4 id=send_msg>send_msg()</h4>
    374 
    375 <p>Sends a message over a specified channel.</p>
    376 
    377 <pre class="prettyprint">
    378 long send_msg(uint32_t handle, ipc_msg_t *msg);
    379 </pre>
    380 
    381 <p>[in] <code>handle</code>: Handle to the channel over which to send the message</p>
    382 
    383 <p>[in] <code>msg</code>: Pointer to the <code>ipc_msg_t structure</code> describing the message</p>
    384 
    385 <p>[retval]: Total number of bytes sent on success; a negative error otherwise</p>
    386 
    387 <p>If the client (or server) is trying to send a message over the channel and
    388 there is no space in the destination peer message queue, the channel might
    389 enter a send-blocked state (this should never happen for a simple synchronous
    390 request/reply protocol but might happen in more complicated cases) that is
    391 indicated by returning an <code>ERR_NOT_ENOUGH_BUFFER</code> error code.
    392 In such a case the caller must wait until the peer frees some
    393 space in its receive queue by retrieving the handling and retiring messages,
    394 indicated by the <code>IPC_HANDLE_POLL_SEND_UNBLOCKED</code> bit set in
    395 the <code>event</code> field of the <code>uevent_t</code> structure
    396 returned by the <code>wait()</code> or <code>wait_any()</code> call.</p>
    397 
    398 <h4 id=get_msg>get_msg()</h4>
    399 
    400 <p>Gets meta-information about the next message in an incoming message queue</p>
    401 
    402 <p>of a specified channel.</p>
    403 
    404 <pre class="prettyprint">
    405 long get_msg(uint32_t handle, ipc_msg_info_t *msg_info);
    406 </pre>
    407 
    408 <p>[in] <code>handle</code>: Handle of the channel on which a new message must be retrieved</p>
    409 
    410 <p>[out] <code>msg_info</code>: Message information structure described as follows:</p>
    411 
    412 <pre class="prettyprint">
    413 typedef struct ipc_msg_info {
    414         size_t    len;  /* total message length */
    415         uint32_t  id;   /* message id */
    416 } ipc_msg_info_t;
    417 </pre>
    418 
    419 <p>Each message is assigned a unique ID across the set of outstanding messages,
    420 and the total length of each message is filled in. If configured and allowed by the
    421 protocol, there can be multiple outstanding (opened) messages at once for a
    422 particular channel.</p>
    423 
    424 <p>[retval]: <code>NO_ERROR</code> on success; a negative error otherwise</p>
    425 
    426 <h4 id=read_msg>read_msg()</h4>
    427 
    428 <p>Reads the content of the message with the specified ID starting from the
    429 specified offset.</p>
    430 
    431 <pre class="prettyprint">
    432 long read_msg(uint32_t handle, uint32_t msg_id, uint32_t offset, ipc_msg_t
    433 *msg);
    434 </pre>
    435 
    436 <p>[in] <code>handle</code>: Handle of the channel from which to read the message</p>
    437 
    438 <p>[in] <code>msg_id</code>: ID of the message to read</p>
    439 
    440 <p>[in] <code>offset</code>: Offset into the message from which to start reading</p>
    441 
    442 <p>[in] <code>msg</code>: Pointer to the <code>ipc_msg_t</code> structure describing
    443 a set of buffers into which to store incoming message
    444 data</p>
    445 
    446 <p>[retval]: Total number of bytes stored in the <code>dst</code> buffers on
    447 success; a negative error otherwise</p>
    448 
    449 <p>The <code>read_msg</code> method can be called multiple times starting at
    450 a different (not necessarily
    451 sequential) offset as needed.</p>
    452 
    453 <h4 id=put_msg>put_msg()</h4>
    454 
    455 <p>Retires a message with a specified ID.</p>
    456 
    457 <pre class="prettyprint">
    458 long put_msg(uint32_t handle, uint32_t msg_id);
    459 </pre>
    460 
    461 <p>[in] <code>handle</code>: Handle of the channel on which the message has arrived</p>
    462 
    463 <p>[in] <code>msg_id</code>: ID of message being retired</p>
    464 
    465 <p>[retval]: <code>NO_ERROR</code> on success; a negative error otherwise</p>
    466 
    467 <p>Message content cannot be accessed after a message has been retired and the
    468 buffer it occupied has been freed.</p>
    469 
    470 <h2 id=file_descriptor_api>File Descriptor API</h2>
    471 
    472 <p>The File Descriptor API includes <code>read()</code>, <code>write()</code>,
    473 and <code>ioctl()</code> calls. All of these calls can operate on a predefined (static) set of file
    474 descriptors traditionally represented by small numbers. In the current
    475 implementation, the file descriptor space is separate from the IPC handle
    476 space. The File Descriptor API in Trusty is
    477 similar to a traditional file descriptor-based API.</p>
    478 
    479 <p>By default, there are 3 predefined (standard and well-known) file descriptors:</p>
    480 
    481 <ul>
    482   <li>0 - standard input. The default implementation of standard input <code>fd</code>
    483   is a no-op (as trusted applications are not expected to have an interactive
    484 console) so reading, writing or invoking <code>ioctl()</code> on <code>fd</code> 0
    485 should return an <code>ERR_NOT_SUPPORTED</code> error.
    486   <li>1 - standard output. Data written to standard output can be routed (depending
    487 on the LK debug level) to UART and/or a memory log available on the non-secure
    488 side, depending on the platform and configuration. Non-critical debug logs and
    489 messages should go in standard output. The <code>read()</code> and <code>ioctl()</code>
    490 methods are no-ops and should return an <code>ERR_NOT_SUPPORTED</code> error.
    491   <li>2 - standard error. Data written to standard error should be routed to the UART
    492 or memory log available on the non-secure side, depending on the platform and
    493 configuration. It is recommended to write only critical messages to standard
    494 error, as this stream is very likely to be unthrottled. The <code>read()</code> and
    495 <code>ioctl()</code> methods are no-ops and should return an <code>ERR_NOT_SUPPORTED</code> error.
    496 </ul>
    497 
    498 <p>Even though this set of file descriptors can be extended to implement more
    499 <code>fds</code> (to implement platform-specific extensions), extending file descriptors needs
    500 to be exercised with caution. Extending file descriptors is prone to create
    501 conflicts and is not generally recommended.</p>
    502 
    503 <h3 id=methods_file_descriptor_api>Methods in the File Descriptor API</h3>
    504 
    505 <h4 id=read>read()</h4>
    506 
    507 <p>Attempts to read up to <code>count</code> bytes of data from a specified file descriptor.</p>
    508 
    509 <pre class="prettyprint">
    510 long read(uint32_t fd, void *buf, uint32_t count);
    511 </pre>
    512 
    513 <p>[in] <code>fd</code>: File descriptor from which to read</p>
    514 
    515 <p>[out] <code>buf</code>: Pointer to a buffer into which to store data</p>
    516 
    517 <p>[in] <code>count</code>: Maximum number of bytes to read</p>
    518 
    519 <p>[retval]: Returned number of bytes read; a negative error otherwise</p>
    520 
    521 <h4 id=write>write()</h4>
    522 
    523 <p>Writes up to <code>count</code> bytes of data to specified file descriptor.</p>
    524 
    525 <pre class="prettyprint">
    526 long write(uint32_t fd, void *buf, uint32_t count);
    527 </pre>
    528 
    529 <p>[in] <code>fd</code>: File descriptor to which to write</p>
    530 
    531 <p>[out] <code>buf</code>: Pointer to data to write</p>
    532 
    533 <p>[in] <code>count</code>: Maximum number of bytes to write</p>
    534 
    535 <p>[retval]: Returned number of bytes written; a negative error otherwise</p>
    536 
    537 <h4 id=ioctl>ioctl()</h4>
    538 
    539 <p>Invokes a specified <code>ioctl</code> command for a given file descriptor.</p>
    540 
    541 <pre class="prettyprint">
    542 long ioctl(uint32_t fd, uint32_t cmd, void *args);
    543 </pre>
    544 
    545 <p>[in] <code>fd</code>: File descriptor on which to invoke <code>ioctl()</code></p>
    546 
    547 <p>[in] <code>cmd</code>: The <code>ioctl</code> command</p>
    548 
    549 <p>[in/out] <code>args</code>: Pointer to <code>ioctl()</code> arguments</p>
    550 
    551 <h2 id=miscellaneous_api>Miscellaneous API</h2>
    552 
    553 <h3 id=methods_misc_api>Methods in the Miscellaneous API</h3>
    554 
    555 <h4 id=gettime>gettime()</h4>
    556 
    557 <p>Returns the current system time (in nanoseconds).</p>
    558 
    559 <pre class="prettyprint">
    560 long gettime(uint32_t clock_id, uint32_t flags, uint64_t *time);
    561 </pre>
    562 
    563 <p>[in] <code>clock_id</code>: Platform-dependent; pass zero for default</p>
    564 
    565 <p>[in] <code>flags</code>: Reserved, should be zero</p>
    566 
    567 <p>[in] <code>time</code>: Pointer to an <code>int64_t</code> value to which to store the current time</p>
    568 
    569 <p>[retval]: <code>NO_ERROR</code> on success; a negative error otherwise</p>
    570 
    571 <h4 id=nanosleep>nanosleep()</h4>
    572 
    573 <p>Suspends execution of the calling application for a specified period of time
    574 and resumes it after that period.</p>
    575 
    576 <pre class="prettyprint">
    577 long nanosleep(uint32_t clock_id, uint32_t flags, uint64_t sleep_time)
    578 </pre>
    579 
    580 <p>[in] <code>clock_id</code>: Reserved, should be zero</p>
    581 
    582 <p>[in] <code>flags</code>: Reserved, should be zero</p>
    583 
    584 <p>[in] <code>sleep_time</code>: Sleep time in nanoseconds</p>
    585 
    586 <p>[retval]: <code>NO_ERROR</code> on success; a negative error otherwise</p>
    587 
    588 <h2 id=example_of_a_trusted_application_server>Example of a trusted application server</h2>
    589 
    590 <p>The following sample application shows the usage of the above APIs. The sample
    591 creates an "echo" service that handles multiple incoming connections and
    592 reflects back to the caller all messages it receives from clients originated
    593 from the secure or non-secure side.</p>
    594 
    595 <pre class="prettyprint">
    596 #include &lt;assert.h>
    597 #include &lt;err.h>
    598 #include &lt;stddef.h>
    599 #include &lt;stdio.h>
    600 #include &lt;stdlib.h>
    601 #include &lt;string.h>
    602 #include &lt;trusty_std.h>
    603 
    604 #include &lt;app/echo/uuids.h>
    605 
    606 #define LOG_TAG "echo_srv"
    607 
    608 #define TLOGE(fmt, ...) \
    609     fprintf(stderr, "%s: %d: " fmt, LOG_TAG, __LINE__,  ## __VA_ARGS__)
    610 
    611 #define MAX_ECHO_MSG_SIZE  64
    612 
    613 static const char *srv_name = "com.android.echo.srv.echo";
    614 
    615 static uint8_t msg_buf[MAX_ECHO_MSG_SIZE];
    616 
    617 /*
    618  *  Message handler
    619  */
    620 static int handle_msg(handle_t chan)
    621 {
    622   int rc;
    623   iovec_t iov;
    624   ipc_msg_t msg;
    625   ipc_msg_info_t msg_inf;
    626 
    627   iov.base = msg_buf;
    628   iov.len  = sizeof(msg_buf);
    629 
    630   msg.num_iov = 1;
    631   msg.iov = &iov;
    632   msg.num_handles = 0;
    633   msg.handles  = NULL;
    634 
    635   /* get message info */
    636   rc = get_msg(chan, &msg_inf);
    637   if (rc == ERR_NO_MSG)
    638     return NO_ERROR; /* no new messages */
    639 
    640   if (rc != NO_ERROR) {
    641     TLOGE("failed (%d) to get_msg for chan (%d)\n",
    642           rc, chan);
    643     return rc;
    644   }
    645 
    646   /* read msg content */
    647   rc = read_msg(chan, msg_inf.id, 0, &msg);
    648   if (rc &lt; 0) {
    649     TLOGE("failed (%d) to read_msg for chan (%d)\n",
    650           rc, chan);
    651     return rc;
    652   }
    653 
    654   /* update number of bytes received */
    655   iov.len = (size_t) rc;
    656 
    657   /* send message back to the caller */
    658   rc = send_msg(chan, &msg);
    659   if (rc &lt; 0) {
    660     TLOGE("failed (%d) to send_msg for chan (%d)\n",
    661           rc, chan);
    662     return rc;
    663   }
    664 
    665   /* retire message */
    666   rc = put_msg(chan, msg_inf.id);
    667   if ( rc != NO_ERROR) {
    668     TLOGE("failed (%d) to put_msg for chan (%d)\n",
    669           rc, chan);
    670     return rc;
    671   }
    672 
    673   return NO_ERROR;
    674 }
    675 
    676 /*
    677  *  Channel event handler
    678  */
    679 static void handle_channel_event(const uevent_t *ev)
    680 {
    681   int rc;
    682 
    683   if (ev->event & IPC_HANDLE_POLL_MSG) {
    684     rc = handle_msg(ev->handle);
    685     if (rc != NO_ERROR) {
    686       /* report an error and close channel */
    687       TLOGE("failed (%d) to handle event on channel %d\n",
    688              rc, ev->handle);
    689       close(ev->handle);
    690     }
    691     return;
    692   }
    693   if (ev->event & IPC_HANDLE_POLL_HUP) {
    694     /* closed by peer. */
    695     close(ev->handle);
    696     return;
    697   }
    698 }
    699 
    700 /*
    701  *  Port event handler
    702  */
    703 static void handle_port_event(const uevent_t *ev)
    704 {
    705   uuid_t peer_uuid;
    706 
    707   if ((ev->event & IPC_HANDLE_POLL_ERROR) ||
    708       (ev->event & IPC_HANDLE_POLL_HUP) ||
    709       (ev->event & IPC_HANDLE_POLL_MSG) ||
    710       (ev->event & IPC_HANDLE_POLL_SEND_UNBLOCKED)) {
    711     /* should never happen with port handles */
    712     TLOGE("error event (0x%x) for port (%d)\n",
    713            ev->event, ev->handle);
    714     abort();
    715   }
    716   if (ev->event & IPC_HANDLE_POLL_READY) {
    717     /* incoming connection: accept it */
    718     int rc = accept(ev->handle, &peer_uuid);
    719     if (rc &lt; 0) {
    720       TLOGE("failed (%d) to accept on port %d\n",
    721              rc, ev->handle);
    722       return;
    723     }
    724   }
    725 }
    726 
    727 /*
    728  *  Main application entry point
    729  */
    730 int main(void)
    731 {
    732   int rc;
    733   handle_t port;
    734 
    735   /* Initialize service */
    736   rc = port_create(srv_name, 1, MAX_ECHO_MSG_SIZE,
    737        IPC_PORT_ALLOW_NS_CONNECT |
    738        IPC_PORT_ALLOW_TA_CONNECT );
    739   if (rc &lt; 0) {
    740     TLOGE("Failed (%d) to create port %s\n",
    741           rc, srv_name);
    742     abort();
    743   }
    744   port = (handle_t)rc;
    745   
    746   /* enter main event loop */
    747   while (true) {
    748     uevent_t ev;
    749 
    750     ev.handle = INVALID_IPC_HANDLE;
    751     ev.event  = 0;
    752     ev.cookie = NULL;
    753 
    754     /* wait forever */
    755     rc = wait_any(&ev, -1);
    756     if (rc == NO_ERROR) {
    757       /* got an event */
    758       if (ev.handle == port) {
    759         handle_port_event(&ev);
    760       } else {
    761         handle_channel_event(&ev);
    762       }
    763     } else {
    764       TLOGE("wait_any returned (%d)\n", rc);
    765       abort();
    766     }
    767   }
    768   return 0;
    769 }
    770 </pre>
    771 
    772 <h2 id=example_of_a_trusted_application_client>Example of a trusted application client</h2>
    773 
    774 <p>The following code snippets show the use of the Trusty messaging APIs to
    775 implement a client of an "echo" service (shown in the code above). The <code>sync_connect()</code>
    776 method shows an implementation of a synchronous connect with a timeout on top
    777 of an asynchronous <code>connect()</code> call.</p>
    778 
    779 <pre class="prettyprint">
    780 /*
    781  *  Local wrapper on top of an async connect that provides a
    782  *  synchronous connect with timeout.
    783  */
    784 int sync_connect(const char *path, uint timeout)
    785 {
    786   int rc;
    787   uevent_t evt;
    788   handle_t chan;
    789 
    790   rc = connect(path, IPC_CONNECT_ASYNC | IPC_CONNECT_WAIT_FOR_PORT);
    791   if (rc >= 0) {
    792     chan = (handle_t) rc;
    793     rc = wait(chan, &evt, timeout);
    794     if (rc == 0) {
    795       rc = ERR_BAD_STATE;
    796       if (evt.handle == chan) {
    797         if (evt.event & IPC_HANDLE_POLL_READY)
    798           return chan;
    799         if (evt.event & IPC_HANDLE_POLL_HUP)
    800           rc = ERR_CHANNEL_CLOSED;
    801       }
    802     }
    803     close(chan);
    804   }
    805   return rc;
    806 }
    807 </pre>
    808 
    809 <p>The <code>run_end_to_end_msg_test()</code> method sends 10,000 messages asynchronously
    810 to the "echo" service and handles
    811 replies.</p>
    812 
    813 <pre class="prettyprint">
    814 static int run_echo_test(void)
    815 {
    816   int rc;
    817   handle_t chan;
    818   uevent_t uevt;
    819   uint8_t tx_buf[64];
    820   uint8_t rx_buf[64];
    821   ipc_msg_info_t inf;
    822   ipc_msg_t   tx_msg;
    823   iovec_t     tx_iov;
    824   ipc_msg_t   rx_msg;
    825   iovec_t     rx_iov;
    826 
    827   /* prepare tx message buffer */
    828   tx_iov.base = tx_buf;
    829   tx_iov.len  = sizeof(tx_buf);
    830   tx_msg.num_iov = 1;
    831   tx_msg.iov     = &tx_iov;
    832   tx_msg.num_handles = 0;
    833   tx_msg.handles = NULL;
    834 
    835   memset (tx_buf, 0x55, sizeof(tx_buf));
    836 
    837   /* prepare rx message buffer */
    838   rx_iov.base = rx_buf;
    839   rx_iov.len  = sizeof(rx_buf);
    840   rx_msg.num_iov = 1;
    841   rx_msg.iov     = &rx_iov;
    842   rx_msg.num_handles = 0;
    843   rx_msg.handles = NULL;
    844 
    845   /* open connection to echo service */
    846   rc = sync_connect(srv_name, 1000);
    847   if(rc &lt; 0)
    848     return rc;
    849 
    850   /* got channel */
    851   chan = (handle_t)rc;
    852 
    853   /* send/receive 10000 messages asynchronously. */
    854   uint tx_cnt = 10000;
    855   uint rx_cnt = 10000;
    856 
    857   while (tx_cnt || rx_cnt) {
    858     /* send messages until all buffers are full */
    859 while (tx_cnt) {
    860     rc = send_msg(chan, &tx_msg);
    861       if (rc == ERR_NOT_ENOUGH_BUFFER)
    862       break;  /* no more space */
    863     if (rc != 64) {
    864       if (rc > 0) {
    865         /* incomplete send */
    866         rc = ERR_NOT_VALID;
    867 }
    868       goto abort_test;
    869 }
    870     tx_cnt--;
    871   }
    872 
    873   /* wait for reply msg or room */
    874   rc = wait(chan, &uevt, 1000);
    875   if (rc != NO_ERROR)
    876     goto abort_test;
    877 
    878   /* drain all messages */
    879   while (rx_cnt) {
    880     /* get a reply */
    881       rc = get_msg(chan, &inf);
    882     if (rc == ERR_NO_MSG)
    883         break;  /* no more messages  */
    884   if (rc != NO_ERROR)
    885 goto abort_test;
    886 
    887   /* read reply data */
    888     rc = read_msg(chan, inf.id, 0, &rx_msg);
    889   if (rc != 64) {
    890     /* unexpected reply length */
    891     rc = ERR_NOT_VALID;
    892     goto abort_test;
    893 }
    894 
    895   /* discard reply */
    896   rc = put_msg(chan, inf.id);
    897   if (rc != NO_ERROR)
    898     goto abort_test;
    899   rx_cnt--;
    900   }
    901 }
    902 
    903 abort_test:
    904   close(chan);
    905   return rc;
    906 }
    907 </pre>
    908 
    909 <h2 id=non-secure_world_apis_and_applications>Non-secure world APIs and applications</h2>
    910 
    911 <p>A set of Trusty services, published from the secure side and marked with
    912 the <code>IPC_PORT_ALLOW_NS_CONNECT</code> attribute, are accessible to kernel
    913 and user space programs running on the
    914 non-secure side.</p>
    915 
    916 <p>The execution environment on the non-secure side (kernel and user space) is
    917 drastically different from the execution environment on the secure-side.
    918 Therefore, rather than a single library for both environments, there are two
    919 different sets of APIs. In the kernel, the Client API is provided by the
    920 trusty-ipc kernel driver and registers a character device node that can be used
    921 by user space processes to communicate with services running on the secure
    922 side.</p>
    923 
    924 <h3 id=user_space_trusty_ipc_client_api>User space Trusty IPC Client API</h3>
    925 
    926 <p>The user space Trusty IPC Client API library is a thin layer on top of the
    927 device node <code>fd</code>.</p>
    928 
    929 <p>A user space program starts a communication session
    930 by calling <code>tipc_connect()</code>,
    931 initializing a connection to a specified Trusty service. Internally,
    932 the <code>tipc_connect()</code> call opens a specified device node to
    933 obtain a file descriptor and invokes a <code>TIPC_IOC_CONNECT ioctl()</code>
    934 call with the <code>argp</code> parameter pointing to a string containing a
    935 service name to which to connect.</p>
    936 
    937 <pre class="prettyprint">
    938 #define TIPC_IOC_MAGIC  'r'
    939 #define TIPC_IOC_CONNECT  _IOW(TIPC_IOC_MAGIC, 0x80, char *)
    940 </pre>
    941 
    942 <p>The resulting file descriptor can only be used to communicate with the service
    943 for which it was created. The file descriptor should be closed by
    944 calling <code>tipc_close()</code> when the connection is not required anymore.</p>
    945 
    946 <p>The file descriptor obtained by the <code>tipc_connect()</code> call
    947 behaves as a typical character device node; the file descriptor:</p>
    948 
    949 <ul>
    950   <li>Can be switched to non-blocking mode if needed
    951   <li>Can be written to using a standard <code>write()</code>
    952   call to send messages to the other side
    953   <li>Can be polled (using <code>poll()</code> calls or <code>select()</code> calls)
    954   for availability of incoming messages as a regular file descriptor
    955   <li>Can be read to retrieve incoming messages
    956 </ul>
    957 
    958 <p>A caller sends a message to the Trusty service by executing a write call for
    959 the specified <code>fd</code>. All data passed to the above <code>write()</code> call
    960 is transformed into a message by the trusty-ipc driver. The message is
    961 delivered to the secure side where the data is handled by the IPC subsystem in
    962 the Trusty kernel and routed to the proper destination and delivered to an app
    963 event loop as an <code>IPC_HANDLE_POLL_MSG</code> event on a particular channel
    964 handle. Depending on the particular,
    965 service-specific protocol, the Trusty service may send one or more reply
    966 messages that are delivered back to the non-secure side and placed in the
    967 appropriate channel file descriptor message queue to be retrieved by the user
    968 space application <code>read()</code> call.</p>
    969 
    970 <h4 id=tipc_connect>tipc_connect()</h4>
    971 
    972 <p>Opens a specified <code>tipc</code> device node and initiates a
    973 connection to a specified Trusty service.</p>
    974 
    975 <pre class="prettyprint">
    976 int tipc_connect(const char *dev_name, const char *srv_name);
    977 </pre>
    978 
    979 <p>[in] <code>dev_name</code>: Path to the Trusty IPC device node to open</p>
    980 
    981 <p>[in] <code>srv_name</code>: Name of a published Trusty service to which to connect</p>
    982 
    983 <p>[retval]: Valid file descriptor on success, -1 otherwise.</p>
    984 
    985 <h4 id=tipc_close>tipc_close()</h4>
    986 
    987 <p>Closes the connection to the Trusty service specified by a file descriptor.</p>
    988 
    989 <pre class="prettyprint">
    990 int tipc_close(int fd);
    991 </pre>
    992 
    993 <p>[in] <code>fd</code>: File descriptor previously opened by
    994 a <code>tipc_connect()</code> call</p>
    995 
    996 <h2 id=kernel_trusty_ipc_client_api>Kernel Trusty IPC Client API</h2>
    997 
    998 <p>The kernel Trusty IPC Client API is available for kernel drivers. The user
    999 space Trusty IPC API is implemented on top of this API.</p>
   1000 
   1001 <p>In general, typical usage of this API consists of a caller creating
   1002 a <code>struct tipc_chan</code> object by using the <code>tipc_create_channel()</code>
   1003 function and then using the <code>tipc_chan_connect()</code> call to initiate a
   1004 connection to the Trusty IPC service running on the secure
   1005 side. The connection to the remote side can be terminated by
   1006 calling <code>tipc_chan_shutdown()</code> followed by
   1007 <code>tipc_chan_destroy()</code> to clean up resources.</p>
   1008 
   1009 <p>Upon receiving a notification (through the <code>handle_event()</code> callback)
   1010 that a connection has been successfully established, a caller does
   1011 the following:</p>
   1012 
   1013 <ul>
   1014   <li>Obtains a message buffer using the <code>tipc_chan_get_txbuf_timeout()</code> call
   1015   <li>Composes a message, and
   1016   <li>Queues the message using the <code>tipc_chan_queue_msg()</code>
   1017   method for delivery to a Trusty service (on the secure side), to which the
   1018 channel is connected
   1019 </ul>
   1020 
   1021 <p>After queueing is successful, the caller should forget the message buffer
   1022 because the message buffer eventually returns to the free buffer pool after
   1023 processing by the remote side (for reuse later, for other messages). The user
   1024 only needs to call <code>tipc_chan_put_txbuf()</code> if it fails to
   1025 queue such buffer or it is not required anymore.</p>
   1026 
   1027 <p>An API user receives messages from the remote side by handling a
   1028 <code>handle_msg()</code> notification callback (which is called in
   1029 the context of the trusty-ipc <code>rx</code> workqueue) that
   1030 provides a pointer to an <code>rx</code> buffer containing an
   1031 incoming message to be handled.</p>
   1032 
   1033 <p>It is expected that the <code>handle_msg()</code> callback
   1034 implementation will return a pointer to a valid <code>struct tipc_msg_buf</code>.
   1035 It can be the same as the incoming message buffer if it is handled locally
   1036 and not required anymore. Alternatively, it can be a new buffer obtained by
   1037 a <code>tipc_chan_get_rxbuf()</code> call if the incoming buffer is queued
   1038 for further processing. A detached <code>rx</code> buffer must be tracked
   1039 and eventually released using a  <code>tipc_chan_put_rxbuf()</code> call when
   1040 it is no longer needed.</p>
   1041 
   1042 <h3 id=methods_ktic_api>Methods in the Kernel Trusty IPC Client API</h3>
   1043 
   1044 <h4 id=tipc_create_channel>tipc_create_channel()</h4>
   1045 
   1046 <p>Creates and configures an instance of a Trusty IPC channel for a particular
   1047 trusty-ipc device.</p>
   1048 
   1049 <pre class="prettyprint">
   1050 struct tipc_chan *tipc_create_channel(struct device *dev,
   1051                           const struct tipc_chan_ops *ops,
   1052                               void *cb_arg);
   1053 </pre>
   1054 
   1055 <p>[in] <code>dev</code>: Pointer to the trusty-ipc for which the device
   1056 channel is created</p>
   1057 
   1058 <p>[in] <code>ops</code>: Pointer to a <code>struct tipc_chan_ops</code>,
   1059 with caller-specific
   1060 callbacks filled in</p>
   1061 
   1062 <p>[in] <code>cb_arg</code>: Pointer to data that will be passed
   1063 to <code>tipc_chan_ops</code> callbacks</p>
   1064 
   1065 <p>[retval]: Pointer to a newly-created instance of
   1066 <code>struct tipc_chan</code> on success,
   1067 <code>ERR_PTR(err)</code> otherwise</p>
   1068 
   1069 <p>In general, a caller must provide two callbacks that are asynchronously invoked
   1070 when the corresponding activity is occurring.</p>
   1071 
   1072 <p>The <code>void (*handle_event)(void *cb_arg, int event)</code>event is invoked
   1073 to notify a caller about a channel state change.</p>
   1074 
   1075 <p>[in] <code>cb_arg</code>: Pointer to data passed to a
   1076 <code>tipc_create_channel()</code> call</p>
   1077 
   1078 <p>[in] <code>event</code>: An event that can be one of the following values:</p>
   1079 
   1080 <ul>
   1081   <li><code>TIPC_CHANNEL_CONNECTED</code> - indicates a successful connection
   1082   to the remote side
   1083   <li><code>TIPC_CHANNEL_DISCONNECTED</code> - indicates the remote side denied the
   1084   new connection request or requested
   1085 disconnection for the previously connected channel
   1086   <li><code>TIPC_CHANNEL_SHUTDOWN</code> - indicates the remote side is shutting down,
   1087   permanently terminating all connections
   1088 </ul>
   1089 
   1090 <p>The <code>struct tipc_msg_buf *(*handle_msg)(void *cb_arg, struct tipc_msg_buf *mb)</code>
   1091 callback is invoked to provide notification that a new message has been
   1092 received over a specified channel:</p>
   1093 
   1094 <ul>
   1095   <li>[in] <code>cb_arg</code>: Pointer to data passed to the
   1096   <code>tipc_create_channel()</code> call
   1097   <li>[in] <code>mb</code>: Pointer to a <code>struct tipc_msg_buf</code>
   1098   describing an incoming message
   1099   <li>[retval]: The callback implementation is expected to return a pointer to a
   1100   <code>struct tipc_msg_buf</code> that can be the same pointer received
   1101   as an
   1102   <code>mb</code> parameter if the message is handled locally and is not
   1103   required anymore (or it
   1104 can be a new buffer obtained by the <code>tipc_chan_get_rxbuf()</code> call)
   1105 </ul>
   1106 
   1107 <h4 id=tipc_chan_connect>tipc_chan_connect()</h4>
   1108 
   1109 <p>Initiates a connection to the specified Trusty IPC service.</p>
   1110 
   1111 <pre class="prettyprint">
   1112 int tipc_chan_connect(struct tipc_chan *chan, const char *port);
   1113 </pre>
   1114 
   1115 <p>[in] <code>chan</code>: Pointer to a channel returned by the
   1116 <code>tipc_create_chan()</code> call</p>
   1117 
   1118 <p>[in] <code>port</code>: Pointer to a string containing the
   1119 service name to which to connect</p>
   1120 
   1121 <p>[retval]: 0 on success, a negative error otherwise</p>
   1122 
   1123 <p>The caller is notified when a connection is established by receiving a
   1124 <code>handle_event</code> callback.</p>
   1125 
   1126 <h4 id=tipc_chan_shutdown>tipc_chan_shutdown()</h4>
   1127 
   1128 <p>Terminates a connection to the Trusty IPC service previously initiated
   1129 by a <code>tipc_chan_connect()</code> call.</p>
   1130 
   1131 <pre class="prettyprint">
   1132 int tipc_chan_shutdown(struct tipc_chan *chan);
   1133 </pre>
   1134 
   1135 <p>[in] <code>chan</code>: Pointer to a channel returned by
   1136 a <code>tipc_create_chan()</code> call</p>
   1137 
   1138 <h4 id=tipc_chan_destroy>tipc_chan_destroy()</h4>
   1139 
   1140 <p>Destroys a specified Trusty IPC channel.</p>
   1141 
   1142 <pre class="prettyprint">
   1143 void tipc_chan_destroy(struct tipc_chan *chan);
   1144 </pre>
   1145 
   1146 <p>[in] <code>chan</code>: Pointer to a channel returned by the
   1147 <code>tipc_create_chan()</code> call</p>
   1148 
   1149 <h4 id=tipc_chan_get_txbuf_timeout>tipc_chan_get_txbuf_timeout()</h4>
   1150 
   1151 <p>Obtains a message buffer that can be used to send data over a specified
   1152 channel. If the buffer is not immediately available the caller may be blocked
   1153 for the specified timeout (in milliseconds).</p>
   1154 
   1155 <pre class="prettyprint">
   1156 struct tipc_msg_buf *
   1157 tipc_chan_get_txbuf_timeout(struct tipc_chan *chan, long timeout);
   1158 </pre>
   1159 
   1160 <p>[in] <code>chan</code>: Pointer to the channel to which to queue a message</p>
   1161 
   1162 <p>[in] <code>chan</code>: Maximum timeout to wait until the
   1163 <code>tx</code> buffer becomes available </p>
   1164 
   1165 <p>[retval]: A valid message buffer on success,
   1166 <code>ERR_PTR(err)</code> on error</p>
   1167 
   1168 <h4 id=tipc_chan_queue_msg>tipc_chan_queue_msg()</h4>
   1169 
   1170 <p>Queues a message to be sent over the specified
   1171 Trusty IPC channels.</p>
   1172 
   1173 <pre class="prettyprint">
   1174 int tipc_chan_queue_msg(struct tipc_chan *chan, struct tipc_msg_buf *mb);
   1175 </pre>
   1176 
   1177 <p>[in] <code>chan</code>: Pointer to the channel to which to queue the message</p>
   1178 
   1179 <p>[in] <code>mb:</code> Pointer to the message to queue
   1180 (obtained by a <code>tipc_chan_get_txbuf_timeout()</code> call)</p>
   1181 
   1182 <p>[retval]: 0 on success, a negative error otherwise</p>
   1183 
   1184 <h4 id=tipc_chan_put_txbuf>tipc_chan_put_txbuf()</h4>
   1185 
   1186 <p>Releases the specified <code>Tx</code> message buffer
   1187 previously obtained by a <code>tipc_chan_get_txbuf_timeout()</code> call.</p>
   1188 
   1189 <pre class="prettyprint">
   1190 void tipc_chan_put_txbuf(struct tipc_chan *chan,
   1191                          struct tipc_msg_buf *mb);
   1192 </pre>
   1193 
   1194 <p>[in] <code>chan</code>: Pointer to the channel to which
   1195 this message buffer belongs</p>
   1196 
   1197 <p>[in] <code>mb</code>: Pointer to the message buffer to release</p>
   1198 
   1199 <p>[retval]: None</p>
   1200 
   1201 <h4 id=tipc_chan_get_rxbuf>tipc_chan_get_rxbuf()</h4>
   1202 
   1203 <p>Obtains a new message buffer that can be used to receive messages over the
   1204 specified channel.</p>
   1205 
   1206 <pre class="prettyprint">
   1207 struct tipc_msg_buf *tipc_chan_get_rxbuf(struct tipc_chan *chan);
   1208 </pre>
   1209 
   1210 <p>[in] <code>chan</code>: Pointer to a channel to which this message buffer belongs</p>
   1211 
   1212 <p>[retval]: A valid message buffer on success, <code>ERR_PTR(err)</code> on error</p>
   1213 
   1214 <h4 id=tipc_chan_put_rxbuf>tipc_chan_put_rxbuf()</h4>
   1215 
   1216 <p>Releases a specified message buffer previously obtained by a
   1217 <code>tipc_chan_get_rxbuf()</code> call.</p>
   1218 
   1219 <pre class="prettyprint">
   1220 void tipc_chan_put_rxbuf(struct tipc_chan *chan,
   1221                          struct tipc_msg_buf *mb);
   1222 </pre>
   1223 
   1224 <p>[in] <code>chan</code>: Pointer to a channel to which this message buffer belongs</p>
   1225 
   1226 <p>[in] <code>mb</code>: Pointer to a message buffer to release</p>
   1227 
   1228 <p>[retval]: None</p>
   1229 
   1230   </body>
   1231 </html>
   1232