1
|
#include "usbctrl.h"
|
2
|
#include "DspParserBase.h"
|
3
|
#include "ReportError.h"
|
4
|
|
5
|
#include <errno.h>
|
6
|
#include <fcntl.h>
|
7
|
#include <unistd.h>
|
8
|
#include <memory.h>
|
9
|
#include <pthread.h>
|
10
|
#include <signal.h>
|
11
|
#include <stdlib.h>
|
12
|
|
13
|
#include <sys/types.h>
|
14
|
#include <sys/stat.h>
|
15
|
#include <sys/ioctl.h>
|
16
|
#include <sys/poll.h>
|
17
|
#include <stdint.h>
|
18
|
|
19
|
#include <sys/syscall.h>
|
20
|
#include <linux/aio_abi.h>
|
21
|
|
22
|
using namespace MityDSP;
|
23
|
|
24
|
extern "C" {
|
25
|
|
26
|
#include <asm/byteorder.h>
|
27
|
|
28
|
#define le16_to_cpu __le16_to_cpu
|
29
|
|
30
|
#include <linux/types.h>
|
31
|
#include <linux/usb/gadgetfs.h>
|
32
|
#include <linux/usb/ch9.h>
|
33
|
|
34
|
#include "usbstring.h"
|
35
|
|
36
|
#define DRIVER_VENDOR_NUM 0x1EF8 /* Critical Link */
|
37
|
#define DRIVER_PRODUCT_NUM 0x1005 /* MityCAM */
|
38
|
#define STRINGID_MFGR 1
|
39
|
#define STRINGID_PRODUCT 2
|
40
|
#define STRINGID_SERIAL 3
|
41
|
#define STRINGID_CONFIG 4
|
42
|
#define STRINGID_INTERFACE 5
|
43
|
|
44
|
#define USB_BUFSIZE (5*1024)
|
45
|
|
46
|
static struct usb_device_descriptor device_desc = {
|
47
|
bLength : sizeof(device_desc),
|
48
|
bDescriptorType : USB_DT_DEVICE,
|
49
|
bcdUSB : __constant_cpu_to_le16(0x0200),
|
50
|
bDeviceClass : USB_CLASS_VENDOR_SPEC,
|
51
|
bDeviceSubClass : 0,
|
52
|
bDeviceProtocol : 0,
|
53
|
bMaxPacketSize0 : 0,
|
54
|
idVendor : __constant_cpu_to_le16(DRIVER_VENDOR_NUM),
|
55
|
idProduct : __constant_cpu_to_le16(DRIVER_PRODUCT_NUM),
|
56
|
bcdDevice : __constant_cpu_to_le16(0x0107),
|
57
|
iManufacturer : STRINGID_MFGR,
|
58
|
iProduct : STRINGID_PRODUCT,
|
59
|
iSerialNumber : STRINGID_SERIAL,
|
60
|
bNumConfigurations : 1,
|
61
|
};
|
62
|
|
63
|
#define MAX_USB_POWER 1
|
64
|
|
65
|
static const struct usb_config_descriptor config = {
|
66
|
bLength : sizeof(config),
|
67
|
bDescriptorType : USB_DT_CONFIG,
|
68
|
wTotalLength : 0,
|
69
|
bNumInterfaces : 1,
|
70
|
bConfigurationValue : 3,
|
71
|
iConfiguration : 0,
|
72
|
bmAttributes : (USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER),
|
73
|
bMaxPower : ((MAX_USB_POWER + 1) / 2),
|
74
|
};
|
75
|
|
76
|
static const struct usb_interface_descriptor bulk_intf = {
|
77
|
bLength : sizeof(bulk_intf),
|
78
|
bDescriptorType : USB_DT_INTERFACE,
|
79
|
bInterfaceNumber : 0,
|
80
|
bAlternateSetting : 0,
|
81
|
bNumEndpoints : 2,
|
82
|
bInterfaceClass : USB_CLASS_VENDOR_SPEC,
|
83
|
bInterfaceSubClass : 0,
|
84
|
bInterfaceProtocol : 0,
|
85
|
iInterface : STRINGID_INTERFACE,
|
86
|
};
|
87
|
|
88
|
static struct usb_endpoint_descriptor fs_source_desc = {
|
89
|
bLength : USB_DT_ENDPOINT_SIZE,
|
90
|
bDescriptorType : USB_DT_ENDPOINT,
|
91
|
bEndpointAddress : USB_DIR_IN | 1,
|
92
|
bmAttributes : USB_ENDPOINT_XFER_BULK,
|
93
|
wMaxPacketSize : __constant_cpu_to_le16(64),
|
94
|
bInterval : 0,
|
95
|
bRefresh : 0,
|
96
|
bSynchAddress : 0,
|
97
|
};
|
98
|
|
99
|
static struct usb_endpoint_descriptor fs_sink_desc = {
|
100
|
bLength : USB_DT_ENDPOINT_SIZE,
|
101
|
bDescriptorType : USB_DT_ENDPOINT,
|
102
|
bEndpointAddress : USB_DIR_OUT | 2,
|
103
|
bmAttributes : USB_ENDPOINT_XFER_BULK,
|
104
|
wMaxPacketSize : __constant_cpu_to_le16(64),
|
105
|
bInterval : 0,
|
106
|
bRefresh : 0,
|
107
|
bSynchAddress : 0,
|
108
|
};
|
109
|
|
110
|
static const struct usb_endpoint_descriptor *fs_eps[2] = {
|
111
|
&fs_source_desc,
|
112
|
&fs_sink_desc,
|
113
|
};
|
114
|
|
115
|
static struct usb_endpoint_descriptor hs_source_desc = {
|
116
|
bLength : USB_DT_ENDPOINT_SIZE,
|
117
|
bDescriptorType : USB_DT_ENDPOINT,
|
118
|
bEndpointAddress : USB_DIR_IN | 1,
|
119
|
bmAttributes : USB_ENDPOINT_XFER_BULK,
|
120
|
wMaxPacketSize : __constant_cpu_to_le16(512),
|
121
|
bInterval : 0,
|
122
|
bRefresh : 0,
|
123
|
bSynchAddress : 0,
|
124
|
};
|
125
|
|
126
|
static struct usb_endpoint_descriptor hs_sink_desc = {
|
127
|
bLength : USB_DT_ENDPOINT_SIZE,
|
128
|
bDescriptorType : USB_DT_ENDPOINT,
|
129
|
bEndpointAddress : USB_DIR_OUT | 2,
|
130
|
bmAttributes : USB_ENDPOINT_XFER_BULK,
|
131
|
wMaxPacketSize : __constant_cpu_to_le16(512),
|
132
|
bInterval : 0,
|
133
|
bRefresh : 0,
|
134
|
bSynchAddress : 0,
|
135
|
};
|
136
|
|
137
|
static const struct usb_endpoint_descriptor *hs_eps[2] = {
|
138
|
&hs_source_desc,
|
139
|
&hs_sink_desc,
|
140
|
};
|
141
|
|
142
|
static char serial[64];
|
143
|
|
144
|
static struct usb_string stringtab[] = {
|
145
|
{ STRINGID_MFGR, "Critical Link, LLC", },
|
146
|
{ STRINGID_PRODUCT, "MityCAM", },
|
147
|
{ STRINGID_SERIAL, serial, },
|
148
|
{ STRINGID_CONFIG, "Config", },
|
149
|
{ STRINGID_INTERFACE, "Bulk Transfer", },
|
150
|
};
|
151
|
|
152
|
static struct usb_gadget_strings strings = {
|
153
|
language : 0x0409, /* en-us */
|
154
|
strings : stringtab,
|
155
|
};
|
156
|
|
157
|
}
|
158
|
|
159
|
/**
|
160
|
* Gadget FS Based USB peripheral driver code.
|
161
|
*
|
162
|
* \param[in] apParser pointer to valid parser for data handling
|
163
|
* \param[in] anSerial the camera serial number
|
164
|
* \param[in] apRe pointer to valid report error class
|
165
|
*/
|
166
|
tcUSB::tcUSB(tcDspParserBase* apParser, int anSerial, tcReportError* apRe)
|
167
|
: mnEP0Fd(-1)
|
168
|
, mnBulkInFd(-1)
|
169
|
, mnBulkOutFd(-1)
|
170
|
, mpParser(apParser)
|
171
|
, mhEP0Thread(pthread_self())
|
172
|
, mhBulkThread(pthread_self())
|
173
|
, mhStartupThread(pthread_self())
|
174
|
, mnBytesIn(0)
|
175
|
, mpReportError(apRe)
|
176
|
, mbConnected(false)
|
177
|
{
|
178
|
sprintf(serial, "%d", anSerial);
|
179
|
}
|
180
|
|
181
|
/**
|
182
|
* Interface destructor
|
183
|
*/
|
184
|
tcUSB::~tcUSB(void)
|
185
|
{
|
186
|
if (mnEP0Fd >= 0)
|
187
|
close(mnEP0Fd);
|
188
|
}
|
189
|
|
190
|
char* tcUSB::build_config(char* cp,
|
191
|
const struct usb_endpoint_descriptor **ep)
|
192
|
{
|
193
|
struct usb_config_descriptor *c;
|
194
|
int i;
|
195
|
|
196
|
c = (struct usb_config_descriptor *)cp;
|
197
|
|
198
|
memcpy(cp, &config, config.bLength);
|
199
|
cp += config.bLength;
|
200
|
|
201
|
memcpy(cp, &bulk_intf, bulk_intf.bLength);
|
202
|
cp += bulk_intf.bLength;
|
203
|
|
204
|
for (i = 0; i < bulk_intf.bNumEndpoints; i++)
|
205
|
{
|
206
|
memcpy(cp, ep[i], USB_DT_ENDPOINT_SIZE);
|
207
|
cp += USB_DT_ENDPOINT_SIZE;
|
208
|
}
|
209
|
c->wTotalLength = __cpu_to_le16(cp - (char*)c);
|
210
|
return cp;
|
211
|
}
|
212
|
|
213
|
int tcUSB::Initialize(void)
|
214
|
{
|
215
|
char buf[4096], *cp = &buf[0];
|
216
|
int rv, status;
|
217
|
|
218
|
mnEP0Fd = open("/dev/gadgetfs/musb-hdrc", O_RDWR);
|
219
|
if (mnEP0Fd < 0)
|
220
|
{
|
221
|
return mnEP0Fd;
|
222
|
}
|
223
|
mpReportError->Report("usb device opened\n");
|
224
|
|
225
|
*(__u32 *)cp = 0;
|
226
|
cp += 4;
|
227
|
|
228
|
/* write full speed configs */
|
229
|
cp = build_config(cp, fs_eps);
|
230
|
|
231
|
/* write high speed configs */
|
232
|
cp = build_config(cp, hs_eps);
|
233
|
|
234
|
/* write device descriptor */
|
235
|
memcpy(cp, &device_desc, sizeof(device_desc));
|
236
|
cp += sizeof(device_desc);
|
237
|
|
238
|
rv = write(mnEP0Fd, &buf[0], cp - buf);
|
239
|
if (rv < 0)
|
240
|
{
|
241
|
mpReportError->Report("initial write error : %s\n", strerror(errno));
|
242
|
close(mnEP0Fd);
|
243
|
mnEP0Fd = -1;
|
244
|
return mnEP0Fd;
|
245
|
}
|
246
|
else if (rv != (cp - buf))
|
247
|
{
|
248
|
mpReportError->Report("rv mismatch : %d, %d\n", rv, (cp-buf));
|
249
|
close(mnEP0Fd);
|
250
|
mnEP0Fd = -2;
|
251
|
return mnEP0Fd;
|
252
|
}
|
253
|
|
254
|
|
255
|
/* spawn the control endpoint reader thread */
|
256
|
pthread_attr_t attr;
|
257
|
rv = pthread_attr_init(&attr);
|
258
|
|
259
|
status = pthread_create(&mhEP0Thread, &attr, DispatchEP0Handler, (void*)this);
|
260
|
if (status)
|
261
|
{
|
262
|
mpReportError->Report("pthread_create (network poll thread) : %s\n", strerror(errno));
|
263
|
return status;
|
264
|
}
|
265
|
|
266
|
return 0;
|
267
|
}
|
268
|
|
269
|
int tcUSB::StopIO(void)
|
270
|
{
|
271
|
if (!pthread_equal(mhBulkThread, mhStartupThread))
|
272
|
{
|
273
|
pthread_cancel(mhBulkThread);
|
274
|
if (pthread_join(mhBulkThread, 0) != 0)
|
275
|
{
|
276
|
mpReportError->Report("Could not stop Bulk Thread");
|
277
|
}
|
278
|
else
|
279
|
{
|
280
|
close(mnBulkOutFd);
|
281
|
mnBulkOutFd = -1;
|
282
|
}
|
283
|
mhBulkThread = mhStartupThread;
|
284
|
}
|
285
|
if (mnBulkInFd >= 0)
|
286
|
{
|
287
|
close(mnBulkInFd);
|
288
|
mnBulkInFd = -1;
|
289
|
}
|
290
|
return 0;
|
291
|
}
|
292
|
|
293
|
int tcUSB::StartIO(void)
|
294
|
{
|
295
|
int status, rv;
|
296
|
uint32_t bufi[256/4];
|
297
|
char* buf = (char*)&bufi[0];
|
298
|
pthread_attr_t attr;
|
299
|
|
300
|
rv = pthread_attr_init(&attr);
|
301
|
|
302
|
/* open up the bulk input endpoint (relative to PC)
|
303
|
* file descriptor for sending data via put() call */
|
304
|
mnBulkInFd = open("/dev/gadgetfs/ep1in", O_WRONLY);
|
305
|
if (mnBulkInFd < 0)
|
306
|
{
|
307
|
mpReportError->Report("Could not open ep1in (%s)\n",
|
308
|
strerror(errno));
|
309
|
return -errno;
|
310
|
}
|
311
|
|
312
|
/* write full speed descriptor in */
|
313
|
*(uint32_t *)buf = 1;
|
314
|
memcpy(buf + 4, &fs_source_desc, USB_DT_ENDPOINT_SIZE);
|
315
|
|
316
|
/* write high speed descriptor in */
|
317
|
memcpy(buf + 4 + USB_DT_ENDPOINT_SIZE,
|
318
|
&hs_source_desc, USB_DT_ENDPOINT_SIZE);
|
319
|
|
320
|
/* push it to control framework */
|
321
|
if (write(mnBulkInFd, buf, 4 + 2 * USB_DT_ENDPOINT_SIZE) < 0)
|
322
|
{
|
323
|
mpReportError->Report("Could not setup bulkin descriptors "
|
324
|
" (%s)\n", strerror(errno));
|
325
|
close(mnBulkInFd);
|
326
|
return -errno;
|
327
|
}
|
328
|
|
329
|
/* open up the bulk output endpoint (relative to PC)
|
330
|
* file descriptor for receiving app data */
|
331
|
mnBulkOutFd = open("/dev/gadgetfs/ep2out", O_RDWR);
|
332
|
if (mnBulkOutFd < 0)
|
333
|
{
|
334
|
mpReportError->Report("Could not open ep2out (%s)\n",
|
335
|
strerror(errno));
|
336
|
close(mnBulkInFd);
|
337
|
return -errno;
|
338
|
}
|
339
|
|
340
|
/* write full speed descriptor in */
|
341
|
*(uint32_t *)buf = 1;
|
342
|
memcpy(buf + 4, &fs_sink_desc, USB_DT_ENDPOINT_SIZE);
|
343
|
|
344
|
/* write high speed descriptor in */
|
345
|
memcpy(buf + 4 + USB_DT_ENDPOINT_SIZE,
|
346
|
&hs_sink_desc, USB_DT_ENDPOINT_SIZE);
|
347
|
|
348
|
/* push it to control framework */
|
349
|
if (write(mnBulkOutFd, buf, 4 + 2 * USB_DT_ENDPOINT_SIZE) < 0)
|
350
|
{
|
351
|
mpReportError->Report("Could not setup bulkout descriptors "
|
352
|
" (%s)\n", strerror(errno));
|
353
|
close(mnBulkInFd);
|
354
|
close(mnBulkOutFd);
|
355
|
return -errno;
|
356
|
}
|
357
|
|
358
|
/* spawn the bulk endpoint reader thread */
|
359
|
status = pthread_create(&mhBulkThread, &attr, DispatchBulkInHandler, (void*)this);
|
360
|
if (status)
|
361
|
{
|
362
|
mpReportError->Report("pthread_create (usb poll thread) : %s\n", strerror(errno));
|
363
|
}
|
364
|
|
365
|
return status;
|
366
|
}
|
367
|
|
368
|
void* tcUSB::DispatchEP0Handler(void *apThis)
|
369
|
{
|
370
|
tcUSB *lpUSB = (tcUSB *)apThis;
|
371
|
lpUSB->EP0Handler();
|
372
|
return NULL;
|
373
|
}
|
374
|
|
375
|
#define USB_REQ_GET_STATE 0xDF
|
376
|
#define USB_REQ_CLEAR_INKTEND 0xDF
|
377
|
#define USB_REQ_PEEK_BUFF 0xDD
|
378
|
#define USB_REQ_POKE_BUFF 0xDC
|
379
|
#define USB_REQ_WRITE_SN 0xDB
|
380
|
#define USB_REQ_READ_SN 0xDA
|
381
|
|
382
|
int tcUSB::HandleControl(struct usb_ctrlrequest *setup)
|
383
|
{
|
384
|
uint16_t value, index, length;
|
385
|
uint8_t buf[256];
|
386
|
int status, tmp;
|
387
|
|
388
|
value = __le16_to_cpu(setup->wValue);
|
389
|
index = __le16_to_cpu(setup->wIndex);
|
390
|
length = __le16_to_cpu(setup->wLength);
|
391
|
|
392
|
#if 0
|
393
|
printf("Handle Control : %02x.%02x v%04x i%04x %d\n",
|
394
|
setup->bRequestType, setup->bRequest,
|
395
|
value, index, length);
|
396
|
#endif
|
397
|
|
398
|
switch(setup->bRequest)
|
399
|
{
|
400
|
case USB_REQ_GET_DESCRIPTOR:
|
401
|
switch(value >> 8)
|
402
|
{
|
403
|
case USB_DT_STRING:
|
404
|
tmp = value & 0xFF;
|
405
|
if (tmp || index != strings.language)
|
406
|
goto stall;
|
407
|
status = usb_gadget_get_string(&strings, tmp, buf);
|
408
|
if (status < 0)
|
409
|
goto stall;
|
410
|
tmp = status;
|
411
|
if (length < tmp)
|
412
|
tmp = length;
|
413
|
write(mnEP0Fd, buf, tmp);
|
414
|
break;
|
415
|
default:
|
416
|
goto stall;
|
417
|
}
|
418
|
return 0;
|
419
|
|
420
|
case USB_REQ_SET_CONFIGURATION:
|
421
|
if (setup->bRequestType != USB_DIR_OUT)
|
422
|
goto stall;
|
423
|
if (value)
|
424
|
{
|
425
|
StartIO();
|
426
|
}
|
427
|
else
|
428
|
{
|
429
|
StopIO();
|
430
|
}
|
431
|
status = read(mnEP0Fd, &status, 0);
|
432
|
if (status)
|
433
|
mpReportError->Report("ack SET_CONFIGURATION\n");
|
434
|
return 0;
|
435
|
|
436
|
case USB_REQ_GET_INTERFACE:
|
437
|
return 0;
|
438
|
|
439
|
case USB_REQ_SET_INTERFACE:
|
440
|
return 0;
|
441
|
|
442
|
case USB_REQ_GET_STATE:
|
443
|
for (int i = 0; i < 20; ++i)
|
444
|
{
|
445
|
buf[i] = 0x01;
|
446
|
}
|
447
|
status = write(mnEP0Fd, buf, 20);
|
448
|
if (status < 0)
|
449
|
goto stall;
|
450
|
return 0;
|
451
|
|
452
|
case USB_REQ_PEEK_BUFF:
|
453
|
for (int i = 0; i < 48; ++i)
|
454
|
{
|
455
|
buf[i] = 0x00;
|
456
|
}
|
457
|
status = write(mnEP0Fd, buf, 48);
|
458
|
if (status < 0)
|
459
|
goto stall;
|
460
|
return 0;
|
461
|
|
462
|
case USB_REQ_POKE_BUFF:
|
463
|
status = read(mnEP0Fd, &status, 0);
|
464
|
return 0;
|
465
|
|
466
|
default:
|
467
|
goto stall;
|
468
|
}
|
469
|
|
470
|
stall:
|
471
|
if (setup->bRequestType & USB_DIR_IN)
|
472
|
status = read(mnEP0Fd, &status, 0);
|
473
|
else
|
474
|
status = write(mnEP0Fd, &status, 0);
|
475
|
|
476
|
if (errno != EL2HLT)
|
477
|
mpReportError->Report("ep0 stall");
|
478
|
|
479
|
return 0;
|
480
|
}
|
481
|
|
482
|
int tcUSB::EP0Handler(void)
|
483
|
{
|
484
|
struct pollfd ep0_poll;
|
485
|
|
486
|
ep0_poll.fd = mnEP0Fd;
|
487
|
ep0_poll.events = POLLIN | POLLOUT | POLLHUP;
|
488
|
|
489
|
while (true)
|
490
|
{
|
491
|
int tmp, i, nevent;
|
492
|
struct usb_gadgetfs_event event[8];
|
493
|
|
494
|
/* TODO - infinite timeout? */
|
495
|
tmp = poll(&ep0_poll, 1, -1);
|
496
|
if (tmp < 0)
|
497
|
{
|
498
|
mpReportError->Report("%s: poll : %s", __func__, strerror(errno));
|
499
|
break;
|
500
|
}
|
501
|
|
502
|
tmp = read(mnEP0Fd, &event, sizeof(event));
|
503
|
if (tmp < 0)
|
504
|
{
|
505
|
if (errno == EAGAIN)
|
506
|
{
|
507
|
continue;
|
508
|
}
|
509
|
mpReportError->Report("ep0 read after poll : %s\n", strerror(errno));
|
510
|
goto done;
|
511
|
}
|
512
|
nevent = tmp / sizeof(event[0]);
|
513
|
for(i = 0; i < nevent; ++i)
|
514
|
{
|
515
|
switch(event[i].type)
|
516
|
{
|
517
|
case GADGETFS_NOP:
|
518
|
break;
|
519
|
case GADGETFS_CONNECT:
|
520
|
mbConnected = true;
|
521
|
break;
|
522
|
case GADGETFS_SETUP:
|
523
|
mbConnected = true;
|
524
|
HandleControl(&event[i].u.setup);
|
525
|
break;
|
526
|
case GADGETFS_DISCONNECT:
|
527
|
mbConnected = false;
|
528
|
StopIO();
|
529
|
break;
|
530
|
case GADGETFS_SUSPEND:
|
531
|
break;
|
532
|
default:
|
533
|
mpReportError->Report("unhandled USB event %d\n", event[i].type);
|
534
|
break;
|
535
|
}
|
536
|
}
|
537
|
continue;
|
538
|
done:
|
539
|
if (mbConnected)
|
540
|
StopIO();
|
541
|
break;
|
542
|
}
|
543
|
return 0;
|
544
|
}
|
545
|
|
546
|
void* tcUSB::DispatchBulkInHandler(void *apThis)
|
547
|
{
|
548
|
tcUSB *lpUSB = (tcUSB *)apThis;
|
549
|
lpUSB->BulkInHandler();
|
550
|
return NULL;
|
551
|
}
|
552
|
|
553
|
int tcUSB::BulkInHandler(void)
|
554
|
{
|
555
|
int status;
|
556
|
char buf[USB_BUFSIZE];
|
557
|
|
558
|
while(true)
|
559
|
{
|
560
|
status = read(mnBulkOutFd, buf, sizeof(buf));
|
561
|
if (status < 0)
|
562
|
{
|
563
|
break;
|
564
|
}
|
565
|
if (status) {
|
566
|
mnBytesIn += status;
|
567
|
mpParser->AddData(buf, status);
|
568
|
}
|
569
|
}
|
570
|
return 0;
|
571
|
}
|
572
|
|
573
|
#define USEAIO
|
574
|
|
575
|
#ifdef USEAIO
|
576
|
inline int io_setup(unsigned nr, aio_context_t *ctxp)
|
577
|
{
|
578
|
return syscall(__NR_io_setup, nr, ctxp);
|
579
|
}
|
580
|
|
581
|
inline int io_destroy(aio_context_t ctx)
|
582
|
{
|
583
|
return syscall(__NR_io_destroy, ctx);
|
584
|
}
|
585
|
|
586
|
inline int io_submit(aio_context_t ctx, long nr, struct iocb **iocbpp)
|
587
|
{
|
588
|
return syscall(__NR_io_submit, ctx, nr, iocbpp);
|
589
|
}
|
590
|
|
591
|
inline int io_getevents(aio_context_t ctx, long min_nr, long max_nr,
|
592
|
struct io_event *events, struct timespect *timeout)
|
593
|
{
|
594
|
return syscall(__NR_io_getevents, ctx, min_nr, max_nr, events, timeout);
|
595
|
}
|
596
|
|
597
|
#define NUM_BUFFERS 8
|
598
|
aio_context_t ctx;
|
599
|
struct iocb iocb[NUM_BUFFERS];
|
600
|
static int pingpong = 0;
|
601
|
struct io_event events[NUM_BUFFERS];
|
602
|
char *buffers[NUM_BUFFERS];
|
603
|
#endif
|
604
|
|
605
|
int bufpos = 0;
|
606
|
#define BUFFER_SIZE (64*1024)
|
607
|
char buffer[BUFFER_SIZE];
|
608
|
|
609
|
/**
|
610
|
* Send data via Bulk transfer output endpoint.
|
611
|
*/
|
612
|
int tcUSB::put(const char* data, int length, int flush)
|
613
|
{
|
614
|
int rv, bytes_sent = 0;
|
615
|
int index;
|
616
|
if (length <= 0)
|
617
|
{
|
618
|
/* printf("Length was %d\n", length); */
|
619
|
return 0;
|
620
|
}
|
621
|
if (mbConnected && mnBytesIn && (mnBulkInFd >= 0))
|
622
|
{
|
623
|
#ifndef USEAIO
|
624
|
if (bufpos + length > BUFFER_SIZE)
|
625
|
{
|
626
|
rv = write(mnBulkInFd, buffer, bufpos);
|
627
|
bufpos = 0;
|
628
|
}
|
629
|
memcpy(&buffer[bufpos], data, length);
|
630
|
bufpos += length;
|
631
|
if (flush) {
|
632
|
rv = write(mnBulkInFd, &buffer[0], bufpos);
|
633
|
bufpos = 0;
|
634
|
}
|
635
|
#else
|
636
|
if (0 == pingpong && !bufpos)
|
637
|
{
|
638
|
for (int i = 0; i < NUM_BUFFERS; ++i)
|
639
|
buffers[i] = (char*)malloc(BUFFER_SIZE);
|
640
|
|
641
|
rv = io_setup(NUM_BUFFERS+1, &ctx);
|
642
|
if (rv < 0)
|
643
|
{
|
644
|
perror("io_setup");
|
645
|
return -1;
|
646
|
}
|
647
|
}
|
648
|
index = pingpong;
|
649
|
index %= NUM_BUFFERS;
|
650
|
|
651
|
int recoverbufs = 0; /* number of buffers we will transfer */
|
652
|
int first_buf_size = 0;
|
653
|
|
654
|
/* if we can't fit this packet in our current buffer, advance to next
|
655
|
* and note fact by increasing buffer transfer count */
|
656
|
if (bufpos + length > BUFFER_SIZE)
|
657
|
{
|
658
|
recoverbufs++;
|
659
|
index++;
|
660
|
index %= NUM_BUFFERS;
|
661
|
first_buf_size = bufpos;
|
662
|
bufpos = 0;
|
663
|
}
|
664
|
/* if we have to flush, then we must mark this packet to transfer */
|
665
|
if (flush)
|
666
|
recoverbufs++;
|
667
|
|
668
|
/* if we need to transfer and all our buffers are outstanding, then
|
669
|
* wait for some to recover */
|
670
|
if (recoverbufs && (pingpong+recoverbufs > NUM_BUFFERS))
|
671
|
{
|
672
|
rv = io_getevents(ctx, recoverbufs, recoverbufs, events, NULL);
|
673
|
if (rv < 0)
|
674
|
{
|
675
|
printf("io_getevents : %d\n", rv);
|
676
|
return -1;
|
677
|
}
|
678
|
}
|
679
|
|
680
|
/* if two transfers send first packet */
|
681
|
if (first_buf_size)
|
682
|
{
|
683
|
int tmp = index-1;
|
684
|
if (tmp < 0) tmp = NUM_BUFFERS-1;
|
685
|
memset(&iocb[tmp],0,sizeof(iocb[tmp]));
|
686
|
iocb[tmp].aio_fildes = mnBulkInFd;
|
687
|
iocb[tmp].aio_lio_opcode = IOCB_CMD_PWRITE;
|
688
|
iocb[tmp].aio_buf = (__u64)buffers[tmp];
|
689
|
iocb[tmp].aio_nbytes = first_buf_size;
|
690
|
iocb[tmp].aio_offset = 0;
|
691
|
struct iocb *cbs[1];
|
692
|
cbs[0] = &iocb[tmp];
|
693
|
rv = io_submit(ctx, 1, cbs);
|
694
|
if (rv != 1)
|
695
|
{
|
696
|
perror("io_submit\n");
|
697
|
return -1;
|
698
|
}
|
699
|
}
|
700
|
/* copy packet data in... */
|
701
|
memcpy(&buffers[index][bufpos], data, length);
|
702
|
bufpos += length;
|
703
|
|
704
|
/* if we need to transfer this packet, send it out */
|
705
|
if (flush)
|
706
|
{
|
707
|
memset(&iocb[index],0,sizeof(iocb[index]));
|
708
|
iocb[index].aio_fildes = mnBulkInFd;
|
709
|
iocb[index].aio_lio_opcode = IOCB_CMD_PWRITE;
|
710
|
iocb[index].aio_buf = (__u64)buffers[index];
|
711
|
iocb[index].aio_nbytes = bufpos;
|
712
|
iocb[index].aio_offset = 0;
|
713
|
struct iocb *cbs[1];
|
714
|
cbs[0] = &iocb[index];
|
715
|
bufpos = 0;
|
716
|
rv = io_submit(ctx, 1, cbs);
|
717
|
if (rv != 1)
|
718
|
{
|
719
|
perror("io_submit\n");
|
720
|
return -1;
|
721
|
}
|
722
|
}
|
723
|
|
724
|
bytes_sent = length;
|
725
|
pingpong += recoverbufs;
|
726
|
#endif
|
727
|
}
|
728
|
else
|
729
|
{
|
730
|
return -1;
|
731
|
}
|
732
|
return bytes_sent;
|
733
|
}
|
734
|
|