xbee_err xbee_frameWait(struct xbee_frameBlock *fBlock, struct xbee_con *con, unsigned char *retVal, struct timespec *timeout) { xbee_err ret; struct xbee_frame *frame; int i, o; if (!fBlock || !con) return XBEE_EMISSINGPARAM; ret = XBEE_EINVAL; xbee_mutex_lock(&fBlock->mutex); frame = NULL; for (i = 0, o = fBlock->lastFrame; i < fBlock->numFrames; i++, o--) { if (o < 0) o = fBlock->numFrames - 1; if (fBlock->frame[o].id != con->frameId) continue; if (fBlock->frame[o].status == 0 || fBlock->frame[o].con != con) { ret = XBEE_ESTALE; } else { frame = &fBlock->frame[o]; frame->status |= XBEE_FRAME_STATUS_WAITING; } break; } xbee_mutex_unlock(&fBlock->mutex); if (!frame) return ret; ret = XBEE_ENONE; if (timeout) { if (xsys_sem_timedwait(&frame->sem, timeout)) { if (errno == ETIMEDOUT) { ret = XBEE_ETIMEOUT; } else { ret = XBEE_ESEMAPHORE; } } } else { if (xsys_sem_wait(&frame->sem)) { ret = XBEE_ESEMAPHORE; } } xbee_mutex_lock(&fBlock->mutex); con->frameId = 0; frame->con = NULL; if (frame->status & XBEE_FRAME_STATUS_COMPLETE && ret == XBEE_ENONE) { if (retVal) *retVal = frame->retVal; frame->status = 0; } else { frame->status &= ~XBEE_FRAME_STATUS_WAITING; } xbee_mutex_unlock(&fBlock->mutex); return ret; }
xbee_err _xbee_ll_add_tail(void *list, void *item, int needMutex) { struct xbee_ll_head *h; struct xbee_ll_info *i, *p; xbee_err ret; ret = XBEE_ENONE; if (!list) return XBEE_EMISSINGPARAM; i = list; h = i->head; if (!(h && h->is_head && h->self == h)) return XBEE_EINVAL; if (needMutex) xbee_mutex_lock(&h->mutex); p = h->tail; if (!(h->tail = calloc(1, sizeof(struct xbee_ll_info)))) { h->tail = p; ret = XBEE_ENOMEM; goto out; } h->tail->head = h; h->tail->next = NULL; if (p) { h->tail->prev = p; p->next = h->tail; } else { h->tail->prev = NULL; h->head = h->tail; } h->tail->item = item; out: if (needMutex) xbee_mutex_unlock(&h->mutex); return ret; }
xbee_err xbee_frameGetID(struct xbee_frameBlock *fBlock, struct xbee_con *con, char abandon) { xbee_err ret; int i, o; if (!fBlock || !con) return XBEE_EMISSINGPARAM; ret = XBEE_EFAILED; xbee_mutex_lock(&fBlock->mutex); for (i = 0, o = fBlock->lastFrame + 1; i < fBlock->numFrames; i++, o++) { o %= fBlock->numFrames; /* skip frame '0x00', this indicates that no ACK is requested */ if (fBlock->frame[o].id == 0) continue; /* skip busy frames */ if (fBlock->frame[o].status) continue; fBlock->lastFrame = o; fBlock->frame[o].status = XBEE_FRAME_STATUS_SCHEDULED; if (abandon) { fBlock->frame[o].status |= XBEE_FRAME_STATUS_ABANDONED; } else { fBlock->frame[o].con = con; } con->frameId = fBlock->frame[o].id; ret = XBEE_ENONE; break; } xbee_mutex_unlock(&fBlock->mutex); return ret; }
xbee_err _xbee_logWrite(struct xbee_log *log, const char *file, int line, const char *function, struct xbee *xbee, int minLevel, char *preStr, char *format, va_list ap) { char tBuf[XBEE_LOG_MAXLEN]; int len; const char * const truncStr = XBEE_LOG_TRUNC_STR; static int truncLen = 0; if (!log || !file || !function || !xbee || !preStr || !format) return XBEE_EMISSINGPARAM; if (!log->f) return XBEE_EINVAL; len = vsnprintf(tBuf, XBEE_LOG_MAXLEN, format, ap); if (len >= XBEE_LOG_MAXLEN) { if (truncLen == 0) { truncLen = strlen(truncStr); } strcpy(&(tBuf[XBEE_LOG_MAXLEN - (truncLen + 1)]), truncStr); } xbee_mutex_lock(&log->mutex); if (!xbee) { fprintf(log->f, "%s%3d#[%s:%d] %s(): %s\n", preStr, minLevel, file, line, function, tBuf); } else if (xbee_validate(xbee) == XBEE_ENONE) { fprintf(log->f, "%s%3d#[%s:%d] %s() %p: %s\n", preStr, minLevel, file, line, function, xbee, tBuf); } else { fprintf(log->f, "%s%3d#[%s:%d] %s() !%p!: %s\n", preStr, minLevel, file, line, function, xbee, tBuf); } xbee_mutex_unlock(&log->mutex); return XBEE_ENONE; }
xbee_err _xbee_ll_ext_tail(void *list, void **retItem, int needMutex) { struct xbee_ll_head *h; struct xbee_ll_info *i, *p; void *ret; if (!list || !retItem) return XBEE_EMISSINGPARAM; i = list; h = i->head; if (!(h && h->is_head && h->self == h)) return XBEE_EINVAL; if (needMutex) xbee_mutex_lock(&h->mutex); p = h->tail; if (!p) { ret = NULL; goto out; } ret = p->item; h->tail = p->prev; if (h->tail) h->tail->next = NULL; if (h->head == p) h->head = NULL; free(p); out: if (needMutex) xbee_mutex_unlock(&h->mutex); *retItem = ret; if (!ret) return XBEE_ERANGE; return XBEE_ENONE; }
xbee_err xbee_ll_unlock(void *list) { struct xbee_ll_head *h; struct xbee_ll_info *i; if (!list) return XBEE_EMISSINGPARAM; i = list; h = i->head; if (!(h && h->is_head && h->self == h)) return XBEE_EINVAL; xbee_mutex_unlock(&h->mutex); return XBEE_ENONE; }
EXPORT xbee_err xbee_logTargetSet(struct xbee *xbee, FILE *f) { if (!xbee) return XBEE_EMISSINGPARAM; #ifndef XBEE_DISABLE_STRICT_OBJECTS if (xbee_validate(xbee) != XBEE_ENONE) return XBEE_EINVAL; #endif /* XBEE_DISABLE_STRICT_OBJECTS */ if (!xbee->log) return XBEE_ENOTIMPLEMENTED; xbee_mutex_lock(&xbee->log->mutex); xbee->log->f = f; xbee_mutex_unlock(&xbee->log->mutex); return XBEE_ENONE; }
EXPORT xbee_err xbee_logLevelSet(struct xbee *xbee, int level) { if (!xbee) return XBEE_EMISSINGPARAM; #ifndef XBEE_DISABLE_STRICT_OBJECTS if (xbee_validate(xbee) != XBEE_ENONE) return XBEE_EINVAL; #endif /* XBEE_DISABLE_STRICT_OBJECTS */ if (!xbee->log) return XBEE_ENOTIMPLEMENTED; xbee_mutex_lock(&xbee->log->mutex); xbee->log->logLevel = level; xbee_mutex_unlock(&xbee->log->mutex); xbee_log(xbee->log->logLevel, "Set log level to: %d", level); return XBEE_ENONE; }
xbee_err _xbee_ll_count_items(void *list, unsigned int *retCount, int needMutex) { struct xbee_ll_head *h; struct xbee_ll_info *i, *p; int count; if (!list || !retCount) return XBEE_EMISSINGPARAM; i = list; h = i->head; if (!(h && h->is_head && h->self == h)) return XBEE_EINVAL; if (needMutex) xbee_mutex_lock(&h->mutex); for (p = h->head, count = 0; p; p = p->next, count++); if (needMutex) xbee_mutex_unlock(&h->mutex); *retCount = count; return XBEE_ENONE; }
xbee_err _xbee_ll_modify_item(void *list, void *oldItem, void *newItem, int needMutex) { struct xbee_ll_head *h; struct xbee_ll_info *i, *p; xbee_err ret; if (!list) return XBEE_EMISSINGPARAM; i = list; h = i->head; if (!(h && h->is_head && h->self == h)) return XBEE_EINVAL; if (needMutex) xbee_mutex_lock(&h->mutex); if ((ret = __xbee_ll_get_item(h, oldItem, &p, 0)) == XBEE_ENONE) { p->item = newItem; } if (needMutex) xbee_mutex_unlock(&h->mutex); return ret; }
xbee_err xbee_ll_combine(void *head, void *tail) { struct xbee_ll_head *hH, *hT; struct xbee_ll_info *iH, *iT; void *v; xbee_err ret; ret = XBEE_ENONE; if (!head || !tail) return XBEE_EMISSINGPARAM; if (head == tail) return XBEE_EINVAL; iH = head; hH = iH->head; if (!(hH && hH->is_head && hH->self == hH)) return XBEE_EINVAL; xbee_mutex_lock(&hH->mutex); iT = tail; hT = iT->head; if (!(hT && hT->is_head && hT->self == hT)) { ret = XBEE_EINVAL; goto out; } xbee_mutex_lock(&hT->mutex); while ((ret = _xbee_ll_ext_head(tail, &v, 0)) == XBEE_ENONE && v) { _xbee_ll_add_tail(head, v, 0); } xbee_mutex_unlock(&hH->mutex); out: xbee_mutex_unlock(&hT->mutex); return XBEE_ENONE; }
xbee_err xbee_frameReturnID(struct xbee_frameBlock *fBlock, struct xbee_con *con) { xbee_err ret; int i; unsigned char frameId; struct xbee_frame *frame; if (!fBlock || !con) return XBEE_EMISSINGPARAM; ret = XBEE_EFAILED; xbee_mutex_lock(&fBlock->mutex); frameId = con->frameId; if (frameId < fBlock->numFrames) { frame = &(fBlock->frame[frameId]); } else { frame = NULL; } if ((frame == NULL) || (frame->id != frameId)) { frame = NULL; for (i = 0; i < fBlock->numFrames; i++) { if (fBlock->frame[i].id == frameId) { frame = &(fBlock->frame[i]); break; } } } if ((frame == NULL) || (frame->con != con)) { ret = XBEE_ESTALE; goto done; } /* clean down the frame */ con->frameId = 0; frame->con = NULL; frame->status = 0; done: xbee_mutex_unlock(&fBlock->mutex); return ret; }
xbee_err _xbee_ll_get_tail(void *list, void **retItem, int needMutex) { struct xbee_ll_head *h; struct xbee_ll_info *i; xbee_err ret; if (!list || !retItem) return XBEE_EMISSINGPARAM; i = list; h = i->head; if (!(h && h->is_head && h->self == h)) return XBEE_EINVAL; if (needMutex) xbee_mutex_lock(&h->mutex); if (h->tail) { *retItem = h->tail->item; ret = XBEE_ENONE; } else { ret = XBEE_ERANGE; } if (needMutex) xbee_mutex_unlock(&h->mutex); return ret; }
/* returns struct xbee_ll_info* or NULL - don't touch the pointer if you don't know what you're doing ;) */ xbee_err __xbee_ll_get_item(void *list, const void *item, struct xbee_ll_info **retItem, int needMutex) { struct xbee_ll_head *h; struct xbee_ll_info *i; if (!list) return XBEE_EMISSINGPARAM; i = list; h = i->head; if (!(h && h->is_head && h->self == h)) return XBEE_EINVAL; if (needMutex) xbee_mutex_lock(&h->mutex); i = h->head; while (i) { if (i->item == item) break; i = i->next; } if (needMutex) xbee_mutex_unlock(&h->mutex); if (retItem) *retItem = (void*)i; if (!i) return XBEE_ENOTEXISTS; return XBEE_ENONE; }
xbee_err xbee_framePost(struct xbee_frameBlock *fBlock, unsigned char frameId, unsigned char retVal) { xbee_err ret; struct xbee_frame *frame; int i; if (!fBlock) return XBEE_EMISSINGPARAM; if (frameId == 0) return XBEE_ENONE; xbee_mutex_lock(&fBlock->mutex); frame = NULL; for (i = 0; i < fBlock->numFrames; i++) { if (fBlock->frame[i].id != frameId) continue; if (fBlock->frame[i].status != 0) { frame = &fBlock->frame[i]; } break; } if (!frame) { ret = XBEE_EINVAL; } else if (frame->con && (frame->status & XBEE_FRAME_STATUS_WAITING)) { ret = XBEE_ENONE; frame->status |= XBEE_FRAME_STATUS_COMPLETE; frame->retVal = retVal; xsys_sem_post(&frame->sem); } else { if (!(frame->status & XBEE_FRAME_STATUS_ABANDONED)) { ret = XBEE_ETIMEOUT; } if (frame->con) { frame->con->frameId = 0; frame->con = NULL; } frame->status = 0; } xbee_mutex_unlock(&fBlock->mutex); return ret; }
xbee_err _xbee_ll_get_prev(void *list, void *ref, void **retItem, int needMutex) { struct xbee_ll_head *h; struct xbee_ll_info *i; void *ret = NULL; if (!list || !retItem) return XBEE_EMISSINGPARAM; if (!ref) return _xbee_ll_get_tail(list, retItem, needMutex); i = list; h = i->head; if (!(h && h->is_head && h->self == h)) return XBEE_EINVAL; if (needMutex) xbee_mutex_lock(&h->mutex); i = h->head; if (__xbee_ll_get_item(h, ref, &i, 0) != XBEE_ENONE) goto out; if (!i) goto out; i = i->prev; if (i) ret = i->item; out: if (needMutex) xbee_mutex_unlock(&h->mutex); *retItem = ret; if (!ret) return XBEE_ERANGE; return XBEE_ENONE; }
/* NULL ref will add to head */ xbee_err _xbee_ll_add_before(void *list, void *ref, void *item, int needMutex) { struct xbee_ll_head *h; struct xbee_ll_info *i, *t; xbee_err ret; ret = XBEE_ENONE; if (!list) return XBEE_EMISSINGPARAM; i = list; h = i->head; if (!(h && h->is_head && h->self == h)) return XBEE_EINVAL; if (!ref) return xbee_ll_add_tail(h, item); if (needMutex) xbee_mutex_lock(&h->mutex); i = h->head; while (i) { if (i->item == ref) break; i = i->next; } if (!i) { ret = XBEE_ENOTEXISTS; goto out; } if (!(t = calloc(1, sizeof(struct xbee_ll_info)))) { ret = XBEE_ENOMEM; goto out; } t->head = i->head; if (!i->prev) { h->head = t; t->prev = NULL; } else { i->prev->next = t; t->prev = i->prev; } i->prev = t; t->next = i; t->item = item; out: if (needMutex) xbee_mutex_unlock(&h->mutex); return ret; }
xbee_err _xbee_ll_get_index(void *list, unsigned int index, void **retItem, int needMutex) { struct xbee_ll_head *h; struct xbee_ll_info *i; int o; if (!list || !retItem) return XBEE_EMISSINGPARAM; i = list; h = i->head; if (!(h && h->is_head && h->self == h)) return XBEE_EINVAL; if (needMutex) xbee_mutex_lock(&h->mutex); i = h->head; for (o = 0; o < index; o++) { i = i->next; if (!i) break; } if (needMutex) xbee_mutex_unlock(&h->mutex); if (!i) { *retItem = NULL; return XBEE_ERANGE; } *retItem = i->item; return XBEE_ENONE; }
xbee_err _xbee_ll_ext_index(void *list, unsigned int index, void **retItem, int needMutex) { struct xbee_ll_head *h; struct xbee_ll_info *i; int o; xbee_err ret; if (!list || !retItem) return XBEE_EMISSINGPARAM; i = list; h = i->head; if (!(h && h->is_head && h->self == h)) return XBEE_EINVAL; if (needMutex) xbee_mutex_lock(&h->mutex); i = h->head; for (o = 0; o < index; o++) { i = i->next; if (!i) break; } if (!i) { *retItem = NULL; ret = XBEE_ERANGE; goto out; } *retItem = i->item; if (i->next) { i->next->prev = i->prev; } else { h->tail = i->prev; } if (i->prev) { i->prev->next = i->next; } else { h->head = i->next; } free(i); ret = XBEE_ENONE; out: if (needMutex) xbee_mutex_unlock(&h->mutex); return ret; }
xbee_err _xbee_ll_ext_item(void *list, void *item, int needMutex) { struct xbee_ll_head *h; struct xbee_ll_info *i, *p; xbee_err ret; if (!list) return XBEE_EMISSINGPARAM; i = list; h = i->head; if (!(h && h->is_head && h->self == h)) return XBEE_EINVAL; if (needMutex) xbee_mutex_lock(&h->mutex); p = h->head; ret = XBEE_ENONE; while (p) { if (p->is_head) { ret = XBEE_ELINKEDLIST; break; } if (p->item == item) { if (p->next) { p->next->prev = p->prev; } else { h->tail = p->prev; } if (p->prev) { p->prev->next = p->next; } else { h->head = p->next; } free(p); break; } p = p->next; } if (needMutex) xbee_mutex_unlock(&h->mutex); if (!p) return XBEE_ENOTEXISTS; return ret; }