==========
Data Types
==========

.. index:: Data Types

This part describes the data-types that are defined in the simple CAN-
interface.

.. index::
   single: sci_Object_Type

sci_Object_Type
---------------

::

  typedef enum sci_Object_Type
    { SCI_READ, SCI_WRITE, SCI_REMOTE_READ, SCI_REMOTE_WRITE
    } sci_Object_Type;
  

This is the data type of a CAN-object. Explanation of each data type:

`SCI_READ`
  This is the data type of a read-object, data is read from the
  CAN-bus with an object of this type. IO-functions for an object of this type
  are `sci_read()`, `sci_read_now()`, `sci_read_new()`
  and `sci_queue_read()`.

`SCI_WRITE`
  This is the data type of a write-object, data is written to
  the CAN-bus with an object of this type. The only IO-function for an object
  of this type is `sci_write()`.

`SCI_REMOTE_READ`
  This is the data type for remote-read objects. These
  objects use the remote-transmission mechanism, that is defined in the
  CAN-specification. A remote-read object reads data by sending a
  CAN remote-request and waiting for a reply from another CAN device. This reply
  contains the data that is read from the other device. Although a
  remote-request sent, from a higher point of view, data is read from the
  CAN bus and from the other CAN device. IO-functions for an object of
  this type are `sci_read()`, `sci_read_now()`,
  `sci_read_new`, `sci_write()` and `sci_queue_read()`.
  `sci_read()` performs a complete request-cycle by sending the
  remote-request and waiting for the answer, while the other functions are used
  for so called divided remote reads. In this case, a remote-request is sent
  by the use of `sci_write()`. This function, however, does not wait
  for the reply to that request. The data can be read later by
  `sci_read_now()`, `sci_read_new` or
  `sci_queue_read()`. The later function has a special function, do
  also have a look at the description of `sci_queue_read()` in this
  documentation.

`SCI_REMOTE_WRITE`
  This is the data type for remote-write objects.
  These objects use the remote-transmission mechanism, that is defined in the
  CAN-specification. The data is not actually written to the CAN bus but only
  stored in the used CAN-interface card. The card will, without notifying the
  user-program, send that data when a remote-request to that object arrives
  (see above, `SCI_REMOTE_READ`).

.. index::
   single: sci_Return_Constants

sci_Return_Constants
--------------------

::

  enum sci_Return_Constants
    { SCI_NOTHING=0, SCI_OLD_DATA=1, SCI_LOST=2, 
      SCI_TMOUT=4, SCI_RESETTED=8, SCI_INCONSISTENT=16,
      SCI_EXISTS=32,
      SCI_WAIT=64,
      SCI_ERROR=INT_MIN 
    };
  
This is a enumeration type that defines several flags. The returned value
of any function of this library can be tested against these flags. A function
can return more than one flag condition. For this reason, the returned value
of a function should be tested against a flag with the '&'-construct.

Here is an example (be `ret` the return-code)::

  (ret & SCI_TMOUT)

This is `1 (TRUE)` when a timeout occurred.

Explanation of the flags:

`SCI_NOTHING`
  This is the return-value of functions when no special
  flags are returned.

`SCI_OLD_DATA`
  This flag signals that old data, data that has already
  been read, was returned. This flag can only be returned by ordinary
  read-functions, all functions that are named `sci_read...()`.

`SCI_LOST`
  This flag indicates that data was lost. There is only a
  buffer of up to 8 bytes available for each CAN object. Each CAN object can
  store one CAN data-frame, the next arriving frame will always overwrite the
  data from the previous frame. The flag indicates, that data was overwritten,
  without having been read by the user program. This flag can only be
  returned by read-functions, all functions that are named
  `sci_read...()` and `sci_queue_read()`.

`SCI_TMOUT`
  This flag indicates that a timeout occurred. Timeouts for
  ordinary read objects (not *remote-read* objects) are not treated as
  errors, but the timeout is just indicated via this flag. The read-functions
  will return valid data from the object, namely the data that is still stored
  in the buffer of the CAN interface, the flag indicates that within the
  specified timeout, no new data did arrive. This flag can only be returned
  by ordinary read-functions, all functions that are named
  `sci_read...()`.

`SCI_RESETTED`
  This flag indicates that the CAN interface has been
  resetted (probably by another process that uses sci). It is no longer
  guaranteed that the CAN-objects that were previously defined, can still be
  used. When this flag is detected, a user program should define all it's needed
  CAN objects again before using any other sci-function.

`SCI_INCONSISTENT`
  This flag indicates inconsistent data. It was,
  probably due to slow program execution or too many CAN transmissions,
  impossible to get data from the CAN bus that is guaranteed to be valid and
  error-free. When this flag is detected, the user program cannot assume that
  the function has returned any valid or usable data. This flag can only be
  returned by read-functions, all functions that are named
  `sci_read...()` and `sci_queue_read()`.

`SCI_EXISTS`
  This flag indicates, that a CAN object that was defined
  with `sci_init_object` was already defined. In this case, if
  the data of the object like length, object type, CAN id and port match,
  the existing object is duplicated. See also the description of
  `sci_dup_object()`. This flag can only be returned by
  `sci_init_object`.

`SCI_WAIT`
  This flag can only be returned by
  `sci_write_inhibit()`. It indicates, that the writing to the CAN object
  did not take place because the time passed since the last writing is smaller
  than the inhibit-time, defined for that object. See also the descriptions of
  `sci_write_inhibit` and `sci_set_inhibit()`.

`SCI_ERROR`
  This flag indicates that an error occurred. Any function
  that returned this flag cannot be expected to have performed it's function
  correctly. The error-code should be requested from sci by the call of
  `sci_get_errcode()`. If any other sci-function is called between
  the return of the `SCI_ERROR` flag by an function and the call of
  `sci_get_errcode()` the error-code may be lost.

.. index::
   single: sci_Return

sci_Return
----------

::

  typedef int sci_Return;
  
This is the type of the data, every function of this library returns.
A variable of this type can be tested against flag-conditions, see also
`sci_Return_Constants`.

.. index::
   single: sci_Bitrate

sci_Bitrate
-----------

::

  typedef enum sci_Bitrate_Constants
    { SCI_1000KB, /* bitrate of 1000KBPS */
      SCI_500KB,  /* bitrate of  500KBPS */
      SCI_250KB,  /* bitrate of  250KBPS */
      SCI_125KB,  /* bitrate of  125KBPS */
      SCI_100KB,  /* bitrate of  100KBPS */
      SCI_66KB,   /* bitrate of   66KBPS */
      SCI_50KB,   /* bitrate of   50KBPS */
      SCI_20KB    /* bitrate of   20KBPS */
    } sci_Bitrate;
  
These constants are used to specify the bitrate for the `sci_init`-
function. A bitrate can be defined for each available port. The names of the
constants are self-describing, `SCI_nnnnKB` stands for a bitrate
of `nnnn` KBit per second.

.. index::
   single: sci_Errcode

sci_Errcode
-----------

::

  typedef enum sci_Errcode_Constants
    { SCI_NO_ERR,         /* no error */
      SCI_PORT_ERR,       /* wrong port-parameter */
      SCI_ID_ERR,         /* wrong can-object-id */
      SCI_TYPE_ERR,       /* unknown object-type */
      SCI_BITRATE_ERR,    /* wrong bitrate chosen */
      SCI_SET_CALLB_ERR,  /* callback was already defined */
      SCI_MODE_ERR,       /* operation on object that has the wrong
                             mode (e.g. reading of a write-object
                             etc.) */
      SCI_LENGTH_ERR,     /* object read or written with wrong
                             length */
      SCI_ACCESS_ERR,     /* tried to access an already owned object*/
      SCI_TIMEOUT_ERR,    /* timeout has occurred */
      SCI_TIMEOUT_VAL_ERR,/* timeout value out of range */
      SCI_OFF_BUS_ERR,    /* controller off-bus */
      SCI_BUS_ERR,        /* CAN bus error */
      SCI_AUTHORIZE_ERR,  /* only the first process that accesses the
                             port is allowed to initialize it */
  
  /*  new error-codes: */
      SCI_DVR_OPEN_ERR,   /* CAN-driver couldn't be opened  */
      SCI_DVR_ACCESS_ERR, /* driver couldn't be accessed, a kind of an
                             internal error */
      SCI_HW_INIT_ERR,    /* general HW initialization error */
      SCI_RESET_ERR,      /* hardware reset failed */
      SCI_CHIP_CONF_ERR,  /* wrong placement of CAN chip (only
                             for certain implementations of sci) */
      SCI_ENV_ERR,        /* missing environment variable (only for
                             certain implementations of sci) */
  
  #if SCI_VER>=230
      SCI_PLUGPORT_ERR,   /* A plug-port number must be between
                             SCI_PLUGPORT_START and
                             SCI_PLUGPORT_START+SCI_MAX_PLUGPORTS-1 */
      SCI_PLUG_DEF_ERR,   /* the plug-port was already defined or
                             should have been defined but wasn't  */
  #endif
  
      SCI_ERR_GENERAL     /* general error */
    } sci_Errcode;

This is the type that describes various errors. When an error occured,
the error-code can be requested with the `sci_get_errcode`-function.
The library can store a single error-code for each thread (threads are
distinguished by the `sci_Struc`-parameter of all functions.

Explanation of the error-codes:

`SCI_NO_ERR`
  No error has been detected

`SCI_PORT_ERR`
  An invalid port-parameter was given to a function

`SCI_ID_ERR`
  An invalid CAN-id parameter was given to a function.
  Valid numbers range from 0 to 2047.

`SCI_TYPE_ERR`
  An invalid object-type parameter was given to a function.
  Valid object-types are defined in the enumeration `sci_Object_Type`.

`SCI_BITRATE_ERR`
  An invalid bitrate parameter was given to a function.
  Valid bitrates are defined in the enumeration `sci_Bitrate`.

`SCI_SET_CALLB_ERR`
  An attempt was made to set an object to the
  *event-mode* (with `sci_set_callback`), although the object
  was already set to the *event-mode*. This error can also occur on
  *duplicated* objects, for these special objects (see also the description
  of `sci_dup_object()`) only one (per CAN id) can be set to the
  *event*-mode. This one is then returned via the `sci_Object`
  pointer when an event was detected. See also the description of
  `sci_set_callback`) for the concept of *event objects*.

`SCI_MODE_ERR`
  A function was performed on an object whose type is
  not compatible with that function, e.g. `sci_write()` was performed
  on an ordinary read-object, or `sci_read()` was performed on a
  write object. Note that applying one of the read-functions `sci_read`,
  `sci_read_now`, `sci_read_new` or `sci_readmany` on an
  *event-object* also causes this error.

`SCI_LENGTH_ERR`
  Either a wrong length parameter was given to a function,
  valid lengths vary from 0 to 8 or an object has received a wrong number of
  bytes from the CAN bus. Since `sci_init_object()` defines a length
  for each object, an error occurs when data arrives for that object, that has
  a different number of bytes. The data-buffer on the CAN interface may be
  overwritten with that new data, but the read functions `sci_read...()`
  and `sci_queue_read()` will not copy that data to the user program.

`SCI_ACCESS_ERR`
  An attempt was made to perform an operation on an
  object that is already in use by another thread. This error can only be
  raised in multitasking-implementations of sci.

`SCI_TIMEOUT_ERR`
  A timeout-error occured. This error can only occur
  when the `sci_write()` is used. Concerning timeouts in read-functions,
  see also the description of the `SCI_TMOUT` flag that is part of
  the `sci_Return_Constants` enumeration type.

`SCI_TIMEOUT_VAL_ERR`
  A wrong timeout-value parameter was given to a
  function. Valid timeouts range from 0 to 32767.

`SCI_OFF_BUS_ERR`
  The CAN interface is in the OFF-BUS state. This error
  can only be caused by a hardware error in the CAN interface or at it's CAN
  connection cable.

`SCI_BUS_ERR`
  A serious CAN bus error was detected, this can only be
  caused by faulty hardware in the CAN interface, the CAN connection cable or
  within another connected CAN device.

`SCI_AUTHORIZE_ERR`
  A thread that was not authorized to reset ports
  or change bitrates tried to do so. This error can only occur in multitasking-
  implementations of sci. Only the first thread that opened the SCI-library
  is allowed to reset ports or change bitrates. If this first thread closed
  the SCI-library and another thread opens the library with the same name as
  the first thread, it is also allowed to reset ports and change bitrates
  (see also the description of `sci_open()`.

`SCI_DVR_OPEN_ERR`
  The driver for the CAN interface couldn't be opened.
  This error can only be returned when `sci_open()` is called. Note
  that only some implementations of sci that are based on a driver, so this error
  can occur on some implementations of sci.

`SCI_DVR_ACCESS_ERR`
  The driver for the CAN interface couldn't be
  accessed. This is an error that is similar in it's meaning to
  `SCI_DVR_OPEN_ERR`, but it indicates an internal sci-error that
  shouldn't happen under normal circumstances.

`SCI_HW_INIT_ERR`
  The CAN interface hardware couldn't be initialized.
  This error can occur on implementations of sci that are not based on a driver
  and access the CAN interface directly.

`SCI_RESET_ERR`
  The reset of the CAN interface failed, this error can
  occur when the `sci_reset()` function is called. It indicates a
  problem with the CAN hardware.

`SCI_CHIP_CONF_ERR`
  A CAN chip was wrongly placed on the CAN card. This
  error can only occur on certain CAN interfaces, that allow the placement of
  one or more CAN chips on the interface card.

`SCI_ENV_ERR`
  An important environment variable is missing. Certain
  implementations of sci need environment variables to be set that characterize
  the hardware addresses of the CAN interface. Please consult the documentation
  of your CAN interface or your local sci implementation if this error happens.

`SCI_PLUGPORT_ERR`
  This error-code can be returned by
  `sci_def_plug_in`. A *plug-port* must be in the range of
  `SCI_PLUGPORT_START` and `SCI_PLUGPORT_START+SCI_MAX_PLUGPORTS-1`.
  If a given *plug-port* is not within this range, `SCI_PLUGPORT_ERR`
  is returned.

`SCI_PLUG_DEF_ERR`
  This error-code can be returned by
  `sci_def_plug_in` and `sci_init_object`. It is returned when it
  is either tried to defined a certain *plug-port* for a second time or
  when a *plug-port* is used that has not yet been defined.

`SCI_ERR_GENERAL`
  A general error occured. This unspecified sci error
  can happen at all sci functions. When an error is detected by your
  implementation of sci whose cause does not fall into one of the categories
  described above, `SCI_ERR_GENERAL` is returned. Either the error is
  an obvious parameter-error (wrong parameters were specified) for the function
  or it is a kind of internal error. In the later case, you should consult
  the author of your sci-implementation.

.. index::
   single: sci_Callback_Func

sci_Callback_Func
-----------------

::

  typedef void (*sci_Callback_Func)(sci_Object *obj, sci_Return ret,
                char data[8]);
  
This is the legacy definition of a callback function type. This is no longer
used. The corresponding parameter of function `sci_set_callback` mist alway be 
`NULL`.

.. index::
   single: sci_Plug_Func

sci_Plug_Func
-------------

::

  typedef void (*sci_Plug_Func)(int l_len, char *l_data,
                                int h_len, char *h_data);
  

This is the prototype of a *plug-in* data-conversion function. 2 functions
of that type are part of a *plug-in*. They perform data-conversion
between the low-level format (raw-data from the CAN bus) and the high-level
format (data that is passed to or from the application). Each data-conversion
function gets a pointer to the low-level data, `l_data`, the length
of the low-level data, `l_len`, a pointer to the high-level
data, `h_data`, and a the length of the high-level data, `h_len`.
The first conversion function, usually called `h2l`, should convert
high-level to low-level data, the second function, usually called `l2h`,
should convert low-level to high-level data.

.. index::
   single: sci_Plug_Lencalc

sci_Plug_Lencalc
----------------

::

  typedef int (*sci_Plug_Lencalc)(int h_len, int *l_len);
  

This is the type of a the *plug-in* length-conversion function. A
*plug-in* has just one function of this type. It gets the length of the
high-level data, `h_len`, calculates the resulting length of the low-level
data and stores it to `l_len`. By this, the length of the low-level
(raw CAN-bus-) data can be different from the length of the high-level
(sci-application-) data. Note that the length can not vary while the
application is running. This is due to the fact that CAN-objects always have
a fixed length as long as they are defined. This function should return
1 (at least not zero) when a certain length conversion is supported by
the *plug-in*, 0 in all other cases.

.. index::
   single: sci_Object

sci_Object
----------

::

  typedef struct sci_Object sci_Object;

This is the abstract type of a CAN-object. It contains a user part, that can
be used to store user-defined pointer. The structure also contains
internal data, but that data cannot be read or written to. Due to this
unspecified internal data, whose size is unknown to the user, memory for
sci-objects is only allocated by the library. A user program should only use
*pointers* to sci-objects but should never create variables of the type
`sci_Object` itself. The data type `sci_Object` is in it's
function similar to the `FILE` - structure that is used in C to
handle files.

sci-objects are created with the `sci_init_object()` function; CAN-id,
port, length and object-type are specified when the object is created. These
properties cannot be modified later, if the CAN-id on that port shall have
new properties, the existing sci-object has to be deleted with the
`sci_delete_object()` function and created again with
`sci_init_object()`.

.. index::
   single: sci_Struc

sci_Struc
---------

::

  typedef struct sci_Struc sci_Struc;
  
This is the abstract type of the CAN resources.
A pointer to a variable of this type is returned, when `sci_open`
is called. This pointer must be given for all other functions of this library.
Different processes or threads must use different `sci_Struc`-
parameters in their calls to the SCI-library. For this reason, the library
can be called by different threads at a time an is by this, thread safe.

Note that the above definition does not represent the real structure of the
sci-structure. All internal data, that this structure contains, is hidden
from the user.