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); } }
static void usb_loop(struct aura_node *node, const struct aura_pollfds *fd) { struct aura_buffer *buf; struct usb_dev_info *inf = aura_get_transportdata(node); struct timeval tv = { .tv_sec = 0, .tv_usec = 0 }; libusb_handle_events_timeout(inf->ctx, &tv); if (inf->cbusy) return; if (inf->state == AUSB_DEVICE_RESTART) { slog(4, SLOG_DEBUG, "usb: transport offlined, starting to look for a device"); aura_set_status(node, AURA_STATUS_OFFLINE); libusb_close(inf->handle); inf->handle = NULL; inf->state = AUSB_DEVICE_SEARCHING; ncusb_watch_for_device(inf->ctx, &inf->dev_descr); return; } if (inf->state == AUSB_DEVICE_OPERATIONAL) { if (inf->pending) submit_event_readout(node); else if ( (buf = aura_dequeue_buffer(&node->outbound_buffers)) ) { submit_call_write(node, buf); } } } static struct aura_transport usb = { .name = "usb", .open = usb_open, .close = usb_close, .loop = usb_loop, .buffer_overhead = LIBUSB_CONTROL_SETUP_SIZE, /* Offset for usb SETUP structure */ .buffer_offset = LIBUSB_CONTROL_SETUP_SIZE }; AURA_TRANSPORT(usb);
/* 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; }