updated license headers in movidius sources (#163)
[platform/upstream/dldt.git] / inference-engine / thirdparty / movidius / USB_WIN / usb_winusb.c
1 // Copyright (C) 2018-2019 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
3 //
4
5 #pragma comment(lib, "winusb.lib")
6 #pragma comment(lib, "setupapi.lib")
7 //#define _CRT_SECURE_NO_WARNINGS
8
9 #define INITGUID
10 #include <Windows.h>
11 #include <winusb.h>
12 #include <Usbiodef.h>
13 #include <SetupAPI.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <stdint.h>
17 #include "usb_winusb.h"
18
19 #define USB_DIR_OUT             0
20 #define USB_DIR_IN              1
21
22 #define USB_DEV_NONE    NULL
23 #define USB_HAN_NONE    NULL
24
25 #define USB_ERR_NONE            0
26 #define USB_ERR_TIMEOUT         -1
27 #define USB_ERR_FAILED          -2
28 #define USB_ERR_INVALID         -3
29
30
31
32 ///*
33 struct ep_info {
34         uint8_t ep;
35         size_t sz;
36         ULONG last_timeout;
37 };
38 struct _usb_han {
39         HANDLE devHan;
40         WINUSB_INTERFACE_HANDLE winUsbHan;
41         struct ep_info eps[2];
42 };
43
44 extern const char * usb_get_pid_name(int);
45
46 #if defined(_MSC_VER) && _MSC_VER < 1900
47 #define snprintf _snprintf
48 #endif
49
50 // Myriad 2: {19E08104-0543-40A5-B107-87EF463DCEF1}
51 DEFINE_GUID(GUID_DEVINTERFACE_Myriad2, 0x19e08104, 0x0543, 0x40a5,
52         0xb1, 0x07, 0x87, 0xef, 0x46, 0x3d, 0xce, 0xf1);
53
54 // Myriad X: {504E1220-E189-413A-BDEC-ECFFAF3A3731}
55 DEFINE_GUID(GUID_DEVINTERFACE_MyriadX, 0x504e1220, 0xe189, 0x413a,
56         0xbd, 0xec, 0xec, 0xff, 0xaf, 0x3a, 0x37, 0x31);
57
58 static FILE *msgfile = NULL;
59 static int verbose = 0, ignore_errors = 0;
60 static DWORD last_bulk_errcode = 0;
61 static char *errmsg_buff = NULL;
62 static size_t errmsg_buff_len = 0;
63
64 static const char *format_win32_msg(DWORD errId) {
65         while(!FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
66                 NULL, errId, 0, errmsg_buff, (DWORD)errmsg_buff_len, NULL)) {
67                 if(GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
68 err_fail:
69                         snprintf(errmsg_buff, errmsg_buff_len, "Win32 Error 0x%08lx (Unable to retrieve error message)", errId);
70                         return errmsg_buff;
71                 }
72                 size_t nlen = errmsg_buff_len + (errmsg_buff_len / 2);
73                 if(nlen > 1024)
74                         goto err_fail;
75                 char *nbuff = realloc(errmsg_buff, nlen);
76                 if(nbuff == NULL)
77                         goto err_fail;
78                 errmsg_buff = nbuff;
79                 errmsg_buff_len = nlen;
80         }
81         return errmsg_buff;
82 }
83
84 static void wperror(const char *errmsg) {
85         DWORD errId = GetLastError();
86         fprintf(stderr, "%s: System err %d\n", errmsg, errId);
87 }
88
89 static void wstrerror(char *buff, const char *errmsg) {
90         DWORD errId = GetLastError();
91         snprintf(buff,strlen(buff), "%s: %s\n", errmsg, format_win32_msg(errId));
92 }
93 const char* libusb_strerror(int x)
94 {
95         return format_win32_msg(x);
96 }
97 int usb_init(void) {
98         msgfile = stdout;
99         if(errmsg_buff == NULL) {
100                 errmsg_buff_len = 64;
101                 errmsg_buff = malloc(errmsg_buff_len);
102                 if(errmsg_buff == NULL) {
103                         perror("malloc");
104                         return -1;
105                 }
106         }
107         return 0;
108 }
109
110 void usb_shutdown(void) {
111         if(errmsg_buff != NULL) {
112                 free(errmsg_buff);
113                 errmsg_buff = NULL;
114         }
115 }
116
117 int usb_can_find_by_guid(void) {
118         return 1;
119 }
120
121 static usb_dev retreive_dev_path(HDEVINFO devInfo, SP_DEVICE_INTERFACE_DATA *ifaceData) {
122         usb_dev res;
123         PSP_DEVICE_INTERFACE_DETAIL_DATA detData;
124         ULONG len, reqLen;
125
126         if(!SetupDiGetDeviceInterfaceDetail(devInfo, ifaceData, NULL, 0, &reqLen, NULL)) {
127                 if(GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
128                         wperror("SetupDiEnumDeviceInterfaces");
129                         SetupDiDestroyDeviceInfoList(devInfo);
130                         return USB_DEV_NONE;
131                 }
132         }
133         detData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)_alloca(reqLen);
134         detData->cbSize = sizeof(*detData);
135         len = reqLen;
136         if(!SetupDiGetDeviceInterfaceDetail(devInfo, ifaceData, detData, len, &reqLen, NULL)) {
137                 wperror("SetupDiGetDeviceInterfaceDetail");
138                 SetupDiDestroyDeviceInfoList(devInfo);
139                 return USB_DEV_NONE;
140         }
141         res = _strdup(detData->DevicePath);
142         if(res == NULL) {
143                 perror("strdup");
144         }
145         SetupDiDestroyDeviceInfoList(devInfo);
146         return res;
147 }
148
149 static const char *gen_addr(HDEVINFO devInfo, SP_DEVINFO_DATA *devInfoData, uint16_t pid) {
150     static char buff[16];
151     char li_buff[128];
152     unsigned int port, hub;
153     if (!SetupDiGetDeviceRegistryProperty(devInfo, devInfoData, SPDRP_LOCATION_INFORMATION, NULL, li_buff, sizeof(li_buff), NULL))
154     {
155         goto ret_err;
156     }
157         if(sscanf(li_buff, "Port_#%u.Hub_#%u", &port, &hub) != 2)
158         goto ret_err;
159
160         //matching it to libusboutput
161         const char* dev_name = usb_get_pid_name(pid);
162         if(dev_name == NULL)
163                 goto ret_err;
164
165         snprintf(buff, sizeof(buff), "%u.%u-%s", hub, port, dev_name);
166     buff[sizeof(buff) - 1] = '\0';
167         return buff;
168 ret_err:
169     return "<error>";
170 }
171 extern DEFAULT_OPENPID;
172
173 static int compareDeviceByHubAndPort(const void *l, const void *r) {
174     int lHub = 0, lPort = 0;
175     int rHub = 0, rPort = 0;
176
177     if (sscanf(((const char *)l + 4), "%d.%d", &lHub, &lPort) == EOF) {
178         perror("Can not parse hub and port of the devices");
179     };
180     if (sscanf(((const char *)r + 4), "%d.%d", &rHub, &rPort) == EOF) {
181         perror("Can not parse hub and port of the devices");
182     }
183
184     if (lHub != rHub) {
185         return rHub - lHub;
186     }
187
188     return rPort - lPort;
189 }
190
191 int usb_list_devices(uint16_t vid, uint16_t pid, uint8_t dev_des[][2 + 2 + 4 * 7 + 7]) {
192         HDEVINFO devInfo;
193         static int i;
194         SP_DEVINFO_DATA devInfoData;
195         char hwid_buff[128];
196
197         devInfoData.cbSize = sizeof(devInfoData);
198
199         devInfo = SetupDiGetClassDevs(&GUID_DEVINTERFACE_USB_DEVICE, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
200         if(devInfo == INVALID_HANDLE_VALUE) {
201                 wperror("SetupDiGetClassDevs");
202                 return -1;
203         }
204
205     for (i=0; SetupDiEnumDeviceInfo(devInfo, i, &devInfoData); i++) {
206         if (!SetupDiGetDeviceRegistryProperty(devInfo, &devInfoData, SPDRP_HARDWAREID, NULL, hwid_buff, sizeof(hwid_buff), NULL)) {
207             continue;
208         }
209         uint16_t fvid, fpid;
210         if(sscanf(hwid_buff, "USB\\VID_%hx&PID_%hx", (int16_t *)&fvid, (int16_t *)&fpid) != 2) {
211             continue;
212         }
213
214         dev_des[i][0] = ((fvid & 0xFF00)>>8);
215         dev_des[i][1] = ((fvid & 0x00FF) >> 0);
216         dev_des[i][2] = ((fpid & 0xFF00) >> 8);
217         dev_des[i][3] = ((fpid & 0x00FF) >> 0);
218         sprintf((char *)&dev_des[i][4], "%s", gen_addr(devInfo, &devInfoData, fpid));
219     }
220     SetupDiDestroyDeviceInfoList(devInfo);
221
222     qsort(dev_des, i, sizeof(dev_des[0]), compareDeviceByHubAndPort);
223
224     return i;
225 }
226
227 void * enumerate_usb_device(uint16_t vid, uint16_t pid, const char *addr, int loud) {
228         HDEVINFO devInfo;
229         SP_DEVICE_INTERFACE_DATA ifaceData;
230         int i;
231         SP_DEVINFO_DATA devInfoData;
232         char hwid_buff[128];
233         int found, found_ind = -1;
234         const char *caddr;
235
236         devInfoData.cbSize = sizeof(devInfoData);
237
238         devInfo = SetupDiGetClassDevs(&GUID_DEVINTERFACE_USB_DEVICE, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
239         if(devInfo == INVALID_HANDLE_VALUE) {
240                 wperror("SetupDiGetClassDevs");
241                 return USB_DEV_NONE;
242         }
243         found = 0;
244         for(i=0; SetupDiEnumDeviceInfo(devInfo, i, &devInfoData); i++) {
245                 if(!SetupDiGetDeviceRegistryProperty(devInfo, &devInfoData, SPDRP_HARDWAREID, NULL, hwid_buff, sizeof(hwid_buff), NULL))
246                         continue;
247                 uint16_t fvid, fpid;
248         if(sscanf(hwid_buff, "USB\\VID_%hx&PID_%hx", (int16_t*)&fvid, (int16_t*)&fpid) != 2)
249                         continue;
250                 if(verbose && loud)
251                         fprintf(msgfile, "Vendor/Product ID: %04x:%04x\n", fvid, fpid);
252                 if((fvid == vid) && (fpid == pid)) {
253                         caddr = gen_addr(devInfo, &devInfoData, fpid);
254                         if((addr == NULL) || !strcmp(caddr, addr)) {
255                                 if(verbose)
256                                         fprintf(msgfile, "Found device with VID/PID %04x:%04x , address %s\n", vid, pid, caddr);
257                                 if(!found) {
258                                         found_ind = i;
259                                         found = 1;
260                                 }
261                                 if(!(verbose && loud))
262                                         break;
263                         }
264                 }
265         }
266         if(!found) {
267                 SetupDiDestroyDeviceInfoList(devInfo);
268                 return USB_DEV_NONE;
269         }
270         if(verbose && loud) {
271                 if(!SetupDiEnumDeviceInfo(devInfo, found_ind, &devInfoData)) {
272                         wperror("SetupDiEnumDeviceInfo");
273                         SetupDiDestroyDeviceInfoList(devInfo);
274                         return USB_DEV_NONE;
275                 }
276         }
277         ifaceData.cbSize = sizeof(ifaceData);
278         if(!SetupDiEnumDeviceInterfaces(devInfo, &devInfoData, &GUID_DEVINTERFACE_USB_DEVICE, 0, &ifaceData)) {
279                 if(GetLastError() != ERROR_NO_MORE_ITEMS) {
280                         wperror("SetupDiEnumDeviceInterfaces");
281                 }
282                 SetupDiDestroyDeviceInfoList(devInfo);
283                 return USB_DEV_NONE;
284         }
285         return retreive_dev_path(devInfo, &ifaceData);
286 }
287
288 usb_dev findDeviceByGUID(GUID guid, int loud)
289 {
290         HDEVINFO devInfo;
291         SP_DEVICE_INTERFACE_DATA ifaceData;
292
293         devInfo = SetupDiGetClassDevs(&guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
294         if (devInfo == INVALID_HANDLE_VALUE) {
295                 wperror("SetupDiGetClassDevs");
296                 return USB_DEV_NONE;
297         }
298         ifaceData.cbSize = sizeof(ifaceData);
299         if (!SetupDiEnumDeviceInterfaces(devInfo, NULL, &guid, 0, &ifaceData)) {
300                 if (GetLastError() != ERROR_NO_MORE_ITEMS) {
301                         wperror("SetupDiEnumDeviceInterfaces");
302                 }
303                 SetupDiDestroyDeviceInfoList(devInfo);
304                 return USB_DEV_NONE;
305         }
306         return retreive_dev_path(devInfo, &ifaceData);
307 }
308
309 void * usb_find_device_by_guid(int loud) {
310         void *dev = USB_DEV_NONE;
311         //Try Myriad 2
312         dev = findDeviceByGUID(GUID_DEVINTERFACE_Myriad2, loud);
313         if (dev == USB_DEV_NONE)
314         {
315                 //Try Myriad X
316                 dev = findDeviceByGUID(GUID_DEVINTERFACE_MyriadX, loud);
317         }
318         return dev;
319 }
320
321 int usb_check_connected(usb_dev dev) {
322         HANDLE han;
323         if(dev == USB_DEV_NONE)
324                 return 0;
325         han = CreateFile(dev, 0, FILE_SHARE_WRITE | FILE_SHARE_READ,
326                 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
327         if(han == INVALID_HANDLE_VALUE)
328                 return 0;
329         CloseHandle(han);
330         return 1;
331 }
332
333 void * usb_open_device(usb_dev dev, uint8_t *ep, uint8_t intfaceno, char *err_string_buff) {
334         HANDLE devHan = INVALID_HANDLE_VALUE;
335         WINUSB_INTERFACE_HANDLE winUsbHan = INVALID_HANDLE_VALUE;
336         USB_INTERFACE_DESCRIPTOR ifaceDesc;
337         WINUSB_PIPE_INFORMATION pipeInfo;
338         usb_hwnd han = NULL;
339         int i;
340
341         if(dev == USB_DEV_NONE)
342                 return USB_HAN_NONE;
343
344         devHan = CreateFile(dev, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ,
345                 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
346         if(devHan == INVALID_HANDLE_VALUE) {
347                 if(err_string_buff != NULL)
348                         wstrerror(err_string_buff, "CreateFile");
349                 goto exit_err;
350         }
351
352         if(!WinUsb_Initialize(devHan, &winUsbHan)) {
353                 if (err_string_buff != NULL)
354                         wstrerror(err_string_buff, "WinUsb_Initialize");
355                 goto exit_err;
356         }
357
358         if(!WinUsb_QueryInterfaceSettings(winUsbHan, 0, &ifaceDesc)) {
359                 if (err_string_buff != NULL)
360                         wstrerror(err_string_buff, "WinUsb_QueryInterfaceSettings");
361                 goto exit_err;
362         }
363
364         han = calloc(1, sizeof(*han));
365         if(han == NULL) {
366                 strcpy(err_string_buff, _strerror("malloc"));
367                 goto exit_err;
368         }
369         han->devHan = devHan;
370         han->winUsbHan = winUsbHan;
371
372         for(i=0; i<ifaceDesc.bNumEndpoints; i++) {
373                 if(!WinUsb_QueryPipe(winUsbHan, 0, i, &pipeInfo)) {
374                         if (err_string_buff != NULL)
375                                 wstrerror(err_string_buff, "WinUsb_QueryPipe");
376                         if(!ignore_errors)
377                                 goto exit_err;
378                 }
379                 if(verbose) {
380                         fprintf(msgfile, "Found EP 0x%02x : max packet size is %u bytes\n",
381                                 pipeInfo.PipeId, pipeInfo.MaximumPacketSize);
382                 }
383                 if(pipeInfo.PipeType != UsbdPipeTypeBulk)
384                         continue;
385                 int ind = USB_ENDPOINT_DIRECTION_IN(pipeInfo.PipeId) ? USB_DIR_IN : USB_DIR_OUT;
386                 han->eps[ind].ep = pipeInfo.PipeId;
387                 han->eps[ind].sz = pipeInfo.MaximumPacketSize;
388                 han->eps[ind].last_timeout = 0;
389         }
390         if(ep)
391                 *ep = han->eps[USB_DIR_OUT].ep;
392
393         if(err_string_buff && (han->eps[USB_DIR_IN].ep == 0)) {
394                 sprintf(err_string_buff, "Unable to find BULK IN endpoint\n");
395                 goto exit_err;
396         }
397         if(err_string_buff && (han->eps[USB_DIR_OUT].ep == 0)) {
398                 sprintf(err_string_buff, "Unable to find BULK OUT endpoint\n");
399                 goto exit_err;
400         }
401         if(err_string_buff && (han->eps[USB_DIR_IN].sz == 0)) {
402                 sprintf(err_string_buff, "Unable to find BULK IN endpoint size\n");
403                 goto exit_err;
404         }
405         if(err_string_buff && (han->eps[USB_DIR_OUT].sz == 0)) {
406                 sprintf(err_string_buff, "Unable to find BULK OUT endpoint size\n");
407                 goto exit_err;
408         }
409         return han;
410 exit_err:
411         usb_close_device(han);
412         return USB_HAN_NONE;
413 }
414
415 uint8_t usb_get_bulk_endpoint(usb_hwnd han, int dir) {
416         if((han == NULL) || ((dir != USB_DIR_OUT) && (dir != USB_DIR_IN)))
417                 return 0;
418         return han->eps[dir].ep;
419 }
420
421 size_t usb_get_endpoint_size(usb_hwnd han, uint8_t ep) {
422         if(han == NULL)
423                 return 0;
424         if(han->eps[USB_DIR_OUT].ep == ep)
425                 return han->eps[USB_DIR_OUT].sz;
426         if(han->eps[USB_DIR_IN].ep == ep)
427                 return han->eps[USB_DIR_IN].sz;
428         return 0;
429 }
430
431 int usb_bulk_write(usb_hwnd han, uint8_t ep, const void *buffer, size_t sz, uint32_t *wrote_bytes, int timeout_ms) {
432         ULONG wb = 0;
433         if(wrote_bytes != NULL)
434                 *wrote_bytes = 0;
435         if(han == NULL)
436                 return USB_ERR_INVALID;
437
438         if(timeout_ms != han->eps[USB_DIR_OUT].last_timeout) {
439                 han->eps[USB_DIR_OUT].last_timeout = timeout_ms;
440                 if(!WinUsb_SetPipePolicy(han->winUsbHan, ep, PIPE_TRANSFER_TIMEOUT,
441                         sizeof(ULONG), &han->eps[USB_DIR_OUT].last_timeout)) {
442                         last_bulk_errcode = GetLastError();
443                         wperror("WinUsb_SetPipePolicy");
444                         return USB_ERR_FAILED;
445                 }
446         }
447         if(!WinUsb_WritePipe(han->winUsbHan, ep, (PUCHAR)buffer, (ULONG)sz, &wb, NULL)) {
448                 last_bulk_errcode = GetLastError();
449                 if(last_bulk_errcode == ERROR_SEM_TIMEOUT)
450                         return USB_ERR_TIMEOUT;
451                 wperror("WinUsb_WritePipe");
452                 printf("\nWinUsb_WritePipe failed with error:=%d\n", GetLastError());
453                 return USB_ERR_FAILED;
454         }
455         last_bulk_errcode = 0;
456         if(wrote_bytes != NULL)
457                 *wrote_bytes = wb;
458         return USB_ERR_NONE;
459 }
460
461 int usb_bulk_read(usb_hwnd han, uint8_t ep, void *buffer, size_t sz, uint32_t *read_bytes, int timeout_ms) {
462         ULONG rb = 0;
463         if(read_bytes != NULL)
464                 *read_bytes = 0;
465         if(han == NULL)
466                 return USB_ERR_INVALID;
467
468         if(timeout_ms != han->eps[USB_DIR_IN].last_timeout) {
469                 han->eps[USB_DIR_IN].last_timeout = timeout_ms;
470                 if(!WinUsb_SetPipePolicy(han->winUsbHan, ep, PIPE_TRANSFER_TIMEOUT,
471                         sizeof(ULONG), &han->eps[USB_DIR_IN].last_timeout)) {
472                         last_bulk_errcode = GetLastError();
473                         wperror("WinUsb_SetPipePolicy");
474                         return USB_ERR_FAILED;
475                 }
476         }
477         if(sz == 0)
478                 return USB_ERR_NONE;
479         if(!WinUsb_ReadPipe(han->winUsbHan, ep, buffer, (ULONG)sz, &rb, NULL)) {
480                 last_bulk_errcode = GetLastError();
481                 if(last_bulk_errcode == ERROR_SEM_TIMEOUT)
482                         return USB_ERR_TIMEOUT;
483                 wperror("WinUsb_ReadPipe");
484                 return USB_ERR_FAILED;
485         }
486         last_bulk_errcode = 0;
487         if(read_bytes != NULL)
488                 *read_bytes = rb;
489         return USB_ERR_NONE;
490 }
491
492 void usb_free_device(usb_dev dev) {
493         if(dev != NULL)
494                 free(dev);
495 }
496
497 void usb_close_device(usb_hwnd han) {
498         if(han == NULL)
499                 return;
500         WinUsb_Free(han->winUsbHan);
501         CloseHandle(han->devHan);
502         free(han);
503 }
504
505 const char *usb_last_bulk_errmsg(void) {
506         return format_win32_msg(last_bulk_errcode);
507 }
508
509 void usb_set_msgfile(FILE *file) {
510         msgfile = file;
511 }
512
513 void usb_set_verbose(int value) {
514         verbose = value;
515 }
516
517 void usb_set_ignoreerrors(int value) {
518         ignore_errors = value;
519 }