static int laura_do_sync_call(lua_State *L) { struct laura_node *lnode = lua_fetch_node(L, 1); struct aura_buffer *buf, *retbuf; struct aura_object *o; int ret; TRACE(); o = aura_etable_find(lnode->node->tbl, lnode->current_call); if (!o) return luaL_error(L, "Attempt to call non-existend method"); buf = lua_to_buffer(L, lnode->node, 2, o); if (!buf) return luaL_error(L, "Serializer failed!"); ret = aura_core_call(lnode->node, o, &retbuf, buf); if (ret != 0) return luaL_error(L, "Call for %s failed", o->name); ret = buffer_to_lua(L, lnode->node, o, retbuf); aura_buffer_release(retbuf); return ret; }
int main() { slog_init(NULL, 18); int count = 5; int ret; struct aura_node *n = aura_open("dummy", NULL); aura_wait_status(n, AURA_STATUS_ONLINE); struct aura_buffer *retbuf; const struct aura_object *o; aura_enable_sync_events(n, 5); while (count--) { ret = aura_get_next_event(n, &o, &retbuf); slog(0, SLOG_DEBUG, "evt get ret %d", ret); aura_hexdump("Out buffer", retbuf->data, retbuf->size); aura_buffer_release(retbuf); } aura_close(n); return 0; }
static void cb_call_write_done(struct libusb_transfer *transfer) { struct aura_node *node = transfer->user_data; struct usb_dev_info *inf = aura_get_transportdata(node); if (0 != check_control(transfer)) { /* Put it back to queue. Core will deal with it later */ goto requeue; } if (transfer->actual_length - LIBUSB_CONTROL_SETUP_SIZE < transfer->length) { slog(0, SLOG_ERROR, "usb: short-write on call packet want %d got %d (API mismatch?)", transfer->length, transfer->actual_length); usb_panic_and_reset_state(node); goto requeue; } aura_buffer_release(node, inf->current_buffer); inf->current_buffer = NULL; slog(4, SLOG_DEBUG, "Call write done"); return; requeue: aura_requeue_buffer(&node->outbound_buffers, inf->current_buffer); inf->current_buffer = NULL; }
int main() { int ret; int i; int passed = 0; int failed = 0; slog_init(NULL, 0); struct aura_node *n = aura_open("simpleusb", "../simpleusbconfigs/susb-test.conf"); if (!n) { printf("err\n"); return -1; } i = 100; while (i--) { printf("Testing %d remaining\r", i); fflush(stdout); aura_wait_status(n, AURA_STATUS_ONLINE); struct aura_buffer *retbuf; ret = aura_call(n, "led_ctl", &retbuf, 0x100, 0x100); if (0 == ret) { aura_buffer_release(retbuf); passed++; } else failed++; } aura_close(n); printf("Stability test (no data): %d succeeded, %d failed total %d\n", passed, failed, passed + failed); return failed; }
int nmppsMax_16sm (const nm16s* src, int size, int16b* pMaxValue, nm32s* tmp) { int ret; struct aura_buffer *iobuf_src = aura_buffer_request(n, size*2); memcpy(iobuf_src->data,src,size*2); struct aura_buffer *retbuf; ret = aura_call(n, "nmppsMax_16sm", &retbuf, iobuf_src, size); if (ret != 0) { BUG(n, "Call:nmppsMax_16sm failed!"); } *pMaxValue = aura_buffer_get_u32(retbuf); ret = aura_buffer_get_u32(retbuf); aura_buffer_release( iobuf_src); aura_buffer_release( retbuf); slog(3, SLOG_INFO, "ARM: Call nmppsMax_16sm -ok"); return ret; }
int nmppsFFT512InvInitAlloc(NmppsFFTSpec** spec, const void* src,const void* dst, int settings) { struct aura_buffer *iobuf_src = aura_buffer_request(n, 512*8); struct aura_buffer *iobuf_dst = aura_buffer_request(n, 512*8); struct aura_buffer *retbuf; int ret = aura_call(n, "nmppsFFT512InvInitAlloc", &retbuf, iobuf_src, iobuf_dst, settings); if (ret != 0) { slog(0, SLOG_ERROR, "call failed, reason: %d\n", ret); BUG(n, "Call nmppsFFT512InvInitAlloc failed!"); } *spec = (NmppsFFTSpec*) aura_buffer_get_u32(retbuf); ret = aura_buffer_get_u32(retbuf); aura_buffer_release( iobuf_src); aura_buffer_release( iobuf_dst); aura_buffer_release( retbuf); slog(3, SLOG_INFO, "ARM: Call nmppsFFT512InvInitAlloc -ok"); return ret; }
int nmppsCmpNeC_8s8um (const nm8s* src, int8b nCmpVal, nm8u* dst, int size, struct NmppsTmpSpec* spec) { int ret; struct aura_buffer *iobuf_src = aura_buffer_request(n, size*1); struct aura_buffer *iobuf_dst = aura_buffer_request(n, size*1); memcpy(iobuf_src->data,src,size*1); struct aura_buffer *retbuf; ret = aura_call(n, "nmppsCmpNeC_8s8um", &retbuf, iobuf_src, nCmpVal, iobuf_dst, size); if (ret != 0) { BUG(n, "Call:nmppsCmpNeC_8s8um failed!"); } memcpy(dst,iobuf_dst->data,size); aura_buffer_release( iobuf_dst); aura_buffer_release( iobuf_src); aura_buffer_release( retbuf); slog(3, SLOG_INFO, "ARM: Call nmppsCmpNeC_8s8um -ok"); return 0; }
long run_first(struct aura_node *n) { struct aura_buffer *retbuf; int i; long start = current_time(); for (i=0; i<90000; i++) { aura_call(n, "echo_u16", &retbuf, 0x0102); aura_buffer_release(retbuf); aura_call(n, "echo_u8", &retbuf, 0x0102); aura_buffer_release(retbuf); aura_call(n, "echo_u32", &retbuf, 0x0102); aura_buffer_release(retbuf); aura_call(n, "echo_u64", &retbuf, 0x0102); aura_buffer_release(retbuf); } return current_time() - start; }
void nmppsFFT512Inv(const nm32sc* src, nm32sc* dst, const NmppsFFTSpec* spec) { int ret; int size=512; int k=8; struct aura_buffer *iobuf_src = aura_buffer_request(n, size*k); struct aura_buffer *iobuf_dst = aura_buffer_request(n, size*k); memcpy(iobuf_src->data,src,size*k); struct aura_buffer *retbuf; ret = aura_call(n, "nmppsFFT512Inv", &retbuf, iobuf_src, iobuf_dst, spec); if (ret != 0) { slog(0, SLOG_ERROR, "call nmppsFFT512Inv failed, reason: %d\n", ret); BUG(n, "Call nmppsFFT512Inv failed!"); } memcpy(dst,iobuf_dst->data,size*k); aura_buffer_release( iobuf_dst); aura_buffer_release( iobuf_src); aura_buffer_release( retbuf); slog(3, SLOG_INFO, "ARM: Call nmppsFFT512Inv -ok"); }
long run_second(struct aura_node *n) { struct aura_buffer *buf; long start = current_time(); int i; for (i=0; i<90000; i++) { buf = aura_buffer_request(n, (rand() % 512) + 1); aura_buffer_release(buf); } return current_time() - start; }
void nmppsFFTFree(NmppsFFTSpec* spec ) { int ret; struct aura_buffer *retbuf; ret = aura_call(n, "nmppsFFTFree", &retbuf, spec); if (ret != 0) BUG(n, "Call nmppsFFTFree failed!"); aura_buffer_release( retbuf); slog(3, SLOG_INFO, "ARM: Call nmppsFFTFree ok"); }
int main() { int ret; int i = 2; slog_init(NULL, 88); struct aura_node *n = aura_open("simpleusb", "./simpleusbconfigs/pw-ctl.conf"); if (!n) { printf("err\n"); return -1; } aura_wait_status(n, AURA_STATUS_ONLINE); struct aura_buffer *retbuf; ret = aura_call(n, "bit_set", &retbuf, 12<<8 | 1, 1); slog(0, SLOG_DEBUG, "call ret %d", ret); if (0 == ret) { printf("====> buf pos %d len %d\n", retbuf->pos, retbuf->size); aura_buffer_release(n, retbuf); } int v = 1; while(1) { v = !v; printf("<=================>\n"); ret = aura_call(n, "bit_set", &retbuf, 12<<8, v); slog(0, SLOG_DEBUG, "call ret %d", ret); if (0 == ret) { printf("====> buf pos %d len %d\n", retbuf->pos, retbuf->size); aura_buffer_release(n, retbuf); } else { aura_wait_status(n, AURA_STATUS_ONLINE); i--; if (!i) goto bailout; } sleep(1); } bailout: aura_close(n); return 0; }
void test_buf(struct aura_node *n) { int ret; struct aura_buffer *retbuf; struct aura_buffer *iobuf = aura_buffer_request(n, 80); uint32_t test = 0xdeadf00d; memcpy(iobuf->data, &test, sizeof(test)); ret = aura_call(n, "echo_buf", &retbuf, iobuf); slog(0, SLOG_DEBUG, "call ret %d", ret); if (ret) BUG(n, "call failed"); struct aura_buffer *tmp = aura_buffer_get_buf(retbuf); if (tmp != iobuf) BUG(n, "test not ok"); aura_buffer_release(n, retbuf); aura_buffer_release(n, tmp); slog(0, SLOG_INFO, "BUF test passed"); }
int main() { slog_init(NULL, 18); int ret; struct aura_node *n = aura_open("dummy", NULL); struct aura_buffer *retbuf; struct aura_buffer *iobuf = aura_buffer_request(n, 80); ret = aura_call(n, "echo_buf", &retbuf, iobuf); slog(0, SLOG_DEBUG, "call ret %d", ret); if (ret) BUG(n, "call failed"); struct aura_buffer *tmp = aura_buffer_get_buf(retbuf); if (tmp != iobuf) BUG(n, "test not ok"); aura_buffer_release(n, retbuf); aura_buffer_release(n, tmp); aura_close(n); return 0; }
static void cleanup_buffer_queue(struct list_head *q) { int i = 0; struct list_head *pos, *tmp; list_for_each_safe(pos, tmp, q) { struct aura_buffer *b; b = list_entry(pos, struct aura_buffer, qentry); list_del(pos); aura_buffer_release(NULL, b); i++; } slog(6, SLOG_LIVE, "Cleaned up %d buffers", i); }
void test_u64(struct aura_node *n) { int ret; struct aura_buffer *retbuf; ret = aura_call(n, "echo64", &retbuf, 0xbeefc0deb00bc0de); if (ret != 0) BUG(n, "Call failed!"); uint64_t v = aura_buffer_get_u64(retbuf); if (v != 0xbeefc0deb00bc0de) slog(0, SLOG_ERROR, "U64 test NOT ok: %llx vs %llx", v, 0xbeefc0deb00bc0de); aura_buffer_release(n, retbuf); slog(0, SLOG_INFO, "U64 echo test passed"); }
static void gpio_handle_event(struct aura_node *node, enum node_event evt, const struct aura_pollfds *fd) { struct aura_buffer *buf; struct aura_object *o; while (1) { buf = aura_dequeue_buffer(&node->outbound_buffers); if (!buf) break; o = buf->object; handle_outbound(node, o, buf); aura_buffer_release(buf); } }
void test_u32(struct aura_node *n) { int ret; struct aura_buffer *retbuf; ret = aura_call(n, "echo32", &retbuf, 0xbeefc0de); if (ret != 0) BUG(n, "Call failed!"); uint32_t v = aura_buffer_get_u32(retbuf); if (v != 0xbeefc0de) { slog(0, SLOG_ERROR, "U32 test NOT ok: %llx vs %llx", v, 0xbeefc0de); } aura_buffer_release(n, retbuf); slog(0, SLOG_INFO, "U32 echo test passed"); }
int main() { slog_init(NULL, 18); int ret; struct aura_node *n = aura_open("dummy", NULL); struct aura_buffer *retbuf; ret = aura_call(n, "echo_u16", &retbuf, 0x0102); slog(0, SLOG_DEBUG, "call ret %d", ret); aura_hexdump("Out buffer", retbuf->data, retbuf->size); aura_buffer_release(n, retbuf); aura_close(n); return 0; }
static void cb_event_readout_done(struct libusb_transfer *transfer) { struct aura_node *node = transfer->user_data; struct usb_dev_info *inf = aura_get_transportdata(node); struct usb_event_packet *evt; struct aura_buffer *buf = inf->current_buffer; struct aura_object *o; if (0 != check_control(transfer)) goto ignore; if (transfer->actual_length < sizeof(struct usb_event_packet)) goto ignore; evt = (struct usb_event_packet *) libusb_control_transfer_get_data(transfer); o = aura_etable_find_id(node->tbl, evt->id); if (!o) { slog(0, SLOG_ERROR, "usb: got bogus event id from device %d, resetting", evt->id); goto panic; } if ((transfer->actual_length - LIBUSB_CONTROL_SETUP_SIZE) < (sizeof(struct usb_event_packet) + o->retlen)) { slog(0, SLOG_ERROR, "usb: short read for evt %d: %d bytes expected %d got", evt->id, o->retlen + sizeof(struct usb_event_packet), transfer->actual_length); goto panic; } inf->pending--; slog(4, SLOG_DEBUG, "Event readout completed, %d bytes, %d evt left", transfer->actual_length, inf->pending); buf->object = o; /* Position the buffer at the start of the responses */ buf->pos = LIBUSB_CONTROL_SETUP_SIZE + sizeof(struct usb_event_packet); aura_queue_buffer(&node->inbound_buffers, buf); return; panic: usb_panic_and_reset_state(node); ignore: aura_buffer_release(node, buf); inf->current_buffer = NULL; return; }
void test_u32u32(struct aura_node *n) { int ret; struct aura_buffer *retbuf; ret = aura_call(n, "echou32u32", &retbuf, 0xbeefc0de, 0xdeadc0de); if (ret != 0) BUG(n, "Call failed!"); uint32_t v1 = aura_buffer_get_u32(retbuf); uint32_t v2 = aura_buffer_get_u32(retbuf); if ((v1 != 0xbeefc0de) && (v2 != 0xdeadc0de)) { slog(0, SLOG_ERROR, "U32 test NOT ok: %llx,%llx vs %llx,%llx", v1, v2, 0xbeefc0de, 0xdeadc0de); } aura_buffer_release(n, retbuf); slog(0, SLOG_INFO, "U32U32 echo test passed"); }
void test_bin(struct aura_node *n) { char buf[64]; int ret; FILE *fd = fopen("/dev/urandom", "r+"); fread(buf, 64, 1, fd); fclose(fd); struct aura_buffer *retbuf; ret = aura_call(n, "echobin", &retbuf, buf); if (ret != 0) BUG(n, "Call failed!"); if (0 != memcmp(buf, retbuf->data, 64)) slog(0, SLOG_ERROR, "BIN test NOT ok"); aura_hexdump("Out buffer", buf, 64); aura_hexdump("In buffer", retbuf->data, 64); aura_buffer_release(retbuf); slog(0, SLOG_INFO, "BIN test passed"); }
/* This one is small, but tricky */ static void aura_handle_inbound(struct aura_node *node) { while(1) { struct aura_buffer *buf; struct aura_object *o; buf = aura_dequeue_buffer(&node->inbound_buffers); if (!buf) break; o = buf->object; node->current_object = o; aura_buffer_rewind(buf); slog(4, SLOG_DEBUG, "Handling %s id %d (%s) sync_call_running=%d", object_is_method(o) ? "response" : "event", o->id, o->name, node->sync_call_running); if (object_is_method(o) && !o->pending) { slog(0, SLOG_WARN, "Dropping orphan call result %d (%s)", o->id, o->name); aura_buffer_release(node, buf); } else if (o->calldonecb) { slog(4, SLOG_DEBUG, "Callback for method/event %d (%s)", o->id, o->name); o->calldonecb(node, AURA_CALL_COMPLETED, buf, o->arg); aura_buffer_release(node, buf); } else if (object_is_method(o) && (node->sync_call_running)) { slog(4, SLOG_DEBUG, "Completing call for method %d (%s)", o->id, o->name); node->sync_call_result = AURA_CALL_COMPLETED; node->sync_ret_buf = buf; o->pending--; if (o->pending < 0) BUG(node, "Internal BUG: pending evt count lesser than zero"); } else { /* This one is tricky. We have an event with no callback */ if (node->sync_event_max > 0) { /* Queue it up into event_queue if it's enabled */ /* If we have an overrun - drop the oldest event to free up space first*/ if (node->sync_event_max <= node->sync_event_count) { struct aura_buffer *todrop; const struct aura_object *dummy; int ret = aura_get_next_event(node, &dummy, &todrop); if (ret != 0) BUG(node, "Internal bug, no next event"); aura_buffer_release(node, todrop); } /* Now just queue the next one */ aura_queue_buffer(&node->event_buffers, buf); node->sync_event_count++; slog(4, SLOG_DEBUG, "Queued event %d (%s) for sync readout", o->id, o->name); } else { /* Last resort - try the catch-all event callback */ if (node->unhandled_evt_cb) node->unhandled_evt_cb(node, buf, node->unhandled_evt_arg); else /* Or just drop it with a warning */ slog(0, SLOG_WARN, "Dropping event %d (%s)", o->id, o->name); aura_buffer_release(node, buf); } } } node->current_object = NULL; }
static struct aura_buffer *lua_to_buffer(lua_State *L, struct aura_node *node, int stackpos, struct aura_object *o) { int i; struct aura_buffer *buf; const char *fmt; fmt = o->arg_fmt; if (lua_gettop(L) - stackpos + 1 != o->num_args) { slog(0, SLOG_ERROR, "Invalid argument count for %s: %d / %d", o->name, lua_gettop(L) - stackpos, o->num_args); return NULL; } buf = aura_buffer_request(node, o->arglen); if (!buf) { slog(0, SLOG_ERROR, "Epic fail during buffer allocation"); return NULL; } /* Let's serialize the data, arguments are on the stack, * Starting from #3. */ for (i = stackpos; i <= lua_gettop(L); i++) { double tmp; switch (*fmt++) { case URPC_U8: tmp = lua_tonumber(L, i); aura_buffer_put_u8(buf, tmp); break; case URPC_S8: tmp = lua_tonumber(L, i); aura_buffer_put_s8(buf, tmp); break; case URPC_U16: tmp = lua_tonumber(L, i); aura_buffer_put_u16(buf, (uint16_t)tmp); break; case URPC_S16: tmp = lua_tonumber(L, i); aura_buffer_put_s16(buf, tmp); break; case URPC_U32: tmp = lua_tonumber(L, i); aura_buffer_put_u32(buf, tmp); break; case URPC_S32: tmp = lua_tonumber(L, i); aura_buffer_put_s32(buf, tmp); break; case URPC_S64: tmp = lua_tonumber(L, i); aura_buffer_put_s64(buf, tmp); break; case URPC_U64: tmp = lua_tonumber(L, i); aura_buffer_put_u64(buf, tmp); break; /* Binary is the tricky part. String or usata? */ case URPC_BIN: { const char *srcbuf = NULL; int len = 0; int blen; if (lua_isstring(L, i)) { srcbuf = lua_tostring(L, i); len = strlen(srcbuf); } else if (lua_isuserdata(L, i)) { srcbuf = lua_touserdata(L, i); } blen = atoi(fmt); if (blen == 0) { slog(0, SLOG_ERROR, "Internal serilizer bug processing: %s", fmt); goto err; } if (!srcbuf) { slog(0, SLOG_ERROR, "Internal bug fetching src pointer"); goto err; } if (blen < len) len = blen; aura_buffer_put_bin(buf, srcbuf, len); while (*fmt && (*fmt++ != '.')); break; } default: BUG(node, "Unknown token: %c\n", *(--fmt)); break; } } return buf; err: aura_buffer_release(buf); return NULL; }
static int laura_do_async_call(lua_State *L) { struct laura_node *lnode = NULL; const char *name; struct aura_buffer *buf; struct aura_object *o; int ret; int callback_ref; TRACE(); /* Sanity */ lnode = lua_fetch_node(L, 1); if (!lnode) { lua_stackdump(L); return aura_typeerror(L, 1, "userdata (node)"); } if (!lua_isstring(L, 2)) { lua_stackdump(L); return aura_typeerror(L, 2, "string (object name)"); } if (!lua_isfunction(L, 3)) { lua_stackdump(L); return aura_typeerror(L, 3, "function (callback)"); } name = lua_tostring(L, 2); o = aura_etable_find(lnode->node->tbl, name); if (!o) return luaL_error(L, "Attempt to call non-existend method"); if (!object_is_method(o)) { lua_stackdump(L); return luaL_error(L, "Attempt to call an event"); } /* Now we're sane! */ buf = lua_to_buffer(L, lnode->node, 5, o); if (!buf) return luaL_error(L, "Serializer failed!"); /* Let's create a table to store our callback and arg */ lua_newtable(L); /* Push the callback function there */ lua_pushnumber(L, 1); lua_pushvalue(L, 3); lua_settable(L, -3); /* And the user argument */ lua_pushnumber(L, 2); lua_pushvalue(L, 4); lua_settable(L, -3); /* And fetch the reference to out table that we'll use in callback */ callback_ref = luaL_ref(L, LUA_REGISTRYINDEX); slog(4, SLOG_DEBUG, "Callback tbl reference: %d", callback_ref); ret = aura_core_start_call(lnode->node, o, calldone_cb, (void *)(long)callback_ref, buf); if (ret != 0) { aura_buffer_release(buf); return luaL_error(L, "Async call for %s failed: %s code (%d)", o->name, strerror(-ret), ret); } return 0; }