EXPORT xbee_err xbee_vsetup(struct xbee **retXbee, const char *mode, va_list ap) { xbee_err ret; const struct xbee_mode *xbeeMode; struct xbee *xbee; if (!retXbee || !mode) return XBEE_EMISSINGPARAM; if ((ret = xbee_modeRetrieve(mode, &xbeeMode)) != XBEE_ENONE) return ret; if ((ret = xbee_alloc(&xbee)) != XBEE_ENONE) return ret; if ((ret = xbee_modeImport(&xbee->iface.conTypes, xbeeMode)) != XBEE_ENONE) goto die; xbee->mode = xbeeMode; xbee->iface.rx->ioFunc = xbee->mode->rx_io; xbee->iface.rx->fBlock = xbee->fBlock; xbee->iface.rx->conTypes = &xbee->iface.conTypes; xbee->iface.tx->ioFunc = xbee->mode->tx_io; if ((ret = xbee->mode->init(xbee, ap)) != XBEE_ENONE) goto die; if ((ret = xbee_threadStart(xbee, NULL, 150000, 0, xbee_rx, xbee->iface.rx)) != XBEE_ENONE) goto die; if ((ret = xbee_threadStart(xbee, NULL, 150000, 0, xbee_rxHandler, xbee->iface.rx)) != XBEE_ENONE) goto die; if ((ret = xbee_threadStart(xbee, NULL, 150000, 0, xbee_tx, xbee->iface.tx)) != XBEE_ENONE) goto die; if (xbee->mode->prepare) if ((ret = xbee->mode->prepare(xbee)) != XBEE_ENONE) goto die; if (xbee->mode->thread) if ((ret = xbee_threadStart(xbee, NULL, 150000, 0, xbee->mode->thread, NULL)) != XBEE_ENONE) goto die; xbee_ll_add_tail(xbeeList, xbee); *retXbee = xbee; return XBEE_ENONE; die: xbee_free(xbee); return ret; }
static xbee_err prepare_backchannel(struct xbee *xbee) { xbee_err ret; struct xbee_modeData *data; unsigned char retVal; struct xbee_conAddress address; struct xbee_pkt *pkt; int callbackCount; int i, pos, slen; struct xbee_con *bc_start; data = xbee->modeData; pkt = NULL; /* create the 'start' backchannel connection - this is ALWAYS ON ENDPOINT 0x00 */ memset(&address, 0, sizeof(address)); address.endpoints_enabled = 1; address.endpoint_local = 0; address.endpoint_remote = 0; if ((ret = _xbee_conNew(xbee, &xbee->iface, 1, &bc_start, "backchannel", &address)) != XBEE_ENONE) return ret; /* transmit our libxbee_commit string - the git commit id */ if ((ret = xbee_conTx(bc_start, &retVal, "%s", libxbee_commit)) != XBEE_ENONE) { switch (retVal) { case 1: xbee_log(0, "The server encountered an internal error"); break; case 2: xbee_log(0, "The server is running a different version of libxbee"); break; default: xbee_log(0, "Failed to initialize connection to server for an unknown reason..."); } goto done; } /* grab the returned data (an in-order list of the back channel endpoints, starting at 0x01) */ if ((ret = xbee_conRx(bc_start, &pkt, NULL)) != XBEE_ENONE) goto done; /* pick out the remote system's mode name, and try to locate it */ for (i = 0; i < pkt->dataLen && pkt->data[i] != '\0'; i++); if (i > 0) { if ((data->serverModeName = malloc(sizeof(char) * (i + 1))) == NULL) { ret = XBEE_ENOMEM; goto done; } strncpy(data->serverModeName, (char*)pkt->data, i); data->serverModeName[i] = '\0'; if (xbee_modeRetrieve(data->serverModeName, &data->serverMode) != XBEE_ENONE) { xbee_log(-10, "WARNING: remote mode '%s' is not avaliable on this system... Some packets may not be fully processed", data->serverModeName); } } callbackCount = pkt->data[i + 1]; memset(&address, 0, sizeof(address)); address.endpoints_enabled = 1; for (pos = i + 2, i = 1; pos < pkt->dataLen && i < callbackCount + 1; pos += slen + 1, i++) { char *name; struct xbee_con **retCon; name = (char *)&(pkt->data[pos]); slen = strlen(name); /* check for a buffer overflow */ if (slen > pkt->dataLen - pos) { slen = pkt->dataLen - pos; name[slen] = '\0'; } retCon = NULL; /* try to match the string with an element in struct xbee_modeData */ #define TRY(conName) if (!data->bc_##conName && !strncasecmp(name, #conName, slen)) TRY (conValidate) { retCon = &data->bc_conValidate; } else TRY (conSleep) { retCon = &data->bc_conSleep; } else TRY (conSettings) {