42#ifndef LELY_IO_CAN_NET_TXLEN
47#define LELY_IO_CAN_NET_TXLEN 1000
50#ifndef LELY_IO_CAN_NET_TXTIMEO
55#define LELY_IO_CAN_NET_TXTIMEO 100
58static void io_can_net_svc_shutdown(
struct io_svc *svc);
61static const struct io_svc_vtbl io_can_net_svc_vtbl = {
63 &io_can_net_svc_shutdown
179static void io_can_net_wait_next_func(
struct ev_task *task);
180static void io_can_net_wait_confirm_func(
struct ev_task *task);
181static void io_can_net_read_func(
struct ev_task *task);
182static void io_can_net_write_func(
struct ev_task *task);
184static int io_can_net_next_func(
const struct timespec *tp,
void *data);
185static int io_can_net_send_func(
const struct can_msg *msg,
void *data);
187static void io_can_net_c_wait_func(
struct spscring *ring,
void *arg);
195static size_t io_can_net_do_abort_tasks(
io_can_net_t *net);
198static void default_on_read_error_func(
int errc,
size_t errcnt,
void *arg);
199static void default_on_queue_error_func(
int errc,
size_t errcnt,
void *arg);
200static void default_on_write_error_func(
int errc,
size_t errcnt,
void *arg);
201static void default_on_can_state_func(
int new_state,
int old_state,
void *arg);
202static void default_on_can_error_func(
int error,
void *arg);
205io_can_net_alloc(
void)
216io_can_net_free(
void *ptr)
249 goto error_create_tq;
252 0, 0, NULL, &io_can_net_wait_next_func);
254 0, 0, NULL, &io_can_net_wait_confirm_func);
263 &io_can_net_read_func);
271 &net->
write_msg, NULL, &io_can_net_write_func);
279 goto error_alloc_tx_buf;
310 goto error_create_net;
312 net->
next = (
struct timespec){ 0, 0 };
353 io_can_net_svc_shutdown(&net->
svc);
361 if (io_can_net_do_abort_tasks(net))
367 "io_can_net_fini() invoked with pending operations");
385 size_t txlen,
int txtimeo)
396 io_can_net_init(net, exec, timer, chan, txlen, txtimeo);
406 io_can_net_free(net);
416 io_can_net_fini(net);
417 io_can_net_free(net);
434 io_can_net_do_wait(net);
688 struct timespec now = { 0, 0 };
695io_can_net_svc_shutdown(
struct io_svc *svc)
713io_can_net_wait_next_func(
struct ev_task *task)
729 int submit_wait_next = 0;
731 struct timespec now = { 0, 0 };
735 submit_wait_next = 1;
744 if (submit_wait_next)
749io_can_net_wait_confirm_func(
struct ev_task *task)
804 }
else if (read->
r.
result == 0) {
807 int old_state = net->
state;
886 if (!net->
shutdown && !io_can_net_do_wait(net))
887 io_can_net_do_write(net);
895io_can_net_next_func(
const struct timespec *tp,
void *data)
926io_can_net_send_func(
const struct can_msg *
msg,
void *data)
959io_can_net_c_wait_func(
struct spscring *ring,
void *arg)
966 if (!io_can_net_do_wait(net))
967 io_can_net_do_write(net);
971io_can_net_from_svc(
const struct io_svc *svc)
986 &net->
tx_ring, 1, &io_can_net_c_wait_func, net))
1060default_on_read_error_func(
int errc,
size_t errcnt,
void *arg)
1068 "CAN frame successfully read after %zu read error%s",
1069 errcnt, errcnt > 1 ?
"s" :
"");
1073default_on_queue_error_func(
int errc,
size_t errcnt,
void *arg)
1079 "CAN transmit queue full; dropping frame");
1082 "CAN frame successfully queued after dropping %zd frame%s",
1083 errcnt, errcnt > 1 ?
"s" :
"");
1087default_on_write_error_func(
int errc,
size_t errcnt,
void *arg)
1095 "CAN frame successfully written after %zu write error%s",
1096 errcnt, errcnt > 1 ?
"s" :
"");
1100default_on_can_state_func(
int new_state,
int old_state,
void *arg)
1105 switch (new_state) {
1110 diag(
DIAG_INFO, 0,
"CAN bus is in the error passive state");
1125default_on_can_error_func(
int error,
void *arg)
1139 "acknowledgment error detected on CAN bus");
1142 "one or more unknown errors detected on CAN bus");
@ CAN_ERROR_FORM
A form error.
@ CAN_ERROR_BIT
A single bit error.
@ CAN_ERROR_STUFF
A bit stuffing error.
@ CAN_ERROR_ACK
An acknowledgment error.
@ CAN_ERROR_CRC
A CRC sequence error.
@ CAN_ERROR_OTHER
One or more other errors.
@ CAN_STATE_BUSOFF
The bus off state (TX/RX error count >= 256).
@ CAN_STATE_SLEEPING
The device is in sleep mode.
@ CAN_STATE_PASSIVE
The error passive state (TX/RX error count < 256).
@ CAN_STATE_STOPPED
The device is stopped.
@ CAN_STATE_ACTIVE
The error active state (TX/RX error count < 128).
#define CAN_MSG_INIT
The static initializer for can_msg.
io_clock_t * io_can_net_get_clock(const io_can_net_t *net)
Returns a pointer to the clock used by the CAN network interface.
void io_can_net_set_on_read_error_func(io_can_net_t *net, io_can_net_on_error_func_t *func, void *arg)
Sets the function invoked when a new CAN frame read error occurs, or when a read operation completes ...
void io_can_net_set_on_can_state_func(io_can_net_t *net, io_can_net_on_can_state_func_t *func, void *arg)
Sets the function to be invoked when a CAN bus state change is detected.
io_tqueue_t * io_can_net_get_tqueue(const io_can_net_t *net)
Returns a pointer to the internal timer queue of a CAN network interface.
can_net_t * io_can_net_get_net(const io_can_net_t *net)
Returns a pointer to the internal interface of a CAN network interface.
io_ctx_t * io_can_net_get_ctx(const io_can_net_t *net)
Returns a pointer to the I/O context with which the CAN network interface is registered.
void io_can_net_get_on_read_error_func(const io_can_net_t *net, io_can_net_on_error_func_t **pfunc, void **parg)
Retrieves the function invoked when a new CAN frame read error occurs, or when a read operation compl...
void io_can_net_start(io_can_net_t *net)
Starts a CAN network interface and begins processing CAN frames.
int io_can_net_unlock(io_can_net_t *net)
Unlocks the mutex protecting the CAN network interface.
#define LELY_IO_CAN_NET_TXTIMEO
The default timeout (in milliseconds) of a CAN network interface when waiting for a CAN frame write c...
io_can_net_t * io_can_net_create(ev_exec_t *exec, io_timer_t *timer, io_can_chan_t *chan, size_t txlen, int txtimeo)
Creates a new CAN network interface.
void io_can_net_set_on_queue_error_func(io_can_net_t *net, io_can_net_on_error_func_t *func, void *arg)
Sets the function invoked when a CAN frame is dropped because the transmit queue is full,...
void io_can_net_get_on_write_error_func(const io_can_net_t *net, io_can_net_on_error_func_t **pfunc, void **parg)
Retrieves the function invoked when a new CAN frame write error occurs, or when a write operation com...
void io_can_net_get_on_queue_error_func(const io_can_net_t *net, io_can_net_on_error_func_t **pfunc, void **parg)
Retrieves the function invoked when a CAN frame is dropped because the transmit queue is full,...
void io_can_net_get_on_can_state_func(const io_can_net_t *net, io_can_net_on_can_state_func_t **pfunc, void **parg)
Retrieves the function invoked when a CAN bus state change is detected.
int io_can_net_set_time(io_can_net_t *net)
Updates the CAN network time.
void io_can_net_destroy(io_can_net_t *net)
Destroys a CAN network interface.
ev_exec_t * io_can_net_get_exec(const io_can_net_t *net)
Returns a pointer to the executor used by the CAN network interface to execute asynchronous tasks.
void io_can_net_set_on_can_error_func(io_can_net_t *net, io_can_net_on_can_error_func_t *func, void *arg)
Sets the function to be invoked when a CAN bus error is detected.
void io_can_net_get_on_can_error_func(const io_can_net_t *net, io_can_net_on_can_error_func_t **pfunc, void **parg)
Retrieves the function invoked when a CAN bus error is detected.
#define LELY_IO_CAN_NET_TXLEN
The default length (in number of CAN frames) of the user-space transmit queue of a CAN network interf...
int io_can_net_lock(io_can_net_t *net)
Locks the mutex protecting the CAN network interface.
void io_can_net_set_on_write_error_func(io_can_net_t *net, io_can_net_on_error_func_t *func, void *arg)
Sets the function invoked when a new CAN frame write error occurs, or when a write operation complete...
This header file is part of the I/O library; it contains the CAN network interface declarations.
void io_can_net_on_can_state_func_t(int new_state, int old_state, void *arg)
The type of function invoked when a CAN bus state change is detected by a CAN network interface.
void io_can_net_on_error_func_t(int errc, size_t errcnt, void *arg)
The type of function invoked when an error occurs during a CAN network interface operations,...
void io_can_net_on_can_error_func_t(int error, void *arg)
The type of function invoked when a CAN bus error is detected by an CAN network interface.
int io_clock_gettime(const io_clock_t *clock, struct timespec *tp)
Obtains the current time value of the specified clock.
const struct io_clock_vtbl *const io_clock_t
An abstract clock.
This header file is part of the I/O library; it contains the I/O context and service declarations.
void io_ctx_insert(io_ctx_t *ctx, struct io_svc *svc)
Registers an I/O service with an I/O context.
#define IO_SVC_INIT(vptr)
The static initializer for io_svc.
void io_ctx_remove(io_ctx_t *ctx, struct io_svc *svc)
Unregisters an I/O service with an I/O context.
This header file is part of the utilities library; it contains the diagnostic declarations.
@ DIAG_INFO
An informational message.
void diag(enum diag_severity severity, int errc, const char *format,...)
Emits a diagnostic message.
errnum_t errc2num(int errc)
Transforms a native error code to a platform-independent error number.
@ ERRNUM_AGAIN
Resource unavailable, try again.
@ ERRNUM_CANCELED
Operation canceled.
int get_errc(void)
Returns the last (thread-specific) native error code set by a system call or library function.
void set_errc(int errc)
Sets the current (thread-specific) native error code to errc.
int errno2c(int errnum)
Transforms a standard C error number to a native error code.
void set_errnum(errnum_t errnum)
Sets the current (thread-specific) platform-independent error number to errnum.
#define _Alignof(x)
Specifies the alignment requirement of the declared object or member.
const struct ev_exec_vtbl *const ev_exec_t
An abstract task executor.
static io_ctx_t * io_can_chan_get_ctx(const io_can_chan_t *chan)
const struct io_can_chan_vtbl *const io_can_chan_t
An abstract CAN channel.
static size_t io_can_chan_abort_write(io_can_chan_t *chan, struct io_can_chan_write *write)
Aborts the specified CAN channel write operation if it is pending.
struct io_can_chan_read * io_can_chan_read_from_task(struct ev_task *task)
Obtains a pointer to a CAN channel read operation from a pointer to its completion task.
static size_t io_can_chan_abort_read(io_can_chan_t *chan, struct io_can_chan_read *read)
Aborts the specified CAN channel read operation if it is pending.
struct io_can_chan_write * io_can_chan_write_from_task(struct ev_task *task)
Obtains a pointer to a CAN channel write operation from a pointer to its completion task.
void io_can_chan_submit_write(io_can_chan_t *chan, struct io_can_chan_write *write)
Submits a write operation to a CAN channel.
void io_can_chan_submit_read(io_can_chan_t *chan, struct io_can_chan_read *read)
Submits a read operation to a CAN channel.
#define IO_CAN_CHAN_WRITE_INIT(msg, exec, func)
The static initializer for io_can_chan_write.
#define IO_CAN_CHAN_READ_INIT(msg, err, tp, exec, func)
The static initializer for io_can_chan_read.
static ev_exec_t * io_can_chan_get_exec(const io_can_chan_t *chan)
static size_t io_can_chan_cancel_write(io_can_chan_t *chan, struct io_can_chan_write *write)
Cancels the specified CAN channel write operation if it is pending.
const struct io_timer_vtbl *const io_timer_t
An abstract timer.
io_clock_t * io_timer_get_clock(const io_timer_t *timer)
Returns a pointer to the clock used by the timer.
This is the public header file of the utilities library.
#define structof(ptr, type, member)
Obtains the address of a structure from the address of one of its members.
#define CAN_ERR_INIT
The static initializer for a can_err struct.
This header file is part of the CAN library; it contains the CAN network interface declarations.
void can_net_get_time(const can_net_t *net, struct timespec *tp)
Retrieves the current time of a CAN network interface.
void can_net_set_send_func(can_net_t *net, can_send_func_t *func, void *data)
Sets the callback function used to send CAN frames from a network interface.
void can_net_destroy(can_net_t *net)
Destroys a CAN network interface.
can_net_t * can_net_create(void)
Creates a new CAN network interface.
void can_net_set_next_func(can_net_t *net, can_timer_func_t *func, void *data)
Sets the callback function invoked when the time at which the next CAN timer triggers is updated.
int can_net_recv(can_net_t *net, const struct can_msg *msg)
Receives a CAN frame with a network interface and processes it with the corresponding receiver(s).
int can_net_set_time(can_net_t *net, const struct timespec *tp)
Sets the current time of a CAN network interface.
This header file is part of the utilities library; it contains the single-producer,...
size_t spscring_c_alloc(struct spscring *ring, size_t *psize)
Allocates a consecutive range of indices, including wrapping, in a single-producer,...
int spscring_c_submit_wait(struct spscring *ring, size_t size, void(*func)(struct spscring *ring, void *arg), void *arg)
Checks if the requested range of indices, including wrapping, in a single-producer,...
size_t spscring_p_commit(struct spscring *ring, size_t size)
Makes the specified number of indices available to a consumer and, if this satisfies a wait operation...
size_t spscring_c_commit(struct spscring *ring, size_t size)
Makes the specified number of indices available to a producer and, if this satisfies a wait operation...
size_t spscring_c_capacity(struct spscring *ring)
Returns the total capacity available for a consumer in a single-producer single-consumer ring buffer,...
int spscring_c_abort_wait(struct spscring *ring)
Aborts a wait operation previously registered with spscring_c_submit_wait().
void spscring_init(struct spscring *ring, size_t size)
Initializes a single-producer, single-consumer ring buffer with the specified size.
size_t spscring_p_alloc(struct spscring *ring, size_t *psize)
Allocates a consecutive range of indices, including wrapping, in a single-producer,...
This is the internal header file of the I/O library.
This header file is part of the C11 and POSIX compatibility library; it includes <stdlib....
void aligned_free(void *ptr)
Causes the space at ptr to be deallocated, that is, made available for further allocation.
void * aligned_alloc(size_t alignment, size_t size)
Allocates space for an object whose alignment is specified by alignment, whose size is specified by s...
int state
The state of the CAN node (one of CAN_STATE_ACTIVE, CAN_STATE_PASSIVE or CAN_STATE_BUSOFF).
int error
The error flags of the CAN bus (any combination of CAN_ERROR_BIT, CAN_ERROR_STUFF,...
A CAN or CAN FD format frame.
int result
The result of the read operation: 1 if a CAN frame is received, 0 if an error frame is received,...
int errc
The error number, obtained as if by get_errc(), if result is -1.
A CAN channel read operation.
struct ev_task task
The task (to be) submitted upon completion (or cancellation) of the read operation.
struct io_can_chan_read_result r
The result of the read operation.
A CAN channel write operation.
const struct can_msg * msg
A pointer to the CAN frame to be written.
struct ev_task task
The task (to be) submitted upon completion (or cancellation) of the write operation.
int errc
The error number, obtained as if by get_errc(), if an error occurred or the operation was canceled.
The implementation of a CAN network interface.
struct can_msg write_msg
The CAN frame being written.
void * on_can_error_arg
The user-specified argument for #on_error_func.
struct io_svc svc
The I/O service representing the channel.
mtx_t mtx
The mutex protecting the callbacks, flags and internal CAN network interface.
int read_errc
The error code of the last read operation.
unsigned started
A flag indicating wheter the CAN network interface has been started.
struct can_msg * tx_buf
The transmit queue.
int txtimeo
The timeout (in milliseconds) when waiting for a CAN frame write confirmation.
struct can_msg read_msg
The CAN frame being read.
void * on_queue_error_arg
The user-specified argument for on_queue_error_func.
unsigned shutdown
A flag indicating whether the I/O service has been shut down.
void * on_can_state_arg
The user-specified argument for #on_state_func.
io_can_net_on_can_state_func_t * on_can_state_func
A pointer to the function to be invoked when a CAN bus state change is detected.
void * on_read_error_arg
The user-specified argument for on_read_error_func.
unsigned read_submitted
A flag indicating whether read has been submitted to chan.
io_can_net_on_error_func_t * on_write_error_func
A pointer to the function invoked when a new CAN frame write error occurs, or when a write operation ...
int write_errc
The error code of the last write operation.
int state
The current state of the CAN bus.
struct io_can_chan_write write
The operation used to write CAN frames.
size_t tx_errcnt
The number of frames dropped due to the transmit queue being full.
size_t write_errcnt
The number of errors since the last successful write operation.
io_timer_t * timer
A pointer to the timer used for CAN network events.
io_can_net_on_error_func_t * on_queue_error_func
A pointer to the function invoked when a CAN frame is dropped because the transmit queue is full,...
struct io_tqueue_wait wait_next
The operation used to wait for the next CANopen event.
io_can_chan_t * chan
A pointer to a CAN channel.
unsigned wait_next_submitted
A flag indicating whether wait_next has been submitted to tq.
io_ctx_t * ctx
A pointer to the I/O context with which the channel is registered.
io_tqueue_t * tq
A pointer to the timer queue used to schedule wait operations.
struct spscring tx_ring
The ring buffer used to control the transmit queue.
struct io_tqueue_wait wait_confirm
The operation used to wait for a CAN frame write confirmation.
can_net_t * net
A pointer to the internal CAN network interface.
size_t read_errcnt
The number of errors since the last successful read operation.
unsigned write_submitted
A flag indicating whether write has been submitted to chan.
io_can_net_on_can_error_func_t * on_can_error_func
A pointer to the function to be invoked when an error is detected on the CAN bus.
io_can_net_on_error_func_t * on_read_error_func
A pointer to the function invoked when a new CAN frame read error occurs, or when a read operation co...
struct io_can_chan_read read
The operation used to read CAN frames.
void * on_write_error_arg
The user-specified argument for on_write_error_func.
unsigned wait_confirm_submitted
A flag indicating whether wait_confirm has been submitted to tq.
struct timespec next
The time at which the next CAN timer will trigger.
ev_exec_t * exec
A pointer to the executor ...
struct can_err read_err
The CAN error frame being read.
The virtual table of an I/O service.
A wait operation suitable for use with a timer queue.
struct ev_task task
The task (to be) submitted upon completion (or cancellation) of the wait operation.
struct timespec value
The absolute expiration time.
A single-producer, single-consumer ring buffer.
This header file is part of the C11 and POSIX compatibility library; it includes <threads....
int mtx_init(mtx_t *mtx, int type)
Creates a mutex object with properties indicated by type, which must have one of the four values:
int mtx_lock(mtx_t *mtx)
Blocks until it locks the mutex at mtx.
void thrd_yield(void)
Endeavors to permit other threads to run, even if the current thread would ordinarily continue to run...
@ thrd_success
Indicates that the requested operation succeeded.
int mtx_unlock(mtx_t *mtx)
Unlocks the mutex at mtx.
pthread_mutex_t mtx_t
A complete object type that holds an identifier for a mutex.
void mtx_destroy(mtx_t *mtx)
Releases any resources used by the mutex at mtx.
@ mtx_plain
A mutex type that supports neither timeout nor test and return.
void io_tqueue_destroy(io_tqueue_t *tq)
Destroys a timer queue.
struct io_tqueue_wait * io_tqueue_wait_from_task(struct ev_task *task)
Obtains a pointer to a timer queue wait operation from a pointer to its completion task.
size_t io_tqueue_abort_wait(io_tqueue_t *tq, struct io_tqueue_wait *wait)
Aborts the specified timer queue wait operation if it is pending.
io_tqueue_t * io_tqueue_create(io_timer_t *timer, ev_exec_t *exec)
Creates a new timer queue.
io_timer_t * io_tqueue_get_timer(const io_tqueue_t *tq)
Returns a pointer to the I/O timer used by the timer queue.
void io_tqueue_submit_wait(io_tqueue_t *tq, struct io_tqueue_wait *wait)
Submits a wait operation to a timer queue.
#define IO_TQUEUE_WAIT_INIT(sec, nsec, exec, func)
The static initializer for io_tqueue_wait.
This header file is part of the utilities library; it contains the time function declarations.
int timespec_cmp(const void *p1, const void *p2)
Compares two times.
void timespec_add_msec(struct timespec *tp, uint_least64_t msec)
Adds msec milliseconds to the time at tp.