========== 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.