aura  0.1
 All Data Structures Functions Variables Modules Pages
transport-susb.c
1 #include <aura/aura.h>
2 #include <aura/private.h>
3 #include <aura/usb_helpers.h>
4 #include <libusb.h>
5 #include <lua.h>
6 #include <lauxlib.h>
7 #include <lualib.h>
8 
9 
10 enum device_state {
11  SUSB_DEVICE_SEARCHING=0,
12  SUSB_DEVICE_OPERATIONAL,
13  SUSB_DEVICE_RESTART
14 };
15 
16 struct usb_dev_info {
17  struct aura_node *node;
18  uint8_t flags;
19  struct aura_export_table *etbl;
20 
21  int state;
22  int current_object;
23  uint16_t num_objects;
24  uint16_t io_buf_size;
25  int pending;
26 
27  struct libusb_context *ctx;
28  libusb_device_handle *handle;
29 
30  struct aura_buffer *current_buffer;
31  struct libusb_transfer* ctransfer;
32  bool cbusy;
33 
34  /* Usb device string */
35  struct ncusb_devwatch_data dev_descr;
36 };
37 
38 static void usb_panic_and_reset_state(struct aura_node *node)
39 {
40  struct usb_dev_info *inf = aura_get_transportdata(node);
41 
42  if (inf->cbusy)
43  BUG(node, "susb: Failing with busy ctransfer");
44 
45  inf->state = SUSB_DEVICE_RESTART;
46 }
47 
48 static void submit_control(struct aura_node *node)
49 {
50  int ret;
51  struct usb_dev_info *inf = aura_get_transportdata(node);
52 
53  ret = libusb_submit_transfer(inf->ctransfer);
54  if (ret!= 0) {
55  slog(0, SLOG_ERROR, "usb: error submitting control transfer");
56  usb_panic_and_reset_state(node);
57  return;
58  }
59  inf->cbusy=true;
60 }
61 
62 static int check_control(struct libusb_transfer *transfer)
63 {
64  struct aura_node *node = transfer->user_data;
65  struct usb_dev_info *inf = aura_get_transportdata(node);
66  int ret = 0;
67 
68  inf->cbusy = false;
69 
70  if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
71  slog(0, SLOG_ERROR, "usb: error completing control transfer");
72  ncusb_print_libusb_transfer(transfer);
73  usb_panic_and_reset_state(node);
74  ret = -EIO;
75  }
76  return ret;
77 }
78 
79 static int usb_start_ops(struct libusb_device_handle *hndl, void *arg)
80 {
81  /* FixMe: Reading descriptors is synchronos. This is not needed
82  * often, but leaves a possibility of a flaky usb device to
83  * screw up the event processing.
84  * A proper workaround would be manually reading out string descriptors
85  * from a device in an async fasion in the background.
86  */
87  struct usb_dev_info *inf = arg;
88 
89  inf->handle = hndl;
90  inf->state = SUSB_DEVICE_OPERATIONAL;
91 
92  slog(4, SLOG_DEBUG, "susb: Device opened and ready to accept calls");
93  return 0;
94 };
95 
96 
97 
98 static void lua_settoken(lua_State *L, const char* name, char t) {
99  char tmp[2];
100  tmp[1]=0x0;
101  tmp[0]=t;
102  lua_pushstring(L, tmp);
103  lua_setglobal(L, name);
104 }
105 
106 static char *lua_strfromstack(lua_State *L, int n)
107 {
108  char *ret = NULL;
109  if (lua_isstring(L, n))
110  ret = strdup(lua_tostring(L, n));
111  return ret;
112 }
113 
114 extern int luaopen_auracore (lua_State *L);
115 static int susb_open(struct aura_node *node, const char *conf)
116 {
117 
118  struct libusb_context *ctx;
119  struct usb_dev_info *inf = calloc(1, sizeof(*inf));
120  int ret;
121  lua_State* L;
122 
123  if (!inf)
124  return -ENOMEM;
125 
126  ret = libusb_init(&ctx);
127  if (ret != 0)
128  goto err_free_inf;
129  inf->ctx = ctx;
130 
131  L=luaL_newstate();
132  if (!L)
133  goto err_free_ctx;
134 
135  inf->ctransfer = libusb_alloc_transfer(0);
136  if (!inf->ctransfer)
137  goto err_free_lua;
138 
139  luaL_openlibs(L);
140  luaopen_auracore(L);
141  lua_setglobal(L, "aura");
142 
143  slog(2, SLOG_INFO, "usbsimple: config file %s", conf);
144 
145  const char scr[] = "return require(\"aura/conf-loader\")\n";
146  ret = luaL_loadbuffer (L, scr, strlen(scr), "ldr");
147  lua_call(L, 0, 1);
148  if (ret) {
149  slog(0, SLOG_ERROR, lua_tostring(L, -1));
150  slog(0, SLOG_ERROR, "usbsimple: config file load error");
151  goto err_free_ct;
152  }
153 
154  lua_pushstring(L, conf);
155  lua_setglobal(L, "simpleconf");
156 
157  lua_pushlightuserdata(L, node);
158  lua_setglobal(L, "node");
159 
160  /* We need to push all format tokens to lua.
161  * We do it here to be always in sync with format.h
162  */
163 
164  lua_settoken(L, "UINT8", URPC_U8);
165  lua_settoken(L, "UINT16", URPC_U16);
166  lua_settoken(L, "UINT32", URPC_U32);
167  lua_settoken(L, "UINT64", URPC_U64);
168 
169  lua_settoken(L, "SINT8", URPC_S8);
170  lua_settoken(L, "SINT16", URPC_S16);
171  lua_settoken(L, "SINT32", URPC_S32);
172  lua_settoken(L, "SINT64", URPC_S64);
173 
174  lua_settoken(L, "FMT_BIN", URPC_BIN);
175 
176  ret = lua_pcall(L, 0, 6, 0);
177  if (ret) {
178  const char* err = lua_tostring(L, -1);
179  slog(0, SLOG_FATAL, "usbsimple: %s", err);
180  goto err_free_ct;
181  }
182 
183  inf->dev_descr.vid = lua_tonumber(L, -6);
184  inf->dev_descr.pid = lua_tonumber(L, -5);
185  inf->dev_descr.vendor = lua_strfromstack(L, -4);
186  inf->dev_descr.product = lua_strfromstack(L, -3);
187  inf->dev_descr.serial = lua_strfromstack(L, -2);
188  inf->etbl = lua_touserdata(L, -1);
189 
190  inf->dev_descr.device_found_func = usb_start_ops;
191  inf->dev_descr.arg = inf;
192  inf->node = node;
193 
194  /* We no not need this state anymore */
195  lua_close(L);
196  aura_set_transportdata(node, inf);
197 
198  ncusb_start_descriptor_watching(node, inf->ctx);
199  slog(1, SLOG_INFO, "usb: Now looking for a device %x:%x %s/%s/%s",
200  inf->dev_descr.vid, inf->dev_descr.pid,
201  inf->dev_descr.vendor, inf->dev_descr.product, inf->dev_descr.serial);
202  ncusb_watch_for_device(inf->ctx, &inf->dev_descr);
203 
204  return 0;
205 err_free_ct:
206  libusb_free_transfer(inf->ctransfer);
207 err_free_lua:
208  lua_close(L);
209 err_free_ctx:
210  libusb_exit(inf->ctx);
211 err_free_inf:
212  free(inf);
213  return -ENOMEM;
214 }
215 
216 static void susb_close(struct aura_node *node)
217 {
218  struct usb_dev_info *inf = aura_get_transportdata(node);
219  slog(3, SLOG_INFO, "Closing susb transport");
220 
221  while (inf->cbusy)
222  libusb_handle_events(inf->ctx);
223 
224  if (inf->dev_descr.vendor)
225  free(inf->dev_descr.vendor);
226  if (inf->dev_descr.product)
227  free(inf->dev_descr.product);
228  if (inf->dev_descr.serial)
229  free(inf->dev_descr.serial);
230 
231  libusb_free_transfer(inf->ctransfer);
232 
233  if (inf->handle)
234  libusb_close(inf->handle);
235 
236  libusb_exit(inf->ctx);
237  free(inf);
238 }
239 
240 static void cb_call_done(struct libusb_transfer *transfer)
241 {
242  struct aura_node *node = transfer->user_data;
243  struct usb_dev_info *inf = aura_get_transportdata(node);
244  struct aura_buffer *buf;
245 
246  /* Put the buffer pointer at the start of the data we've got */
247  /* It only makes sense when we succeed */
248  if (0 == check_control(transfer)) {
249  slog(4, SLOG_DEBUG, "Requeuing!");
250  buf = aura_dequeue_buffer(&inf->node->outbound_buffers);
251  aura_queue_buffer(&node->inbound_buffers, buf);
252  inf->current_buffer = NULL;
253  }
254 }
255 
256 static void susb_issue_call(struct aura_node *node, struct aura_buffer *buf)
257 {
258  struct aura_object *o = buf->object;
259  struct usb_dev_info *inf = aura_get_transportdata(node);
260  uint8_t rqtype;
261  uint16_t wIndex, wValue, *ptr;
262  size_t datalen; /*Actual data in packet, save for setup */
263 
264  if (o->retlen) {
265  rqtype = LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN;
266  datalen = o->retlen;
267  } else {
268  datalen = o->arglen - 2 * sizeof(uint16_t);
269  rqtype = LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT;
270  }
271  ptr = (uint16_t *) &buf->data[buf->pos];
272  wValue = *ptr++;
273  wIndex = *ptr++;
274 
275  memmove(&buf->data[buf->pos], ptr, datalen);
276 
277  /*
278  VUSB-based devices (or libusb?) do not seem to play nicely when we have the
279  setup packet with no data. Transfers may fail instantly.
280  A typical run at my box gives:
281 
282  9122 succeeded, 878 failed total 10000
283 
284  See tests-transports/test-susb-stability-none
285  Adding just one byte of data to the packet fix the issue.
286  Posible workarounds are:
287  1. Retry N times
288  2. Add just one dummy byte for the transfer
289  Since nobody reported this workaround breaking support for their
290  hardware - we'll do it the second way. For now.
291  */
292 
293  if (!datalen)
294  datalen++; /* buffer's big enough anyway */
295 
296  /* e.g if device is big endian, but has le descriptors
297  * we have to be extra careful here
298  */
299 
300  if (node->need_endian_swap) {
301  wValue = __swap16(wValue);
302  wIndex = __swap16(wValue);
303  }
304 
305  inf->current_buffer = buf;
306  libusb_fill_control_setup((unsigned char *) buf->data, rqtype, o->id, wValue, wIndex,
307  datalen);
308  libusb_fill_control_transfer(inf->ctransfer, inf->handle,
309  (unsigned char *) buf->data, cb_call_done, node, 4000);
310  submit_control(node);
311 }
312 
313 static void susb_loop(struct aura_node *node, const struct aura_pollfds *fd)
314 {
315  struct aura_buffer *buf;
316  struct usb_dev_info *inf = aura_get_transportdata(node);
317  struct timeval tv = {
318  .tv_sec = 0,
319  .tv_usec = 0
320  };
321 
322  libusb_handle_events_timeout(inf->ctx, &tv);
323  if (inf->cbusy)
324  return;
325 
326  if (inf->state == SUSB_DEVICE_RESTART) {
327  slog(4, SLOG_DEBUG, "usb: transport offlined, starting to look for a device");
328  aura_set_status(node, AURA_STATUS_OFFLINE);
329  libusb_close(inf->handle);
330  inf->handle = NULL;
331  inf->state = SUSB_DEVICE_SEARCHING;
332  ncusb_watch_for_device(inf->ctx, &inf->dev_descr);
333  } else if (inf->state == SUSB_DEVICE_OPERATIONAL) {
334 
335  if (inf->etbl) {
336  /* Hack: Since libusb tends to send and receive data in one buffer,
337  we need to adjust argument buffer to fit in return values as well.
338  It helps us to avoid needless copying.
339  */
340  int i;
341  for (i=0; i < inf->etbl->next; i++) {
342  struct aura_object *tmp;
343  tmp=&inf->etbl->objects[i];
344  tmp->arglen += tmp->retlen;
345  }
346  aura_etable_activate(inf->etbl);
347  inf->etbl = NULL;
348  }
349  aura_set_status(node, AURA_STATUS_ONLINE);
350  buf = aura_peek_buffer(&node->outbound_buffers);
351  if (!buf)
352  return;
353  susb_issue_call(node, buf);
354  }
355 
356 }
357 
358 static struct aura_transport tusb = {
359  .name = "simpleusb",
360  .open = susb_open,
361  .close = susb_close,
362  .loop = susb_loop,
363  /* We write wIndex and wValue in the setup part of the packet */
364  .buffer_overhead = LIBUSB_CONTROL_SETUP_SIZE,
365  .buffer_offset = LIBUSB_CONTROL_SETUP_SIZE
366 };
367 
368 AURA_TRANSPORT(tusb);
void aura_set_status(struct aura_node *node, int status)
Definition: aura.c:808
struct aura_buffer * aura_dequeue_buffer(struct list_head *head)
Definition: queue.c:45
const char * name
Required.
Definition: aura.h:168
static void aura_set_transportdata(struct aura_node *node, void *udata)
Definition: inlines.h:60
int pos
Definition: aura.h:339
static void * aura_get_transportdata(struct aura_node *node)
Definition: inlines.h:69
void aura_queue_buffer(struct list_head *list, struct aura_buffer *buf)
Definition: queue.c:16
char * data
Definition: aura.h:347
struct aura_buffer * aura_peek_buffer(struct list_head *head)
Definition: queue.c:28
struct aura_object * object
Definition: aura.h:341