ypkt_win.c
Go to the documentation of this file.
1 /*********************************************************************
2  *
3  * $Id: ypkt_win.c 29389 2017-12-07 08:57:39Z seb $
4  *
5  * OS-specific USB packet layer, Windows version
6  *
7  * - - - - - - - - - License information: - - - - - - - - -
8  *
9  * Copyright (C) 2011 and beyond by Yoctopuce Sarl, Switzerland.
10  *
11  * Yoctopuce Sarl (hereafter Licensor) grants to you a perpetual
12  * non-exclusive license to use, modify, copy and integrate this
13  * file into your software for the sole purpose of interfacing
14  * with Yoctopuce products.
15  *
16  * You may reproduce and distribute copies of this file in
17  * source or object form, as long as the sole purpose of this
18  * code is to interface with Yoctopuce products. You must retain
19  * this notice in the distributed source file.
20  *
21  * You should refer to Yoctopuce General Terms and Conditions
22  * for additional information regarding your rights and
23  * obligations.
24  *
25  * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
26  * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
27  * WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS
28  * FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO
29  * EVENT SHALL LICENSOR BE LIABLE FOR ANY INCIDENTAL, SPECIAL,
30  * INDIRECT OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA,
31  * COST OF PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR
32  * SERVICES, ANY CLAIMS BY THIRD PARTIES (INCLUDING BUT NOT
33  * LIMITED TO ANY DEFENSE THEREOF), ANY CLAIMS FOR INDEMNITY OR
34  * CONTRIBUTION, OR OTHER SIMILAR COSTS, WHETHER ASSERTED ON THE
35  * BASIS OF CONTRACT, TORT (INCLUDING NEGLIGENCE), BREACH OF
36  * WARRANTY, OR OTHERWISE.
37  *
38  *********************************************************************/
39 
40 #define __FILE_ID__ "ypkt_win"
41 #include "yapi.h"
42 #if defined(WINDOWS_API) && !defined(WINCE)
43 #include "yproto.h"
44 #include <TlHelp32.h>
45 #ifdef LOG_DEVICE_PATH
46 #define DP(PATH) (PATH)
47 #else
48 #define DP(PATH) "..."
49 #endif
50 
51 #ifndef _MSC_VER
52 #define SPDRP_INSTALL_STATE (0x00000022)
53 #define _TRUNCATE ((size_t)-1)
54 #endif
55 
56 #define yWinSetErr(iface,errmsg) yWinSetErrEx(__LINE__,iface,GetLastError(),"",errmsg)
57 
58 static int yWinSetErrEx(u32 line, yInterfaceSt *iface, DWORD err, const char *msg, char *errmsg)
59 {
60  int len;
61  if (errmsg == NULL)
62  return YAPI_IO_ERROR;
63  if (iface) {
64  YSPRINTF(errmsg, YOCTO_ERRMSG_LEN, "%s:%d(%s:%d): %s(%d)", iface->serial, iface->ifaceno, __FILE_ID__, line, msg, (u32)err);
65  } else {
66  YSPRINTF(errmsg, YOCTO_ERRMSG_LEN, "%s:%d: %s(%d)", __FILE_ID__, line, msg, (u32)err);
67  }
68  len = YSTRLEN(errmsg);
69  FormatMessageA(
70  FORMAT_MESSAGE_FROM_SYSTEM |
71  FORMAT_MESSAGE_IGNORE_INSERTS,
72  NULL,
73  err,
74  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
75  (LPSTR)(errmsg + len),
76  YOCTO_ERRMSG_LEN - len, NULL);
77 
78  return YAPI_IO_ERROR;
79 }
80 
81 
82 #if 0
83 static void yWinPushEx(u32 line, yInterfaceSt *iface, pktQueue *q, DWORD err)
84 {
85  int len;
86  char errmsg[YOCTO_ERRMSG_LEN];
87 
88  YSPRINTF(errmsg, YOCTO_ERRMSG_LEN, "%s:%d(%s:%d): (%d)", iface->serial, iface->ifaceno, __FILE_ID__, line, (u32)err);
89  len = YSTRLEN(errmsg);
90  FormatMessageA(
91  FORMAT_MESSAGE_FROM_SYSTEM |
92  FORMAT_MESSAGE_IGNORE_INSERTS,
93  NULL,
94  err,
95  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
96  (LPSTR)(errmsg + len),
97  YOCTO_ERRMSG_LEN - len, NULL);
98  yPktQueueSetError(q, YAPI_IO_ERROR, errmsg);
99 }
100 
101 #endif
102 
103 
104 static u32 decodeHex(const char *p, int nbdigit)
105 {
106  u32 ret = 0;
107  int i;
108  for (i = nbdigit - 1; i >= 0; i--, p++) {
109  u32 digit;
110  if (*p >= 'a' && *p <= 'f') {
111  digit = 10 + *p - 'a';
112  } else if (*p >= 'A' && *p <= 'F') {
113  digit = 10 + *p - 'A';
114  } else if (*p >= '0' && *p <= '9') {
115  digit = *p - '0';
116  } else {
117  return 0;
118  }
119  ret += digit << (4 * i);
120  }
121  return ret;
122 }
123 
124 
125 
126 #define FIRST_OF 1
127 #define FIRST_NOT_OF 2
128 
129 static char* findDelim(char *str, const char *delimiters, const int nbdelim, const int mode)
130 {
131  int d;
132 
133  while (*str) {
134  for (d = 0; d < nbdelim; d++) {
135  if (*str == delimiters[d]) {
136  break;
137  }
138  }
139  if (mode == FIRST_OF) {
140  if (d < nbdelim) {
141  return str;
142  }
143  } else {
144  if (d == nbdelim) {
145  return str;
146  }
147  }
148  str++;
149  }
150  return str;
151 }
152 
153 
154 void DecodeHardwareid(char *str, u32 *vendorid, u32 *deviceid, u32 *release, u32 *iface)
155 {
156  const char *delim = "\\&?";
157  char *token_start, *token_stop;
158  token_start = findDelim(str, delim, 4, FIRST_NOT_OF);
159  token_stop = findDelim(token_start, delim, 4, FIRST_OF);
160  *vendorid = *deviceid = *release = *iface = 0;
161  while (token_start != token_stop) {
162  if (YSTRNICMP(token_start, "VID_", 4) == 0) {
163  *vendorid = decodeHex(token_start + 4, 4);
164  } else if (YSTRNICMP(token_start, "PID_", 4) == 0) {
165  *deviceid = decodeHex(token_start + 4, 4);
166  } else if (YSTRNICMP(token_start, "REV_", 4) == 0) {
167  *release = decodeHex(token_start + 4, 4);
168  } else if (YSTRNICMP(token_start, "MI_", 3) == 0) {
169  *iface = decodeHex(token_start + 3, 2);
170  }
171  token_start = findDelim(token_stop, delim, 2, FIRST_NOT_OF);
172  token_stop = findDelim(token_start, delim, 2, FIRST_OF);
173  }
174 }
175 
176 
177 
178 static int getProcName(char *buffer, int buffer_size)
179 {
180  HANDLE hProcessSnap;
181  PROCESSENTRY32 pe32;
182  DWORD pid = GetCurrentProcessId();
183  *buffer = 0;
184 
185  // Take a snapshot of all processes in the system.
186  hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
187  if (hProcessSnap == INVALID_HANDLE_VALUE) {
188  dbglog("CreateToolhelp32Snapshot (of processes)\n");
189  return pid;
190  }
191 
192  // Set the size of the structure before using it.
193  pe32.dwSize = sizeof(PROCESSENTRY32);
194 
195  // Retrieve information about the first process,
196  // and exit if unsuccessful
197  if (!Process32First(hProcessSnap, &pe32)) {
198  dbglog("Process32First error\n"); // show cause of failure
199  CloseHandle(hProcessSnap); // clean the snapshot object
200  return pid;
201  }
202 
203  // Now walk the snapshot of processes, and
204  // display information about each process in turn
205  do {
206  if (pid == pe32.th32ProcessID) {
207 #ifndef UNICODE
208  YSTRCPY(buffer, buffer_size, pe32.szExeFile);
209 #else
210 #if defined(_MSC_VER) && (_MSC_VER > MSC_VS2003)
211  {
212  size_t len;
213  wcstombs_s(&len, buffer, buffer_size, (wchar_t*)pe32.szExeFile, _TRUNCATE);
214  }
215 #else
216  wcstombs(buffer, (wchar_t*)pe32.szExeFile, buffer_size);
217 #endif
218 #endif
219 
220  break;
221  }
222  } while (Process32Next(hProcessSnap, &pe32));
223  buffer[buffer_size - 1] = 0;
224  CloseHandle(hProcessSnap);
225  return pid;
226 }
227 
228 
229 
230 #define LEGACY_YOCTOPUCE_KEY "Software\\Yoctopuce\\"
231 #define USB_LOCK_KEY "Software\\Yoctopuce\\usb_lock\\"
232 #ifndef KEY_WOW64_32KEY
233 // dirty hack to work with mingw32
234 #define KEY_WOW64_32KEY 0
235 #endif
236 
237 static int yConvertUSBLockKey(yContextSt *ctx, int deletekey)
238 {
239  HKEY key;
240  LONG res;
241  res = ctx->registry.yRegOpenKeyEx(HKEY_LOCAL_MACHINE, LEGACY_YOCTOPUCE_KEY, 0, KEY_WRITE | KEY_READ | KEY_WOW64_32KEY, &key);
242  if (res == ERROR_SUCCESS) {
243  //save information
244  char process_name[512];
245  char buffer[32];
246  DWORD value_length = 32;
247  res = ctx->registry.yRegQueryValueEx(key, "process_id", NULL, NULL, (LPBYTE)buffer, &value_length);
248  if (res != ERROR_SUCCESS) {
249  return -1;
250  }
251  value_length = 512;
252  res = ctx->registry.yRegQueryValueEx(key, "process_name", NULL, NULL, (LPBYTE)process_name, &value_length);
253  if (res != ERROR_SUCCESS) {
254  return -1;
255  }
256  if (deletekey) {
257  // delete key
258  ctx->registry.yRegCloseKey(key);
259  res = ctx->registry.yRegDeleteKeyEx(HKEY_LOCAL_MACHINE, LEGACY_YOCTOPUCE_KEY, KEY_WOW64_32KEY, 0);
260  } else {
261  ctx->registry.yRegDeleteValue(key, "process_id");
262  ctx->registry.yRegDeleteValue(key, "process_name");
263  ctx->registry.yRegCloseKey(key);
264  }
265  // create new one
266  res = ctx->registry.yRegCreateKeyEx(HKEY_LOCAL_MACHINE, USB_LOCK_KEY, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE | KEY_READ | KEY_WOW64_32KEY, NULL, &key, NULL);
267  // save value in new key
268  if (ctx->registry.yRegSetValueEx(key, "process_id", 0, REG_SZ, (BYTE*)buffer, YSTRLEN(buffer)) != ERROR_SUCCESS) {
269  dbglog("Unable to set registry value yapi_process");
270  }
271  if (ctx->registry.yRegSetValueEx(key, "process_name", 0, REG_SZ, (BYTE*)process_name, YSTRLEN(process_name)) != ERROR_SUCCESS) {
272  dbglog("Unable to set registry value yapi_process");
273  }
274  ctx->registry.yRegCloseKey(key);
275  return 1;
276  } else {
277  return -1;
278  }
279 }
280 
281 // return 1 if we can reserve access to the device 0 if the device
282 // is already reserved
283 static int yReserveGlobalAccess(yContextSt *ctx, char * errmsg)
284 {
285  int has_reg_key = 1;
286  char process_name[512];
287  char buffer[32];
288  DWORD value_length = 512;
289  int retval;
290  s64 pid;
291  HKEY key = NULL;
292  LONG res;
293 
294  if (ctx->registry.hREG != NULL) {
295  res = ctx->registry.yRegCreateKeyEx(HKEY_LOCAL_MACHINE, USB_LOCK_KEY, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE | KEY_READ | KEY_WOW64_32KEY, NULL, &key, NULL);
296  if (res == ERROR_CHILD_MUST_BE_VOLATILE) {
297  yConvertUSBLockKey(ctx, 1);
298  res = ctx->registry.yRegCreateKeyEx(HKEY_LOCAL_MACHINE, USB_LOCK_KEY, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE | KEY_READ | KEY_WOW64_32KEY, NULL, &key, NULL);
299  if (res != ERROR_SUCCESS) {
300  has_reg_key = 0;
301  }
302  } else if (res == ERROR_SUCCESS) {
303  yConvertUSBLockKey(ctx, 0);
304  } else {
305  has_reg_key = 0;
306  }
307  } else {
308  has_reg_key = 0;
309  }
310 
311  ctx->apiLock = CreateMailslotA("\\\\.\\mailslot\\yoctopuce_yapi", 8, 0, NULL);
312  ctx->nameLock = CreateMailslotA("\\\\.\\mailslot\\yoctopuce_yapi_name", 8, 0, NULL);
313  if (ctx->apiLock == INVALID_HANDLE_VALUE) {
314  // unable to create lock -> another instance is already using the device
315  retval = YAPI_DOUBLE_ACCES;
316  YERRMSG(YAPI_DOUBLE_ACCES, "Another process is already using yAPI");
317  if (has_reg_key && ctx->nameLock == INVALID_HANDLE_VALUE) {
318  pid = -1;
319  res = ctx->registry.yRegQueryValueEx(key, "process_id", NULL, NULL, (LPBYTE)buffer, &value_length);
320  if (res == ERROR_SUCCESS) {
321  pid = atoi(buffer);
322  }
323  value_length = 512;
324  res = ctx->registry.yRegQueryValueEx(key, "process_name", NULL, NULL, (LPBYTE)process_name, &value_length);
325  if (res == ERROR_SUCCESS && pid >= 0) {
326  char current_name[512];
327  getProcName(current_name, 512);
328  if (YSTRCMP(process_name, current_name)) {
329  YSPRINTF(errmsg, YOCTO_ERRMSG_LEN, "Another process named %s (pid %"FMTs64") is already using yAPI", process_name, pid);
330  } else {
331  YSPRINTF(errmsg, YOCTO_ERRMSG_LEN, "Another %s (pid %"FMTs64") is already using yAPI", process_name, pid);
332  }
333  }
334  }
335  } else {
336  retval = YAPI_SUCCESS;
337  if (has_reg_key) {
338  int pid = getProcName(process_name, 512);
339  YSPRINTF(buffer, 32, "%d", pid);
340  if (ctx->registry.yRegSetValueEx(key, "process_id", 0, REG_SZ, (BYTE*)buffer, YSTRLEN(buffer)) != ERROR_SUCCESS) {
341  dbglog("Unable to set registry value yapi_process");
342  }
343  if (ctx->registry.yRegSetValueEx(key, "process_name", 0, REG_SZ, (BYTE*)process_name, YSTRLEN(process_name)) != ERROR_SUCCESS) {
344  dbglog("Unable to set registry value yapi_process");
345  }
346  }
347  }
348  if (has_reg_key) {
349  ctx->registry.yRegCloseKey(key);
350  }
351 
352  return retval;
353 }
354 
355 static void yReleaseGlobalAccess(yContextSt *ctx)
356 {
357  CloseHandle(ctx->apiLock);
358  ctx->apiLock = INVALID_HANDLE_VALUE;
359  CloseHandle(ctx->nameLock);
360  ctx->nameLock = INVALID_HANDLE_VALUE;
361 }
362 
363 
364 
365 int yyyUSB_init(yContextSt *ctx, char *errmsg)
366 {
367  ctx->registry.hREG = LoadLibraryA("Advapi32.dll");
368  if (ctx->registry.hREG != NULL) {
369  //Update the pointers:
370  ctx->registry.yRegCreateKeyEx = (PYRegCreateKeyEx)GetProcAddress(ctx->registry.hREG, "RegCreateKeyExA");
371  ctx->registry.yRegOpenKeyEx = (PYRegOpenKeyEx)GetProcAddress(ctx->registry.hREG, "RegOpenKeyExA");
372  ctx->registry.yRegSetValueEx = (PYRegSetValueEx)GetProcAddress(ctx->registry.hREG, "RegSetValueExA");
373  ctx->registry.yRegQueryValueEx = (PYRegQueryValueEx)GetProcAddress(ctx->registry.hREG, "RegQueryValueExA");
374  ctx->registry.yRegDeleteValue = (PYRegDeleteValue)GetProcAddress(ctx->registry.hREG, "RegDeleteValueA");
375  ctx->registry.yRegCloseKey = (PYRegCloseKey)GetProcAddress(ctx->registry.hREG, "RegCloseKey");
376  ctx->registry.yRegDeleteKeyEx = (PYRegDeleteKeyEx)GetProcAddress(ctx->registry.hREG, "RegDeleteKeyExA");
377  }
378 
379 
380  YPROPERR(yReserveGlobalAccess(ctx, errmsg));
381  ctx->hid.hHID = LoadLibraryA("HID.DLL");
382  if (ctx->hid.hHID == NULL) {
383  return yWinSetErr(NULL, errmsg);
384  }
385  //Update the pointers:
386  ctx->hid.GetHidGuid = (PHidD_GetHidGuid)GetProcAddress(ctx->hid.hHID, "HidD_GetHidGuid");
387  ctx->hid.GetAttributes = (PHidD_GetAttributes)GetProcAddress(ctx->hid.hHID, "HidD_GetAttributes");
388  ctx->hid.GetManufacturerString = (PHidD_GetManufacturerString)GetProcAddress(ctx->hid.hHID, "HidD_GetManufacturerString");
389  ctx->hid.GetProductString = (PHidD_GetProductString)GetProcAddress(ctx->hid.hHID, "HidD_GetProductString");
390  ctx->hid.GetSerialNumberString = (PHidD_GetSerialNumberString)GetProcAddress(ctx->hid.hHID, "HidD_GetSerialNumberString");
391  ctx->hid.SetNumInputBuffers = (PHidD_SetNumInputBuffers)GetProcAddress(ctx->hid.hHID, "HidD_SetNumInputBuffers");
392  yInitializeCriticalSection(&ctx->prevEnum_cs);
393 
394  return YAPI_SUCCESS;
395 }
396 
397 
398 int yyyUSB_stop(yContextSt *ctx, char *errmsg)
399 {
400  yDeleteCriticalSection(&ctx->prevEnum_cs);
401  if (ctx->prevEnum) {
402  yFree(ctx->prevEnum);
403  ctx->prevEnum = NULL;
404  }
405  ctx->prevEnumCnt = 0;
406  yReleaseGlobalAccess(ctx);
407  return YAPI_SUCCESS;
408 }
409 /*****************************************************************
410 * yPacket API without cycling logic
411 *****************************************************************/
412 
413 
414 // no check on reentrance or initializations since we are only called
415 // by the yUpdateDeviceList witch take care of all this stuff
416 // the caller is responsible of freeing the ifaces buffer (if not set to NULL)
417 int yyyUSBGetInterfaces(yInterfaceSt **ifaces, int *nbifaceDetect, char *errmsg)
418 {
419  PSP_DEVICE_INTERFACE_DETAIL_DATA_A pDetailedInterfaceData;
420  int index = 0;
421  GUID InterfaceClassGuid;
422  DWORD needsize;
423  HDEVINFO DeviceInfoTable = INVALID_HANDLE_VALUE;
424  int nbifaceAlloc;
425  char buffer[WIN_DEVICE_PATH_LEN];//buffer forp DetailedInterfaceData
426 
427  *ifaces = NULL;
428  //setup some windows stuff
429  yContext->hid.GetHidGuid(&InterfaceClassGuid);
430  DeviceInfoTable = SetupDiGetClassDevs(&InterfaceClassGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
431  if (DeviceInfoTable == INVALID_HANDLE_VALUE) {
432  return yWinSetErr(NULL, errmsg);
433  }
434  yEnterCriticalSection(&yContext->prevEnum_cs);
435  pDetailedInterfaceData = (PSP_DEVICE_INTERFACE_DETAIL_DATA_A)buffer;
436  // allocate buffer for detected interfaces
437  *nbifaceDetect = 0;
438  nbifaceAlloc = yContext->prevEnumCnt + 8;
439  *ifaces = (yInterfaceSt*)yMalloc(nbifaceAlloc * sizeof(yInterfaceSt));
440  memset(*ifaces, 0, nbifaceAlloc * sizeof(yInterfaceSt));
441 
442  //Now look through the list we just populated. We are trying to see if any of them match our device.
443  for (;; index++) {
444  u32 vendorid, deviceid, release, ifaceno, inst_state;
445  SP_DEVINFO_DATA DevInfoData;
446 
447  DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
448  if (!SetupDiEnumDeviceInfo(DeviceInfoTable, index, &DevInfoData)) {
449  //no more device
450  break;
451  }
452  // get device hardwareid string
453  SetupDiGetDeviceRegistryPropertyA(DeviceInfoTable, &DevInfoData, SPDRP_HARDWAREID, NULL, (PBYTE)buffer, 512, NULL);
454  // skip 4 first char ("HID/")
455  DecodeHardwareid(buffer + 4, &vendorid, &deviceid, &release, &ifaceno);
456  // get installation status see:http://msdn.microsoft.com/en-us/library/ff543130
457  SetupDiGetDeviceRegistryProperty(DeviceInfoTable, &DevInfoData, SPDRP_INSTALL_STATE, NULL, (PBYTE)&inst_state, sizeof(inst_state), &needsize);
458  if (vendorid == YOCTO_VENDORID && inst_state == 0) {
459  SP_DEVICE_INTERFACE_DATA InterfaceData;
460  yInterfaceSt *iface;
461  int find, retry = 16;
462 
463  //ensure the buffer of detected interface is big enought
464  if (*nbifaceDetect == nbifaceAlloc) {
465  yInterfaceSt *tmp;
466  u32 newsize = nbifaceAlloc * 2 * sizeof(yInterfaceSt);
467  tmp = (yInterfaceSt*)yMalloc(newsize);
468  memset(tmp, 0, newsize);
469  yMemcpy(tmp, *ifaces, nbifaceAlloc * sizeof(yInterfaceSt));
470  yFree(*ifaces);
471  *ifaces = tmp;
472  nbifaceAlloc *= 2;
473  }
474  iface = *ifaces + *nbifaceDetect;
475  iface->vendorid = (u16)vendorid;
476  iface->deviceid = (u16)deviceid;
477  iface->ifaceno = (u16)ifaceno;
478 
479  InterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
480  if (!SetupDiEnumDeviceInterfaces(DeviceInfoTable, &DevInfoData, &InterfaceClassGuid, 0, &InterfaceData)) {
481  dbglog("Fail to retrieve DeviceInterfaces");
482  continue;
483  }
484  SetupDiGetDeviceInterfaceDetailA(DeviceInfoTable, &InterfaceData, NULL, 0, &needsize, NULL);
485  if (WIN_DEVICE_PATH_LEN < needsize) {
486  dbglog("buffer too small");
487  continue;
488  }
489  pDetailedInterfaceData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A);
490  SetupDiGetDeviceInterfaceDetailA(DeviceInfoTable, &InterfaceData, pDetailedInterfaceData, needsize, NULL, NULL);
491  YSTRNCPY(iface->devicePath, WIN_DEVICE_PATH_LEN, pDetailedInterfaceData->DevicePath, WIN_DEVICE_PATH_LEN);
492  for (find = 0; find < yContext->prevEnumCnt; find++) {
493  if (YSTRCMP(iface->devicePath, yContext->prevEnum[find].devicePath) == 0) break;
494  }
495  if (find < yContext->prevEnumCnt) {
496  yMemcpy(iface->serial, yContext->prevEnum[find].serial, YOCTO_SERIAL_LEN * 2);
497  } else {
498  HANDLE control;
499  HALLOG("Get serial for %s\n", pDetailedInterfaceData->DevicePath);
500  control = CreateFileA(pDetailedInterfaceData->DevicePath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
501  if (control == INVALID_HANDLE_VALUE) {
502  dbglog("Unable to open device %s to get serial\n", pDetailedInterfaceData->DevicePath);
503  continue;
504  }
505  while (!yContext->hid.GetSerialNumberString(control, buffer, WIN_DEVICE_PATH_LEN) && --retry >= 0) {
506  dbglog("Unable to get serial for %s (%d), retrying (%d)\n", pDetailedInterfaceData->DevicePath, GetLastError(), retry);
507  Sleep(17);
508  }
509  if (retry < 0) {
510  dbglog("Unable to get serial for %s (%d), giving up\n", pDetailedInterfaceData->DevicePath, GetLastError());
511  CloseHandle(control);
512  continue;
513  }
514 #if defined(_MSC_VER) && (_MSC_VER > MSC_VS2003)
515  {
516  size_t len;
517  wcstombs_s(&len, iface->serial, YOCTO_SERIAL_LEN * 2, (wchar_t*)buffer, _TRUNCATE);
518  }
519 #else
520  wcstombs(iface->serial, (wchar_t*)buffer, YOCTO_SERIAL_LEN * 2);
521 #endif
522  CloseHandle(control);
523  }
524  (*nbifaceDetect)++;
525  if (deviceid > YOCTO_DEVID_BOOTLOADER) {
526  HALENUMLOG("----Running Dev %x:%x:%d:%s ---\n", vendorid, deviceid, ifaceno, iface->serial);
527 #ifdef LOG_DEVICE_PATH
528  HALENUMLOG("----DevicePath %s ---\n", iface->devicePath);
529 #endif
530  } else {
531  HALENUMLOG("----Running Firm %x:%x:%d:%s ---\n", vendorid, deviceid, ifaceno, iface->serial);
532  }
533  } else {
534  //HALLOG("Drop device vendorid=%x inst_state=%x\n", vendorid, inst_state);
535  }
536  }
537  // unallocate Device infos
538  if (!SetupDiDestroyDeviceInfoList(DeviceInfoTable)) {
539  HALLOG("Unable to unallocated Device Info Table (%d)", GetLastError());
540  }
541  // save enumeration result to prevent later USB packets to redetect serial
542  if (yContext->prevEnum) yFree(yContext->prevEnum);
543  yContext->prevEnumCnt = *nbifaceDetect;
544  if (*nbifaceDetect > 0) {
545  yContext->prevEnum = (yInterfaceSt*)yMalloc(*nbifaceDetect * sizeof(yInterfaceSt));
546  yMemcpy(yContext->prevEnum, *ifaces, *nbifaceDetect * sizeof(yInterfaceSt));
547  } else {
548  yContext->prevEnum = NULL;
549  }
550  yLeaveCriticalSection(&yContext->prevEnum_cs);
551 
552  return YAPI_SUCCESS;
553 }
554 
555 
556 // return 1 if OS hdl are identicals
557 // 0 if any of the interface has changed
558 int yyyOShdlCompare(yPrivDeviceSt *dev, yInterfaceSt *newiface)
559 {
560  if (dev->infos.nbinbterfaces != 1) {
561  HALLOG("bad number of inteface for %s (%d)\n", dev->infos.serial, dev->infos.nbinbterfaces);
562  return 0;
563  }
564  if (YSTRCMP(dev->iface.devicePath, newiface->devicePath) != 0) {
565  HALLOG("devref has changed for %s (%s)\n", dev->infos.serial, DP(dev->iface.devicePath));
566  return 0;
567  }
568  return 1;
569 }
570 
571 
572 
573 /*****************************************************************
574 * Window implementation of yyypacket functions
575 *****************************************************************/
576 
577 
578 
579 
580 
581 static int OpenWriteHandles(yInterfaceSt *iface)
582 {
583  int res;
584  iface->wrHDL = INVALID_HANDLE_VALUE;
585  //open blocking write handle
586  iface->wrHDL = CreateFileA(iface->devicePath, GENERIC_WRITE | GENERIC_READ,
587  FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
588  if (iface->wrHDL == INVALID_HANDLE_VALUE) {
589  char errmsg[YOCTO_ERRMSG_LEN];
590  res = yWinSetErr(iface, errmsg);
591  HALLOG("OpenWriteHandles error of %s:%d (%s)\n", iface->serial, iface->ifaceno, errmsg);
592  return res;
593  }
594  return YAPI_SUCCESS;
595 }
596 
597 
598 static void CloseWriteHandles(yInterfaceSt *iface)
599 {
600  if (iface->wrHDL != INVALID_HANDLE_VALUE) {
601  CloseHandle(iface->wrHDL);
602  iface->wrHDL = INVALID_HANDLE_VALUE;
603  }
604 }
605 
606 
607 
608 static int OpenReadHandles(yInterfaceSt *iface)
609 {
610  char errmsg[YOCTO_ERRMSG_LEN];
611  int res;
612  BOOLEAN setbuffres;
613  //open non blocking read handle
614  iface->rdHDL = CreateFileA(iface->devicePath, GENERIC_WRITE | GENERIC_READ,
615  FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
616  if (iface->rdHDL == INVALID_HANDLE_VALUE) {
617  res = yWinSetErr(iface, errmsg);
618  HALLOG("OpenReadHandles of %s error %d of %s:%d (%s)\n", DP(iface->devicePath), res, iface->serial, iface->ifaceno, errmsg);
619  return res;
620  }
621  // since Win Xp HID buffer sizw is 32 by default and can be up to 512
622  setbuffres = yContext->hid.SetNumInputBuffers(iface->rdHDL, 256);
623  if (!setbuffres) {
624  res = yWinSetErr(iface, errmsg);
625  dbglog("SetNumInputBuffers of %s error %d of %s:%d (%s)\n", DP(iface->devicePath), res, iface->serial, iface->ifaceno, errmsg);
626  }
627  // create Event for non blocking read
628  iface->EV[YWIN_EVENT_READ] = CreateEvent(NULL, TRUE, TRUE, NULL);
629  if (iface->EV[YWIN_EVENT_READ] == NULL) {
630  res = yWinSetErr(iface, errmsg);
631  HALLOG("OpenReadHandles error %d of %s:%d (%s)\n", res, iface->serial, iface->ifaceno, errmsg);
632  return res;
633  }
634  return YAPI_SUCCESS;
635 }
636 
637 
638 static void CloseReadHandles(yInterfaceSt *iface)
639 {
640  DWORD readed;
641 
642  if (iface->rdpending && iface->rdHDL != INVALID_HANDLE_VALUE) {
643  if (CancelIo(iface->rdHDL) == 0) {
644  HALLOG("CancelIo failed with %d\n", GetLastError());
645  } else {
646  if (GetOverlappedResult(iface->rdHDL, &iface->rdOL, &readed, TRUE)) {
647  //finished
648  if (readed != sizeof(OS_USB_Packet)) {
649  HALLOG("invalid packet size read %d %d\n", iface->ifaceno, readed);
650  } else {
651  yPktQueuePushD2H(iface, &iface->tmpd2hpkt.pkt, NULL);
652  }
654  } else {
655  u32 error = GetLastError();
656  if (error != ERROR_OPERATION_ABORTED) {
657  HALLOG("Error when stoping read IO on %s:%d\n", iface->serial, iface->ifaceno);
658  }
659  }
660  }
661  }
662  if (iface->EV[YWIN_EVENT_READ] != NULL) {
663  CloseHandle(iface->EV[YWIN_EVENT_READ]);
664  iface->EV[YWIN_EVENT_READ] = NULL;
665  }
666  if (iface->rdHDL != INVALID_HANDLE_VALUE) {
667  CloseHandle(iface->rdHDL);
668  iface->rdHDL = INVALID_HANDLE_VALUE;
669  }
670  iface->rdpending = 0;
671 }
672 
673 
674 static int StartReadIO(yInterfaceSt *iface, char *errmsg)
675 {
676  DWORD readed;
677  u32 retrycount = 0;
678 retry:
679  YASSERT(iface->rdpending == 0);
680  memset(&iface->rdOL, 0, sizeof(iface->rdOL));
681  //check if we need that : if(!SetEvent(iface->rdEV)) return yWinSetErr(errmsg);
682  iface->rdOL.hEvent = iface->EV[YWIN_EVENT_READ];
683  if (!ReadFile(iface->rdHDL, &iface->tmpd2hpkt, sizeof(OS_USB_Packet), &readed, &iface->rdOL)) {
684  u32 error = GetLastError();
685  if (error != ERROR_IO_PENDING) {
686  return yWinSetErrEx(__LINE__, iface, error, "", errmsg);
687  }
688  iface->rdpending = 1;
689  } else {
690  yPktQueuePushD2H(iface, &iface->tmpd2hpkt.pkt, NULL);
692  // TODO: add some kind of timeout to be able to send reset packet
693  // if device become crazy
694  retrycount++;
695  goto retry;
696  }
697  return YAPI_SUCCESS;
698 }
699 
700 
701 
702 
703 
704 //Look if we have new packet arrived
705 static int yyyyRead(yInterfaceSt *iface, char *errmsg)
706 {
707  DWORD readed;
708  int res;
709  int retrycount = 1;
710 retry:
711  if (iface->rdpending == 0) {
712  // no IO started -> start a new one
713  res = StartReadIO(iface, errmsg);
714  if (YISERR(res)) {
715  if (retrycount--) {
716  CloseReadHandles(iface);
717  if (YISERR(OpenReadHandles(iface))) {
718  HALLOG("Open handles restared failed %s:%d\n", iface->serial, iface->ifaceno);
719  return res;
720  }
721  //seep a bit to let the OS restart thing correctly
723  goto retry;
724  }
725  HALLOG("Read IO error %s:%d (%s/%s)\n", iface->serial, iface->ifaceno, errmsg, DP(iface->devicePath));
726  return res;
727  }
728  }
729  if (GetOverlappedResult(iface->rdHDL, &iface->rdOL, &readed, 0)) {
730  iface->rdpending = 0;
731  if (readed != sizeof(OS_USB_Packet)) {
732  HALLOG("drop invalid packet on %s:%d (invalid size %d)\n", iface->serial, iface->ifaceno, readed);
733  } else {
734  yPktQueuePushD2H(iface, &iface->tmpd2hpkt.pkt, NULL);
736  }
737  res = StartReadIO(iface, errmsg);
738  if (YISERR(res)) {
739  if (retrycount--) {
740  CloseReadHandles(iface);
741  if (YISERR(OpenReadHandles(iface))) {
742  HALLOG("Open handles restared failed %s:%d\n", iface->serial, iface->ifaceno);
743  return res;
744  }
745  //seep a bit to let the OS restart thing correctly
747  goto retry;
748  }
749  HALLOG("Read IO error %s:%d (%s/%s)\n", iface->serial, iface->ifaceno, errmsg, DP(iface->devicePath));
750  return res;
751  }
752  } else {
753  u32 error = GetLastError();
754  if (error != ERROR_IO_INCOMPLETE) {
755  iface->rdpending = 0;
756  res = yWinSetErrEx(__LINE__, iface, error, "", errmsg);
757  if (retrycount--) {
758  CloseReadHandles(iface);
759  if (YISERR(OpenReadHandles(iface))) {
760  HALLOG("Open handles restared failed %s:%d\n", iface->serial, iface->ifaceno);
761  return res;
762  }
763  //seep a bit to let the OS restart thing correctly
765  goto retry;
766  }
767  HALLOG("Read IO error %s:%d (%s/%s)\n", iface->serial, iface->ifaceno, errmsg, DP(iface->devicePath));
768  return res;
769  }
770  }
771  if (retrycount == 0) {
772  HALLOG("Read IO needed 1 retry %s:%d (%s/%s)\n", iface->serial, iface->ifaceno, errmsg, DP(iface->devicePath));
773  }
774  return YAPI_SUCCESS;
775 }
776 
777 
778 static int yyyyWrite(yInterfaceSt *iface, pktItem *pktItem)
779 {
780  char errmsg[YOCTO_ERRMSG_LEN];
781  DWORD written;
782  OS_USB_Packet winpkt;
783  int retrycount = 1;
784 
785  winpkt.dummy = 0;
786  memcpy(&winpkt.pkt, &pktItem->pkt, sizeof(USB_Packet));
787 retry:
788  if (!WriteFile(iface->wrHDL, &winpkt, sizeof(OS_USB_Packet), &written, NULL)) {
789  YRETCODE code = yWinSetErr(iface, errmsg);
790  if (retrycount--) {
791  // reset handles
792  CloseWriteHandles(iface);
793  if (YISERR(OpenWriteHandles(iface))) {
794  HALLOG("Write handles restared failed %s:%d\n", iface->serial, iface->ifaceno);
795  return code;
796  }
797  //seep a bit to let the OS restart thing correctly
799  goto retry;
800  }
801  HALLOG("Write IO error %s:%d (%s/%s)\n", iface->serial, iface->ifaceno, errmsg, DP(iface->devicePath));
802  return code;
803  }
804  if (retrycount == 0) {
805  HALLOG("Write IO needed 1 retry %s:%d (%s/%s)\n", iface->serial, iface->ifaceno, errmsg, DP(iface->devicePath));
806  }
807  return YAPI_SUCCESS;
808 }
809 
810 
811 
812 static void* yyyUsbIoThread(void* thread_void)
813 {
814  u32 i;
815  char errmsg[YOCTO_ERRMSG_LEN];
816  DWORD dwEvent;
817  yThread *thread = (yThread*)thread_void;
818  yInterfaceSt *iface = (yInterfaceSt*)thread->ctx;
819 
820 
821  iface->wrHDL = INVALID_HANDLE_VALUE;
822  iface->rdHDL = INVALID_HANDLE_VALUE;
823  for (i = 0; i < 2; i++) {
824  iface->EV[i] = NULL;
825  }
826 
827  //open blocking write handle
828  if (YISERR(OpenWriteHandles(iface))) {
829  yThreadSignalStart(thread);
830  goto exitThread;
831  }
832  //open blocking write handle
833  if (YISERR(OpenReadHandles(iface))) {
834  yThreadSignalStart(thread);
835  goto exitThread;
836  }
837  // create Event for breaking wait
838  iface->EV[YWIN_EVENT_INTERRUPT] = CreateEvent(NULL, FALSE, FALSE, NULL);
839  if (iface->EV[YWIN_EVENT_INTERRUPT] == NULL) {
840  yWinSetErr(iface, errmsg);
841  HALLOG("IO error %s:%d (%s)\n", iface->serial, iface->ifaceno, errmsg);
842  yThreadSignalStart(thread);
843  goto exitThread;
844  }
845 
846 
847  HALLOG("yyyReady I%x wr=%x rd=%x se=%s\n", iface->ifaceno, iface->wrHDL, iface->rdHDL, iface->serial);
848  yThreadSignalStart(thread);
849  //CloseHandle(iface->EV[YWIN_EVENT_INTERRUPT]);
850 
851 
852  if (yyyyRead(iface, errmsg) != YAPI_SUCCESS) {
853  HALLOG("Read error %s:%d (%s)\n", iface->serial, iface->ifaceno, errmsg);
854  goto exitThread;
855  }
856 
857 
858  HALLOG("----IoThread start of %s:%d (%s) ---\n", iface->serial, iface->ifaceno, DP(iface->devicePath));
859 
860  while (!yThreadMustEnd(thread)) {
861  pktItem *pktItem;
862  yPktQueuePeekH2D(iface, &pktItem);
863  //first write pending out packet
864  while (pktItem) {
865 #ifdef DEBUG_PKT_TIMING
866  u64 timeBeforeWrite, timeAfterWrite, stop;
867  YASSERT(pktItem->time);
868  timeBeforeWrite = yapiGetTickCount() - pktItem->time;
869  YASSERT(timeBeforeWrite >= 0 && timeBeforeWrite < 50);
870 #endif
871  if (YISERR(yyyyWrite(iface, pktItem))) {
872  goto exitThread;
873  }
874  yPktQueuePopH2D(iface, &pktItem);
875 #ifdef DEBUG_PKT_TIMING
876  stop = yapiGetTickCount();
877  timeAfterWrite = stop - pktItem->time;
878  if (pktItem->next) {
879  u64 tmp = yapiGetTickCount() - pktItem->time;
880  printf("outpkt no %llu %llu -> %llu (%llu=>%llu) (next=no %llu %llu)\n", pktItem->ospktno, timeBeforeWrite, timeAfterWrite, pktItem->time, stop, pktItem->next->ospktno, tmp);
881  } else {
882  printf("outpkt no %llu %llu -> %llu (%llu=>%llu) (no next)\n",
883  pktItem->ospktno, timeBeforeWrite, timeAfterWrite, pktItem->time, stop);
884  }
885  YASSERT(timeAfterWrite >= 0 && timeAfterWrite < 50);
886 #endif
887  yFree(pktItem);
888  yPktQueuePeekH2D(iface, &pktItem);
889  }
890 
891  // Wait for the thread to signal one of the event objects
892  dwEvent = WaitForMultipleObjects(
893  2, // number of objects in array
894  iface->EV, // array of objects
895  FALSE, // wait for any object
896  50); // wait for max 50 ms
897  if (dwEvent == WAIT_FAILED) {
898  YRETCODE code = yWinSetErr(iface, errmsg);
899  HALLOG("Wait error %s:%d (%s)\n", iface->serial, iface->ifaceno, errmsg);
900  yPktQueueSetError(&iface->txQueue, code, errmsg);
901  yPktQueueSetError(&iface->rxQueue, code, errmsg);
903  continue;
904  }
905  if (dwEvent != WAIT_TIMEOUT) {
906  if (yyyyRead(iface, errmsg) != YAPI_SUCCESS) {
907  HALLOG("Read error %s:%d (%s)\n", iface->serial, iface->ifaceno, errmsg);
908  yPktQueueSetError(&iface->rxQueue, YAPI_IO_ERROR, errmsg);
909  break;
910  }
911  }
912  }
913 
914 exitThread:
915  HALLOG("----IoThread end of %s:%d (%s) ---\n", iface->serial, iface->ifaceno, DP(iface->devicePath));
916  if (iface->EV[YWIN_EVENT_INTERRUPT] != NULL) {
917  CloseHandle(iface->EV[YWIN_EVENT_INTERRUPT]);
918  iface->EV[YWIN_EVENT_INTERRUPT] = NULL;
919  }
920  CloseWriteHandles(iface);
921  CloseReadHandles(iface);
922  yThreadSignalEnd(thread);
923  return NULL;
924  }
925 
926 
927 int yyySetup(yInterfaceSt *iface, char *errmsg)
928 {
929  HALLOG("yyySetup %p\n", iface);
930  yPktQueueInit(&iface->rxQueue);
931  yPktQueueInit(&iface->txQueue);
932  memset(&iface->io_thread, 0, sizeof(yThread));
933  if (yThreadCreate(&iface->io_thread, yyyUsbIoThread, (void*)iface) < 0) {
934  return YERRMSG(YAPI_IO_ERROR, "Unable to start USB IO thread");
935  }
936  return YAPI_SUCCESS;
937 }
938 
939 int yyySignalOutPkt(yInterfaceSt *iface, char *errmsg)
940 {
941  ySetEvent(&iface->EV[YWIN_EVENT_INTERRUPT]);
942  return YAPI_SUCCESS;
943 }
944 
945 void yyyPacketShutdown(yInterfaceSt *iface)
946 {
947  HALLOG("yyyPacketShutdown %p\n", iface);
948  if (yThreadIsRunning(&iface->io_thread)) {
949  u64 timeout;
950  yThreadRequestEnd(&iface->io_thread);
952  while (yThreadIsRunning(&iface->io_thread) && timeout >= yapiGetTickCount()) {
953  yApproximateSleep(10);
954  }
955  yThreadKill(&iface->io_thread);
956  }
957  yPktQueueFree(&iface->rxQueue);
958  yPktQueueFree(&iface->txQueue);
959 }
960 
961 #endif
962 
963 
964 #ifdef WINCE
965 #include "yproto.h"
966 
967 
968 int yUSB_init(yContextSt *ctx, char *errmsg)
969 {
970  return YAPI_SUCCESS;
971 }
972 
973 
974 int yUSB_stop(yContextSt *ctx, char *errmsg)
975 {
976  return 0;
977 }
978 
979 
980 
981 int yUSBGetInterfaces(yInterfaceSt **ifaces, int *nbifaceDetect, char *errmsg)
982 {
983  *nbifaceDetect = 0;
984  return 0;
985 }
986 
987 
988 
989 int yyyTestOShdl(yPrivDeviceSt *dev, DevEnum *newdev)
990 {
991  return 1;
992 }
993 
994 
995 
996 
997 int yyySetup(yInterfaceSt *iface, char *errmsg)
998 {
999  return YERR(YAPI_NOT_SUPPORTED);
1000 }
1001 
1002 int yyySignalOutPkt(yInterfaceSt *iface)
1003 {
1004  return YAPI_SUCCESS;
1005 }
1006 
1007 void yyyPacketShutdown(yInterfaceSt *iface)
1008 {}
1009 
1010 #endif
d
void yThreadKill(yThread *yth)
Definition: ythread.c:343
#define YERRMSG(code, message)
Definition: yproto.h:458
void yInitializeCriticalSection(yCRITICAL_SECTION *cs)
Definition: ythread.c:629
#define YOCTO_DEVID_BOOTLOADER
Definition: ydef.h:404
USB_Packet pkt
Definition: yproto.h:493
USB_Packet pkt
Definition: yproto.h:508
yDeviceSt infos
Definition: yproto.h:689
yContextSt * yContext
Definition: ystream.c:59
#define YWIN_EVENT_INTERRUPT
Definition: yproto.h:560
int yThreadCreate(yThread *yth, void *(*fun)(void *), void *arg)
Definition: ythread.c:293
#define YERR(code)
Definition: yproto.h:456
#define dbglog(args...)
Definition: yproto.h:413
#define YPROPERR(call)
Definition: yproto.h:455
int yyySetup(yInterfaceSt *iface, char *errmsg)
int yyyUSBGetInterfaces(yInterfaceSt **ifaces, int *nbifaceDetect, char *errmsg)
#define YOCTO_SERIAL_LEN
Definition: ydef.h:420
void yLeaveCriticalSection(yCRITICAL_SECTION *cs)
Definition: ythread.c:672
#define YOCTO_ERRMSG_LEN
Definition: ydef.h:418
struct _pktItem pktItem
#define WIN_DEVICE_PATH_LEN
Definition: yproto.h:555
#define YSTRNICMP(A, B, len)
Definition: yproto.h:229
YRETCODE yPktQueuePopH2D(yInterfaceSt *iface, pktItem **pkt)
Definition: ystream.c:1176
int yyyUSB_init(yContextSt *ctx, char *errmsg)
YRETCODE
Definition: ydef.h:376
#define HALENUMLOG(fmt, args...)
Definition: yproto.h:310
int yyySignalOutPkt(yInterfaceSt *iface, char *errmsg)
void yThreadRequestEnd(yThread *yth)
Definition: ythread.c:331
#define yApproximateSleep(ms)
Definition: yproto.h:433
void * ctx
Definition: ythread.h:96
pktQueue txQueue
Definition: yproto.h:572
#define YSTRCPY(dst, dstsize, src)
Definition: yproto.h:234
int yyyUSB_stop(yContextSt *ctx, char *errmsg)
yInterfaceSt iface
Definition: yproto.h:698
void yPktQueueSetError(pktQueue *q, YRETCODE code, const char *msg)
Definition: ystream.c:985
#define YWIN_EVENT_READ
Definition: yproto.h:559
pktQueue rxQueue
Definition: yproto.h:571
struct _yInterfaceSt yInterfaceSt
#define YASSERT(x)
Definition: yproto.h:454
#define YSPRINTF
Definition: yproto.h:238
YRETCODE yPktQueuePeekH2D(yInterfaceSt *iface, pktItem **pkt)
Definition: ystream.c:1160
#define YOCTO_VENDORID
Definition: ydef.h:402
u16 ifaceno
Definition: yproto.h:565
#define HALLOG(fmt, args...)
Definition: yproto.h:295
void yEnterCriticalSection(yCRITICAL_SECTION *cs)
Definition: ythread.c:647
#define yFree(ptr)
Definition: yproto.h:199
char serial[YOCTO_SERIAL_LEN *2]
Definition: yproto.h:567
u16 deviceid
Definition: yproto.h:564
#define __FILE_ID__
Definition: ypkt_win.c:40
#define yMalloc(size)
Definition: yproto.h:198
#define YSTRLEN(str)
Definition: yproto.h:230
YRETCODE yPktQueuePushD2H(yInterfaceSt *iface, const USB_Packet *pkt, char *errmsg)
Definition: ystream.c:1097
void yDeleteCriticalSection(yCRITICAL_SECTION *cs)
Definition: ythread.c:682
void ySetEvent(yEvent *ev)
Definition: ythread.c:175
void yPktQueueFree(pktQueue *q)
Definition: ystream.c:928
u64 YAPI_FUNCTION_EXPORT yapiGetTickCount(void)
Definition: yapi.c:2713
void yyyPacketShutdown(yInterfaceSt *iface)
void yThreadSignalEnd(yThread *yth)
Definition: ythread.c:326
char serial[YOCTO_SERIAL_LEN]
Definition: ydef.h:454
u16 nbinbterfaces
Definition: ydef.h:451
yEvent exitSleepEvent
Definition: yproto.h:926
#define yMemcpy(dst, src, size)
Definition: yproto.h:204
int yThreadMustEnd(yThread *yth)
Definition: ythread.c:338
int yyyOShdlCompare(yPrivDeviceSt *dev, yInterfaceSt *newiface)
#define YISERR(retcode)
Definition: ydef.h:394
#define YIO_DEFAULT_USB_TIMEOUT
Definition: ydef.h:249
int yThreadIsRunning(yThread *yth)
Definition: ythread.c:311
void yThreadSignalStart(yThread *yth)
Definition: ythread.c:318
#define YSTRCMP(A, B)
Definition: yproto.h:226
struct _pktItem * next
Definition: yproto.h:513
void yPktQueueInit(pktQueue *q)
Definition: ystream.c:919
#define YSTRNCPY(dst, dstsize, src, len)
Definition: yproto.h:237
u16 vendorid
Definition: yproto.h:563


yoctopuce_altimeter
Author(s): Anja Sheppard
autogenerated on Mon Jun 10 2019 15:49:11