updated license headers in movidius sources (#163)
[platform/upstream/dldt.git] / inference-engine / thirdparty / movidius / XLink / pc / XLinkPlatform.c
1 // Copyright (C) 2018-2019 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
3 //
4
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <sys/types.h>
8 #include <sys/stat.h>
9 #include <fcntl.h>
10 #include <sys/timeb.h>
11 #include <errno.h>
12 #include <assert.h>
13
14 #include "XLinkPlatform.h"
15 #include "usb_boot.h"
16 #include "pcie_host.h"
17
18 #if (defined(_WIN32) || defined(_WIN64))
19 #include "usb_winusb.h"
20 #include "gettime.h"
21 #include "win_pthread.h"
22 extern void initialize_usb_boot();
23 #else
24 #include <unistd.h>
25 #include <sys/wait.h>
26 #include <sys/un.h>
27 #include <sys/ioctl.h>
28 #include <pthread.h>
29 #include <termios.h>
30 #include <libusb.h>
31 #endif  /*defined(_WIN32) || defined(_WIN64)*/
32
33 #ifdef USE_LINK_JTAG
34 #include <sys/types.h>          /* See NOTES */
35 #include <sys/socket.h>
36 #include <netdb.h>
37 #include <netinet/in.h>
38 #include <arpa/inet.h>
39 #endif  /*USE_LINK_JTAG*/
40
41 #define USBLINK_ERROR_PRINT
42
43 #ifdef USBLINK_ERROR_PRINT
44 #define USBLINK_ERROR(...) printf(__VA_ARGS__)
45 #else
46 #define USBLINK_ERROR(...) (void)0
47 #endif  /*USBLINK_ERROR_PRINT*/
48 #ifdef USBLINKDEBUG
49
50
51 #define USBLINK_PRINT(...) printf(__VA_ARGS__)
52 #else
53 #define USBLINK_PRINT(...) (void)0
54 #endif  /*USBLINKDEBUG*/
55 #ifdef USBLINKWARN
56
57
58 #define USBLINK_WARN(...) printf(__VA_ARGS__)
59 #else
60 #define USBLINK_WARN(...) (void)0
61 #endif  /*USBLINKWARN*/
62
63 #define USB_LINK_SOCKET_PORT 5678
64 #define MAX_EVENTS 64
65 #define USB_ENDPOINT_IN 0x81
66 #define USB_ENDPOINT_OUT 0x01
67
68 #ifndef USE_USB_VSC
69 int usbFdWrite = -1;
70 int usbFdRead = -1;
71 #endif  /*USE_USB_VSC*/
72
73 static int statuswaittimeout = 5;
74
75 #include <assert.h>
76
77 pthread_t readerThreadId;
78
79 // Communication protocol used
80 // Few functions could be called without XLink initialization
81 #ifdef USE_PCIE
82 int gl_protocol = PCIE;
83 #else   // use USB as default
84 int gl_protocol = USB_VSC;
85 #endif
86
87 #define MAX_EVENTS 64
88 #if (defined(_WIN32) || defined(_WIN64))
89 extern void initialize_usb_boot();
90 #endif
91
92 static xLinkPlatformErrorCode_t parseUsbBootError(usbBootError_t rc) {
93     switch (rc) {
94         case USB_BOOT_SUCCESS:
95             return X_LINK_PLATFORM_SUCCESS;
96         case USB_BOOT_DEVICE_NOT_FOUND:
97             return X_LINK_PLATFORM_DEVICE_NOT_FOUND;
98         case USB_BOOT_TIMEOUT:
99             return X_LINK_PLATFORM_TIMEOUT;
100         default:
101             return X_LINK_PLATFORM_ERROR;
102     }
103 }
104
105 static int usb_write(libusb_device_handle *f, const void *data, size_t size, unsigned int timeout)
106 {
107     while(size > 0)
108     {
109         int bt, ss = size;
110         if(ss > 1024*1024*5)
111             ss = 1024*1024*5;
112 #if (defined(_WIN32) || defined(_WIN64) )
113         int rc = usb_bulk_write(f, USB_ENDPOINT_OUT, (unsigned char *)data, ss, &bt, timeout);
114 #else
115         int rc = libusb_bulk_transfer(f, USB_ENDPOINT_OUT, (unsigned char *)data, ss, &bt, timeout);
116 #endif
117         if(rc)
118             return rc;
119         data = (char *)data + bt;
120         size -= bt;
121     }
122     return 0;
123 }
124
125
126 static int usb_read(libusb_device_handle *f, void *data, size_t size, unsigned int timeout)
127 {
128     while(size > 0)
129     {
130         int bt, ss = size;
131         if(ss > 1024*1024*5)
132             ss = 1024*1024*5;
133 #if (defined(_WIN32) || defined(_WIN64))
134         int rc = usb_bulk_read(f, USB_ENDPOINT_IN, (unsigned char *)data, ss, &bt, timeout);
135 #else
136         int rc = libusb_bulk_transfer(f, USB_ENDPOINT_IN,(unsigned char *)data, ss, &bt, timeout);
137 #endif
138         if(rc)
139             return rc;
140         data = ((char *)data) + bt;
141         size -= bt;
142     }
143     return 0;
144 }
145
146
147 static double seconds()
148 {
149     static double s;
150     struct timespec ts;
151
152     clock_gettime(CLOCK_MONOTONIC, &ts);
153     if(!s)
154         s = ts.tv_sec + ts.tv_nsec * 1e-9;
155     return ts.tv_sec + ts.tv_nsec * 1e-9 - s;
156 }
157
158 libusb_device_handle *usblink_open(const char *path)
159 {
160     if (path == NULL) {
161         return 0;
162     }
163
164     usbBootError_t rc = USB_BOOT_DEVICE_NOT_FOUND;
165     libusb_device_handle *h = NULL;
166     libusb_device *dev = NULL;
167     double waittm = seconds() + statuswaittimeout;
168     while(seconds() < waittm){
169         int size = strlen(path);
170
171 #if (!defined(_WIN32) && !defined(_WIN64))
172         uint16_t  bcdusb = -1;
173         rc = usb_find_device_with_bcd(0, (char *)path, size, (void **)&dev, DEFAULT_OPENVID, DEFAULT_OPENPID,&bcdusb);
174 #else
175                 rc = usb_find_device(0, (char *)path, size, (void **)&dev, DEFAULT_OPENVID, DEFAULT_OPENPID);
176 #endif
177         if(rc == USB_BOOT_SUCCESS)
178             break;
179         usleep(1000);
180     }
181     if (rc == USB_BOOT_TIMEOUT || rc == USB_BOOT_DEVICE_NOT_FOUND) // Timeout
182         return 0;
183 #if (defined(_WIN32) || defined(_WIN64) )
184         h = usb_open_device(dev, NULL, 0, stderr);
185         int libusb_rc = ((h != NULL) ? (0) : (-1));
186         if (libusb_rc < 0)
187         {
188                 usb_close_device(h);
189                 usb_free_device(dev);
190                 return 0;
191         }
192         usb_free_device(dev);
193 #else
194     int libusb_rc = libusb_open(dev, &h);
195     if (libusb_rc < 0)
196     {
197         libusb_unref_device(dev);
198         return 0;
199     }
200     libusb_unref_device(dev);
201     libusb_detach_kernel_driver(h, 0);
202     libusb_rc = libusb_claim_interface(h, 0);
203     if(libusb_rc < 0)
204     {
205         libusb_close(h);
206         return 0;
207     }
208 #endif
209     return h;
210 }
211
212 void usblink_close(libusb_device_handle *f)
213 {
214 #if (defined(_WIN32) || defined(_WIN64))
215     usb_close_device(f);
216 #else
217     libusb_release_interface(f, 0);
218     libusb_close(f);
219 #endif
220 }
221
222 int USBLinkWrite(void* fd, void* data, int size, unsigned int timeout)
223 {
224     int rc = 0;
225 #ifndef USE_USB_VSC
226     int byteCount = 0;
227 #ifdef USE_LINK_JTAG
228     while (byteCount < size){
229         byteCount += write(usbFdWrite, &((char*)data)[byteCount], size - byteCount);
230         printf("write %d %d\n", byteCount, size);
231     }
232 #else
233     if(usbFdWrite < 0)
234     {
235         return -1;
236     }
237     while(byteCount < size)
238     {
239        int toWrite = (PACKET_LENGTH && (size - byteCount > PACKET_LENGTH)) \
240                         ? PACKET_LENGTH:size - byteCount;
241        int wc = write(usbFdWrite, ((char*)data) + byteCount, toWrite);
242
243        if ( wc != toWrite)
244        {
245            return -2;
246        }
247
248        byteCount += toWrite;
249        unsigned char acknowledge;
250        int rc;
251        rc = read(usbFdWrite, &acknowledge, sizeof(acknowledge));
252
253        if ( rc < 0)
254        {
255            return -2;
256        }
257
258        if (acknowledge != 0xEF)
259        {
260            return -2;
261        }
262     }
263 #endif  /*USE_LINK_JTAG*/
264 #else
265     rc = usb_write((libusb_device_handle *) fd, data, size, timeout);
266 #endif  /*USE_USB_VSC*/
267     return rc;
268 }
269
270  int USBLinkRead(void* fd, void* data, int size, unsigned int timeout)
271 {
272     // FIXME USE_LINK_JTAG not compiled
273 #ifndef USE_PCIE
274     int rc = 0;
275 #ifndef USE_USB_VSC
276     int nread =  0;
277 #ifdef USE_LINK_JTAG
278     while (nread < size){
279         nread += read(usbFdWrite, &((char*)data)[nread], size - nread);
280         printf("read %d %d\n", nread, size);
281     }
282 #else
283     if(usbFdRead < 0)
284     {
285         return -1;
286     }
287
288     while(nread < size)
289     {
290         int toRead = (PACKET_LENGTH && (size - nread > PACKET_LENGTH)) \
291                         ? PACKET_LENGTH : size - nread;
292
293         while(toRead > 0)
294         {
295             rc = read(usbFdRead, &((char*)gl_protocoldata)[nread], toRead);
296             if ( rc < 0)
297             {
298                 return -2;
299             }
300             toRead -=rc;
301             nread += rc;
302         }
303         unsigned char acknowledge = 0xEF;
304         int wc = write(usbFdRead, &acknowledge, sizeof(acknowledge));
305         if (wc != sizeof(acknowledge))
306         {
307             return -2;
308         }
309     }
310 #endif  /*USE_LINK_JTAG*/
311 #else
312     rc = usb_read((libusb_device_handle *) fd, data, size, timeout);
313 #endif  /*USE_USB_VSC*/
314     return rc;
315 #endif  // USE_PCIE
316     return 0;
317 }
318
319 int USBLinkPlatformResetRemote(void* fd)
320 {
321
322 #ifndef USE_USB_VSC
323 #ifdef USE_LINK_JTAG
324     /*Nothing*/
325 #else
326     if (usbFdRead != -1){
327         close(usbFdRead);
328         usbFdRead = -1;
329     }
330     if (usbFdWrite != -1){
331         close(usbFdWrite);
332         usbFdWrite = -1;
333     }
334 #endif  /*USE_LINK_JTAG*/
335 #else
336     usblink_close((libusb_device_handle *) fd);
337 #endif  /*USE_USB_VSC*/
338     return -1;
339 }
340
341 int UsbLinkPlatformConnect(const char* devPathRead, const char* devPathWrite, void** fd)
342 {
343     #if (!defined(USE_USB_VSC) && !defined(USE_PCIE))
344 #ifdef USE_LINK_JTAG
345     struct sockaddr_in serv_addr;
346     usbFdWrite = socket(AF_INET, SOCK_STREAM, 0);
347     usbFdRead = socket(AF_INET, SOCK_STREAM, 0);
348     assert(usbFdWrite >=0);
349     assert(usbFdRead >=0);
350     memset(&serv_addr, '0', sizeof(serv_addr));
351
352     serv_addr.sin_family = AF_INET;
353     serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
354     serv_addr.sin_port = htons(USB_LINK_SOCKET_PORT);
355
356     if (connect(usbFdWrite, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0)
357     {
358         perror("ERROR connecting");
359         exit(1);
360     }
361     printf("this is working\n");
362     return 0;
363
364 #else
365     usbFdRead= open(devPathRead, O_RDWR);
366     if(usbFdRead < 0)
367     {
368         return -1;
369     }
370     // set tty to raw mode
371     struct termios  tty;
372     speed_t     spd;
373     int rc;
374     rc = tcgetattr(usbFdRead, &tty);
375     if (rc < 0) {
376         usbFdRead = -1;
377         return -2;
378     }
379
380     spd = B115200;
381     cfsetospeed(&tty, (speed_t)spd);
382     cfsetispeed(&tty, (speed_t)spd);
383
384     cfmakeraw(&tty);
385
386     rc = tcsetattr(usbFdRead, TCSANOW, &tty);
387     if (rc < 0) {
388         usbFdRead = -1;
389         return -2;
390     }
391
392     usbFdWrite= open(devPathWrite, O_RDWR);
393     if(usbFdWrite < 0)
394     {
395         usbFdWrite = -1;
396         return -2;
397     }
398     // set tty to raw mode
399     rc = tcgetattr(usbFdWrite, &tty);
400     if (rc < 0) {
401         usbFdWrite = -1;
402         return -2;
403     }
404
405     spd = B115200;
406     cfsetospeed(&tty, (speed_t)spd);
407     cfsetispeed(&tty, (speed_t)spd);
408
409     cfmakeraw(&tty);
410
411     rc = tcsetattr(usbFdWrite, TCSANOW, &tty);
412     if (rc < 0) {
413         usbFdWrite = -1;
414         return -2;
415     }
416     return 0;
417 #endif  /*USE_LINK_JTAG*/
418 #else
419     *fd = usblink_open(devPathWrite);
420     if (*fd == 0)
421     {
422        /* could fail due to port name change */
423        return -1;
424     }
425
426     if(*fd)
427         return 0;
428     else
429         return -1;
430 #endif  /*USE_USB_VSC*/
431 }
432
433 int UsbLinkPlatformInit(int loglevel)
434 {
435     usb_loglevel = loglevel;
436 #if (defined(_WIN32) || defined(_WIN64))
437     initialize_usb_boot();
438 #endif
439     return 0;
440 }
441
442 void deallocateData(void* ptr,uint32_t size, uint32_t alignment)
443 {
444     if (!ptr)
445         return;
446 #if (defined(_WIN32) || defined(_WIN64) )
447     _aligned_free(ptr);
448 #else
449     free(ptr);
450 #endif
451 }
452
453 void* allocateData(uint32_t size, uint32_t alignment)
454 {
455     void* ret = NULL;
456 #if (defined(_WIN32) || defined(_WIN64) )
457     ret = _aligned_malloc(size, alignment);
458 #else
459     if (posix_memalign(&ret, alignment, size) != 0) {
460         perror("memalign failed");
461     }
462 #endif
463     return ret;
464 }
465
466
467 /*#################################################################################
468 ################################### PCIe FUNCTIONS ################################
469 ##################################################################################*/
470
471 static int write_pending = 0;
472 static int read_pending = 0;
473
474
475 static int pcie_host_write(void *f,
476                            void *data, int size,
477                            unsigned int timeout)
478 {
479 #define CHUNK_SIZE_BYTES (5ULL * 1024ULL * 1024ULL)
480
481     while (size)
482     {
483         write_pending = 1;
484
485         size_t chunk = size < CHUNK_SIZE_BYTES ? size : CHUNK_SIZE_BYTES;
486         int num_written = pcie_write(f, data, chunk, timeout);
487
488         write_pending = 0;
489
490         if (num_written == -EAGAIN)  {
491             // Let read commands be submitted
492             if (read_pending > 0) {
493                 usleep(1000);
494             }
495             continue;
496         }
497
498         if (num_written < 0) {
499             return num_written;
500         }
501
502         data = ((char*) data) + num_written;
503         /**
504          * num_written is always not greater than size
505          */
506         size -= num_written;
507     }
508
509     return 0;
510 #undef CHUNK_SIZE_BYTES
511 }
512
513 static int pcie_host_read(void *f,
514                           void *data, int size,
515                           unsigned int timeout)
516 {
517     while (size)
518     {
519         read_pending = 1;
520
521         int num_read = pcie_read(f, data, size, timeout);
522
523         read_pending = 0;
524
525         if (num_read == -EAGAIN)  {
526             // Let write commands be submitted
527             if (write_pending > 0) {
528                 usleep(1000);
529             }
530             continue;
531         }
532
533         if(num_read < 0) {
534             return num_read;
535         }
536
537         data = ((char *)data) + num_read;
538         /**
539          * num_read is always not greater than size
540          */
541         size -= num_read;
542     }
543
544     return 0;
545 }
546
547 static int pcie_host_open(const char* devPathRead,
548                           const char* devPathWrite,
549                           void** fd )
550 {
551     return pcie_init(devPathWrite, fd);
552 }
553
554 static int pcie_host_close(void *f)
555 {
556     pcie_close(f);
557     return 0;
558 }
559
560 /*############################### FUNCTION ARRAYS #################################*/
561 /*These arrays hold the write/read/open/close operation functions
562 specific for each communication protocol.
563 Add more functions if adding another protocol*/
564 int (*write_fcts[NMB_OF_PROTOCOLS])(void*, void*, int, unsigned int) = \
565                             {USBLinkWrite, USBLinkWrite, pcie_host_write};
566 int (*read_fcts[NMB_OF_PROTOCOLS])(void*, void*, int, unsigned int) = \
567                             {USBLinkRead, XLinkRead, pcie_host_read};
568 int (*open_fcts[NMB_OF_PROTOCOLS])(const char*, const char*, void**) = \
569                             {UsbLinkPlatformConnect, UsbLinkPlatformConnect, pcie_host_open};
570 int (*close_fcts[NMB_OF_PROTOCOLS])(void*) = \
571                             {USBLinkPlatformResetRemote, USBLinkPlatformResetRemote, pcie_host_close};
572
573
574 /*#################################################################################
575 ###################################################################################
576 ###################################### EXTERNAL ###################################
577 ###################################################################################
578 ##################################################################################*/
579 int XLinkPlatformConnect(const char* devPathRead, const char* devPathWrite, void** fd)
580 {
581     return open_fcts[gl_protocol](devPathRead, devPathWrite, fd);
582 }
583
584 int XLinkWrite(void* fd, void* data, int size, unsigned int timeout)
585 {
586     return write_fcts[gl_protocol](fd, data, size, timeout);
587 }
588
589 int XLinkRead(void* fd, void* data, int size, unsigned int timeout)
590 {
591     return read_fcts[gl_protocol](fd, data, size, timeout);
592 }
593
594 int XLinkPlatformCloseRemote(void *fd)
595 {
596     return close_fcts[gl_protocol](fd);
597 }
598
599 int XLinkPlatformInit(XLinkProtocol_t protocol, int loglevel)
600 {
601     gl_protocol = protocol;
602     usb_loglevel = loglevel;
603 #if (defined(_WIN32) || defined(_WIN64))
604     initialize_usb_boot();
605 #endif
606     return 0;
607 }
608
609 static int getDeviceName(int index, char* name, int nameSize , int pid)
610 {
611     if (index < 0 ) {
612         perror("Incorrect index value\n");
613         return X_LINK_PLATFORM_ERROR;
614     }
615     switch (gl_protocol) {
616         case PCIE: {
617             return pcie_find_device_port(index, name, nameSize);
618         }
619         case IPC:
620             perror("IPC not supported, switched to USB\n");
621             break;
622         case USB_CDC:
623             perror("USB_CDC not supported, switch to USB\n");
624             break;
625         case USB_VSC:
626             /*should have common device(temporary moved to 'default')*/
627         default:
628         {
629             // At the moment there is no situation where you may need a non standard vid
630             int vid = AUTO_PID;
631
632 #if (!defined(_WIN32) && !defined(_WIN64))
633             uint16_t  bcdusb = -1;
634             usbBootError_t rc = usb_find_device_with_bcd(index, name, nameSize, 0, vid, pid, &bcdusb);
635 #else
636             usbBootError_t rc = usb_find_device(index, name, nameSize, 0, vid, pid);
637 #endif
638             // TODO convert usb error to xLinkPlatformErrorCode
639             return parseUsbBootError(rc);
640         }
641     }
642     return X_LINK_PLATFORM_SUCCESS;
643 }
644
645 int XLinkPlatformGetDeviceName(int index, char* name, int nameSize)
646 {
647     return getDeviceName(index, name, nameSize, AUTO_PID);
648 }
649
650 int XLinkPlatformGetDeviceNameExtended(int index, char* name, int nameSize, int pid)
651 {
652     return getDeviceName(index, name, nameSize, pid);
653 }
654
655 int XLinkPlatformBootRemote(const char* deviceName, const char* binaryPath)
656 {
657 /* Don't try to boot FW if PCIe */
658 #ifdef USE_PCIE
659     return 0;
660 #else
661     long filesize;
662     FILE *fp;
663     char *tx_buf;
664     char subaddr[28+2];
665     int rc;
666
667 #ifndef USE_USB_VSC
668     if (usbFdRead != -1){
669         close(usbFdRead);
670         usbFdRead = -1;
671     }
672     if (usbFdWrite != -1){
673         close(usbFdWrite);
674         usbFdWrite = -1;
675     }
676 #endif  /*USE_USB_VSC*/
677
678     // Load the executable
679     fp = fopen(binaryPath, "rb");
680     if(fp == NULL)
681     {
682         if(usb_loglevel)
683             perror(binaryPath);
684         return -7;
685     }
686     fseek(fp, 0, SEEK_END);
687     filesize = ftell(fp);
688     rewind(fp);    
689     if(filesize <= 0 || !(tx_buf = (char*)malloc(filesize)))
690     {
691         if(usb_loglevel)
692             perror("buffer");
693         fclose(fp);
694         return -3;
695     }
696     if(fread(tx_buf, 1, filesize, fp) != filesize)
697     {
698         if(usb_loglevel)
699             perror(binaryPath);
700         fclose(fp);
701         free(tx_buf);
702         return -7;
703     }
704     fclose(fp);
705
706     // This will be the string to search for in /sys/dev/char links
707     int chars_to_write = snprintf(subaddr, 28, "-%s:", deviceName);
708     if(chars_to_write >= 28) {
709         printf("Path to your boot util is too long for the char array here!\n");
710     }
711     // Boot it
712     rc = usb_boot(deviceName, tx_buf, filesize);
713     free(tx_buf);
714     if(rc)
715     {
716         return rc;
717     }
718     if(usb_loglevel > 1)
719         fprintf(stderr, "Boot successful, device address %s\n", deviceName);
720     return 0;
721 #endif  // USE_PCIE
722 }