ystream.c
Go to the documentation of this file.
1 /*********************************************************************
2  *
3  * $Id: ystream.c 29651 2018-01-17 20:48:29Z mvuilleu $
4  *
5  * USB stream implementation
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__ "ystream"
41 #include "yproto.h"
42 #include "yhash.h"
43 
44 #include <stdlib.h>
45 #include <stdio.h>
46 #include <ctype.h>
47 #include <string.h>
48 #include <stdarg.h>
49 #ifdef WINDOWS_API
50 #include <time.h>
51 #else
52 #include <sys/time.h>
53 #endif
54 
55 /*****************************************************************************
56  Global variables
57  ***************************************************************************/
58 
60 
61 #ifdef DEBUG_TRACE_FILE
62 char ytracefile[512]=DEBUG_TRACE_FILE;
63 #else
64 char ytracefile[512]="";
65 #endif
66 
67 /*****************************************************************************
68  Error and logs functions
69  ***************************************************************************/
70 
71 
72 int ySetErr(int code, char *outmsg, const char *erreur,const char *file,u32 line)
73 {
74  const char *msg;
75  if(outmsg==NULL){
76  // no output buffer only return code
77  return code;
78  }
79  if(erreur==NULL){
80  switch(code){
81  case YAPI_SUCCESS: msg="Success";break;
82  case YAPI_NOT_INITIALIZED: msg="API not initialized";break;
83  case YAPI_INVALID_ARGUMENT: msg="Invalid argument";break;
84  case YAPI_NOT_SUPPORTED: msg="Not supported";break;
85  case YAPI_DEVICE_NOT_FOUND: msg="Device not found";break;
86  case YAPI_VERSION_MISMATCH: msg="Version mismatch"; break;
87  case YAPI_DEVICE_BUSY: msg="Device busy";break;
88  case YAPI_TIMEOUT: msg="Timeout";break;
89  case YAPI_IO_ERROR: msg="I/O error";break;
90  case YAPI_NO_MORE_DATA: msg="No more data";break;
91  case YAPI_EXHAUSTED: msg="Resource exhausted";break;
92  case YAPI_DOUBLE_ACCES: msg="double access to the same device";break;
93  case YAPI_UNAUTHORIZED: msg="unauthorized access";break;
94  case YAPI_RTC_NOT_READY: msg="real-time clock has not been initialized";break;
95  case YAPI_FILE_NOT_FOUND: msg="file is not found";break;
96  default: msg="Unknown error";
97  break;
98  }
99  }else{
100  msg=erreur;
101  }
102  if (file) {
103  YSPRINTF(outmsg, YOCTO_ERRMSG_LEN, "%s (%s:%d)", msg, file, line);
104  } else {
105  YSTRCPY(outmsg, YOCTO_ERRMSG_LEN, msg);
106  }
107  return code;
108 }
109 
110 
111 
112 int FusionErrmsg(int code,char *errmsg, const char *generr, const char *detailerr)
113 {
114  int len;
115  if(YISERR(code) && errmsg){
116  YSTRCPY(errmsg,YOCTO_ERRMSG_LEN,generr);
117  YSTRCAT(errmsg,YOCTO_ERRMSG_LEN,":");
118  len=YSTRLEN(errmsg);
119  YSTRNCAT(errmsg,YOCTO_ERRMSG_LEN,detailerr,YOCTO_ERRMSG_LEN-len);
120  }
121  return code;
122 }
123 
124 
125 
126 
127 
128 #if !defined(_MSC_VER) || (_MSC_VER <= MSC_VS2003)
129 
130 int YFOPEN(FILE** f, const char *filename, const char *mode)
131 {
132  *f=fopen(filename,mode);
133  if(*f==NULL){
134  return -1;
135  }
136  return 0;
137 }
138 
139 #endif
140 
141 
142 
143 #define DBGLOGOUT(str) yContext->log(str,YSTRLEN(str))
144 
145 static int dayofs[] = { 0,31,59,90,120,151,181,212,243,273,304,334 };
146 
147 static void WriteTsamp(FILE *f)
148 {
149  u32 year, month, day, h, m, s;
150 
151 #ifdef WINCE
152  SYSTEMTIME time;
153  GetLocalTime( &time);
154  year = time.wYear;
155  month = time.wMonth;
156  day = time.wDay;
157  h = time.wHour;
158  m = time.wMinute;
159  s = time.wSecond;
160 #else
161 
162  u32 secs, days,y;
163  time_t ltime;
164 
165  time(&ltime);
166  secs = (u32)(ltime % 86400);
167  days = (u32)(ltime / 86400);
168  h = secs / 3600;
169  m = (secs % 3600) / 60;
170  s = secs % 60;
171  y = days / 365; /* relative to 1970 */
172  if (((y + 1) >> 2) + 365 * (u32)y > days) y--;
173  days -= ((y + 1) >> 2) + 365 * (u32)y;
174  if ((y & 3) == 2 && days == 59) {
175  month = 2;
176  } else {
177  if((y & 3) == 2 && days >= 59)
178  days--;
179  for (month = 1; month < 12; (month)++)
180  if (dayofs[month] > (u16)days) break;
181  }
182  year = y + 1970;
183  day = days - dayofs[month - 1] + 1;
184 #endif
185  fprintf(f,"[%04d-%02d-%02d/%02d:%02d:%02d]:",year,month,day,h,m,s);
186 }
187 
188 
189 int vdbglogf(const char *fileid,int line,const char *fmt,va_list args)
190 {
191  char buffer[2048];
192  int len;
193  int threadIdx;
194  threadIdx = yThreadIndex();
195  len=YSPRINTF(buffer,2048,"[%d]%s:% 4d: ",threadIdx,fileid,line);
196  if(len<0 || len>=2028 || (len = YVSPRINTF(buffer+len,2048-len,fmt,args))<0){
197  YSTRCPY(buffer,2048,"dbglogf failed\n");
198  return -1;
199  }
200  len =YSTRLEN(buffer);
201 
202  if(yContext && yContext->log)
203  yContext->log(buffer,len);
204 
205 #if 0
206  buffer[len] = 0;
207  printf("%s", buffer);
208 #endif
209 
210  if(ytracefile[0]){
211  FILE *f;
212  if(YFOPEN(&f,ytracefile,"a+")!=0){
213  return -1;
214  }
215  WriteTsamp(f);
216  fwrite(buffer,1,len,f);
217  fclose(f);
218  }
219  return len;
220 }
221 
222 int dbglogf(const char *fileid,int line,const char *fmt,...)
223 {
224  int len;
225  va_list args;
226 
227  va_start( args, fmt );
228  len =vdbglogf(fileid,line,fmt,args);
229  va_end(args);
230  return len;
231 }
232 
233 
234 #ifdef __BORLANDC__
235 #pragma argsused
236 int sprintf_s(char *buffer,size_t sizeOfBuffer,const char *format,...)
237 {
238  va_list args;
239  va_start( args, format);
240  return vsprintf(buffer,format,args);
241 }
242 #pragma argsused
243 int wcstombs_s(size_t *pReturnValue, char *mbstr, size_t sizeInBytes, const wchar_t *wcstr, size_t count)
244 {
245  *pReturnValue = wcstombs(mbstr, wcstr, count);
246  return 0;
247 }
248 #endif
249 
250 
251 /*****************************************************************************
252  Whitepage and Yellowpage wrapper for USB devices
253  ****************************************************************************/
254 
255 void ypUpdateUSB(const char *serial, const char *funcid, const char *funcname, int funclass, int funydx, const char *funcval)
256 {
257  char funcid_cstr[YOCTO_FUNCTION_LEN];
258  char categ[YOCTO_FUNCTION_LEN];
259  yStrRef serialref, funcidref, funcnameref = INVALID_HASH_IDX;
260  u16 i;
261 
262  funcid_cstr[0] = funcid[0];
263  categ[0] = (funcid[0] & ~0x20); // aka to_upper()
264  for(i = 1; i < YOCTO_FUNCTION_LEN-1; i++) {
265  char c = funcid[i];
266  if(!c || (c <= '9' && c >= '0')) break;
267  funcid_cstr[i] = c;
268  categ[i] = c;
269  }
270  categ[i] = 0;
271  for(; i < YOCTO_FUNCTION_LEN-1; i++) {
272  char c = funcid[i];
273  if(!c) break;
274  funcid_cstr[i] = c;
275  }
276  funcid_cstr[i] = 0;
277  serialref = yHashPutStr(serial);
278  funcidref = yHashPutStr(funcid_cstr);
279  if(funcname) funcnameref = yHashPutStr(funcname);
280  if(ypRegister(yHashPutStr(categ), serialref, funcidref, funcnameref, funclass, funydx, funcval)){
281  // Forward high-level notification to API user
282  yFunctionUpdate(((s32)funcidref << 16) | serialref, funcval);
283  }
284 }
285 
286 void ypUpdateYdx(int devydx, Notification_funydx funInfo, const char *funcval)
287 {
288  YAPI_FUNCTION fundesc;
289 
290  if(ypRegisterByYdx(devydx, funInfo, funcval, &fundesc)){
291  // Forward high-level notification to API user
292  if (funcval) {
293  char buffer[YOCTO_PUBVAL_LEN];
294  decodePubVal(funInfo, funcval, buffer);
295  yFunctionUpdate(fundesc,buffer);
296  }
297  }
298 }
299 
300 void ypUpdateHybrid(const char *serial, Notification_funydx funInfo, const char *funcval)
301 {
302  int devydx;
303  yStrRef serialref;
304 
305  serialref = yHashPutStr(serial);
306  devydx = wpGetDevYdx(serialref);
307  if(devydx >= 0) {
308  ypUpdateYdx(devydx, funInfo, funcval);
309  }
310 }
311 
312 /*****************************************************************************
313  THEAD / CONCURENCY RELATED FUNCTIONS
314  ***************************************************************************/
315 //#define DEBUG_DEVICE_LOCK
316 #ifdef DEBUG_DEVICE_LOCK
317 #define LOCATION int line,
318 #define PUSH_LOCATION __LINE__,
319 #define PUSH_LOCATION __LINE__,
320 #else
321 #define LOCATION
322 #define PUSH_LOCATION
323 #endif
324 
326  {
327  yInitializeCriticalSection(&dev->acces_state);
328  }
329 
331  {
332  yDeleteCriticalSection(&dev->acces_state);
333  }
334 
335 static int devStartIdle(LOCATION yPrivDeviceSt *dev,char *errmsg)
336 {
337  int res =YAPI_DEVICE_BUSY;
338  //get access
339  if (yTryEnterCriticalSection(&dev->acces_state)==0) {
340  return YERR(YAPI_DEVICE_BUSY);
341  }
342 
343  if (dev->dStatus!=YDEV_WORKING){
344  yLeaveCriticalSection(&dev->acces_state);
345  return YERR(YAPI_DEVICE_NOT_FOUND);
346  }
347 
348  switch(dev->rstatus){
349  case YRUN_STOPED:
350  case YRUN_ERROR:
351  res= YERRMSG(YAPI_DEVICE_NOT_FOUND,"This device is not available");
352  break;
353  case YRUN_REQUEST:
354  case YRUN_BUSY:
355  res = YERR(YAPI_DEVICE_BUSY);
356  break;
357  case YRUN_AVAIL:
358  dev->rstatus = YRUN_IDLE;
359  // do not release the mutex on purpose!
360 #ifdef DEBUG_DEVICE_LOCK
361  dbglog("start Idle on %s (line %d)\n",dev->infos.serial,line);
362 #endif
363  return YAPI_SUCCESS;
364  case YRUN_IDLE:
365 #ifdef DEBUG_DEVICE_LOCK
366  dbglog("doube Idle on %s (line %d)\n",dev->infos.serial,line);
367 #endif
368  res = YERR(YAPI_DEVICE_BUSY);
369  break;
370  }
371 
372  yLeaveCriticalSection(&dev->acces_state);
373  return res;
374 }
375 
376 
378 {
379 
380  switch(dev->rstatus){
381  case YRUN_STOPED:
382  break;
383  case YRUN_ERROR:
384  case YRUN_REQUEST:
385  case YRUN_BUSY:
386  case YRUN_AVAIL:
387 #ifdef DEBUG_DEVICE_LOCK
388  dbglog("panic on %s (line %d)\n",dev->infos.serial,line);
389 #endif
390  YPANIC;
391  break;
392  case YRUN_IDLE:
393  dev->rstatus = YRUN_AVAIL;
394 #ifdef DEBUG_DEVICE_LOCK
395  dbglog("stop Idle on %s (line %d)\n",dev->infos.serial,line);
396 #endif
397  break;
398  }
399 
400  yLeaveCriticalSection(&dev->acces_state);
401 }
402 
403 
404 
406 {
407  u64 timeref;
408  //get access
409  yEnterCriticalSection(&dev->acces_state);
410 
411  timeref = yapiGetTickCount();
412  while((dev->rstatus == YRUN_IDLE || dev->rstatus == YRUN_BUSY ) && (u64)(yapiGetTickCount() - timeref) < 2000){
413  // if someone is doing IO release the mutex and give him 2 second to quit
414  yLeaveCriticalSection(&dev->acces_state);
415  yPktQueueSetError(&dev->iface.rxQueue, YAPI_DEVICE_NOT_FOUND, "Device need to be stoped");
416  yApproximateSleep(100);
417  yEnterCriticalSection(&dev->acces_state);
418  }
419  dev->rstatus = YRUN_STOPED;
420  // keep the Mutex on purpose
421 }
422 
423 
425 {
426  yLeaveCriticalSection(&dev->acces_state);
427 }
428 
429 
430 
431 
432 static void devReportErrorFromIdle(LOCATION yPrivDeviceSt *dev, char *error_to_set)
433 {
434  //get access
435  dbglog("Error from idle %s(%d) : %s\n",dev->infos.serial,dev->rstatus,error_to_set);
436  switch(dev->rstatus){
437  case YRUN_STOPED:
438  break;
439  case YRUN_ERROR:
440  case YRUN_REQUEST:
441  case YRUN_BUSY:
442  case YRUN_AVAIL:
443 #ifdef DEBUG_DEVICE_LOCK
444  dbglog("panic on %s (line %d)\n",dev->infos.serial,line);
445 #endif
446  YPANIC;
447  break;
448  case YRUN_IDLE:
449  dev->rstatus = YRUN_ERROR;
450  YSTRCPY(dev->errmsg,YOCTO_ERRMSG_LEN,error_to_set);
451  break;
452  }
453  yLeaveCriticalSection(&dev->acces_state);
454 }
455 
456 
457 
458 
459 static int devStartIO(LOCATION yPrivDeviceSt *dev, char *errmsg)
460 {
461  int res =YAPI_DEVICE_BUSY;
462  //get access
463  yEnterCriticalSection(&dev->acces_state);
464 
465  if (dev->dStatus!=YDEV_WORKING){
466  yLeaveCriticalSection(&dev->acces_state);
467  return YERR(YAPI_DEVICE_NOT_FOUND);
468  }
469 
470  switch(dev->rstatus){
471  case YRUN_ERROR:
472  res = YERRMSG(YAPI_IO_ERROR,dev->errmsg);
473  break;
474  case YRUN_STOPED:
475  res = YERRMSG(YAPI_DEVICE_NOT_FOUND,"This device is not available");
476  break;
477  case YRUN_REQUEST:
478  case YRUN_BUSY:
479  res = YERR(YAPI_DEVICE_BUSY);
480  break;
481  case YRUN_AVAIL:
482  dev->rstatus = YRUN_BUSY;
483  res = YAPI_SUCCESS;
484 #ifdef DEBUG_DEVICE_LOCK
485  dbglog("start IO on %s (line %d)\n",dev->infos.serial,line);
486 #endif
487  break;
488  case YRUN_IDLE:
489  //should never occure since we keep the mutex during idlle
490 #ifdef DEBUG_DEVICE_LOCK
491  dbglog("panic on %s (line %d)\n",dev->infos.serial,line);
492 #endif
493  YPANIC;
494  res = YERR(YAPI_DEVICE_BUSY);
495  break;
496  }
497  yLeaveCriticalSection(&dev->acces_state);
498  return res;
499 }
500 
501 
502 static int devPauseIO(LOCATION yPrivDeviceSt *dev,char *errmsg)
503 {
504  int res = YAPI_SUCCESS;
505 
506  yEnterCriticalSection(&dev->acces_state);
507  switch(dev->rstatus){
508  case YRUN_ERROR:
509  res = YERRMSG(YAPI_IO_ERROR,dev->errmsg);
510  break;
511  case YRUN_STOPED:
512  res = YERRMSG(YAPI_DEVICE_NOT_FOUND,"This device is not available");
513  break;
514  case YRUN_REQUEST:
515  //should never ocuure
516 #ifdef DEBUG_DEVICE_LOCK
517  dbglog("panic on %s (line %d)\n",dev->infos.serial,line);
518 #endif
519  YPANIC;
520  res = YERR(YAPI_DEVICE_BUSY);
521  break;
522  case YRUN_BUSY:
523  dev->rstatus = YRUN_REQUEST;
524 #ifdef DEBUG_DEVICE_LOCK
525  dbglog("pause IO on %s (line %d)\n",dev->infos.serial,line);
526 #endif
527  break;
528  case YRUN_AVAIL:
529  res = YERRMSG(YAPI_INVALID_ARGUMENT,"No IO started");
530  break;
531  case YRUN_IDLE:
532  //should never occure since we keep the mutex during idlle
533 #ifdef DEBUG_DEVICE_LOCK
534  dbglog("panic on %s (line %d)\n",dev->infos.serial,line);
535 #endif
536  YPANIC;
537  res = YERR(YAPI_DEVICE_BUSY);
538  break;
539  }
540 
541  yLeaveCriticalSection(&dev->acces_state);
542  return res;
543 }
544 
545 
546 
547 static int devCheckIO(LOCATION yPrivDeviceSt *dev, YIOHDL_internal *iohdl,char *errmsg)
548 {
549  int res = YAPI_SUCCESS;
550 
551  yEnterCriticalSection(&dev->acces_state);
552 
553  if (dev->dStatus!=YDEV_WORKING){
554  yLeaveCriticalSection(&dev->acces_state);
555  return YERR(YAPI_DEVICE_NOT_FOUND);
556  }
557 
558  switch(dev->rstatus){
559  case YRUN_ERROR:
560  res = YERRMSG(YAPI_IO_ERROR,dev->errmsg);
561  break;
562  case YRUN_STOPED:
563  res = YERRMSG(YAPI_DEVICE_NOT_FOUND,"This device is not available");
564  break;
565  case YRUN_REQUEST:
566  if(YIO_USB != iohdl->type || dev->pendingIO.hdl != iohdl->hdl){
567  res=YERRMSG(YAPI_INVALID_ARGUMENT,"Invalid IO Handle");
568  }else{
569  dev->rstatus = YRUN_BUSY;
570 #ifdef DEBUG_DEVICE_LOCK
571  dbglog("restart IO on %s (line %d)\n",dev->infos.serial,line);
572 #endif
573  }
574  break;
575  case YRUN_BUSY:
576  res=YERRMSG(YAPI_INVALID_ARGUMENT,"Access violation");
577  break;
578  case YRUN_AVAIL:
579  res = YERRMSG(YAPI_INVALID_ARGUMENT,"No IO started");
580  break;
581  case YRUN_IDLE:
582  //should never occure since we keep the mutex during idlle
583 #ifdef DEBUG_DEVICE_LOCK
584  dbglog("panic on %s (line %d)\n",dev->infos.serial,line);
585 #endif
586  YPANIC;
587  res = YERR(YAPI_DEVICE_BUSY);
588  break;
589  }
590 
591  yLeaveCriticalSection(&dev->acces_state);
592  return res;
593 }
594 
595 static int devCheckAsyncIO(LOCATION yPrivDeviceSt *dev, char *errmsg)
596 {
597  int res = YAPI_SUCCESS;
598 
599  yEnterCriticalSection(&dev->acces_state);
600 
601  if (dev->dStatus!=YDEV_WORKING){
602  yLeaveCriticalSection(&dev->acces_state);
603  return YERR(YAPI_DEVICE_NOT_FOUND);
604  }
605 
606  switch(dev->rstatus){
607  case YRUN_ERROR:
608  res = YERRMSG(YAPI_IO_ERROR,dev->errmsg);
609  break;
610  case YRUN_STOPED:
611  res = YERRMSG(YAPI_DEVICE_NOT_FOUND,"This device is not available");
612  break;
613  case YRUN_REQUEST:
614  if (dev->pendingIO.callback == NULL) {
615  res=YERRMSG(YAPI_INVALID_ARGUMENT,"Invalid IO Handle");
616  } else {
617  dev->rstatus = YRUN_BUSY;
618 #ifdef DEBUG_DEVICE_LOCK
619  dbglog("Async IO bg process on %s (line %d)\n",dev->infos.serial,line);
620 #endif
621  }
622  break;
623  case YRUN_BUSY:
624  res=YERRMSG(YAPI_INVALID_ARGUMENT,"Access violation");
625  break;
626  case YRUN_AVAIL:
627  res = YERRMSG(YAPI_INVALID_ARGUMENT,"No IO started");
628  break;
629  case YRUN_IDLE:
630  //should never occure since we keep the mutex during idlle
631 #ifdef DEBUG_DEVICE_LOCK
632  dbglog("panic on %s (line %d)\n",dev->infos.serial,line);
633 #endif
634  YPANIC;
635  res = YERR(YAPI_DEVICE_BUSY);
636  break;
637  }
638 
639  yLeaveCriticalSection(&dev->acces_state);
640  return res;
641 }
642 
643 
644 static int devStopIO(LOCATION yPrivDeviceSt *dev, char *errmsg)
645 {
646  int res = YAPI_SUCCESS;
647 
648  yEnterCriticalSection(&dev->acces_state);
649  switch(dev->rstatus){
650  case YRUN_ERROR:
651  res = YERRMSG(YAPI_IO_ERROR,dev->errmsg);
652  break;
653  case YRUN_STOPED:
654  res = YERRMSG(YAPI_DEVICE_NOT_FOUND,"This device is not available");
655  break;
656  case YRUN_REQUEST:
657  res=YERRMSG(YAPI_INVALID_ARGUMENT,"Access violation");
658  break;
659  case YRUN_BUSY:
660  dev->rstatus = YRUN_AVAIL;
661 #ifdef DEBUG_DEVICE_LOCK
662  dbglog("Stop IO on %s (line %d)\n",dev->infos.serial,line);
663 #endif
664  break;
665  case YRUN_AVAIL:
666  res = YERRMSG(YAPI_INVALID_ARGUMENT,"No IO started");
667  break;
668  case YRUN_IDLE:
669  //should never occure since we keep the mutex during idlle
670 #ifdef DEBUG_DEVICE_LOCK
671  dbglog("panic on %s (line %d)\n",dev->infos.serial,line);
672 #endif
673  YPANIC;
674  res = YERR(YAPI_DEVICE_BUSY);
675  break;
676  }
677 
678  yLeaveCriticalSection(&dev->acces_state);
679  return res;
680 
681 }
682 
683 static void devReportError(LOCATION yPrivDeviceSt *dev, char *error_to_set)
684 {
685  //get access
686  yEnterCriticalSection(&dev->acces_state);
687  switch(dev->rstatus){
688  case YRUN_STOPED:
689  case YRUN_ERROR:
690  case YRUN_REQUEST:
691  case YRUN_BUSY:
692  case YRUN_AVAIL:
693  dbglog("Error %s(%d) : %s\n",dev->infos.serial,dev->rstatus,error_to_set);
694  dev->rstatus = YRUN_ERROR;
695  YSTRCPY(dev->errmsg,YOCTO_ERRMSG_LEN,error_to_set);
696  break;
697  case YRUN_IDLE:
698  //should never occure since we keep the mutex during idlle
699 #ifdef DEBUG_DEVICE_LOCK
700  dbglog("panic on %s (line %d)\n",dev->infos.serial,line);
701 #endif
702  YPANIC;
703  break;
704  }
705 
706  yLeaveCriticalSection(&dev->acces_state);
707 }
708 
709 
710 
711 /*****************************************************************************
712  Dump functions
713  ***************************************************************************/
714 
715 
716 
717 #ifdef DEBUG_DUMP_PKT
718 
719 static void dumpAnyStream(char *prefix,int iface,u8 pkt,u8 stream,u8 size,u8 *data,u8 pktno)
720 {
721 
722  USB_Notify_Pkt *notif= (USB_Notify_Pkt*) data;
723  int pos, j;
724  char buff[17];
725  buff[16] = 0;
726  dbglog("%s:%d: head: type=%d stream/cmd=%d size=%d (pktno=%d)\n",
727  prefix,iface ,pkt ,stream,size,pktno);
728 
729  if(pkt== YPKT_CONF){
730  switch(stream){
731  case USB_CONF_RESET:
732  dbglog("%s: USB_CONF_RESET\n",prefix);
733  break;
734  case USB_CONF_START:
735  dbglog("%s: USB_CONF_START\n",prefix);
736  break;
737  default:
738  dbglog("%s: CONF PKT INVALID!\n",prefix);
739  break;
740  }
741  }else if(pkt == YPKT_STREAM){
742  switch(stream){
743  case YSTREAM_EMPTY:
744  dbglog("%s: Stream Empty\n",prefix);
745  break;
746  case YSTREAM_NOTICE:
747  case YSTREAM_NOTICE_V2:
748  if(notif->firstByte <= NOTIFY_1STBYTE_MAXTINY) {
749  dbglog("%s: TINY FUNCTION VALUE\n",prefix);
750  } else if(notif->firstByte >= NOTIFY_1STBYTE_MINSMALL) {
751  dbglog("%s: SMALL FUNCTION VALUE\n",prefix);
752  } else switch(notif->head.type){
753  case NOTIFY_PKT_NAME:
754  dbglog("%s: NOTIFY LOGICAL NAME\n",prefix);
755  break;
756  case NOTIFY_PKT_PRODNAME:
757  dbglog("%s: NOTIFY PRODNAME\n",prefix);
758  break;
759  case NOTIFY_PKT_CHILD:
760  dbglog("%s: NOTIFY CHILD\n",prefix);
761  break;
762  case NOTIFY_PKT_FIRMWARE:
763  dbglog("%s: NOTIFY FIRMWARE\n",prefix);
764  break;
765  case NOTIFY_PKT_FUNCNAME:
766  dbglog("%s: NOTIFY FUNCTION NAME\n",prefix);
767  break;
768  case NOTIFY_PKT_FUNCVAL:
769  dbglog("%s: NOTIFY FUNCTION VALUE\n",prefix);
770  break;
772  dbglog("%s: NOTIFY DEVICE READY\n",prefix);
773  break;
774  case NOTIFY_PKT_LOG:
775  dbglog("%s: NOTIFY DEVICE LOG\n",prefix);
776  break;
777  default:
778  dbglog("%s: Unknown NOTIFY\n",prefix);
779  break;
780  }
781  break;
782  case YSTREAM_TCP:
783  dbglog("%s: Stream tcp\n",prefix);
784  for(pos = 0; pos < size; pos += 16) {
785  memset(buff, '.', 16);
786  for(j = 0; j < 16; j++)
787  if(data[pos+j] >= ' ')
788  buff[j] = data[pos+j];
789  dbglog(" %02x.%02x.%02x.%02x %02x.%02x.%02x.%02x %02x.%02x.%02x.%02x %02x.%02x.%02x.%02x %s\n",
790  data[pos+0], data[pos+1], data[pos+2], data[pos+3],
791  data[pos+4], data[pos+5], data[pos+6], data[pos+7],
792  data[pos+8], data[pos+9], data[pos+10], data[pos+11],
793  data[pos+12], data[pos+13], data[pos+14], data[pos+15],
794  buff);
795  }
796  break;
797  case YSTREAM_TCP_CLOSE:
798  dbglog("%s: Stream tcp close\n",prefix);
799  for(pos = 0; pos < size; pos += 16) {
800  memset(buff, '.', 16);
801  for(j = 0; j < 16; j++)
802  if(data[pos+j] >= ' ')
803  buff[j] = data[pos+j];
804  dbglog(" %02x.%02x.%02x.%02x %02x.%02x.%02x.%02x %02x.%02x.%02x.%02x %02x.%02x.%02x.%02x %s\n",
805  data[pos+0], data[pos+1], data[pos+2], data[pos+3],
806  data[pos+4], data[pos+5], data[pos+6], data[pos+7],
807  data[pos+8], data[pos+9], data[pos+10], data[pos+11],
808  data[pos+12], data[pos+13], data[pos+14], data[pos+15],
809  buff);
810  }
811  break;
812  default:
813  dbglog("%s: Stream invalid !\n",prefix);
814  break;
815  }
816 
817  }
818 }
819 static u32 dumpAnyStreamHead(char *prefix,int iface,YSTREAM_Head *head,int dumpContent)
820 {
821  u8 *data =((u8*)head)+sizeof(YSTREAM_Head);
822  dumpAnyStream(prefix,iface,head->pkt , head->stream, head->size, data, head->pktno);
823  return head->size;
824 }
825 
826 void dumpAnyPacket(char *prefix, int iface,USB_Packet *pkt)
827 {
828  u32 pos=0;
829  //dbglog("%s:%d: DUMP FULL PACKET!\n",prefix,iface);
830  while(pos < USB_PKT_SIZE-sizeof(YSTREAM_Head)){
831  YSTREAM_Head *head =(YSTREAM_Head*) (pkt->data+pos);
832  pos+=sizeof(YSTREAM_Head)+dumpAnyStreamHead(prefix,iface,head,1);
833  }
834 
835 }
836 
837 #endif
838 
839 
840 
841 /*****************************************************************************
842  PACKET QUEUING FUNCTIONS
843  ***************************************************************************/
844 //#define DUMP_USB_PKT_SHORT
845 #ifdef DUMP_USB_PKT_SHORT
846 static void dumpPktSummary(char *prefix, int iface,int isInput,const USB_Packet *pkt)
847 {
848  u32 pos=0;
849  char buffer[512];
850  u32 len;
851 
852  len =YSPRINTF(buffer,512,"%s%s:%d",(isInput?"<-":"->"),prefix,iface);
853 #if 0
854  while(pos < USB_PKT_SIZE-sizeof(YSTREAM_Head)){
855  YSTREAM_Head *head =(YSTREAM_Head*) (pkt->data+pos);
856  char ty,st;
857  switch(head->pkt){
858  case YPKT_STREAM :
859  ty='S';
860  switch(head->stream){
861  case YSTREAM_EMPTY:
862  st ='e';
863  break;
864  case YSTREAM_TCP:
865  st ='T';
866  break;
867  case YSTREAM_TCP_CLOSE:
868  st ='C';
869  break;
870  case YSTREAM_NOTICE:
871  st ='N';
872  break;
873  case YSTREAM_REPORT:
874  st ='X';
875  break;
876  case YSTREAM_META:
877  st ='M';
878  break;
879  case YSTREAM_REPORT_V2:
880  st ='V';
881  break;
882  case YSTREAM_NOTICE_V2:
883  st ='U';
884  break;
885  default:
886  st='?';
887  break;
888  }
889  break;
890  case YPKT_CONF:
891  ty='C';
892  switch(head->stream){
893  case USB_CONF_RESET:
894  st ='R';
895  break;
896  case USB_CONF_START:
897  st ='S';
898  break;
899  default:
900  st='?';
901  break;
902  }
903  break;
904  default:
905  ty='?';
906  st='!';
907  break;
908  }
909  len += YSPRINTF(buffer+len,512-len," /ty=%c st=%c sz=%d pno=%d",
910  ty ,st,head->size,head->pktno);
911  pos+=sizeof(YSTREAM_Head)+head->size;
912  }
913 #endif
914  dbglog("%s\n",buffer);
915 
916 }
917 #endif
918 
920 {
921  memset(q,0,sizeof(pktQueue));
922  q->status = YAPI_SUCCESS;
926 }
927 
929 {
930  pktItem *p,*t;
931 
932  p=q->first;
933  while(p){
934  t=p;
935  p=p->next;
936  yFree(t);
937  }
940  yCloseEvent(&q->emptyEvent);
941  memset(q,0xca,sizeof(pktQueue));
942 }
943 
944 static YRETCODE yPktQueuePushEx(pktQueue *q,const USB_Packet *pkt, char * errmsg)
945 {
946  pktItem *newpkt;
947  YRETCODE res;
949 
950  if (q->status != YAPI_SUCCESS) {
951  res = q->status;
952  if(errmsg)
953  YSTRCPY(errmsg,YOCTO_ERRMSG_LEN,q->errmsg);
954  //dbglog("%X:yPktQueuePush drop pkt\n",q);
955  } else {
956  res = YAPI_SUCCESS;
957  // allocate new buffer
958  newpkt= ( pktItem *) yMalloc(sizeof(pktItem));
959  memcpy(&newpkt->pkt,pkt,sizeof(USB_Packet));
960 #ifdef DEBUG_PKT_TIMING
961  newpkt->time = yapiGetTickCount();
962  newpkt->ospktno = q->totalPush;
963 #endif
964  newpkt->next = NULL;
965  //lock the queue acces
966  if (q->first == NULL) {
967  //empty queue
968  q->first = newpkt;
969  q->last = newpkt;
970  yResetEvent(&q->emptyEvent);
971  //dbglog("%X:yPktQueuePush First pkt\n",q);
972  } else {
973  q->last->next = newpkt;
974  q->last = newpkt;
975  //dbglog("%X:yPktQueuePush a pkt\n",q);
976  }
977  q->count++;
978  q->totalPush++;
979  }
982  return res;
983 }
984 
985 void yPktQueueSetError(pktQueue *q, YRETCODE code, const char * msg)
986 {
987  //lock the queue acces
989  //dbglog("PKTSetErr %d:%s\n",code,msg);
991  q->status = code;
992  ySetEvent(&q->emptyEvent);
995 }
996 
997 
998 static int yPktQueueIsEmpty(pktQueue *q, char * errmsg)
999 {
1000  int retval;
1001 
1003  retval = q->status;
1004  if(retval !=YAPI_SUCCESS){
1005  //dbglog("%X:yPktQueuePop error %d:%s\n",q,q->status,q->errmsg);
1006  if(errmsg)
1007  YSTRCPY(errmsg,YOCTO_ERRMSG_LEN,q->errmsg);
1008  }else{
1009  if(q->first==NULL)
1010  retval=1;
1011  }
1013  return retval;
1014 }
1015 
1016 static YRETCODE yPktQueuePeek(pktQueue *q, pktItem **pkt, char * errmsg)
1017 {
1018  YRETCODE retval;
1019 
1021  retval = q->status;
1022  if(retval !=YAPI_SUCCESS){
1023  //dbglog("%X:yPktQueuePop error %d:%s\n",q,q->status,q->errmsg);
1024  *pkt = NULL;
1025  if(errmsg)
1026  YSTRCPY(errmsg,YOCTO_ERRMSG_LEN,q->errmsg);
1027  }else{
1028  *pkt = q->first;
1029  }
1031  return retval;
1032 }
1033 
1034 
1035 
1036 static YRETCODE yPktQueuePop(pktQueue *q, pktItem **pkt, char * errmsg)
1037 {
1038  YRETCODE retval;
1039 
1041  retval = q->status;
1042  if(retval !=YAPI_SUCCESS){
1043  //dbglog("%X:yPktQueuePop error %d:%s\n",q,q->status,q->errmsg);
1044  *pkt = NULL;
1045  if(errmsg)
1046  YSTRCPY(errmsg,YOCTO_ERRMSG_LEN,q->errmsg);
1047  }else{
1048  *pkt = q->first;
1049  if(q->first!=NULL){
1050  if(q->first == q->last){
1051  q->first=NULL;
1052  q->last=NULL;
1053  //dbglog("%X:yPktQueuePop last pkt\n",q);
1055  ySetEvent(&q->emptyEvent);
1056  }else{
1057  //dbglog("%X:yPktQueuePop a pkt\n",q);
1058  q->first = q->first->next;
1059  }
1060  q->count--;
1061  q->totalPop++;
1062  }
1063  }
1065  return retval;
1066 }
1067 
1068 
1069 static void yPktQueueDup(pktQueue *q, int expected_pkt_no, const char *file, int line)
1070 {
1071  int verifcount = 0;
1072  pktItem *pkt;
1073 
1075  dbglogf(file, line, "PKTs: %dpkts (%lld in / %lld out)\n", q->count, q->totalPush, q->totalPop);
1076  dbglogf(file, line, "PKTs: start %x stop =%X\n", q->first, q->last);
1077  if (q->status != YAPI_SUCCESS) {
1078  dbglogf(file, line, "PKTs: state = %s\n", q->status, q->errmsg);
1079  }
1080  pkt = q->first;
1081  while (pkt != NULL){
1082  if (expected_pkt_no != pkt->pkt.first_stream.pktno) {
1083  dbglogf(file, line, "PKTs: invalid pkt %d (no=%d should be %d\n", verifcount, pkt->pkt.first_stream.pktno, expected_pkt_no);
1084  }
1085 
1086  verifcount++;
1087  expected_pkt_no = NEXT_YPKT_NO(expected_pkt_no);
1088  pkt = pkt->next;
1089  }
1090  if (verifcount != q->count) {
1091  dbglogf(file, line, "PKTs: invalid pkt count has %d report %d\n", verifcount, q->count);
1092  }
1094 }
1095 
1096 
1097 YRETCODE yPktQueuePushD2H(yInterfaceSt *iface,const USB_Packet *pkt, char * errmsg)
1098 {
1099 #ifdef DUMP_USB_PKT_SHORT
1100  dumpPktSummary(iface->serial, iface->ifaceno,1,pkt);
1101 #endif
1102 #ifdef DEBUG_MISSING_PACKET
1103  {
1104  int mustdump = 0;
1105  yEnterCriticalSection(&iface->rxQueue.cs);
1106  if (pkt->first_stream.pkt != YPKT_CONF) {
1107  pktItem *p = iface->rxQueue.last;
1108  if (p != NULL && p->pkt.first_stream.pkt == YPKT_CONF) {
1109  int pktno = p->pkt.first_stream.pktno + 1;
1110  if (pktno > 7)
1111  pktno = 0;
1112  if (pkt->first_stream.pktno != pktno) {
1113  dbglog("mssing packet on push (need %d received %d)\n", pktno, pkt->first_stream.pktno );
1114  mustdump++;
1115  }
1116  }
1117  }
1118  yLeaveCriticalSection(&iface->rxQueue.cs);
1119  if (mustdump) {
1120  yPktQueueDup(&iface->rxQueue, __FILE_ID__, __LINE__);
1121  }
1122  }
1123 #endif
1124 
1125  return yPktQueuePushEx(&iface->rxQueue,pkt,errmsg);
1126 }
1127 
1128 YRETCODE yPktQueueWaitAndPopD2H(yInterfaceSt *iface,pktItem **pkt, int ms, char * errmsg)
1129 {
1130 
1131  YRETCODE res;
1132  *pkt = NULL;
1133  res= yPktQueuePop(&iface->rxQueue,pkt,errmsg);
1134  if(res != YAPI_SUCCESS || ms == 0){
1135  return res;
1136  }
1137  if (*pkt == NULL) {
1138  yWaitForEvent(&iface->rxQueue.notEmptyEvent, ms);
1139  return yPktQueuePop(&iface->rxQueue,pkt, errmsg);
1140  }
1141  return res;
1142 }
1143 
1144 
1145 YRETCODE yPktQueuePushH2D(yInterfaceSt *iface,const USB_Packet *pkt, char * errmsg)
1146 {
1147  return yPktQueuePushEx(&iface->txQueue,pkt,errmsg);
1148 }
1149 
1150 // return 1 if empty, 0 if not empty, or an error code
1151 static int yPktQueueWaitEmptyH2D(yInterfaceSt *iface,int ms, char * errmsg)
1152 {
1153  if (ms > 0) {
1154  yWaitForEvent(&iface->txQueue.emptyEvent, ms);
1155  }
1156  return yPktQueueIsEmpty(&iface->txQueue,errmsg);
1157 }
1158 
1159 
1161 {
1162 
1163 #ifdef DUMP_USB_PKT_SHORT
1164  pktItem *tmp;
1165  YRETCODE res = yPktQueuePeek(&iface->txQueue,&tmp,NULL);
1166  if(tmp!=NULL){
1167  dumpPktSummary(iface->serial, iface->ifaceno, 0, &tmp->pkt);
1168  }
1169  *pkt=tmp;
1170  return res;
1171 #else
1172  return yPktQueuePeek(&iface->txQueue,pkt,NULL);
1173 #endif
1174 }
1175 
1177 {
1178 
1179 #ifdef DUMP_USB_PKT_SHORT
1180  pktItem *tmp;
1181  YRETCODE res = yPktQueuePop(&iface->txQueue,&tmp,NULL);
1182  if(tmp!=NULL){
1183  dumpPktSummary(iface->serial, iface->ifaceno,0,&tmp->pkt);
1184  }
1185  *pkt=tmp;
1186  return res;
1187 #else
1188  return yPktQueuePop(&iface->txQueue,pkt,NULL);
1189 #endif
1190 }
1191 
1192 
1193 /*****************************************************************************
1194  yyPACKET ioFUNCTIONS
1195  ***************************************************************************/
1196 
1197 
1198 // this function copy the pkt into the interface out queue and send the packet
1199 YRETCODE yyySendPacket(yInterfaceSt *iface, const USB_Packet *pkt, char *errmsg)
1200 {
1201  int res;
1202  res = yPktQueuePushH2D(iface,pkt,errmsg);
1203  if (YISERR(res)) {
1204  return (YRETCODE) res;
1205  }
1206  res = yyySignalOutPkt(iface, errmsg);
1207  if (YISERR(res)) {
1208  return res;
1209  }
1210  res = yPktQueueWaitEmptyH2D(iface,5000,errmsg);
1211  if (YISERR(res)) {
1212  return (YRETCODE) res;
1213  }else if(res > 0){
1214  return YAPI_SUCCESS;
1215  }
1216  return YERRMSG(YAPI_TIMEOUT,"Unable to send packet to the device");
1217 }
1218 
1219 static YRETCODE yAckPkt(yInterfaceSt *iface, int pktno, char *errmsg)
1220 {
1221 
1222  pktItem qpkt;
1223 
1224  YSTREAM_Head *yshead = (YSTREAM_Head*)(qpkt.pkt.data);
1225  u8 *data = qpkt.pkt.data + sizeof(YSTREAM_Head);
1226  yshead->pktno = 0;
1227  yshead->pkt = YPKT_STREAM;
1228  yshead->stream = YSTREAM_META;
1229  yshead->size = 2;
1230  data[0] = USB_META_ACK_D2H_PACKET;
1231  data[1] = pktno & 0xff;
1232  yshead = (YSTREAM_Head*)(qpkt.pkt.data + 2 + sizeof(YSTREAM_Head));
1233  yshead->pkt = YPKT_STREAM;
1234  yshead->stream = YSTREAM_EMPTY;
1235  yshead->size = USB_PKT_SIZE - (2 * sizeof(YSTREAM_Head) + 2);
1236  return yyySendPacket(iface, &qpkt.pkt, errmsg);
1237 }
1238 
1239 
1240 
1241 
1242 // wait for the next Configuration packet to come on a particular interface
1243 // ALL OTHER PACKET OF THIS INTERFACE ARE DROPED
1244 static int yyWaitOnlyConfPkt(yInterfaceSt *iface, u8 cmdtowait,pktItem **rpkt,u32 s_timeout,char *errmsg)
1245 {
1246  u64 timeout = yapiGetTickCount() + s_timeout * 1000;
1247  pktItem *tmp;
1248  u32 dropcount = 0;
1249  YRETCODE error;
1250 
1251  *rpkt = NULL;
1252  do{
1253  error = yPktQueueWaitAndPopD2H(iface, &tmp, 1000, errmsg);
1254  if(error!=YAPI_SUCCESS){
1255  return error;
1256  }
1257  if (tmp != NULL){
1258  if(tmp->pkt.confpkt.head.pkt == YPKT_CONF && tmp->pkt.confpkt.head.stream == cmdtowait){
1259  //conf packet has bee received
1260  YASSERT(tmp->pkt.confpkt.head.size >= sizeof(USB_Conf_Pkt));
1261  *rpkt=tmp;
1262  if(dropcount)
1263  dbglog("drop %d pkt on iface %d\n",dropcount, iface->ifaceno);
1264  return YAPI_SUCCESS;
1265  }
1266 #ifdef DEBUG_DUMP_PKT
1267  else{
1268  dumpAnyPacket("Drop non-config pkt",(u8)iface->ifaceno, &tmp->pkt);
1269  }
1270 #endif
1271  dropcount++;
1272  yFree(tmp);
1273  }
1274  } while(timeout> yapiGetTickCount());
1275 
1276  return YERR(YAPI_TIMEOUT);
1277 }
1278 
1279 
1280 static void yyFormatConfPkt(pktItem *pkt, u8 conftype)
1281 {
1282  pkt->pkt.confpkt.head.pkt = YPKT_CONF;
1283  pkt->pkt.confpkt.head.stream = conftype;
1284  pkt->pkt.confpkt.head.size = USB_PKT_SIZE - sizeof(pkt->pkt.confpkt.head);
1285  pkt->pkt.confpkt.head.pktno = 0;
1286 }
1287 
1288 
1289 // check procol version compatibility
1290 // compatiblewithout limitation -> return 1
1291 // compatible with limitations -> return 0;
1292 // incompatible -> return YAPI_IO_ERROR
1293 static int CheckVersionCompatibility(u16 version,const char *serial, char *errmsg)
1294 {
1295  if ((version & 0xff00) != (YPKT_USB_VERSION_BCD & 0xff00)) {
1296  // major version change
1297  if ((version & 0xff00) > (YPKT_USB_VERSION_BCD & 0xff00)) {
1298  dbglog("Yoctopuce library is too old (using 0x%x, need 0x%x) to handle device %s, please upgrade your Yoctopuce library\n",YPKT_USB_VERSION_BCD,version,serial);
1299  return YERRMSG(YAPI_IO_ERROR,"Library is too old to handle this device");
1300  } else {
1301  // implement backward compatibility when implementing a new protocol
1302  YPANIC;
1303  return 1;
1304  }
1305  } else if (version != YPKT_USB_VERSION_BCD) {
1306  if (version == YPKT_USB_VERSION_NO_RETRY_BCD && (yContext->detecttype & Y_RESEND_MISSING_PKT) == 0) {
1307  // do prompt for firmware update since the Y_RESEND_MISSING_PKT feature is not used
1308  return 1;
1309  }
1310  if (version > YPKT_USB_VERSION_BCD) {
1311  dbglog("Device %s is using a newer protocol, consider upgrading your Yoctopuce library\n",serial);
1312  } else {
1313  dbglog("Device %s is using an older protocol, consider upgrading the device firmware\n",serial);
1314  }
1315  return 0;
1316  }
1317  return 1;
1318 }
1319 
1320 
1321 static int ySendStart(yPrivDeviceSt *dev,char *errmsg)
1322 {
1323  int nextiface;
1324  pktItem qpkt,*rpkt;
1325 
1329  } else{
1330  dev->pktAckDelay = 0;
1331  }
1332  qpkt.pkt.confpkt.conf.start.nbifaces = 1;
1333  qpkt.pkt.confpkt.conf.start.ack_delay = dev->pktAckDelay;
1334  YPROPERR(yyySendPacket(&dev->iface, &qpkt.pkt, errmsg));
1335  YPROPERR(yyWaitOnlyConfPkt(&dev->iface, USB_CONF_START, &rpkt, 5, errmsg));
1336  nextiface = rpkt->pkt.confpkt.conf.start.nbifaces;
1337  if (dev->pktAckDelay) {
1338  // update ack delay with the one from the device (in case device does not implement pkt ack)
1339  dev->pktAckDelay = rpkt->pkt.confpkt.conf.start.ack_delay;
1340  dbglog("Activate USB pkt ack (%dms)\n", dev->pktAckDelay);
1341  }
1342  dev->lastpktno = rpkt->pkt.first_stream.pktno;
1343  yFree(rpkt);
1344  if(nextiface!=0 ){
1345  return YERRMSG(YAPI_VERSION_MISMATCH,"Device has not been started correctly");
1346  }
1347  return YAPI_SUCCESS;
1348 }
1349 
1350 
1351 static int yPacketSetup(yPrivDeviceSt *dev,char *errmsg)
1352 {
1353  pktItem qpkt, *rpkt = NULL;
1354  int res;
1355 
1356  YPROPERR(yyySetup(&dev->iface, errmsg));
1357 
1358  //first try to send a connection reset
1360  qpkt.pkt.confpkt.conf.reset.ok = 1;
1362  YPROPERR(yyySendPacket(&dev->iface, &qpkt.pkt, errmsg));
1363 
1364  if (YISERR(yyWaitOnlyConfPkt(&dev->iface, USB_CONF_RESET, &rpkt, 5, errmsg)) || rpkt == NULL) {
1365  res = YERRMSG(YAPI_VERSION_MISMATCH, "Device does not respond to reset");
1366  goto error;
1367  }
1369  if (CheckVersionCompatibility(dev->iface.pkt_version, dev->iface.serial, errmsg)<0) {
1370  res = YAPI_VERSION_MISMATCH;
1371  goto error;
1372  }
1374  if (rpkt->pkt.confpkt.conf.reset.nbifaces != 1) {
1375  res = YERRMSG(YAPI_VERSION_MISMATCH, "Multiples USB interface are no more supported");
1376  goto error;
1377  }
1378  dev->iface.ifaceno = 0;
1379  yFree(rpkt);
1380  rpkt = NULL;
1381 
1382  if(!YISERR(res=ySendStart(dev,errmsg))){
1383  return YAPI_SUCCESS;
1384  }
1385 error:
1386  if (rpkt) {
1387  yFree(rpkt);
1388  }
1389  //shutdown all previously started interfaces;
1390  dbglog("Closing partially opened device %s\n",dev->infos.serial);
1391  yyyPacketShutdown(&dev->iface);
1392  return res;
1393 }
1394 
1395 // Trigger a non blocking read
1396 static int yGetNextPktEx(yPrivDeviceSt *dev, pktItem **pkt_out, u64 blockUntilTime, char *errmsg)
1397 {
1398  int dropcount=0;
1399  u8 nextpktno;
1400  YRETCODE res;
1401  pktItem *item;
1402  u64 wait;
1403  u64 now;
1404  yInterfaceSt *iface;
1405 
1406  *pkt_out = NULL;
1407  iface = &dev->iface;
1408 again:
1409  now = yapiGetTickCount();
1410  if (blockUntilTime > now)
1411  wait = blockUntilTime - now;
1412  else
1413  wait = 0;
1414 
1415 
1416 
1417  // ptr is set to null by yPktQueueWaitAndPop
1418  res = yPktQueueWaitAndPopD2H(iface, &item, (int)wait, errmsg);
1419  if (YISERR(res))
1420  return res;
1421  nextpktno = NEXT_YPKT_NO(dev->lastpktno);
1422  if (item != NULL) {
1423  if (dev->pktAckDelay > 0) {
1424  res = yAckPkt(iface, item->pkt.first_stream.pktno, errmsg);
1425  if (YISERR(res)){
1426  yFree(item);
1427  return res;
1428  }
1429  }
1430  // verfiy the packet
1431  if (item->pkt.first_stream.pkt == YPKT_CONF) {
1432 #ifdef DEBUG_DUMP_PKT
1433  dumpAnyPacket("Drop Late config pkt",iface->ifaceno,&item->pkt);
1434 #endif
1435  yFree(item);
1436  dropcount++;
1437  if(dropcount >10){
1438  dbglog("Too many packets dropped, disable %s\n",dev->infos.serial);
1439  return YERRMSG(YAPI_IO_ERROR,"Too many packets dropped");
1440  }
1441  goto again;
1442  }
1443  if (item->pkt.first_stream.pktno == dev->lastpktno) {
1444  //late retry : drop it since we allready have the packet.
1445  yFree(item);
1446  goto again;
1447  }
1448 
1449  if(item->pkt.first_stream.pktno == nextpktno){
1450  *pkt_out = item;
1451  dev->lastpktno = nextpktno;
1452 #ifdef DEBUG_DUMP_PKT
1453  dumpAnyPacket("POP Pkt",iface->ifaceno,&item->pkt);
1454 #endif
1455  return YAPI_SUCCESS;
1456  } else {
1457  yPktQueueDup(&iface->rxQueue, nextpktno, __FILE_ID__, __LINE__);
1458  yFree(item);
1459  return YERRMSG(YAPI_IO_ERROR, "Missing Packet");
1460  }
1461  }
1462  return YAPI_SUCCESS;
1463 }
1464 
1465 
1466 /*****************************************************************
1467  * yStream API with cycling logic of the inside of the packet
1468 *****************************************************************/
1469 static int yStreamGetTxBuff(yPrivDeviceSt *dev, u8 **data, u8 *maxsize);
1470 static int yStreamTransmit(yPrivDeviceSt *dev, u8 proto, u8 size, char *errmsg);
1471 static int yStreamFlush(yPrivDeviceSt *dev, char *errmsg);
1472 
1473 static int yStreamSetup(yPrivDeviceSt *dev,char *errmsg)
1474 {
1475  u32 currUtcTime;
1476  YPROPERR(yPacketSetup(dev,errmsg));
1477  // now we have all setup packet sent and received
1478  dev->currxpkt=NULL;
1479  dev->curxofs=0xff;
1480  dev->curtxpkt = &dev->tmptxpkt;
1481  dev->tmptxpkt.next=NULL;
1482  dev->curtxofs=0;
1483  dev->devYdxMap=NULL;
1484  dev->lastUtcUpdate=0;
1485  // send UTC time to the device
1486  currUtcTime = (u32)time(NULL);
1487  if (currUtcTime > (u32)0x51f151f1){ // timestamp appears to be valid
1488  u8 *pktdata;
1489  u8 maxpktlen;
1490  // send updated UTC timestamp to keep datalogger on time
1491  if (yStreamGetTxBuff(dev, &pktdata, &maxpktlen) && maxpktlen >= 5) {
1492  dev->lastUtcUpdate = currUtcTime;
1493  pktdata[0] = USB_META_UTCTIME;
1494  pktdata[1] = currUtcTime & 0xff;
1495  pktdata[2] = (currUtcTime >> 8) & 0xff;
1496  pktdata[3] = (currUtcTime >> 16) & 0xff;
1497  pktdata[4] = (currUtcTime >> 24) & 0xff;
1498  YPROPERR(yStreamTransmit(dev, YSTREAM_META, 5, errmsg));
1499  YPROPERR(yStreamFlush(dev, errmsg));
1500  }
1501  }
1502  return YAPI_SUCCESS;
1503 }
1504 
1505 
1506 static int yStreamReceived(yPrivDeviceSt *dev, u8 *stream, u8 **data, u8 *size, u64 blockUntilTime, char *errmsg)
1507 {
1508  YSTREAM_Head *yshead;
1509  int res;
1510 
1511  //check if we have processed the full usb packet
1512  if (dev->curxofs >= USB_PKT_SIZE - sizeof(YSTREAM_Head)) {
1513  // look if we have the next packet on a interface
1514  if (dev->currxpkt) {
1515  yFree(dev->currxpkt);
1516  dev->currxpkt=NULL;
1517  }
1518  res = yGetNextPktEx(dev, &dev->currxpkt, blockUntilTime, errmsg);
1519  YPROPERR(res);
1520  if (dev->currxpkt != NULL) {
1521  dev->curxofs=0;
1522  } else {
1523  // no pkt avail
1524  return 0;
1525  }
1526  }
1527 
1528  yshead= (YSTREAM_Head*) &dev->currxpkt->pkt.data[dev->curxofs];
1529  YASSERT(dev->curxofs + sizeof(YSTREAM_Head) + yshead->size <= USB_PKT_SIZE);
1530  *stream = yshead->stream;
1531  *size = yshead->size;
1532  *data = &dev->currxpkt->pkt.data[ dev->curxofs + sizeof(YSTREAM_Head) ];
1533 
1534  return 1;
1535 }
1536 
1537 static int yStreamReceptionDone(yPrivDeviceSt *dev,char *errmsg)
1538 {
1539  YSTREAM_Head * yshead= (YSTREAM_Head*) &dev->currxpkt->pkt.data[dev->curxofs];
1540  dev->curxofs += sizeof(YSTREAM_Head) + yshead->size;
1541  return YAPI_SUCCESS;
1542 }
1543 // return 0 when no more buff is available
1544 static int yStreamGetTxBuff(yPrivDeviceSt *dev, u8 **data, u8 *maxsize)
1545 {
1546  u8 avail;
1547  avail = USB_PKT_SIZE - dev->curtxofs;
1548  if(avail <= sizeof(YSTREAM_Head)){
1549  //we may want to allocate an new buffer
1550  return 0;
1551  }
1552 
1553  *maxsize = avail - sizeof(YSTREAM_Head);
1554  *data = &dev->curtxpkt->pkt.data[dev->curtxofs+sizeof(YSTREAM_Head)];
1555  return 1;
1556 }
1557 
1558 static int yStreamFlush(yPrivDeviceSt *dev,char *errmsg)
1559 {
1560  u8 avail;
1561 
1562  if(dev->curtxofs==0){
1563  return YAPI_SUCCESS;
1564  }
1565 
1566  avail = USB_PKT_SIZE - dev->curtxofs;
1567 
1568  if(avail >=sizeof(YSTREAM_Head) ){
1569  YSTREAM_Head *yshead = (YSTREAM_Head*) (dev->curtxpkt->pkt.data + dev->curtxofs);
1570  yshead->pkt = YPKT_STREAM;
1571  yshead->stream = YSTREAM_EMPTY;
1572  yshead->size = avail - sizeof(YSTREAM_Head);
1573  dev->curtxofs += sizeof(YSTREAM_Head)+yshead->size;
1574  }
1575  YPROPERR( yyySendPacket(&dev->iface,&dev->curtxpkt->pkt, errmsg));
1576  dev->curtxofs =0;
1577  return YAPI_SUCCESS;
1578 }
1579 
1580 
1581 static int yStreamTransmit(yPrivDeviceSt *dev, u8 proto,u8 size,char *errmsg)
1582 {
1583  //dbglog("yPacketTransmit\n");
1584 
1585  YSTREAM_Head *yshead;
1586  yshead = (YSTREAM_Head*) dev->curtxpkt->pkt.data + dev->curtxofs ;
1587  yshead->pktno =0;
1588  yshead->pkt = YPKT_STREAM;
1589  yshead->stream = proto;
1590  yshead->size = size;
1591  if(!(dev->curtxofs + sizeof(YSTREAM_Head) + size <=USB_PKT_SIZE)){
1592  dbglog("Buffer overrun detected on (%s)\n",dev->infos.serial);
1593  dbglog("unable to append data proto=%d (%d + %d + %d <= %d) (%s)\n",
1594  proto,dev->curtxofs,sizeof(YSTREAM_Head),size,USB_PKT_SIZE);
1595  //dumpAnyPacket("ystream buffer",0,&dev->curtxpkt->pkt);
1596  return YERRMSG(YAPI_IO_ERROR,"buffer overrun");
1597  }
1598  dev->curtxofs += sizeof(YSTREAM_Head)+size;
1599  if( dev->curtxofs >= USB_PKT_SIZE-sizeof(YSTREAM_Head))
1600  return yStreamFlush(dev,errmsg);
1601  return YAPI_SUCCESS;
1602 }
1603 
1604 
1606 {
1607  if(dev->devYdxMap) {
1608  yFree(dev->devYdxMap);
1609  dev->devYdxMap = NULL;
1610  }
1611  yyyPacketShutdown(&dev->iface);
1612 }
1613 
1614 
1615 // Notification packet dispatcher
1616 //
1617 static void yDispatchNotice(yPrivDeviceSt *dev, USB_Notify_Pkt *notify, int pktsize, int isV2)
1618 {
1619  yPrivDeviceSt *notDev;
1620  u16 vendorid,deviceid;
1621 
1622  if(isV2 || notify->firstByte <= NOTIFY_1STBYTE_MAXTINY || notify->firstByte >= NOTIFY_1STBYTE_MINSMALL) {
1623  // Tiny or small pubval notification:
1624  // create a new null-terminated small notification that we can use and forward
1625  char buff[sizeof(Notification_small)+YOCTO_PUBVAL_SIZE+2];
1626  Notification_small *smallnot = (Notification_small *)buff;
1627  memset(smallnot->pubval,0,YOCTO_PUBVAL_SIZE+2);
1628 
1629  if (notify->smallpubvalnot.funInfo.v2.isSmall == 0) {
1630  // convert tiny notification to samll notification
1631  memcpy(smallnot->pubval, notify->tinypubvalnot.pubval,pktsize - sizeof(Notification_tiny));
1632  smallnot->funInfo.v2.funydx = notify->tinypubvalnot.funInfo.v2.funydx;
1633  smallnot->funInfo.v2.typeV2 = notify->tinypubvalnot.funInfo.v2.typeV2;
1634  smallnot->funInfo.v2.isSmall = 1;
1635  smallnot->devydx = wpGetDevYdx(yHashPutStr(dev->infos.serial));
1636  } else {
1637 #ifndef __BORLANDC__
1638  YASSERT(0);
1639 #endif
1640  // Assert added on 2015-02-25, remove code below when confirmed dead code
1641  memcpy(smallnot->pubval,notify->smallpubvalnot.pubval,pktsize - sizeof(Notification_small));
1642  smallnot->funInfo.raw = notify->smallpubvalnot.funInfo.raw;
1643  if(dev->devYdxMap) {
1644  smallnot->devydx = dev->devYdxMap[notify->smallpubvalnot.devydx];
1645  } else {
1646  smallnot->devydx = 255;
1647  }
1648  }
1649 #ifdef DEBUG_NOTIFICATION
1650  if(smallnot->funInfo.v2.typeV2 == NOTIFY_V2_LEGACY) {
1651  dbglog("notifysmall %d %d %s\n",smallnot->devydx,smallnot->funInfo.v2.funydx,smallnot->pubval);
1652  } else {
1653  u8 *tmpbuff = (u8 *)smallnot->pubval;
1654  dbglog("notifysmall %d %d %d:%02x.%02x.%02x.%02x.%02x.%02x\n",smallnot->devydx,smallnot->funInfo.v2.funydx,smallnot->funInfo.v2.typeV2,
1655  tmpbuff[0],tmpbuff[1],tmpbuff[2],tmpbuff[3],tmpbuff[4],tmpbuff[5]);
1656  }
1657 #endif
1658  if (smallnot->devydx < 255 && smallnot->funInfo.v2.typeV2 != NOTIFY_V2_FLUSHGROUP) {
1659  ypUpdateYdx(smallnot->devydx,smallnot->funInfo,smallnot->pubval);
1660  if(yContext->rawNotificationCb){
1661  yContext->rawNotificationCb((USB_Notify_Pkt *)smallnot);
1662  }
1663  }
1664  return;
1665  }
1666 
1667  notDev=findDev(notify->head.serial,FIND_FROM_SERIAL);
1668  if(notDev==NULL){
1669  dbglog("drop Notification %d for %s received (device missing)\n", notify->head.type,notify->head.serial);
1670  return;
1671  }
1672 
1673 #ifdef DEBUG_NOTIFICATION
1674  dbglog("Notification %d received\n", notify->head.type);
1675 #endif
1676  switch(notify->head.type){
1677  case NOTIFY_PKT_NAME:
1679 #ifdef DEBUG_NOTIFICATION
1680  dbglog("new name is \"%s\"\n", notify->namenot.name);
1681 #endif
1682  notDev->infos.beacon=notify->namenot.beacon;
1683 #ifdef DEBUG_NOTIFICATION
1684  dbglog("new beacon %x\n",notify->namenot.beacon);
1685 #endif
1686  {
1687  yStrRef serialref = yHashPutStr(notify->head.serial);
1688  yStrRef lnameref = yHashPutStr(notify->namenot.name);
1689  wpSafeUpdate(NULL, MAX_YDX_PER_HUB,serialref,lnameref,yHashUrlUSB(serialref),notify->namenot.beacon);
1690  if(yContext->rawNotificationCb){
1691  yContext->rawNotificationCb(notify);
1692  }
1693  }
1694  break;
1695  case NOTIFY_PKT_PRODNAME:
1697 #ifdef DEBUG_NOTIFICATION
1698  dbglog("Product name update %s\n",notify->productname);
1699 #endif
1700  break;
1701  case NOTIFY_PKT_CHILD:
1702 #ifdef DEBUG_NOTIFICATION
1703  dbglog("child update %s %d %u\n",notify->childserial.childserial,notify->childserial.onoff,notify->childserial.devydx);
1704 #endif
1705  if(notDev == dev) {
1706  // build devYdx mapping for immediate child hubs
1707  if(dev->devYdxMap == NULL) {
1708  dev->devYdxMap = (u8*) yMalloc(ALLOC_YDX_PER_HUB);
1709  memset(dev->devYdxMap, 255, ALLOC_YDX_PER_HUB);
1710  }
1712  }
1713  break;
1714  case NOTIFY_PKT_FIRMWARE:
1715 #ifdef DEBUG_NOTIFICATION
1716  dbglog("notify firmware %s\n",notify->firmwarenot.firmware);
1717 #endif
1719  FROM_SAFE_U16(notify->firmwarenot.deviceid,deviceid);
1720  FROM_SAFE_U16(notify->firmwarenot.vendorid,vendorid);
1721  YASSERT(notDev->infos.deviceid == deviceid);
1722  YASSERT(notDev->infos.vendorid == vendorid);
1723  break;
1724  case NOTIFY_PKT_FUNCNAME:
1725  notify->funcnameydxnot.funydx = -1;
1726  // common code below
1729  // Unknown subclass, use YFunction instead
1731  }
1732 #ifdef DEBUG_NOTIFICATION
1733  if(notify->funcnameydxnot.funydx >= 0) {
1734  dbglog("notify functnameydx %s %s %d %d\n",notify->funcnamenot.funcid, notify->funcnamenot.funcname,
1735  notify->funcnameydxnot.funydx, notify->funcnameydxnot.funclass);
1736  } else {
1737  dbglog("notify functname %s %s\n",notify->funcnamenot.funcid, notify->funcnamenot.funcname);
1738  }
1739 #endif
1741  if(yContext->rawNotificationCb){
1742  yContext->rawNotificationCb(notify);
1743  }
1744  break;
1745  case NOTIFY_PKT_FUNCVAL:
1746  {
1747  char buff[YOCTO_PUBVAL_SIZE+2];
1748  memset(buff,0,YOCTO_PUBVAL_SIZE+2);
1749  memcpy(buff,notify->pubvalnot.pubval,YOCTO_PUBVAL_SIZE);
1750 #ifdef DEBUG_NOTIFICATION
1751  dbglog("notify funcval %s %s\n",notify->pubvalnot.funcid, buff);
1752 #endif
1753  ypUpdateUSB(notDev->infos.serial,notify->pubvalnot.funcid,NULL,-1,-1,buff);
1754  if(yContext->rawNotificationCb){
1755  yContext->rawNotificationCb(notify);
1756  }
1757  }
1758  break;
1760 #ifdef DEBUG_NOTIFICATION
1761  dbglog("notify steam ready (%x)\n",notify->raw);
1762 #endif
1763  notDev->rstatus = YRUN_AVAIL;
1764  break;
1765  case NOTIFY_PKT_LOG:
1766  {
1767  if (!strncmp(notify->head.serial, dev->infos.serial, YOCTO_SERIAL_LEN)) {
1768  yStrRef serialref = yHashPutStr(notify->head.serial);
1769  int devydx = wpGetDevYdx(serialref);
1770  if (devydx >=0 ) {
1771  yEnterCriticalSection(&yContext->generic_cs);
1772  if (yContext->generic_infos[devydx].flags & DEVGEN_LOG_ACTIVATED) {
1773  yContext->generic_infos[devydx].flags |= DEVGEN_LOG_PENDING;
1774 #ifdef DEBUG_NOTIFICATION
1775  dbglog("notify device log for %s\n",dev->infos.serial);
1776 #endif
1777  }
1778 #ifdef DEBUG_NOTIFICATION
1779  else {
1780  dbglog("notify device log for %s dropped\n",dev->infos.serial);
1781  }
1782 #endif
1783  yLeaveCriticalSection(&yContext->generic_cs);
1784  }
1785 
1786  }
1787  if(yContext->rawNotificationCb){
1788  yContext->rawNotificationCb(notify);
1789  }
1790  }
1791  default:
1792  break;
1793  }
1794 }
1795 
1796 // Timed report packet dispatcher
1797 //
1798 static void yDispatchReportV1(yPrivDeviceSt *dev, u8 *data, int pktsize)
1799 {
1800  yStrRef serialref = yHashPutStr(dev->infos.serial);
1801 #ifdef DEBUG_NOTIFICATION
1802  {
1803  USB_Report_Pkt_V1 *report = (USB_Report_Pkt_V1*)data;
1804  dbglog("timed report (v1) for %d %d\n", wpGetDevYdx(serialref), report->funYdx);
1805  }
1806 #endif
1807  if(yContext->rawReportCb) {
1808  yContext->rawReportCb(serialref, (USB_Report_Pkt_V1*) data, pktsize);
1809  }
1810  if (yContext->timedReportCallback) {
1811  int devydx = wpGetDevYdx(serialref);
1812  if (devydx < 0)
1813  return;
1814  while (pktsize > 0) {
1815  USB_Report_Pkt_V1 *report = (USB_Report_Pkt_V1*) data;
1816  int len = report->extraLen + 1;
1817  if (report->funYdx == 0xf) {
1818  u32 t = data[1] + 0x100u * data[2] + 0x10000u * data[3] + 0x1000000u * data[4];
1819  yEnterCriticalSection(&yContext->generic_cs);
1820  yContext->generic_infos[devydx].deviceTime = (double)t + data[5] / 250.0;
1821  yLeaveCriticalSection(&yContext->generic_cs);
1822  } else {
1823  YAPI_FUNCTION fundesc;
1824  double devtime;
1825  Notification_funydx funInfo;
1826  funInfo.raw = report->funYdx;
1827  ypRegisterByYdx(devydx, funInfo, NULL, &fundesc);
1828  data[0] = report->isAvg ? 1 : 0;
1829  yEnterCriticalSection(&yContext->generic_cs);
1830  devtime = yContext->generic_infos[devydx].deviceTime;
1831  yLeaveCriticalSection(&yContext->generic_cs);
1832  yFunctionTimedUpdate(fundesc, devtime, data, len + 1);
1833  }
1834  pktsize -= 1 + len;
1835  data += 1 + len;
1836  }
1837  }
1838 }
1839 
1840 // Timed report packet dispatcher
1841 //
1842 static void yDispatchReportV2(yPrivDeviceSt *dev, u8 *data, int pktsize)
1843 {
1844  yStrRef serialref = yHashPutStr(dev->infos.serial);
1845 #ifdef DEBUG_NOTIFICATION
1846  {
1847  USB_Report_Pkt_V2 *report = (USB_Report_Pkt_V2*)data;
1848  dbglog("timed report (v2) for %d %d\n", wpGetDevYdx(serialref), report->funYdx);
1849  }
1850 #endif
1851  if(yContext->rawReportV2Cb) {
1852  yContext->rawReportV2Cb(serialref, (USB_Report_Pkt_V2*) data, pktsize);
1853  }
1854  if (yContext->timedReportCallback) {
1855  int devydx = wpGetDevYdx(serialref);
1856  if (devydx < 0)
1857  return;
1858  while (pktsize > 0) {
1859  USB_Report_Pkt_V2 *report = (USB_Report_Pkt_V2*) data;
1860  int len = report->extraLen + 1;
1861  if (report->funYdx == 0xf) {
1862  u32 t = data[1] + 0x100u * data[2] + 0x10000u * data[3] + 0x1000000u * data[4];
1863  yEnterCriticalSection(&yContext->generic_cs);
1864  yContext->generic_infos[devydx].deviceTime = (double)t + data[5] / 250.0;
1865  yLeaveCriticalSection(&yContext->generic_cs);
1866  } else {
1867  YAPI_FUNCTION fundesc;
1868  double devtime;
1869  Notification_funydx funInfo;
1870  funInfo.raw = report->funYdx;
1871  ypRegisterByYdx(devydx, funInfo, NULL, &fundesc);
1872  data[0] = 2;
1873  yEnterCriticalSection(&yContext->generic_cs);
1874  devtime = yContext->generic_infos[devydx].deviceTime;
1875  yLeaveCriticalSection(&yContext->generic_cs);
1876  yFunctionTimedUpdate(fundesc, devtime, data, len + 1);
1877  }
1878  pktsize -= 1 + len;
1879  data += 1 + len;
1880  }
1881  }
1882 }
1883 
1884 // blockUntilTime:
1885 // 0 -> only check pending (non blocking)
1886 // >0 -> wait util yapiGetTickCount is >= blockUntilTime
1887 static int yDispatchReceive(yPrivDeviceSt *dev, u64 blockUntilTime, char *errmsg)
1888 {
1889  u8 stream;
1890  u8 size;
1891  u8 *data;
1892 #ifdef DEBUG_USB_TRAFIC
1893  char dump[64];
1894 #endif
1895  int pktavail;
1896 
1897  pktavail = yStreamReceived(dev, &stream, &data, &size, blockUntilTime,errmsg);
1898  YPROPERR(pktavail);
1899  while (pktavail && yFifoGetFree(&dev->http_fifo) > size) {
1900  switch (stream) {
1901  case YSTREAM_TCP_CLOSE:
1902 #ifdef DEBUG_USB_TRAFIC
1903  dbglog("YSTREAM : TCP_CLOSE %d (%d:%d)\n",size,dev->pendingIO.hdl,dev->httpstate);
1904  memcpy(dump,data,size);
1905  dump[size]=0;
1906  dbglog("---------------------------\n");
1907  dbglog("%s\n",dump);
1908  dbglog("---------------------------\n");
1909 #endif
1910  if(dev->httpstate == YHTTP_OPENED || dev->httpstate == YHTTP_INREQUEST) {
1911  //handle new received packet
1912  if(size != yPushFifo(&dev->http_fifo, data, size)){
1913  return YERRMSG(YAPI_IO_ERROR,"FIFO overrun");
1914  }
1916  } else if(dev->httpstate == YHTTP_CLOSE_BY_API) {
1917  dev->httpstate = YHTTP_CLOSED;
1918  }
1919  break;
1920  case YSTREAM_TCP:
1921 #ifdef DEBUG_USB_TRAFIC
1922  dbglog("YSTREAM : TCP %d (%d:%d)\n",size,dev->pendingIO.hdl,dev->httpstate);
1923  memcpy(dump,data,size);
1924  dump[size]='\0';
1925  dbglog("---------------------------\n");
1926  dbglog("%s\n",dump);
1927  dbglog("---------------------------\n");
1928 #endif
1929  if (dev->httpstate == YHTTP_OPENED || dev->httpstate == YHTTP_INREQUEST) {
1930  //handle new received packet
1931  if(size!=yPushFifo(&dev->http_fifo, data, size)){
1932  return YERRMSG(YAPI_IO_ERROR,"FIFO overrun");
1933  }
1934  }
1935  break;
1936  case YSTREAM_NOTICE:
1937  yDispatchNotice(dev, (USB_Notify_Pkt*)data, size, 0);
1938  break;
1939  case YSTREAM_NOTICE_V2:
1940  yDispatchNotice(dev, (USB_Notify_Pkt*)data, size, 1);
1941  break;
1942  case YSTREAM_REPORT:
1943  yDispatchReportV1(dev, data, size);
1944  break;
1945  case YSTREAM_REPORT_V2:
1946  yDispatchReportV2(dev, data, size);
1947  break;
1948  case YSTREAM_EMPTY:
1949  default:
1950  //packet droped
1951  break;
1952  }
1953  //listen again
1954  YPROPERR(yStreamReceptionDone(dev,errmsg));
1955  // do not block on second atempt
1956  pktavail=yStreamReceived(dev,&stream, &data, &size, 0, errmsg);
1957  YPROPERR(pktavail);
1958  }
1959  return YAPI_SUCCESS;
1960 }
1961 
1962 
1963 
1964 
1965 
1966 /*****************************************************************************
1967  ENUMERATION RELATED FUNCTION
1968  ***************************************************************************/
1969 #ifdef DEBUG_DEV_ENUM
1970 const char *YDEV_STATUS_TXT[] =
1971 {
1972  "YDEV_UNPLUGED", // device has been plugged by the past but is no more
1973  // -> YDEV_ARRIVAL
1974  "YDEV_WORKING", // device is plugged and running
1975  // -> YDEV->UNPLUGET, YDEV_ALLREADY_THERE
1976  "YDEV_NOTRESPONDING" // device has not repsond to StartDevice and we will never try to speak with it
1977  // -> none
1978 } ;
1979 #endif
1980 
1981 static void enuResetDStatus(void)
1982 {
1983 
1984  yPrivDeviceSt *p=yContext->devs;
1985 
1986  while(p){
1987 #ifdef DEBUG_DEV_ENUM_VERBOSE
1988  dbglog("Initial State of %s is %s\n",p->infos.serial,YDEV_STATUS_TXT[p->dStatus]);
1989 #endif
1990  if( p->dStatus== YDEV_WORKING){
1991  p->enumAction=YENU_STOP;
1992  }else{
1993  p->enumAction=YENU_NONE;
1994  }
1995  p=p->next;
1996  }
1997 }
1998 
1999 
2001 {
2002  yPrivDeviceSt *p;
2003 
2004  for(p=yContext->devs ; p ; p=p->next ){
2005  if(p->infos.vendorid == iface->vendorid && p->infos.deviceid == iface->deviceid
2006  && strncmp(p->infos.serial,iface->serial,YOCTO_SERIAL_LEN)==0){
2007  return p;
2008  }
2009  }
2010  return NULL;
2011 }
2012 
2013 //allocate a new device structure
2015 {
2016  yPrivDeviceSt *dev;
2017  dev = (yPrivDeviceSt*) yMalloc(sizeof(yPrivDeviceSt));
2018  yMemset(dev,0,sizeof(yPrivDeviceSt));
2019  dev->http_raw_buf = (u8*) yMalloc(HTTP_RAW_BUFF_SIZE);
2022  return dev;
2023 }
2024 
2025 static void FreeDevice(yPrivDeviceSt *dev)
2026 {
2028  yFree(dev->http_raw_buf);
2029  yFifoCleanup(&dev->http_fifo);
2030  yFree(dev);
2031 }
2032 
2033 
2034 
2035 // Start an interface
2036 static int StartDevice(yPrivDeviceSt *dev, char *errmsg)
2037 {
2038  unsigned delay = 10;
2039  int nb_try;
2040  int res = YERRMSG(YAPI_IO_ERROR, "Negotiation failed");
2041 
2042  for (nb_try = 0; nb_try < 4; nb_try++, delay *= 4, dbglog("retrying StartDevice (%s)\n", errmsg)) {
2043  u64 timeout;
2044  int res = yStreamSetup(dev, errmsg);
2045  if (YISERR(res)) {
2046  continue;
2047  }
2048  timeout = yapiGetTickCount() + 10000;
2049  do {
2050  res = yDispatchReceive(dev, timeout, errmsg);
2052  dev->rstatus = YRUN_AVAIL;
2053  }
2054  if (yapiGetTickCount() >= timeout) {
2055  yStreamShutdown(dev);
2056  return YERRMSG(YAPI_TIMEOUT, "Negotiation failed (device did not respond for 10 secs");
2057  }
2058  } while (res == YAPI_SUCCESS && dev->rstatus != YRUN_AVAIL);
2059  if (res == YAPI_SUCCESS && dev->rstatus == YRUN_AVAIL) {
2060  return YAPI_SUCCESS;
2061  }
2062  yStreamShutdown(dev);
2063  }
2064  return res;
2065 }
2066 
2067 
2068 static int StopDevice(yPrivDeviceSt *dev,char *errmsg)
2069 
2070 {
2071  dev->rstatus=YRUN_STOPED;
2072  yStreamShutdown(dev);
2073  return YAPI_SUCCESS;
2074 }
2075 
2076 //thread safe because only modified only by yDetectDevices which is not reentrant
2077 static void enuUpdateDStatus(void)
2078 {
2079  yPrivDeviceSt *p=yContext->devs;
2080  char errmsg[YOCTO_ERRMSG_LEN];
2081  int res, updateWP;
2082  yStrRef lnameref, prodref;
2083  yUrlRef usb;
2084  u8 beacon;
2085  u16 deviceid;
2086 
2087  while(p){
2088  yStrRef serialref = yHashPutStr(p->infos.serial);
2089  switch(p->enumAction){
2090  case YENU_STOP:
2091  devStartEnum(p);
2092 #ifdef DEBUG_DEV_ENUM
2093  dbglog("ENU:stop %s(%d)->YDEV_UNPLUGED\n",p->infos.serial,p->infos.nbinbterfaces);
2094 #endif
2095  p->dStatus = YDEV_UNPLUGGED;
2096  if(YISERR(StopDevice(p,errmsg))){
2097  dbglog("Unable to stop the device %s correctly:(%s)\n",p->infos.serial,errmsg);
2098  }
2099  dbglog("Device %s unplugged\n",p->infos.serial);
2100  devStopEnum(p);
2101  wpSafeUnregister(serialref);
2102  break;
2103 
2104  case YENU_RESTART:
2105  devStartEnum(p);
2106  if(YISERR(StopDevice(p,errmsg))){
2107  dbglog("Unable to stop the device %s correctly:(%s)\n",p->infos.serial,errmsg);
2108  }
2109  p->dStatus = YDEV_WORKING; //we need to put the device in working to start device (safe because we alread have the mutex)
2110  res = StartDevice(p, errmsg);
2111  if(YISERR(res)){
2112  // we are unable to restart the device -> unplug it and follow the traditional process (white page update etc...)
2113 #ifdef DEBUG_DEV_ENUM
2114  dbglog("ENU:Restart %s(%d)->YDEV_UNPLUGED (restart failed)\n",p->infos.serial,p->infos.nbinbterfaces);
2115 #endif
2116 
2117  p->dStatus = YDEV_UNPLUGGED;
2118  }else{
2119 #ifdef DEBUG_DEV_ENUM
2120  dbglog("ENU:restart %s(%d)->YDEV_WORKING(restart)\n",p->infos.serial,p->infos.nbinbterfaces);
2121 #endif
2122  }
2123  devStopEnum(p);
2124  if (YISERR(res)) {
2125  wpSafeUnregister(serialref);
2126  }
2127  break;
2128  case YENU_START:
2129  if( p->next_startup_attempt <= yapiGetTickCount()) {
2130  devStartEnum(p);
2131  updateWP = 0;
2132  p->dStatus = YDEV_WORKING; //we need to put the device in working to start device (safe because we alread have the mutex)
2133  res = StartDevice(p, errmsg);
2134  if(YISERR(res)){
2136  dbglog("Unable to start the device %s correctly (%s). retry later\n", p->infos.serial, errmsg);
2137 #ifdef DEBUG_DEV_ENUM
2138  dbglog("ENU:start %s(%d)->YDEV_UNPLUGED\n", p->infos.serial, p->infos.nbinbterfaces);
2139 #endif
2140  p->dStatus = YDEV_UNPLUGGED;
2141  p->next_startup_attempt = yapiGetTickCount() + 1000;
2142  p->nb_startup_retry++;
2143  } else {
2144 #ifdef DEBUG_DEV_ENUM
2145  dbglog("ENU:start %s(%d)->YDEV_NOTRESPONDING\n", p->infos.serial, p->infos.nbinbterfaces);
2146 #endif
2147  dbglog("Disable device %s (reason:%s)\n",p->infos.serial,errmsg);
2149  updateWP = 1;
2150  }
2151  devStopEnum(p);
2152  if (updateWP) {
2153  wpSafeUnregister(serialref);
2154  }
2155  } else {
2156 #ifdef DEBUG_DEV_ENUM
2157  dbglog("ENU:start %s(%d)->YDEV_WORKING\n",p->infos.serial,p->infos.nbinbterfaces);
2158 #endif
2159  p->yhdl = yContext->devhdlcount++;
2160  dbglog("Device %s plugged\n",p->infos.serial);
2161  lnameref = yHashPutStr(p->infos.logicalname);
2162  prodref = yHashPutStr(p->infos.productname);
2163  beacon = p->infos.beacon;
2164  deviceid = p->infos.deviceid;
2165  usb = yHashUrlUSB(serialref);
2166  devStopEnum(p);
2167  wpSafeRegister(NULL, MAX_YDX_PER_HUB, serialref, lnameref, prodref, deviceid, usb, beacon);
2168  }
2169  } else {
2170 #ifdef DEBUG_DEV_ENUM_VERBOSE
2171  dbglog("enum : %s (%d ifaces) waiting for next attempt\n",p->infos.serial,p->infos.nbinbterfaces);
2172 #endif
2173  }
2174  break;
2175  case YENU_NONE:
2176  break;
2177  }
2178  p=p->next;
2179  }
2180 }
2181 
2183 {
2184  yEnterCriticalSection(&yContext->enum_cs);
2185  enuResetDStatus();
2186  enuUpdateDStatus();
2187  yLeaveCriticalSection(&yContext->enum_cs);
2188 
2189 }
2190 
2192 {
2193  int nbifaces=0;
2194  yInterfaceSt *iface;
2195  int j;
2196  yInterfaceSt *runifaces=NULL;
2197 
2198  YPROPERR(yyyUSBGetInterfaces(&runifaces,&nbifaces,errmsg));
2199 
2200  yEnterCriticalSection(&yContext->enum_cs);
2201  enuResetDStatus();
2202 
2203  for (j = 0, iface = runifaces; j < nbifaces; j++, iface++){
2204  yPrivDeviceSt *dev;
2205  if (iface->deviceid <= YOCTO_DEVID_BOOTLOADER)
2206  continue;
2207 
2208  dev =enuFindDevSlot(iface);
2209  if(dev){
2210  //device already allocated
2211  if(dev->dStatus == YDEV_WORKING ){
2212  if(!yyyOShdlCompare(dev, iface)){
2213  ENUMLOG("%s was already there but OS handles are no more valid\n",dev->infos.serial);
2214  dev->enumAction = YENU_RESTART;
2215  } else if (dev->rstatus==YRUN_ERROR){
2216  ENUMLOG("%s was already there but need to be reset due to runtime error\n",dev->infos.serial);
2217  dev->enumAction = YENU_RESTART;
2218  } else {
2219  // device is working correctly
2220  dev->enumAction = YENU_NONE;
2221  }
2222  }else if(dev->dStatus == YDEV_UNPLUGGED) {
2223  ENUMLOG("%s replug of a previously detected device\n",dev->infos.serial);
2224  dev->enumAction = YENU_START;
2225  // to be safe we update infos with fresh data form last enumeration
2226  dev->infos.nbinbterfaces = 1;
2227  memcpy(&dev->iface, iface, sizeof(yInterfaceSt));
2228  } else if(dev->dStatus == YDEV_NOTRESPONDING && !yyyOShdlCompare(dev, iface) ){
2229  ENUMLOG("%s replug of a previously detected device that was not responding\n",dev->infos.serial);
2230  dev->enumAction = YENU_START;
2231  // to be safe we update infos with fresh data form last enumeration
2232  dev->infos.nbinbterfaces = 1;
2233  memcpy(&dev->iface, iface, sizeof(yInterfaceSt));
2234  }
2235  }else{
2236  ENUMLOG("%s newly plugged device \n",iface->serial);
2237  //ALLOCATE A NEW DEVICE STUCTURE
2238  dev = AllocateDevice();
2239  dev->enumAction = YENU_START;
2240  //mark device a stopped
2241  dev->rstatus = YRUN_STOPED;
2242  dev->infos.vendorid = iface->vendorid;
2243  dev->infos.deviceid = iface->deviceid;
2245  dev->infos.nbinbterfaces = 1;
2246  memcpy(&dev->iface, iface, sizeof(yInterfaceSt));
2247  dev->next = yContext->devs;
2248  yContext->devs=dev;
2249  }
2250  }
2251  enuUpdateDStatus();
2252  yLeaveCriticalSection(&yContext->enum_cs);
2253 
2254  // free all tmp ifaces
2255  if(runifaces){
2256  yFree(runifaces);
2257  }
2258  return YAPI_SUCCESS;
2259 }
2260 
2261 
2262 
2263 
2264 /*****************************************************************************
2265  GENERIC DEVICE LIST FUNCTION
2266  ***************************************************************************/
2267 
2268 // return the YHANDLE from a matching string (serial or name)
2269 yPrivDeviceSt *findDev(const char *str,u32 flags)
2270 {
2271  yPrivDeviceSt *p;
2272 
2273  if(flags& FIND_FROM_SERIAL){
2274  for( p=yContext->devs ; p ; p=p->next){
2275  if(p->dStatus == YDEV_UNPLUGGED){
2276  continue;
2277  }
2278  if(strncmp(str,p->infos.serial,YOCTO_SERIAL_LEN)==0){
2279  return p;
2280  }
2281  }
2282  }
2283  if (flags & FIND_FROM_NAME) {
2284  for( p=yContext->devs ; p ; p=p->next){
2285  if(p->dStatus == YDEV_UNPLUGGED){
2286  continue;
2287  }
2288  if(strncmp(str,p->infos.logicalname,YOCTO_LOGICAL_LEN)==0){
2289  return p;
2290  }
2291  }
2292  }
2293 
2294  return NULL;
2295 }
2296 
2297 
2298 // return the YHANDLE from a matching string (serial or name)
2299 YUSBDEV findDevHdlFromStr(const char *str)
2300 {
2302 
2303  if(p != NULL) {
2304  return p->yhdl;
2305  }
2306  return INVALID_YHANDLE;
2307 }
2308 
2309 
2311 {
2312  yPrivDeviceSt *p;
2313  if(iohdl->type!=YIO_USB)
2314  return NULL;
2315  for( p=yContext->devs ; p ; p=p->next){
2316  if(p->pendingIO.hdl ==iohdl->hdl)
2317  return p;
2318  }
2319  return NULL;
2320 }
2321 
2322 // find a device from his YHANDLE
2324 {
2325  yPrivDeviceSt *p;
2326 
2327  for( p=yContext->devs ; p ; p=p->next){
2328  if(p->yhdl ==hdl)
2329  return p;
2330  }
2331  return NULL;
2332 }
2333 
2334 void devHdlInfo(YUSBDEV hdl,yDeviceSt *infos)
2335 {
2336  yPrivDeviceSt *p;
2337 
2338  p=findDevFromDevHdl(hdl);
2339  if(p!=NULL){
2340  *infos = p->infos;
2341  } else {
2342  memset(infos, 0, sizeof(yDeviceSt));
2343  }
2344 }
2345 
2346 
2347 
2348 /*****************************************************************************
2349  USB REQUEST FUNCTIONS
2350  ***************************************************************************/
2351 
2352 
2353 void dumpYPerfEntry(yPerfMon *entry,const char *name)
2354 {
2355  dbglog("%s count %lld(%lld) totaltime=%lld (avg =%lld)\n",name,entry->count,entry->leave,entry->totaltime,(entry->count>0?entry->totaltime/entry->count:0));
2356 }
2357 
2358 
2359 
2360 //#define PERF_YHUB_FUNCTIONS
2361 #ifdef PERF_YHUB_FUNCTIONS
2362 
2363 
2364 typedef struct {
2372  yPerfMon yUsbEOF;
2374 } yUsbPerfMonSt;
2375 
2376 yUsbPerfMonSt yUsbPerf;
2377 
2378 
2379 #define YPERF_ENTER(NAME) {yUsbPerf.NAME.count++;yUsbPerf.NAME.tmp=yapiGetTickCount();}
2380 #define YPERF_LEAVE(NAME) {yUsbPerf.NAME.leave++;yUsbPerf.NAME.totaltime += yapiGetTickCount()- yUsbPerf.NAME.tmp;}
2381 
2382 
2383 
2384 void dumpYUSBPerf(void)
2385 {
2386  dumpYPerfEntry(&yUsbPerf.yUsbIdle,"yUsbIdle");
2387  dumpYPerfEntry(&yUsbPerf.yUsbTrafficPending,"yUsbTrafficPending");
2388  dumpYPerfEntry(&yUsbPerf.yUsbOpen,"yUsbOpen");
2389  dumpYPerfEntry(&yUsbPerf.yUsbSetIOAsync,"yUsbSetIOAsync");
2390  dumpYPerfEntry(&yUsbPerf.yUsbWrite,"yUsbWrite");
2391  dumpYPerfEntry(&yUsbPerf.yUsbReadNonBlock,"yUsbReadNonBlock");
2392  dumpYPerfEntry(&yUsbPerf.yUsbReadBlock,"yUsbReadBlock");
2393  dumpYPerfEntry(&yUsbPerf.yUsbEOF,"yUsbEOF");
2394  dumpYPerfEntry(&yUsbPerf.yUsbClose,"yUsbClose");
2395 }
2396 #else
2397 #define YPERF_ENTER(NAME)
2398 #define YPERF_LEAVE(NAME)
2399 #endif
2400 
2401 int yUsbInit(yContextSt *ctx,char *errmsg)
2402 {
2403 #ifdef PERF_YHUB_FUNCTIONS
2404  memset(&yUsbPerf,0,sizeof(yUsbPerfMonSt));
2405 #endif
2406  return yyyUSB_init(ctx,errmsg);
2407 }
2408 
2409 
2410 int yUsbFree(yContextSt *ctx,char *errmsg)
2411 {
2412 
2413  yPrivDeviceSt *p,*next;
2414 
2415 #ifdef PERF_YHUB_FUNCTIONS
2416  dumpYUSBPerf();
2417 #endif
2418  p = ctx->devs;
2419  ctx->devs = NULL;
2420  while(p) {
2421  if(p->dStatus == YDEV_WORKING){
2422  int csTaken = yTryEnterCriticalSection(&p->acces_state);
2423  yStrRef serialref = yHashTestStr(p->infos.serial);
2424  p->dStatus = YDEV_UNPLUGGED;
2425  StopDevice(p,NULL);
2426  wpSafeUnregister(serialref);
2427  if(csTaken)
2429  }
2430  if(p->replybuf) {
2431  yFree(p->replybuf);
2432  p->replybuf = NULL;
2433  }
2434  next = p->next;
2435  FreeDevice(p);
2436  p = next;
2437  }
2438  return yyyUSB_stop(yContext,errmsg);
2439 }
2440 
2441 int yUsbIdle(void)
2442 {
2443  yPrivDeviceSt *p;
2444  int res;
2445  char errmsg[YOCTO_ERRMSG_LEN];
2446 
2448  for( p=yContext->devs ; p ; p=p->next){
2449 
2450  if(p->dStatus != YDEV_WORKING){
2451  continue;
2452  }
2453 
2454  res = devStartIdle(PUSH_LOCATION p,errmsg);
2455  if (res == YAPI_SUCCESS) {
2456  u32 currUtcTime;
2457  if(YISERR(yDispatchReceive(p,0,errmsg))){
2458  dbglog("yPacketDispatchReceive error:%s\n",errmsg);
2460  continue;
2461  }
2462  currUtcTime = (u32)time(NULL);
2463  if(currUtcTime > (u32)0x51f151f1 && // timestamp appears to be valid
2464  (!p->lastUtcUpdate || currUtcTime < p->lastUtcUpdate || currUtcTime >= p->lastUtcUpdate+60u)) {
2465  u8 *pktdata;
2466  u8 maxpktlen;
2467  // send updated UTC timestamp to keep datalogger on time
2468  if(yStreamGetTxBuff(p,&pktdata, &maxpktlen) && maxpktlen >= 5){
2469  p->lastUtcUpdate = currUtcTime;
2470  pktdata[0] = USB_META_UTCTIME;
2471  pktdata[1] = currUtcTime & 0xff;
2472  pktdata[2] = (currUtcTime>>8) & 0xff;
2473  pktdata[3] = (currUtcTime>>16) & 0xff;
2474  pktdata[4] = (currUtcTime>>24) & 0xff;
2475  if(YISERR(yStreamTransmit(p,YSTREAM_META,5,errmsg))){
2476  dbglog("Unable to send UTC timestamp\n");
2477  } else if(YISERR(yStreamFlush(p,errmsg))) {
2478  dbglog("Unable to flush UTC timestamp\n");
2479  }
2480  }
2481  }
2483  yapiPullDeviceLog(p->infos.serial);
2484  } else if(res == YAPI_DEVICE_BUSY){
2485  if (p->httpstate != YHTTP_CLOSED && p->pendingIO.callback) {
2486  // if we have an async IO on this device
2487  // simulate read from users
2488  if (!YISERR(devCheckAsyncIO(PUSH_LOCATION p,errmsg))) {
2489  int sendClose=0;
2490  if(YISERR(yDispatchReceive(p,0,errmsg))){
2491  dbglog("yPacketDispatchReceive error:%s\n",errmsg);
2492  devReportError(PUSH_LOCATION p,errmsg);
2493  continue;
2494  }
2495  if(p->httpstate == YHTTP_CLOSE_BY_DEV) {
2496  sendClose=1;
2497  }else if(p->pendingIO.timeout<yapiGetTickCount()){
2498  dbglog("Last async request did not complete (%X:%d)\n",p->pendingIO.hdl,p->httpstate);
2499  sendClose=1;
2500  }
2501  if (sendClose) {
2502  u8 *pktdata;
2503  u8 maxpktlen;
2504  // send connection close
2505  if(yStreamGetTxBuff(p,&pktdata, &maxpktlen)){
2506  u8 * ptr;
2507  u16 len;
2508  if(YISERR(yStreamTransmit(p,YSTREAM_TCP_CLOSE,0,errmsg))){
2509  dbglog("Unable to send async connection close\n");
2510  } else if(YISERR(yStreamFlush(p,errmsg))) {
2511  dbglog("Unable to flush async connection close\n");
2512  }
2513  // since we empty the fifo at each request we can use yPeekContinuousFifo
2514  len = yPeekContinuousFifo(&p->http_fifo, &ptr, 0);
2515  p->pendingIO.callback(p->pendingIO.context, ptr, len, YAPI_SUCCESS, NULL);
2516  yFifoEmpty(&p->http_fifo);
2517  p->httpstate = YHTTP_CLOSED;
2518  }
2519  }
2520  if(p->httpstate == YHTTP_CLOSED) {
2521  if (YISERR(res =devStopIO(PUSH_LOCATION p,errmsg))) {
2522  dbglog("Idle : devStopIO err %s : %X:%s\n",p->infos.serial,res,errmsg);
2523  }
2524  } else {
2525  devPauseIO(PUSH_LOCATION p,NULL);
2526  }
2527  }
2528  }
2529  }
2530  }
2532  return YAPI_SUCCESS;
2533 }
2534 
2536 {
2537  yPrivDeviceSt *p;
2539  for( p=yContext->devs ; p ; p=p->next){
2540  if(p->dStatus != YDEV_WORKING){
2541  continue;
2542  }
2543  if(p->httpstate != YHTTP_CLOSED && p->pendingIO.callback) {
2545  return 1;
2546  }
2547  }
2549  return 0;
2550 }
2551 
2552 
2553 int yUsbOpenDevDescr(YIOHDL_internal *ioghdl, yStrRef devdescr, char *errmsg)
2554 {
2555  char serialBuf[YOCTO_SERIAL_LEN];
2556  int res;
2557 
2559  yHashGetStr(devdescr, serialBuf, YOCTO_SERIAL_LEN);
2560  res = yUsbOpen(ioghdl, serialBuf, errmsg);
2562 
2563  return res;
2564 }
2565 
2566 int yUsbOpen(YIOHDL_internal *ioghdl, const char *device, char *errmsg)
2567 {
2568  int res;
2569  yPrivDeviceSt *p;
2570 
2572  p=findDev(device,FIND_FROM_ANY);
2573  if(p==NULL){
2575  return YERR(YAPI_DEVICE_NOT_FOUND);
2576  }
2577 
2578  memset(ioghdl, 0, sizeof(YIOHDL_internal));
2579  res = devStartIO(PUSH_LOCATION p,errmsg);
2580  if(YISERR(res)){
2582  return res;
2583  }
2584  //process some packet
2585  if(YISERR(res=yDispatchReceive(p,0,errmsg))){
2586  devReportError(PUSH_LOCATION p,errmsg);
2588  return res;
2589  }
2590  p->httpstate = YHTTP_OPENED;
2591  ioghdl->type = YIO_USB;
2592  memset(&p->pendingIO,0,sizeof(USB_HDL));
2593  yEnterCriticalSection(&yContext->io_cs);
2594  p->pendingIO.hdl = ioghdl->hdl = ++(yContext->io_counter);
2595  yLeaveCriticalSection(&yContext->io_cs);
2596  p->pendingIO.timeout = YIO_DEFAULT_USB_TIMEOUT+yapiGetTickCount();
2597  res = devPauseIO(PUSH_LOCATION p,errmsg);
2599  return res;
2600 }
2601 
2602 int yUsbSetIOAsync(YIOHDL_internal *ioghdl, yapiRequestAsyncCallback callback, void *context, char *errmsg)
2603 {
2604  int res;
2605  yPrivDeviceSt *p;
2606 
2608  p = findDevFromIOHdl(ioghdl);
2609  if(p == NULL){
2611  return YERR(YAPI_DEVICE_NOT_FOUND);
2612  }
2613  res = devCheckIO(PUSH_LOCATION p,ioghdl,errmsg);
2614  if(YISERR(res)){
2616  return res;
2617  }
2618  p->pendingIO.callback = callback;
2619  p->pendingIO.context = context;
2620  res = devPauseIO(PUSH_LOCATION p,errmsg);
2622 
2623  return res;
2624 }
2625 
2626 
2627 
2628 int yUsbWrite(YIOHDL_internal *ioghdl, const char *buffer, int writelen,char *errmsg)
2629 {
2630  yPrivDeviceSt *p;
2631  int totalsend=0;
2632  u8 *pktdata;
2633  u8 maxpktlen;
2634  int res;
2635 
2637  p=findDevFromIOHdl(ioghdl);
2638  if(p==NULL){
2640  return YERR(YAPI_DEVICE_NOT_FOUND);
2641  }
2642  YPROPERR(devCheckIO(PUSH_LOCATION p,ioghdl,errmsg));
2643  if(YISERR(res=yDispatchReceive(p,0,errmsg))){
2644  devReportError(PUSH_LOCATION p,errmsg);
2646  return res;
2647  }
2648 
2649  if(p->httpstate != YHTTP_OPENED && p->httpstate != YHTTP_INREQUEST) {
2650  devPauseIO(PUSH_LOCATION p,NULL);
2652  return YERRMSG(YAPI_IO_ERROR,"Connection closed");
2653  }
2654  p->httpstate = YHTTP_INREQUEST;
2655  while (writelen){
2656  while(writelen && yStreamGetTxBuff(p,&pktdata, &maxpktlen)==1) {
2657  u8 pktlen =(maxpktlen < writelen ? maxpktlen: writelen);
2658  memcpy(pktdata,buffer,pktlen);
2659  if(YISERR(res=yStreamTransmit(p,YSTREAM_TCP,pktlen,errmsg))) {
2660  devReportError(PUSH_LOCATION p,errmsg);
2662  return res;
2663  }
2664  buffer += pktlen;
2665  writelen -= pktlen;
2666  totalsend += pktlen;
2667  }
2668  if(YISERR(res=yStreamFlush(p,errmsg))) {
2669  devReportError(PUSH_LOCATION p,errmsg);
2671  return res;
2672  }
2673  }
2674 
2675  res = devPauseIO(PUSH_LOCATION p,errmsg);
2676  if(res==YAPI_SUCCESS)
2677  res = totalsend;
2679  return res;
2680 }
2681 
2682 
2683 
2684 int yUsbReadNonBlock(YIOHDL_internal *ioghdl, char *buffer, int len,char *errmsg)
2685 {
2686  yPrivDeviceSt *p;
2687  u16 readed;
2688  int res;
2689 
2691 
2692  p=findDevFromIOHdl(ioghdl);
2693  if(p==NULL){
2695  return YERR(YAPI_DEVICE_NOT_FOUND);
2696  }
2697 
2698  res =devCheckIO(PUSH_LOCATION p,ioghdl,errmsg);
2699  if(YISERR(res)){
2701  return res ;
2702  }
2703  if(p->pendingIO.callback){
2704  YPROPERR(devPauseIO(PUSH_LOCATION p,errmsg));
2706  return YERRMSG(YAPI_INVALID_ARGUMENT,"Operation not supported on async IO");
2707  }
2708 
2709  if(YISERR(res=yDispatchReceive(p, 0, errmsg))){
2710  devReportError(PUSH_LOCATION p,errmsg);
2712  return res;
2713  }
2714  if(len > HTTP_RAW_BUFF_SIZE){
2715  len = HTTP_RAW_BUFF_SIZE;
2716  }
2717  //get all available data
2718  readed=yPopFifo(&p->http_fifo,(u8*)buffer,(u16)len);
2719  YPROPERR(devPauseIO(PUSH_LOCATION p,errmsg));
2721  return readed;
2722 }
2723 
2724 
2725 
2726 
2727 
2728 int yUsbReadBlock(YIOHDL_internal *ioghdl, char *buffer, int len,u64 blockUntil,char *errmsg)
2729 {
2730  yPrivDeviceSt *p;
2731  u16 readed, avail;
2732  int res;
2733 
2735 
2736  p=findDevFromIOHdl(ioghdl);
2737  if(p==NULL){
2739  return YERR(YAPI_DEVICE_NOT_FOUND);
2740  }
2741  res =devCheckIO(PUSH_LOCATION p,ioghdl,errmsg);
2742  if(YISERR(res)){
2744  return res ;
2745  }
2746  if(p->pendingIO.callback){
2747  YPROPERR(devPauseIO(PUSH_LOCATION p,errmsg));
2749  return YERRMSG(YAPI_INVALID_ARGUMENT,"Operation not supported on async IO");
2750  }
2751 
2752  avail = yFifoGetUsed(&p->http_fifo);
2753  if(YISERR(res=yDispatchReceive(p,(avail==0 ? blockUntil : 0) ,errmsg))){
2754  devReportError(PUSH_LOCATION p,errmsg);
2756  return res;
2757  }
2758  if(len > HTTP_RAW_BUFF_SIZE){
2759  len = HTTP_RAW_BUFF_SIZE;
2760  }
2761  //get all available data
2762  readed=yPopFifo(&p->http_fifo,(u8*)buffer,(u16)len);
2763  YPROPERR(devPauseIO(PUSH_LOCATION p,errmsg));
2765  return readed;
2766 }
2767 
2768 
2769 
2770 
2771 int yUsbEOF(YIOHDL_internal *ioghdl,char *errmsg)
2772 {
2773  yPrivDeviceSt *p;
2774  int res;
2775 
2777 
2778  p=findDevFromIOHdl(ioghdl);
2779  if(p==NULL){
2781  return YERR(YAPI_DEVICE_NOT_FOUND);
2782  }
2783  res =devCheckIO(PUSH_LOCATION p,ioghdl,errmsg);
2784  if(YISERR(res)){
2786  return res;
2787  }
2788  if(p->pendingIO.callback){
2789  YPROPERR(devPauseIO(PUSH_LOCATION p,errmsg));
2791  return YERRMSG(YAPI_INVALID_ARGUMENT,"Operation not supported on async IO");
2792  }
2793  if(YISERR(res=yDispatchReceive(p,0,errmsg))){
2794  devReportError(PUSH_LOCATION p,errmsg);
2796  return res;
2797  }
2798  res=0;
2799  if(yFifoGetUsed(&p->http_fifo)==0 && p->httpstate == YHTTP_CLOSE_BY_DEV){
2800  //dbglog("* yUsbEOF for %d is TRUE\n",p->iohdl);
2801  res =1;
2802  p->pendingIO.flags |= YIO_REMOTE_CLOSE;
2803  }
2804  devPauseIO(PUSH_LOCATION p,NULL);
2806  return res;
2807 }
2808 
2809 
2810 
2811 int yUsbClose(YIOHDL_internal *ioghdl,char *errmsg)
2812 {
2813  yPrivDeviceSt *p;
2814  u8 *pktdata;
2815  u8 maxpktlen;
2816  u16 deviceDead = 0;
2817  int res;
2818 
2820 
2821  p = findDevFromIOHdl(ioghdl);
2822  if (p == NULL) {
2824  return YERR(YAPI_DEVICE_NOT_FOUND);
2825  }
2826  //dbglog("* yUsbClose for %d, httpstate=%d\n",p->iohdl,p->httpstate);
2827  if(p->httpstate == YHTTP_CLOSED || p->httpstate == YHTTP_CLOSE_BY_API) {
2828  dbglog("yUsb double-close");
2830  return YAPI_SUCCESS;
2831  }
2832  res = devCheckIO(PUSH_LOCATION p,ioghdl,errmsg);
2833  if(YISERR(res)) {
2835  return res;
2836  }
2837  if(p->pendingIO.callback){
2838  YPROPERR(devPauseIO(PUSH_LOCATION p,errmsg));
2840  return YERRMSG(YAPI_INVALID_ARGUMENT,"Operation not supported on async IO");
2841  }
2842 
2843  // send connection close
2844  if(!yStreamGetTxBuff(p,&pktdata, &maxpktlen)) {
2845  if(YISERR(yStreamFlush(p,errmsg))) {
2846  dbglog("Unable to flush pending data");
2847  deviceDead = 1;
2848  }
2849  yStreamGetTxBuff(p,&pktdata, &maxpktlen);
2850  }
2851  if (!deviceDead && p->httpstate >= YHTTP_INREQUEST) {
2852  if(YISERR(yStreamTransmit(p,YSTREAM_TCP_CLOSE,0,errmsg))) {
2853  dbglog("Unable to send connection close");
2854  deviceDead = 1;
2855  } else if(YISERR(yStreamFlush(p,errmsg))) {
2856  dbglog("Unable to flush connection close");
2857  deviceDead = 1;
2858  }
2859  }
2860  if (p->httpstate == YHTTP_OPENED || p->httpstate == YHTTP_CLOSE_BY_DEV || deviceDead) {
2861  p->httpstate = YHTTP_CLOSED;
2862  } else {
2863  //wait for the device close packet
2864  u64 timeout = yapiGetTickCount() + 100;
2865  p->httpstate = YHTTP_CLOSE_BY_API;
2866  while (!YISERR(yDispatchReceive(p, 5, errmsg))) {
2867  if(p->httpstate == YHTTP_CLOSED) {
2868  // received close from device
2869  break;
2870  }
2871  if(timeout<yapiGetTickCount()) {
2872  dbglog("yUSBClose without device ack\n");
2873  break;
2874  }
2875  }
2876  }
2877  yFifoEmpty(&p->http_fifo);
2878  memset(&p->pendingIO, 0, sizeof(USB_HDL));
2879  ioghdl->type=YIO_INVALID;
2880  res =devStopIO(PUSH_LOCATION p,errmsg);
2881  yapiPullDeviceLog(p->infos.serial);
2883  return res;
2884 }
#define yMemset(dst, val, size)
Definition: yproto.h:203
pktItem tmptxpkt
Definition: yproto.h:695
int yUsbFree(yContextSt *ctx, char *errmsg)
Definition: ystream.c:2410
#define NOTIFY_PKT_LOG
Definition: ydef.h:546
u8 ifaceno
Definition: ydef.h:510
pktItem * last
Definition: yproto.h:519
int YFOPEN(FILE **f, const char *filename, const char *mode)
Definition: ystream.c:130
#define FIND_FROM_SERIAL
Definition: yproto.h:1035
static YRETCODE yPktQueuePop(pktQueue *q, pktItem **pkt, char *errmsg)
Definition: ystream.c:1036
#define YSTREAM_NOTICE
Definition: ydef.h:526
static int devStartIO(LOCATION yPrivDeviceSt *dev, char *errmsg)
Definition: ystream.c:459
#define YPKT_USB_VERSION_NO_RETRY_BCD
Definition: ydef.h:468
static void devStopEnum(LOCATION yPrivDeviceSt *dev)
Definition: ystream.c:424
static int yyWaitOnlyConfPkt(yInterfaceSt *iface, u8 cmdtowait, pktItem **rpkt, u32 s_timeout, char *errmsg)
Definition: ystream.c:1244
static int devStopIO(LOCATION yPrivDeviceSt *dev, char *errmsg)
Definition: ystream.c:644
#define FIND_FROM_ANY
Definition: yproto.h:1037
yCRITICAL_SECTION acces_state
Definition: yproto.h:679
int yWaitForEvent(yEvent *ev, int time)
Definition: ythread.c:196
#define YERRMSG(code, message)
Definition: yproto.h:458
static int devCheckAsyncIO(LOCATION yPrivDeviceSt *dev, char *errmsg)
Definition: ystream.c:595
#define HTTP_RAW_BUFF_SIZE
Definition: yproto.h:556
static void devReportErrorFromIdle(LOCATION yPrivDeviceSt *dev, char *error_to_set)
Definition: ystream.c:432
int yUsbReadNonBlock(YIOHDL_internal *ioghdl, char *buffer, int len, char *errmsg)
Definition: ystream.c:2684
char ytracefile[512]
Definition: ystream.c:64
char funcid[YOCTO_FUNCTION_LEN]
Definition: ydef.h:636
static void devStopIdle(LOCATION yPrivDeviceSt *dev)
Definition: ystream.c:377
Notification_child childserial
Definition: ydef.h:662
u16 yPeekContinuousFifo(yFifoBuf *buf, u8 **ptr, u16 startofs)
Definition: yfifo.c:303
char pubval[VARIABLE_SIZE]
Definition: ydef.h:604
#define YPKT_USB_VERSION_BCD
Definition: ydef.h:469
void yInitializeCriticalSection(yCRITICAL_SECTION *cs)
Definition: ythread.c:629
#define ENUMLOG(fmt, args...)
Definition: yproto.h:356
void yFifoCleanup(yFifoBuf *buf)
Definition: yfifo.c:70
static int yDispatchReceive(yPrivDeviceSt *dev, u64 blockUntilTime, char *errmsg)
Definition: ystream.c:1887
char funcid[YOCTO_FUNCTION_LEN]
Definition: ydef.h:641
s32 YAPI_FUNCTION
Definition: ydef.h:217
yHash yStrRef
Definition: ydef.h:214
int yUsbInit(yContextSt *ctx, char *errmsg)
Definition: ystream.c:2401
f
int yUsbSetIOAsync(YIOHDL_internal *ioghdl, yapiRequestAsyncCallback callback, void *context, char *errmsg)
Definition: ystream.c:2602
#define YOCTO_DEVID_BOOTLOADER
Definition: ydef.h:404
#define YOCTO_PRODUCTNAME_LEN
Definition: ydef.h:422
YUSBDEV findDevHdlFromStr(const char *str)
Definition: ystream.c:2299
yHash yUrlRef
Definition: ydef.h:215
void yFunctionTimedUpdate(YAPI_FUNCTION fundescr, double deviceTime, const u8 *report, u32 len)
Definition: yapi.c:237
USB_Packet pkt
Definition: yproto.h:508
static int dayofs[]
Definition: ystream.c:145
SAFE_U16 api
Definition: ydef.h:508
u64 count
Definition: yproto.h:477
u8 ack_delay
Definition: ydef.h:515
static void yPktQueueDup(pktQueue *q, int expected_pkt_no, const char *file, int line)
Definition: ystream.c:1069
u16 yPushFifo(yFifoBuf *buf, const u8 *data, u16 datalen)
Definition: yfifo.c:143
YRETCODE yPktQueuePopH2D(yInterfaceSt *iface, pktItem **pkt)
Definition: ystream.c:1176
YRETCODE yUSBUpdateDeviceList(char *errmsg)
Definition: ystream.c:2191
u8 data[USB_PKT_SIZE]
Definition: ydef.h:1004
#define YIO_REMOTE_CLOSE
Definition: yproto.h:662
void yHashGetStr(yHash yhash, char *destbuf, u16 bufsize)
Definition: yhash.c:365
YDEV_STATUS dStatus
Definition: yproto.h:681
int yUsbOpen(YIOHDL_internal *ioghdl, const char *device, char *errmsg)
Definition: ystream.c:2566
#define YPKT_CONF
Definition: ydef.h:497
int ypRegisterByYdx(u8 devYdx, Notification_funydx funInfo, const char *funcVal, YAPI_FUNCTION *fundesc)
Definition: yhash.c:1395
#define NOTIFY_PKT_CHILD
Definition: ydef.h:541
yEvent emptyEvent
Definition: yproto.h:527
static yPrivDeviceSt * enuFindDevSlot(yInterfaceSt *iface)
Definition: ystream.c:2000
int yUsbTrafficPending(void)
Definition: ystream.c:2535
XmlRpcServer s
#define NOTIFY_PKT_FUNCNAME
Definition: ydef.h:543
#define YPKT_VERSION_ORIGINAL_RELEASE
Definition: yproto.h:469
int vdbglogf(const char *fileid, int line, const char *fmt, va_list args)
Definition: ystream.c:189
static void yyFormatConfPkt(pktItem *pkt, u8 conftype)
Definition: ystream.c:1280
yDeviceSt infos
Definition: yproto.h:689
int yUsbReadBlock(YIOHDL_internal *ioghdl, char *buffer, int len, u64 blockUntil, char *errmsg)
Definition: ystream.c:2728
#define YSTRCAT(dst, dstsize, src)
Definition: yproto.h:235
void devHdlInfo(YUSBDEV hdl, yDeviceSt *infos)
Definition: ystream.c:2334
pktItem * curtxpkt
Definition: yproto.h:693
static int yGetNextPktEx(yPrivDeviceSt *dev, pktItem **pkt_out, u64 blockUntilTime, char *errmsg)
Definition: ystream.c:1396
#define yFifoInit(fifo, buffer, len)
Definition: yfifo.h:84
#define PUSH_LOCATION
Definition: ystream.c:322
static void enuResetDStatus(void)
Definition: ystream.c:1981
YRETCODE yPktQueuePushH2D(yInterfaceSt *iface, const USB_Packet *pkt, char *errmsg)
Definition: ystream.c:1145
static int ySendStart(yPrivDeviceSt *dev, char *errmsg)
Definition: ystream.c:1321
YUSBIO hdl
Definition: yproto.h:914
struct USB_Conf_Pkt::@8 reset
char errmsg[YOCTO_ERRMSG_LEN]
Definition: yproto.h:524
#define YOCTO_FIRMWARE_LEN
Definition: ydef.h:423
#define YERR(code)
Definition: yproto.h:456
yEvent notEmptyEvent
Definition: yproto.h:526
#define dbglog(args...)
Definition: yproto.h:413
#define YSTREAM_REPORT
Definition: ydef.h:527
static int devCheckIO(LOCATION yPrivDeviceSt *dev, YIOHDL_internal *iohdl, char *errmsg)
Definition: ystream.c:547
#define DEVGEN_LOG_ACTIVATED
Definition: yproto.h:646
#define NOTIFY_PKT_FUNCVAL
Definition: ydef.h:544
u16 yFifoGetUsed(yFifoBuf *buf)
Definition: yfifo.c:385
#define YPROPERR(call)
Definition: yproto.h:455
SAFE_U16 vendorid
Definition: ydef.h:631
int yyySetup(yInterfaceSt *iface, char *errmsg)
yRawReportV2Cb rawReportV2Cb
Definition: yproto.h:945
#define NBMAX_INTERFACE_PER_DEV
Definition: yproto.h:605
static YRETCODE yPktQueuePeek(pktQueue *q, pktItem **pkt, char *errmsg)
Definition: ystream.c:1016
int yyyUSBGetInterfaces(yInterfaceSt **ifaces, int *nbifaceDetect, char *errmsg)
int wpGetDevYdx(yStrRef serial)
Definition: yhash.c:968
#define YOCTO_SERIAL_LEN
Definition: ydef.h:420
void yLeaveCriticalSection(yCRITICAL_SECTION *cs)
Definition: ythread.c:672
int dbglogf(const char *fileid, int line, const char *fmt,...)
Definition: ystream.c:222
u8 nbifaces
Definition: ydef.h:511
static yPrivDeviceSt * findDevFromDevHdl(YUSBDEV hdl)
Definition: ystream.c:2323
int yUsbWrite(YIOHDL_internal *ioghdl, const char *buffer, int writelen, char *errmsg)
Definition: ystream.c:2628
#define YOCTO_ERRMSG_LEN
Definition: ydef.h:418
void wpSafeUnregister(yStrRef serialref)
Definition: yapi.c:703
YUSBIO hdl
Definition: yproto.h:667
static void yStreamShutdown(yPrivDeviceSt *dev)
Definition: ystream.c:1605
yCRITICAL_SECTION cs
Definition: yproto.h:525
#define USB_META_ACK_D2H_PACKET
Definition: ydef.h:778
static int yPktQueueIsEmpty(pktQueue *q, char *errmsg)
Definition: ystream.c:998
u64 totalPop
Definition: yproto.h:522
u8 firstByte
Definition: ydef.h:653
int ySetErr(int code, char *outmsg, const char *erreur, const char *file, u32 line)
Definition: ystream.c:72
int yyyUSB_init(yContextSt *ctx, char *errmsg)
YRETCODE yapiPullDeviceLog(const char *serial)
Definition: yapi.c:563
int pktAckDelay
Definition: yproto.h:697
#define YSTREAM_REPORT_V2
Definition: ydef.h:529
yHash yHashTestStr(const char *str)
Definition: yhash.c:333
u64 totalPush
Definition: yproto.h:521
static int yStreamFlush(yPrivDeviceSt *dev, char *errmsg)
Definition: ystream.c:1558
#define YOCTO_PUBVAL_LEN
Definition: ydef.h:428
char firmware[YOCTO_FIRMWARE_LEN]
Definition: ydef.h:630
#define YPANIC
Definition: yproto.h:453
#define NB_MAX_STARTUP_RETRY
Definition: yproto.h:672
struct USB_Packet::@41 confpkt
#define YSTREAM_NOTICE_V2
Definition: ydef.h:530
#define YSTREAM_TCP_CLOSE
Definition: ydef.h:525
YRETCODE
Definition: ydef.h:376
int yUsbClose(YIOHDL_internal *ioghdl, char *errmsg)
Definition: ystream.c:2811
YRETCODE yPktQueuePushD2H(yInterfaceSt *iface, const USB_Packet *pkt, char *errmsg)
Definition: ystream.c:1097
Notification_product productname
Definition: ydef.h:660
yCRITICAL_SECTION io_cs
Definition: yproto.h:937
#define Y_DEFAULT_PKT_RESEND_DELAY
Definition: yapi.h:128
YSTREAM_Head first_stream
Definition: ydef.h:1007
#define USB_CONF_START
Definition: ydef.h:504
YRETCODE status
Definition: yproto.h:523
static int yPktQueueWaitEmptyH2D(yInterfaceSt *iface, int ms, char *errmsg)
Definition: ystream.c:1151
pktItem * currxpkt
Definition: yproto.h:691
static void yDispatchNotice(yPrivDeviceSt *dev, USB_Notify_Pkt *notify, int pktsize, int isV2)
Definition: ystream.c:1617
u16 vendorid
Definition: ydef.h:448
u16 deviceid
Definition: ydef.h:449
USB_Conf_Pkt conf
Definition: ydef.h:1011
yapiTimedReportCallback timedReportCallback
Definition: yproto.h:957
Notification_funydx funInfo
Definition: ydef.h:596
u32 lastUtcUpdate
Definition: yproto.h:690
static void yDispatchReportV2(yPrivDeviceSt *dev, u8 *data, int pktsize)
Definition: ystream.c:1842
int yyySignalOutPkt(yInterfaceSt *iface, char *errmsg)
#define TO_SAFE_U16(safe, unsafe)
Definition: ydef.h:470
#define USB_PKT_SIZE
Definition: ydef.h:467
yUrlRef yHashUrlUSB(yHash serial)
Definition: yhash.c:637
u64 next_startup_attempt
Definition: yproto.h:686
void decodePubVal(Notification_funydx funInfo, const char *funcval, char *buffer)
Definition: yfifo.c:429
#define yApproximateSleep(ms)
Definition: yproto.h:433
char funcname[YOCTO_LOGICAL_LEN]
Definition: ydef.h:637
u64 totaltime
Definition: yproto.h:476
YSTREAM_Head head
Definition: ydef.h:1010
pktQueue txQueue
Definition: yproto.h:572
struct Notification_funydx::@10 v2
static int yStreamReceptionDone(yPrivDeviceSt *dev, char *errmsg)
Definition: ystream.c:1537
char serial[YOCTO_SERIAL_LEN]
Definition: ydef.h:569
#define YSTRCPY(dst, dstsize, src)
Definition: yproto.h:234
#define YOCTO_PUBVAL_SIZE
Definition: ydef.h:427
int yyyUSB_stop(yContextSt *ctx, char *errmsg)
#define USB_META_UTCTIME
Definition: ydef.h:776
void yPktQueueFree(pktQueue *q)
Definition: ystream.c:928
yInterfaceSt iface
Definition: yproto.h:698
pktQueue rxQueue
Definition: yproto.h:571
#define NOTIFY_1STBYTE_MINSMALL
Definition: ydef.h:537
char pubval[YOCTO_PUBVAL_SIZE]
Definition: ydef.h:642
char logicalname[YOCTO_LOGICAL_LEN]
Definition: ydef.h:455
static int devPauseIO(LOCATION yPrivDeviceSt *dev, char *errmsg)
Definition: ystream.c:502
YRETCODE yPktQueueWaitAndPopD2H(yInterfaceSt *iface, pktItem **pkt, int ms, char *errmsg)
Definition: ystream.c:1128
yRawNotificationCb rawNotificationCb
Definition: yproto.h:943
pktItem * first
Definition: yproto.h:518
#define NOTIFY_V2_LEGACY
Definition: ydef.h:550
char pubval[VARIABLE_SIZE]
Definition: ydef.h:597
#define YOCTO_FUNCTION_LEN
Definition: ydef.h:425
Notification_funcname funcnamenot
Definition: ydef.h:664
YRETCODE yPktQueuePeekH2D(yInterfaceSt *iface, pktItem **pkt)
Definition: ystream.c:1160
#define YPKT_STREAM
Definition: ydef.h:496
static void FreeDevice(yPrivDeviceSt *dev)
Definition: ystream.c:2025
void yPktQueueInit(pktQueue *q)
Definition: ystream.c:919
yRawReportCb rawReportCb
Definition: yproto.h:944
#define YASSERT(x)
Definition: yproto.h:454
char firmware[YOCTO_FIRMWARE_LEN]
Definition: ydef.h:456
static void devInitAccces(LOCATION yPrivDeviceSt *dev)
Definition: ystream.c:325
#define YSPRINTF
Definition: yproto.h:238
#define NOTIFY_V2_FLUSHGROUP
Definition: ydef.h:553
YRETCODE yyySendPacket(yInterfaceSt *iface, const USB_Packet *pkt, char *errmsg)
Definition: ystream.c:1199
void wpSafeRegister(HubSt *hub, u8 devYdx, yStrRef serialref, yStrRef lnameref, yStrRef productref, u16 deviceid, yUrlRef devUrl, s8 beacon)
Definition: yapi.c:599
yHash yHashPutStr(const char *str)
Definition: yhash.c:318
u16 ifaceno
Definition: yproto.h:565
#define NOTIFY_PKT_PRODNAME
Definition: ydef.h:540
static void devStartEnum(LOCATION yPrivDeviceSt *dev)
Definition: ystream.c:405
#define YPERF_LEAVE(NAME)
Definition: ystream.c:2398
#define FIND_FROM_NAME
Definition: yproto.h:1036
static void devDeleteAccces(LOCATION yPrivDeviceSt *dev)
Definition: ystream.c:330
#define YPERF_ENTER(NAME)
Definition: ystream.c:2397
int yUsbIdle(void)
Definition: ystream.c:2441
void yFifoEmpty(yFifoBuf *buf)
Definition: yfifo.c:100
yPrivDeviceSt * findDevFromIOHdl(YIOHDL_internal *iohdl)
Definition: ystream.c:2310
struct USB_Conf_Pkt::@9 start
u16 yFifoGetFree(yFifoBuf *buf)
Definition: yfifo.c:401
YUSBDEV yhdl
Definition: yproto.h:680
void yPktQueueSetError(pktQueue *q, YRETCODE code, const char *msg)
Definition: ystream.c:985
#define YSTREAM_META
Definition: ydef.h:528
void yResetEvent(yEvent *ev)
Definition: ythread.c:187
Notification_funcnameydx funcnameydxnot
Definition: ydef.h:666
void yEnterCriticalSection(yCRITICAL_SECTION *cs)
Definition: ythread.c:647
#define yFree(ptr)
Definition: yproto.h:199
char childserial[YOCTO_SERIAL_LEN]
Definition: ydef.h:624
char serial[YOCTO_SERIAL_LEN *2]
Definition: yproto.h:567
u16 deviceid
Definition: yproto.h:564
#define YIO_USB
Definition: ydef.h:243
Notification_firmware firmwarenot
Definition: ydef.h:663
u8 pkt
Definition: ydef.h:484
void(* yapiRequestAsyncCallback)(void *context, const u8 *result, u32 resultlen, int retcode, const char *errmsg)
Definition: ydef.h:864
#define yMalloc(size)
Definition: yproto.h:198
double deviceTime
Definition: yproto.h:655
#define NEXT_YPKT_NO(current)
Definition: yproto.h:674
YRUN_STATUS rstatus
Definition: yproto.h:683
u8 * devYdxMap
Definition: yproto.h:703
USB_HDL pendingIO
Definition: yproto.h:687
#define NOTIFY_PKT_FIRMWARE
Definition: ydef.h:542
#define YIO_INVALID
Definition: ydef.h:242
static int CheckVersionCompatibility(u16 version, const char *serial, char *errmsg)
Definition: ystream.c:1293
int yUsbOpenDevDescr(YIOHDL_internal *ioghdl, yStrRef devdescr, char *errmsg)
Definition: ystream.c:2553
#define YSTRLEN(str)
Definition: yproto.h:230
static yPrivDeviceSt * AllocateDevice(void)
Definition: ystream.c:2014
#define LOCATION
Definition: ystream.c:321
#define YVSPRINTF
Definition: yproto.h:239
Notification_small smallpubvalnot
Definition: ydef.h:655
yGenericDeviceSt generic_infos[ALLOC_YDX_PER_HUB]
Definition: yproto.h:929
#define NOTIFY_PKT_STREAMREADY
Definition: ydef.h:545
u8 * http_raw_buf
Definition: yproto.h:702
char name[YOCTO_LOGICAL_LEN]
Definition: ydef.h:612
static void enuUpdateDStatus(void)
Definition: ystream.c:2077
int detecttype
Definition: yproto.h:932
void yDeleteCriticalSection(yCRITICAL_SECTION *cs)
Definition: ythread.c:682
int yTryEnterCriticalSection(yCRITICAL_SECTION *cs)
Definition: ythread.c:657
u8 beacon
Definition: ydef.h:457
static YRETCODE yAckPkt(yInterfaceSt *iface, int pktno, char *errmsg)
Definition: ystream.c:1219
static void yDispatchReportV1(yPrivDeviceSt *dev, u8 *data, int pktsize)
Definition: ystream.c:1798
yPrivDeviceSt * findDev(const char *str, u32 flags)
Definition: ystream.c:2269
const int Y_RESEND_MISSING_PKT
Definition: yocto_api.h:206
int count
Definition: yproto.h:520
yPrivDeviceSt * devs
Definition: yproto.h:934
void ySetEvent(yEvent *ev)
Definition: ythread.c:175
int yUsbEOF(YIOHDL_internal *ioghdl, char *errmsg)
Definition: ystream.c:2771
YUSBDEV devhdlcount
Definition: yproto.h:933
yCRITICAL_SECTION generic_cs
Definition: yproto.h:928
#define __FILE_ID__
Definition: ystream.c:40
void yFunctionUpdate(YAPI_FUNCTION fundescr, const char *value)
Definition: yapi.c:225
#define NOTIFY_PKT_FUNCNAMEYDX
Definition: ydef.h:547
char * replybuf
Definition: yproto.h:699
void wpSafeUpdate(HubSt *hub, u8 devYdx, yStrRef serialref, yStrRef lnameref, yUrlRef devUrl, s8 beacon)
Definition: yapi.c:659
#define INVALID_HASH_IDX
Definition: ydef.h:219
int yThreadIndex(void)
Definition: ythread.c:264
void yCreateManualEvent(yEvent *ev, int initialState)
Definition: ythread.c:167
Notification_name namenot
Definition: ydef.h:659
static int yStreamSetup(yPrivDeviceSt *dev, char *errmsg)
Definition: ystream.c:1473
#define MAX_YDX_PER_HUB
Definition: yproto.h:727
YHTTP_STATUS httpstate
Definition: yproto.h:688
#define USB_CONF_RESET
Definition: ydef.h:503
unsigned int nb_startup_retry
Definition: yproto.h:685
u64 YAPI_FUNCTION_EXPORT yapiGetTickCount(void)
Definition: yapi.c:2713
u64 leave
Definition: yproto.h:478
Notification_tiny tinypubvalnot
Definition: ydef.h:654
SAFE_U16 deviceid
Definition: ydef.h:632
void yyyPacketShutdown(yInterfaceSt *iface)
yCRITICAL_SECTION enum_cs
Definition: yproto.h:931
#define DEVGEN_LOG_PENDING
Definition: yproto.h:647
char serial[YOCTO_SERIAL_LEN]
Definition: ydef.h:454
u16 nbinbterfaces
Definition: ydef.h:451
#define NOTIFY_PKT_NAME
Definition: ydef.h:539
static void devReportError(LOCATION yPrivDeviceSt *dev, char *error_to_set)
Definition: ystream.c:683
Notification_funcval pubvalnot
Definition: ydef.h:665
yFifoBuf http_fifo
Definition: yproto.h:701
static int yStreamReceived(yPrivDeviceSt *dev, u8 *stream, u8 **data, u8 *size, u64 blockUntilTime, char *errmsg)
Definition: ystream.c:1506
static int devStartIdle(LOCATION yPrivDeviceSt *dev, char *errmsg)
Definition: ystream.c:335
void yCloseEvent(yEvent *ev)
Definition: ythread.c:223
int ypRegister(yStrRef categ, yStrRef serial, yStrRef funcId, yStrRef funcName, int funClass, int funYdx, const char *funcVal)
Definition: yhash.c:1253
u8 stream
Definition: ydef.h:483
void dumpYPerfEntry(yPerfMon *entry, const char *name)
Definition: ystream.c:2353
int yyyOShdlCompare(yPrivDeviceSt *dev, yInterfaceSt *newiface)
Notification_header head
Definition: ydef.h:657
u16 pkt_version
Definition: yproto.h:566
#define YISERR(retcode)
Definition: ydef.h:394
void yUSBReleaseAllDevices(void)
Definition: ystream.c:2182
void ypUpdateYdx(int devydx, Notification_funydx funInfo, const char *funcval)
Definition: ystream.c:286
u8 size
Definition: ydef.h:485
char productname[YOCTO_PRODUCTNAME_LEN]
Definition: ydef.h:453
static int StopDevice(yPrivDeviceSt *dev, char *errmsg)
Definition: ystream.c:2068
#define YIO_DEFAULT_USB_TIMEOUT
Definition: ydef.h:249
static YRETCODE yPktQueuePushEx(pktQueue *q, const USB_Packet *pkt, char *errmsg)
Definition: ystream.c:944
#define ALLOC_YDX_PER_HUB
Definition: yproto.h:728
#define INVALID_YHANDLE
Definition: ydef.h:265
static int StartDevice(yPrivDeviceSt *dev, char *errmsg)
Definition: ystream.c:2036
#define NOTIFY_1STBYTE_MAXTINY
Definition: ydef.h:536
static int yStreamGetTxBuff(yPrivDeviceSt *dev, u8 **data, u8 *maxsize)
Definition: ystream.c:1544
yapiLogFunction log
Definition: yproto.h:951
s32 YUSBDEV
Definition: ydef.h:239
struct _pktItem * next
Definition: yproto.h:513
#define YSTREAM_EMPTY
Definition: ydef.h:523
yContextSt * yContext
Definition: ystream.c:59
int FusionErrmsg(int code, char *errmsg, const char *generr, const char *detailerr)
Definition: ystream.c:112
#define YOCTO_AKA_YFUNCTION
Definition: ydef.h:413
#define YSTRNCAT(dst, dstsize, src, len)
Definition: yproto.h:236
#define YSTRNCPY(dst, dstsize, src, len)
Definition: yproto.h:237
static void WriteTsamp(FILE *f)
Definition: ystream.c:147
#define YSTREAM_TCP
Definition: ydef.h:524
struct _yPrivDeviceSt * next
Definition: yproto.h:704
u16 vendorid
Definition: yproto.h:563
static int yPacketSetup(yPrivDeviceSt *dev, char *errmsg)
Definition: ystream.c:1351
u16 yPopFifo(yFifoBuf *buf, u8 *data, u16 datalen)
Definition: yfifo.c:187
u32 io_counter
Definition: yproto.h:939
yapiRequestAsyncCallback callback
Definition: yproto.h:668
u8 pktno
Definition: ydef.h:482
#define FROM_SAFE_U16(safe, unsafe)
Definition: ydef.h:471
#define YOCTO_N_BASECLASSES
Definition: ydef.h:415
YENU_ACTION enumAction
Definition: yproto.h:682
void ypUpdateHybrid(const char *serial, Notification_funydx funInfo, const char *funcval)
Definition: ystream.c:300
#define YOCTO_LOGICAL_LEN
Definition: ydef.h:424
static int yStreamTransmit(yPrivDeviceSt *dev, u8 proto, u8 size, char *errmsg)
Definition: ystream.c:1581
void ypUpdateUSB(const char *serial, const char *funcid, const char *funcname, int funclass, int funydx, const char *funcval)
Definition: ystream.c:255
Notification_funydx funInfo
Definition: ydef.h:602


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