Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 41 additions & 4 deletions src/hal/hal.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ RTAPI_BEGIN_DECLS
#include "rtapi_errno.h"

#define HAL_NAME_LEN 55 /* length for pin, signal, etc, names */
#define HAL_PSEUDO_COMP_PREFIX "__" /* prefix to identify a pseudo component */

/** These locking codes define the state of HAL locking, are used by most functions */
/** The functions locked will return a -EPERM error message **/
Expand Down Expand Up @@ -233,6 +234,10 @@ extern int hal_set_unready(int comp_id);
*/
extern int hal_unready(int comp_id);

// hal_strerror() returns a brief textual description string about the error
// identified. The argument should be the negative errno value, as returned by
// most HAL functions.
const char *hal_strerror(int err);

/** hal_comp_name() returns the name of the given component, or NULL
if comp_id is not a loaded component
Expand Down Expand Up @@ -556,6 +561,7 @@ int hal_param_new_ui32(int compid, hal_pdir_t dir, hal_uint_t *ref, rtapi_u32 d
int hal_param_new_sint(int compid, hal_pdir_t dir, hal_sint_t *ref, rtapi_sint def, const char *fmt, ...) __HAL_PFMT(5,6);
int hal_param_new_uint(int compid, hal_pdir_t dir, hal_uint_t *ref, rtapi_uint def, const char *fmt, ...) __HAL_PFMT(5,6);
int hal_param_new_real(int compid, hal_pdir_t dir, hal_real_t *ref, rtapi_real def, const char *fmt, ...) __HAL_PFMT(5,6);
int hal_param_new_fake(int compid, hal_refs_u *refs);
Comment thread
grandixximo marked this conversation as resolved.
#undef __HAL_PFMT

/***********************************************************************
Expand Down Expand Up @@ -1173,12 +1179,12 @@ extern void hal_port_wait_writable(hal_port_t** port, unsigned count, sig_atomic
*/

typedef union hal_stream_data {
real_t f;
bool b;
rtapi_real f;
rtapi_bool b;
rtapi_s32 s;
rtapi_u32 u;
rtapi_s64 l;
rtapi_u64 k;
rtapi_sint l;
rtapi_uint k;
} hal_stream_data_u;
typedef hal_stream_data_u *hal_stream_data_ptr_u;

Expand Down Expand Up @@ -1320,6 +1326,37 @@ static inline rtapi_s64 hal_extend_counter(rtapi_s64 old, rtapi_s64 newlow, int
return (rtapi_u64)old + (diff_shifted >> nshift); // unsigned to avoid signed overflow
}

//***********************************************************************
// Mapping/umapping HAL memory segment pointers
//***********************************************************************

// Pointers into HAL memory are dependent on process memory. Transporting them
// between processes does not work. These need to be handled as offsets from
// where the memory is mapped.
rtapi_intptr_t hal_reference_unmap(const void *ref);
void *hal_reference_map(rtapi_intptr_t ref);

//***********************************************************************
//
// User-land only functions to query HAL's internals
//
//***********************************************************************

// HAL 'component' type.
// Assigned according to RTAPI and ULAPI definitions.
typedef enum {
HAL_COMP_TYPE_UNKNOWN = -1,
HAL_COMP_TYPE_USER,
HAL_COMP_TYPE_REALTIME,
HAL_COMP_TYPE_OTHER
} hal_comp_type_t;
// These COMPONENT_TYPE_* names are for compatibility. The HAL_COMP_TYPE_*
// versions are better names for what they represent.
#define COMPONENT_TYPE_UNKNOWN HAL_COMP_TYPE_UNKNOWN
#define COMPONENT_TYPE_USER HAL_COMP_TYPE_USER
#define COMPONENT_TYPE_REALTIME HAL_COMP_TYPE_REALTIME
#define COMPONENT_TYPE_OTHER HAL_COMP_TYPE_OTHER

// Only enable the query API when we are compiling the user-land HAL library
#ifdef ULAPI

Expand Down
129 changes: 102 additions & 27 deletions src/hal/hal_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -355,10 +355,10 @@ int hal_init(const char *name)
/* initialize the structure */
comp->comp_id = comp_id;
#ifdef RTAPI
comp->type = COMPONENT_TYPE_REALTIME;
comp->type = HAL_COMP_TYPE_REALTIME;
comp->pid = 0;
#else /* ULAPI */
comp->type = COMPONENT_TYPE_USER;
comp->type = HAL_COMP_TYPE_USER;
comp->pid = getpid();
#endif
comp->ready = 0;
Expand Down Expand Up @@ -462,6 +462,25 @@ int hal_exit(int comp_id)
return 0;
}

int hal_is_init(void)
Comment thread
grandixximo marked this conversation as resolved.
{
return hal_shmem_base != NULL;
}

rtapi_intptr_t hal_reference_unmap(const void *ref)
{
if(!hal_shmem_base || !ref || !SHMCHK(ref))
return 0;
return (rtapi_intptr_t)SHMOFF(ref);
}

void *hal_reference_map(rtapi_intptr_t ref)
{
if(!hal_shmem_base || ref <= 0 || ref >= HAL_SIZE)
return NULL;
return SHMPTR(ref);
}

void *hal_malloc(long int size)
{
void *retval;
Expand Down Expand Up @@ -620,6 +639,33 @@ int hal_unready(int comp_id) {
return 0;
}

//
// Return an appropriate error string for HAL error values
//
// The error value should be a negative errno value returned by
// a HAL function.
//
const char *hal_strerror(int err)
{
switch(err) {
case -EINVAL: return "invalid argument";
case -ENOENT: return "not found";
case -EACCES: return "not writable";
case -EIO: return "missing target storage";
case -EBADF: return "invalid type";
case -ERANGE: return "value out of range";
case -ENOMEM: return "out of memory";
case -EISCONN: return "queue already allocated";
case -EEXIST: return "name exists"; // also when pin/param/sig matched with different type
case -EFAULT: return "shared memory not mapped";
case -EMFILE: return "too many modules";
case -EPROTO: return "hal data version mismatch";
case -EPERM: return "hal is locked";
case -ENOEXEC: return "missing constructor";
default: return "unknown error";
Comment thread
grandixximo marked this conversation as resolved.
}
}

char *hal_comp_name(int comp_id)
{
hal_comp_t *comp;
Expand Down Expand Up @@ -662,9 +708,12 @@ int hal_set_lock(unsigned char lock_type) {

unsigned char hal_get_lock() {
if (hal_data == NULL) {
rtapi_print_msg(RTAPI_MSG_ERR,
"HAL: ERROR: get_lock called before init\n");
return -EINVAL;
rtapi_print_msg(RTAPI_MSG_ERR, "HAL: ERROR: get_lock called before init\n");
// There is no point in returning a negative error value. The return
// type wont allow it. We just pretend that everything is locked tight
// and nothing can change, which would adequately describe the
// unavailability of shared memory.
return HAL_LOCK_ALL;
Comment thread
BsAtHome marked this conversation as resolved.
}
return hal_data->lock;
}
Expand Down Expand Up @@ -814,7 +863,7 @@ int hal_pin_port_newf(hal_pin_dir_t dir,

// *** New interface ***

int hal_pin_new_bool(int compid, hal_pdir_t dir, hal_bool_t *ref, bool def, const char *fmt, ...)
int hal_pin_new_bool(int compid, hal_pdir_t dir, hal_bool_t *ref, rtapi_bool def, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
Expand Down Expand Up @@ -850,7 +899,7 @@ int hal_pin_new_ui32(int compid, hal_pdir_t dir, hal_uint_t *ref, rtapi_u32 def,
return 0;
}

int hal_pin_new_sint(int compid, hal_pdir_t dir, hal_sint_t *ref, rtapi_s64 def, const char *fmt, ...)
int hal_pin_new_sint(int compid, hal_pdir_t dir, hal_sint_t *ref, rtapi_sint def, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
Expand All @@ -862,7 +911,7 @@ int hal_pin_new_sint(int compid, hal_pdir_t dir, hal_sint_t *ref, rtapi_s64 def,
return 0;
}

int hal_pin_new_uint(int compid, hal_pdir_t dir, hal_uint_t *ref, rtapi_u64 def, const char *fmt, ...)
int hal_pin_new_uint(int compid, hal_pdir_t dir, hal_uint_t *ref, rtapi_uint def, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
Expand All @@ -874,7 +923,7 @@ int hal_pin_new_uint(int compid, hal_pdir_t dir, hal_uint_t *ref, rtapi_u64 def,
return 0;
}

int hal_pin_new_real(int compid, hal_pdir_t dir, hal_real_t *ref, real_t def, const char *fmt, ...)
int hal_pin_new_real(int compid, hal_pdir_t dir, hal_real_t *ref, rtapi_real def, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
Expand Down Expand Up @@ -1444,7 +1493,7 @@ int hal_link(const char *pin_name, const char *sig_name)
//*((hal_data_u *)data_addr) = pin->dummysig;

switch (pin->type) {
case HAL_BIT:
case HAL_BOOL:
*((hal_bit_t *) data_addr) = pin->dummysig.b;
break;
case HAL_S32:
Expand All @@ -1453,13 +1502,13 @@ int hal_link(const char *pin_name, const char *sig_name)
case HAL_U32:
*((hal_u32_t *) data_addr) = pin->dummysig.u;
break;
case HAL_S64:
*((hal_s64_t *) data_addr) = pin->dummysig.s;
case HAL_SINT:
*((hal_s64_t *) data_addr) = pin->dummysig.ls;
break;
case HAL_U64:
*((hal_u64_t *) data_addr) = pin->dummysig.u;
case HAL_UINT:
*((hal_u64_t *) data_addr) = pin->dummysig.lu;
break;
case HAL_FLOAT:
case HAL_REAL:
*((hal_float_t *) data_addr) = pin->dummysig.f;
break;
default:
Expand Down Expand Up @@ -1810,7 +1859,7 @@ static int hal_param_new_newapi(hal_type_t type, hal_pdir_t dir, void *data_addr

// *** New interface ***

int hal_param_new_bool(int compid, hal_pdir_t dir, hal_bool_t *ref, bool def, const char *fmt, ...)
int hal_param_new_bool(int compid, hal_pdir_t dir, hal_bool_t *ref, rtapi_bool def, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
Expand Down Expand Up @@ -1846,7 +1895,7 @@ int hal_param_new_ui32(int compid, hal_pdir_t dir, hal_uint_t *ref, rtapi_u32 de
return 0;
}

int hal_param_new_sint(int compid, hal_pdir_t dir, hal_sint_t *ref, rtapi_s64 def, const char *fmt, ...)
int hal_param_new_sint(int compid, hal_pdir_t dir, hal_sint_t *ref, rtapi_sint def, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
Expand All @@ -1858,7 +1907,7 @@ int hal_param_new_sint(int compid, hal_pdir_t dir, hal_sint_t *ref, rtapi_s64 de
return 0;
}

int hal_param_new_uint(int compid, hal_pdir_t dir, hal_uint_t *ref, rtapi_u64 def, const char *fmt, ...)
int hal_param_new_uint(int compid, hal_pdir_t dir, hal_uint_t *ref, rtapi_uint def, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
Expand All @@ -1870,7 +1919,7 @@ int hal_param_new_uint(int compid, hal_pdir_t dir, hal_uint_t *ref, rtapi_u64 de
return 0;
}

int hal_param_new_real(int compid, hal_pdir_t dir, hal_real_t *ref, real_t def, const char *fmt, ...)
int hal_param_new_real(int compid, hal_pdir_t dir, hal_real_t *ref, rtapi_real def, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
Expand All @@ -1882,6 +1931,23 @@ int hal_param_new_real(int compid, hal_pdir_t dir, hal_real_t *ref, real_t def,
return 0;
}

// This is a special case for parameters, where you want them available, but
// not exposed. This is for example used in hostmot2.
// We ensure a valid target for the pointer destination but do not have a name
// attached. The code can then use whatever type read/write and run.
int hal_param_new_fake(int compid, hal_refs_u *ref)
{
(void)compid;
if(!ref)
return -EINVAL;
__hal_private_vals_u *ptr = hal_malloc(sizeof(*ptr));
if(!ptr)
return -ENOMEM;
memset(ptr, 0, sizeof(*ptr));
*(void **)ref = ptr;
return 0;
}

/* wrapper functs for typed params - these call the generic funct below */

int hal_param_bit_set(const char *name, int value)
Expand Down Expand Up @@ -2242,7 +2308,7 @@ int hal_export_funct(const char *name, void (*funct) (void *, long),
"HAL: ERROR: component %d not found\n", comp_id);
return -EINVAL;
}
if (comp->type == COMPONENT_TYPE_USER) {
if (comp->type == HAL_COMP_TYPE_USER) {
/* not a realtime component */
halpr_mutex_release();
rtapi_print_msg(RTAPI_MSG_ERR,
Expand Down Expand Up @@ -3502,11 +3568,14 @@ static int init_hal_data(void)
{
/* has the hal_data block already been initialized? */

/* Lock hal_data by taking the mutex, so that two processes
don't both try to initialize hal_data at the same time. NOTE:
The first time through, the hal_data memory buffer is fresh from
rtapi_shmem_new(), which means it's initialized to all zero bytes.
This means mutex is valid and locked. */
// Lock hal_data by taking the mutex, so that two processes don't both try
// to initialize hal_data at the same time.
// NOTE: The first time through, the hal_data memory buffer is fresh from
// rtapi_shmem_new(), which means it's initialized to all zero bytes.
// The used mutex in halpr_mutex_acquire()/halpr_mutex_release() uses a
// reversed default mutex, where zero means it is locked and non-zero when
// unlocked. This is required for recursive mutex functionality where the
// default is locked at init.
halpr_mutex_acquire();

if (hal_data->version != 0) {
Expand Down Expand Up @@ -3655,7 +3724,7 @@ hal_comp_t *halpr_alloc_comp_struct(void)
p->next_ptr = 0;
p->comp_id = 0;
p->mem_id = 0;
p->type = COMPONENT_TYPE_USER;
p->type = HAL_COMP_TYPE_USER;
p->shmem_base = NULL;
p->name[0] = '\0';
}
Expand Down Expand Up @@ -3923,7 +3992,7 @@ static void free_comp_struct(hal_comp_t * comp)
/* clear contents of struct */
comp->comp_id = 0;
comp->mem_id = 0;
comp->type = COMPONENT_TYPE_USER;
comp->type = HAL_COMP_TYPE_USER;
comp->shmem_base = NULL;
comp->name[0] = '\0';
/* add it to free list */
Expand Down Expand Up @@ -4954,12 +5023,17 @@ int hal_stream_num_underruns(hal_stream_t *stream)
/* only export symbols when we're building a kernel module */

EXPORT_SYMBOL(hal_init);
EXPORT_SYMBOL(hal_is_init);
EXPORT_SYMBOL(hal_ready);
EXPORT_SYMBOL(hal_set_unready);
EXPORT_SYMBOL(hal_exit);
EXPORT_SYMBOL(hal_malloc);
EXPORT_SYMBOL(hal_comp_name);
EXPORT_SYMBOL(hal_get_realtime_type);
EXPORT_SYMBOL(hal_strerror);

EXPORT_SYMBOL(hal_reference_map);
EXPORT_SYMBOL(hal_reference_unmap);

EXPORT_SYMBOL(hal_pin_new_bool);
EXPORT_SYMBOL(hal_pin_new_si32);
Expand Down Expand Up @@ -5013,6 +5087,7 @@ EXPORT_SYMBOL(hal_param_new_ui32);
EXPORT_SYMBOL(hal_param_new_sint);
EXPORT_SYMBOL(hal_param_new_uint);
EXPORT_SYMBOL(hal_param_new_real);
EXPORT_SYMBOL(hal_param_new_fake);

EXPORT_SYMBOL(hal_param_bit_set);
EXPORT_SYMBOL(hal_param_float_set);
Expand Down
Loading
Loading