#include #include #include #include #include #include #include #include #include #include #include #include "avm_event.h" #define AVM_EVENT_DEVICE "/dev/avm_event" /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ #undef DEB_ERR #undef DEB_WARN #undef DEB_INFO #undef DEB_TRC #define DEB_ERR(args...) fprintf(stderr, args) #define DEB_WARN(args...) fprintf(stderr, args) #define DEB_INFO(args...) fprintf(stderr, args) /*--- #define DEB_TRC(args...) fprintf(stderr, args) ---*/ #if 0 static FILE *debug_stream = NULL; #define DBG_TRC(args...) { if(debug_stream == NULL) debug_stream = fopen ("/dev/console", "w"); \ if(debug_stream) fprintf(debug_stream, args); } #endif /*-------------------------------------------------------------------------------------*\ \*-------------------------------------------------------------------------------------*/ static int __avm_event_register(char* name, struct _avm_event_id_mask *id_mask, unsigned long long mask) { int fd, len; struct _avm_event_cmd cmd; fd = open(AVM_EVENT_DEVICE, O_RDWR); if (fd < 0) { return AVM_EVENT_UNKNOWN_HANDLE; } cmd.cmd = avm_event_cmd_register; #define min(a, b) ((a) < (b) ? (a) : (b)) len = min(strlen(name), MAX_EVENT_CLIENT_NAME_LEN); strncpy(cmd.param.avm_event_cmd_param_register.Name, name, len); cmd.param.avm_event_cmd_param_register.Name[len] = '\0'; #if (AVM_DIST_EVENT_VERSION >= 0x10000) /*--- Event 2.0: ---*/ if(id_mask) { memcpy(&cmd.param.avm_event_cmd_param_register.mask, id_mask, sizeof(cmd.param.avm_event_cmd_param_register.mask)); } else { memset(&cmd.param.avm_event_cmd_param_register.mask, 0, sizeof(cmd.param.avm_event_cmd_param_register.mask)); cmd.param.avm_event_cmd_param_register.mask.mask[0] = mask; } #else /*--- #if (AVM_DIST_EVENT_VERSION >= 0x10000) ---*/ if(id_mask) { cmd.param.avm_event_cmd_param_register.mask = id_mask->mask[0]; } else { cmd.param.avm_event_cmd_param_register.mask = mask; } /*--- DBG_TRC("%s: id_mask: %p mask=%Lx -> mask[0]=%Lx\n", __func__, id_mask, mask, cmd.param.avm_event_cmd_param_register.mask.mask[0]); ---*/ #endif /*--- #else ---*/ /*--- #if (AVM_DIST_EVENT_VERSION >= 0x10000) ---*/ if (write(fd, &cmd, sizeof(cmd)) < 0) { close(fd); switch (errno) { case EBADF: return AVM_EVENT_UNKNOWN_HANDLE; default: return AVM_EVENT_RESOURCE_ERROR; } } avm_event_set_blocking(fd + 1); return fd + 1; } /*--------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------*/ int avm_event_register(char* name, unsigned long long mask) { return __avm_event_register( name, NULL, mask); } #define AVM_EVENT_MASK_BITS (sizeof(avm_event_mask_fieldentry) * 8) #define AVM_EVENT_MASK_BITMASK (AVM_EVENT_MASK_BITS - 1) #define AVM_EVENT_MASK_IDX( id) ((id) / AVM_EVENT_MASK_BITS) #define AVM_EVENT_MASK_BIT( id) ((id) & AVM_EVENT_MASK_BITMASK) /*--------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------*/ int avm_event_register20(char* name, int num_ids, ...) { struct _avm_event_id_mask id_mask; int i; va_list listPointer; va_start(listPointer, num_ids); memset(&id_mask, 0, sizeof(struct _avm_event_id_mask)); if(num_ids < 0) { va_end(listPointer); return -EINVAL; } for(i = 0; i < num_ids; i++ ) { enum _avm_event_id id = va_arg( listPointer, enum _avm_event_id); if((unsigned int)id >= avm_event_last) { /*--- id out of range ---*/ va_end(listPointer); return -EINVAL; } id_mask.mask[AVM_EVENT_MASK_IDX(id)] |= (avm_event_mask_fieldentry)1 << AVM_EVENT_MASK_BIT(id); } va_end(listPointer); return __avm_event_register(name, &id_mask, 0ULL); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static int __avm_event_source_register(int handle, char *name, struct _avm_event_id_mask *id_mask, unsigned long long mask) { struct _avm_event_cmd cmd; int fd, len; fd = handle - 1; cmd.cmd = avm_event_cmd_source_register; len = min(strlen(name), MAX_EVENT_CLIENT_NAME_LEN); strncpy(cmd.param.avm_event_cmd_param_source_register.Name, name, len); cmd.param.avm_event_cmd_param_source_register.Name[len] = '\0'; #if (AVM_DIST_EVENT_VERSION >= 0x10000) /*--- Event 2.0: ---*/ if(id_mask) { memcpy(&cmd.param.avm_event_cmd_param_register.mask, id_mask, sizeof(cmd.param.avm_event_cmd_param_register.mask)); } else { memset(&cmd.param.avm_event_cmd_param_register.mask, 0, sizeof(cmd.param.avm_event_cmd_param_register.mask)); cmd.param.avm_event_cmd_param_register.mask.mask[0] = mask; } /*--- DBG_TRC("%s: id_mask: %p mask[0]=%Lx -> %Lx\n", __func__, id_mask, mask, cmd.param.avm_event_cmd_param_register.mask.mask[0]); ---*/ #else /*--- #if (AVM_DIST_EVENT_VERSION >= 0x10000) ---*/ if(id_mask) { cmd.param.avm_event_cmd_param_register.mask = id_mask->mask[0]; } else { cmd.param.avm_event_cmd_param_register.mask = mask; } #endif /*--- #else ---*/ /*--- #if (AVM_DIST_EVENT_VERSION >= 0x10000) ---*/ if (write(fd, &cmd, sizeof(cmd)) < 0) { switch (errno) { case EBADF: return AVM_EVENT_UNKNOWN_HANDLE; default: return AVM_EVENT_RESOURCE_ERROR; } } return AVM_EVENT_OK; } /*--------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------*/ int avm_event_source_register(int handle, char *name, unsigned long long mask) { return __avm_event_source_register(handle, name, NULL, mask); } /*--------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------*/ int avm_event_source_register20(int handle, char *name, int num_ids, ...) { struct _avm_event_id_mask id_mask; int i; va_list listPointer; va_start(listPointer, num_ids); memset(&id_mask, 0, sizeof(struct _avm_event_id_mask)); if(num_ids <= 0) { va_end(listPointer); return -EINVAL; } for(i = 0; i < num_ids; i++ ) { enum _avm_event_id id = va_arg( listPointer, enum _avm_event_id); if((unsigned int)id >= avm_event_last) { /*--- id out of range ---*/ va_end(listPointer); return -EINVAL; } id_mask.mask[AVM_EVENT_MASK_IDX(id)] |= (avm_event_mask_fieldentry)1 << AVM_EVENT_MASK_BIT(id); } va_end(listPointer); return __avm_event_source_register(handle, name, &id_mask, 0ULL); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int avm_event_source_release(int handle) { struct _avm_event_cmd cmd; int fd; fd = handle - 1; cmd.cmd = avm_event_cmd_source_release; if (write(fd, &cmd, sizeof(cmd)) < 0) { switch (errno) { case EBADF: return AVM_EVENT_UNKNOWN_HANDLE; default: return AVM_EVENT_RESOURCE_ERROR; } } return AVM_EVENT_OK; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int avm_event_source_trigger(int handle, unsigned int data_length, struct _avm_event_header *data) { struct _avm_event_cmd *cmd; int fd; int status = AVM_EVENT_OK; fd = handle - 1; cmd = malloc(sizeof(struct _avm_event_cmd) + data_length); if(cmd == NULL) { return AVM_EVENT_RESOURCE_ERROR; } cmd->cmd = avm_event_cmd_source_trigger; cmd->param.avm_event_cmd_param_source_trigger.id = data->id; cmd->param.avm_event_cmd_param_source_trigger.data_length = data_length; memcpy((unsigned char *)cmd + sizeof(struct _avm_event_cmd), data, data_length); if (write(fd, cmd, sizeof(struct _avm_event_cmd) + data_length) < 0) { switch (errno) { case EBADF: status = AVM_EVENT_UNKNOWN_HANDLE; break; default: status = AVM_EVENT_RESOURCE_ERROR; break; } } free(cmd); return status; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int avm_event_trigger(int handle, unsigned int id) { struct _avm_event_cmd cmd; int fd; int status = AVM_EVENT_OK; fd = handle - 1; cmd.cmd = avm_event_cmd_trigger; cmd.param.avm_event_cmd_param_trigger.id = id; if (write(fd, &cmd, sizeof(struct _avm_event_cmd)) < 0) { switch (errno) { case EBADF: status = AVM_EVENT_UNKNOWN_HANDLE; break; default: status = AVM_EVENT_RESOURCE_ERROR; break; } } return status; } /*-------------------------------------------------------------------------------------*\ \*-------------------------------------------------------------------------------------*/ int avm_event_get_fd(int handle) { return handle - 1; } /*-------------------------------------------------------------------------------------*\ \*-------------------------------------------------------------------------------------*/ int avm_event_dup(int handle) { return dup(handle - 1) + 1; } /*-------------------------------------------------------------------------------------*\ \*-------------------------------------------------------------------------------------*/ int avm_event_undup(int handle) { if(close(handle - 1)) return AVM_EVENT_UNKNOWN_HANDLE; return AVM_EVENT_OK; } /*-------------------------------------------------------------------------------------*\ \*-------------------------------------------------------------------------------------*/ int avm_event_release(int handle) { int fd; struct _avm_event_cmd cmd; fd = handle - 1; cmd.cmd = avm_event_cmd_release; cmd.param.avm_event_cmd_param_release.Name[0] = '\0'; if (write(fd, &cmd, sizeof(cmd)) < 0) { switch (errno) { case EBADF: return AVM_EVENT_UNKNOWN_HANDLE; default: return AVM_EVENT_RESOURCE_ERROR; } } close(fd); return AVM_EVENT_OK; } /*-------------------------------------------------------------------------------------*\ \*-------------------------------------------------------------------------------------*/ int avm_event_set_non_blocking(int handle) { int flags; int fd = handle - 1; flags = fcntl(fd, F_GETFL); if (flags == -1) { switch (errno) { case EBADF: return AVM_EVENT_UNKNOWN_HANDLE; default: return AVM_EVENT_RESOURCE_ERROR; } } if ((flags & O_NONBLOCK)) return AVM_EVENT_OK; flags |= O_NONBLOCK; if (fcntl(fd, F_SETFL, flags)) { switch (errno) { case EBADF: return AVM_EVENT_UNKNOWN_HANDLE; default: return AVM_EVENT_RESOURCE_ERROR; } } return AVM_EVENT_OK; } /*-------------------------------------------------------------------------------------*\ \*-------------------------------------------------------------------------------------*/ int avm_event_set_blocking(int handle) { int flags; int fd = handle - 1; flags = fcntl(fd, F_GETFL); if (flags == -1) { switch (errno) { case EBADF: return AVM_EVENT_UNKNOWN_HANDLE; default: return AVM_EVENT_RESOURCE_ERROR; } } if ((flags & O_NONBLOCK) == 0) return AVM_EVENT_OK; flags &= ~O_NONBLOCK; if (fcntl(fd, F_SETFL, flags)) { switch (errno) { case EBADF: return AVM_EVENT_UNKNOWN_HANDLE; default: return AVM_EVENT_RESOURCE_ERROR; } } return AVM_EVENT_OK; } /*------------------------------------------------------------------------------------------*\ * Paramter: * handle * data Buffer für daten * length input: maximal datenlaenge, output: gelesene Bytes \*------------------------------------------------------------------------------------------*/ int avm_event_read(int handle, void *data, unsigned int *length) { int fd = handle - 1; int ret; ret = read(fd, data, *length); if(ret >= 0) { *length = ret; return AVM_EVENT_OK; } *length = 0; return AVM_EVENT_UNKNOWN_HANDLE; }