1 // Copyright (C) 2018-2019 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
10 #include <sys/timeb.h>
14 #include "XLinkPlatform.h"
16 #include "pcie_host.h"
18 #if (defined(_WIN32) || defined(_WIN64))
19 #include "usb_winusb.h"
21 #include "win_pthread.h"
22 extern void initialize_usb_boot();
27 #include <sys/ioctl.h>
31 #endif /*defined(_WIN32) || defined(_WIN64)*/
34 #include <sys/types.h> /* See NOTES */
35 #include <sys/socket.h>
37 #include <netinet/in.h>
38 #include <arpa/inet.h>
39 #endif /*USE_LINK_JTAG*/
41 #define USBLINK_ERROR_PRINT
43 #ifdef USBLINK_ERROR_PRINT
44 #define USBLINK_ERROR(...) printf(__VA_ARGS__)
46 #define USBLINK_ERROR(...) (void)0
47 #endif /*USBLINK_ERROR_PRINT*/
51 #define USBLINK_PRINT(...) printf(__VA_ARGS__)
53 #define USBLINK_PRINT(...) (void)0
54 #endif /*USBLINKDEBUG*/
58 #define USBLINK_WARN(...) printf(__VA_ARGS__)
60 #define USBLINK_WARN(...) (void)0
61 #endif /*USBLINKWARN*/
63 #define USB_LINK_SOCKET_PORT 5678
65 #define USB_ENDPOINT_IN 0x81
66 #define USB_ENDPOINT_OUT 0x01
71 #endif /*USE_USB_VSC*/
73 static int statuswaittimeout = 5;
77 pthread_t readerThreadId;
79 // Communication protocol used
80 // Few functions could be called without XLink initialization
82 int gl_protocol = PCIE;
83 #else // use USB as default
84 int gl_protocol = USB_VSC;
88 #if (defined(_WIN32) || defined(_WIN64))
89 extern void initialize_usb_boot();
92 static xLinkPlatformErrorCode_t parseUsbBootError(usbBootError_t 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;
101 return X_LINK_PLATFORM_ERROR;
105 static int usb_write(libusb_device_handle *f, const void *data, size_t size, unsigned int timeout)
112 #if (defined(_WIN32) || defined(_WIN64) )
113 int rc = usb_bulk_write(f, USB_ENDPOINT_OUT, (unsigned char *)data, ss, &bt, timeout);
115 int rc = libusb_bulk_transfer(f, USB_ENDPOINT_OUT, (unsigned char *)data, ss, &bt, timeout);
119 data = (char *)data + bt;
126 static int usb_read(libusb_device_handle *f, void *data, size_t size, unsigned int timeout)
133 #if (defined(_WIN32) || defined(_WIN64))
134 int rc = usb_bulk_read(f, USB_ENDPOINT_IN, (unsigned char *)data, ss, &bt, timeout);
136 int rc = libusb_bulk_transfer(f, USB_ENDPOINT_IN,(unsigned char *)data, ss, &bt, timeout);
140 data = ((char *)data) + bt;
147 static double seconds()
152 clock_gettime(CLOCK_MONOTONIC, &ts);
154 s = ts.tv_sec + ts.tv_nsec * 1e-9;
155 return ts.tv_sec + ts.tv_nsec * 1e-9 - s;
158 libusb_device_handle *usblink_open(const char *path)
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);
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);
175 rc = usb_find_device(0, (char *)path, size, (void **)&dev, DEFAULT_OPENVID, DEFAULT_OPENPID);
177 if(rc == USB_BOOT_SUCCESS)
181 if (rc == USB_BOOT_TIMEOUT || rc == USB_BOOT_DEVICE_NOT_FOUND) // Timeout
183 #if (defined(_WIN32) || defined(_WIN64) )
184 h = usb_open_device(dev, NULL, 0, stderr);
185 int libusb_rc = ((h != NULL) ? (0) : (-1));
189 usb_free_device(dev);
192 usb_free_device(dev);
194 int libusb_rc = libusb_open(dev, &h);
197 libusb_unref_device(dev);
200 libusb_unref_device(dev);
201 libusb_detach_kernel_driver(h, 0);
202 libusb_rc = libusb_claim_interface(h, 0);
212 void usblink_close(libusb_device_handle *f)
214 #if (defined(_WIN32) || defined(_WIN64))
217 libusb_release_interface(f, 0);
222 int USBLinkWrite(void* fd, void* data, int size, unsigned int timeout)
228 while (byteCount < size){
229 byteCount += write(usbFdWrite, &((char*)data)[byteCount], size - byteCount);
230 printf("write %d %d\n", byteCount, size);
237 while(byteCount < size)
239 int toWrite = (PACKET_LENGTH && (size - byteCount > PACKET_LENGTH)) \
240 ? PACKET_LENGTH:size - byteCount;
241 int wc = write(usbFdWrite, ((char*)data) + byteCount, toWrite);
248 byteCount += toWrite;
249 unsigned char acknowledge;
251 rc = read(usbFdWrite, &acknowledge, sizeof(acknowledge));
258 if (acknowledge != 0xEF)
263 #endif /*USE_LINK_JTAG*/
265 rc = usb_write((libusb_device_handle *) fd, data, size, timeout);
266 #endif /*USE_USB_VSC*/
270 int USBLinkRead(void* fd, void* data, int size, unsigned int timeout)
272 // FIXME USE_LINK_JTAG not compiled
278 while (nread < size){
279 nread += read(usbFdWrite, &((char*)data)[nread], size - nread);
280 printf("read %d %d\n", nread, size);
290 int toRead = (PACKET_LENGTH && (size - nread > PACKET_LENGTH)) \
291 ? PACKET_LENGTH : size - nread;
295 rc = read(usbFdRead, &((char*)gl_protocoldata)[nread], toRead);
303 unsigned char acknowledge = 0xEF;
304 int wc = write(usbFdRead, &acknowledge, sizeof(acknowledge));
305 if (wc != sizeof(acknowledge))
310 #endif /*USE_LINK_JTAG*/
312 rc = usb_read((libusb_device_handle *) fd, data, size, timeout);
313 #endif /*USE_USB_VSC*/
319 int USBLinkPlatformResetRemote(void* fd)
326 if (usbFdRead != -1){
330 if (usbFdWrite != -1){
334 #endif /*USE_LINK_JTAG*/
336 usblink_close((libusb_device_handle *) fd);
337 #endif /*USE_USB_VSC*/
341 int UsbLinkPlatformConnect(const char* devPathRead, const char* devPathWrite, void** fd)
343 #if (!defined(USE_USB_VSC) && !defined(USE_PCIE))
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));
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);
356 if (connect(usbFdWrite, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0)
358 perror("ERROR connecting");
361 printf("this is working\n");
365 usbFdRead= open(devPathRead, O_RDWR);
370 // set tty to raw mode
374 rc = tcgetattr(usbFdRead, &tty);
381 cfsetospeed(&tty, (speed_t)spd);
382 cfsetispeed(&tty, (speed_t)spd);
386 rc = tcsetattr(usbFdRead, TCSANOW, &tty);
392 usbFdWrite= open(devPathWrite, O_RDWR);
398 // set tty to raw mode
399 rc = tcgetattr(usbFdWrite, &tty);
406 cfsetospeed(&tty, (speed_t)spd);
407 cfsetispeed(&tty, (speed_t)spd);
411 rc = tcsetattr(usbFdWrite, TCSANOW, &tty);
417 #endif /*USE_LINK_JTAG*/
419 *fd = usblink_open(devPathWrite);
422 /* could fail due to port name change */
430 #endif /*USE_USB_VSC*/
433 int UsbLinkPlatformInit(int loglevel)
435 usb_loglevel = loglevel;
436 #if (defined(_WIN32) || defined(_WIN64))
437 initialize_usb_boot();
442 void deallocateData(void* ptr,uint32_t size, uint32_t alignment)
446 #if (defined(_WIN32) || defined(_WIN64) )
453 void* allocateData(uint32_t size, uint32_t alignment)
456 #if (defined(_WIN32) || defined(_WIN64) )
457 ret = _aligned_malloc(size, alignment);
459 if (posix_memalign(&ret, alignment, size) != 0) {
460 perror("memalign failed");
467 /*#################################################################################
468 ################################### PCIe FUNCTIONS ################################
469 ##################################################################################*/
471 static int write_pending = 0;
472 static int read_pending = 0;
475 static int pcie_host_write(void *f,
476 void *data, int size,
477 unsigned int timeout)
479 #define CHUNK_SIZE_BYTES (5ULL * 1024ULL * 1024ULL)
485 size_t chunk = size < CHUNK_SIZE_BYTES ? size : CHUNK_SIZE_BYTES;
486 int num_written = pcie_write(f, data, chunk, timeout);
490 if (num_written == -EAGAIN) {
491 // Let read commands be submitted
492 if (read_pending > 0) {
498 if (num_written < 0) {
502 data = ((char*) data) + num_written;
504 * num_written is always not greater than size
510 #undef CHUNK_SIZE_BYTES
513 static int pcie_host_read(void *f,
514 void *data, int size,
515 unsigned int timeout)
521 int num_read = pcie_read(f, data, size, timeout);
525 if (num_read == -EAGAIN) {
526 // Let write commands be submitted
527 if (write_pending > 0) {
537 data = ((char *)data) + num_read;
539 * num_read is always not greater than size
547 static int pcie_host_open(const char* devPathRead,
548 const char* devPathWrite,
551 return pcie_init(devPathWrite, fd);
554 static int pcie_host_close(void *f)
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};
574 /*#################################################################################
575 ###################################################################################
576 ###################################### EXTERNAL ###################################
577 ###################################################################################
578 ##################################################################################*/
579 int XLinkPlatformConnect(const char* devPathRead, const char* devPathWrite, void** fd)
581 return open_fcts[gl_protocol](devPathRead, devPathWrite, fd);
584 int XLinkWrite(void* fd, void* data, int size, unsigned int timeout)
586 return write_fcts[gl_protocol](fd, data, size, timeout);
589 int XLinkRead(void* fd, void* data, int size, unsigned int timeout)
591 return read_fcts[gl_protocol](fd, data, size, timeout);
594 int XLinkPlatformCloseRemote(void *fd)
596 return close_fcts[gl_protocol](fd);
599 int XLinkPlatformInit(XLinkProtocol_t protocol, int loglevel)
601 gl_protocol = protocol;
602 usb_loglevel = loglevel;
603 #if (defined(_WIN32) || defined(_WIN64))
604 initialize_usb_boot();
609 static int getDeviceName(int index, char* name, int nameSize , int pid)
612 perror("Incorrect index value\n");
613 return X_LINK_PLATFORM_ERROR;
615 switch (gl_protocol) {
617 return pcie_find_device_port(index, name, nameSize);
620 perror("IPC not supported, switched to USB\n");
623 perror("USB_CDC not supported, switch to USB\n");
626 /*should have common device(temporary moved to 'default')*/
629 // At the moment there is no situation where you may need a non standard vid
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);
636 usbBootError_t rc = usb_find_device(index, name, nameSize, 0, vid, pid);
638 // TODO convert usb error to xLinkPlatformErrorCode
639 return parseUsbBootError(rc);
642 return X_LINK_PLATFORM_SUCCESS;
645 int XLinkPlatformGetDeviceName(int index, char* name, int nameSize)
647 return getDeviceName(index, name, nameSize, AUTO_PID);
650 int XLinkPlatformGetDeviceNameExtended(int index, char* name, int nameSize, int pid)
652 return getDeviceName(index, name, nameSize, pid);
655 int XLinkPlatformBootRemote(const char* deviceName, const char* binaryPath)
657 /* Don't try to boot FW if PCIe */
668 if (usbFdRead != -1){
672 if (usbFdWrite != -1){
676 #endif /*USE_USB_VSC*/
678 // Load the executable
679 fp = fopen(binaryPath, "rb");
686 fseek(fp, 0, SEEK_END);
687 filesize = ftell(fp);
689 if(filesize <= 0 || !(tx_buf = (char*)malloc(filesize)))
696 if(fread(tx_buf, 1, filesize, fp) != filesize)
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");
712 rc = usb_boot(deviceName, tx_buf, filesize);
719 fprintf(stderr, "Boot successful, device address %s\n", deviceName);