00001
00002 #include "stdafx.h"
00003 #include "cphidgetmanager.h"
00004 #include "cphidget.h"
00005 #include "cthread.h"
00006 #include "cusb.h"
00007 #include "cphidgetlist.h"
00008 #include "csocket.h"
00009
00010
00011 CPhidgetManagerListHandle localPhidgetManagers = NULL;
00012 int ActivePhidgetManagers = 0;
00013
00014
00015 int managerLockInitialized = PFALSE;
00016 CThread_mutex_t managerLock;
00017
00018 int CPhidgetManager_areEqual(void *arg1, void *arg2)
00019 {
00020 if(arg1 == arg2) return 1;
00021 return 0;
00022 }
00023
00024 void CPhidgetManager_free(void *arg)
00025 {
00026 CPhidgetManagerHandle phidm = (CPhidgetManagerHandle)arg;
00027 if(!phidm) return;
00028
00029 if(CPhidget_statusFlagIsSet(phidm->status, PHIDGET_REMOTE_FLAG))
00030 {
00031 CList_emptyList((CListHandle *)&phidm->AttachedPhidgets, PTRUE, CPhidget_free);
00032 }
00033
00034 CThread_mutex_destroy(&phidm->lock);
00035 CThread_mutex_destroy(&phidm->openCloseLock);
00036
00037 free(phidm); phidm = NULL;
00038 return;
00039 }
00040
00041 int CCONV CPhidgetManager_set_OnError_Handler(CPhidgetManagerHandle phidm,
00042 int(CCONV *fptr)(CPhidgetManagerHandle, void *, int, const char *), void *userPtr)
00043 {
00044 TESTPTR(phidm)
00045 phidm->fptrError = fptr;
00046 phidm->fptrErrorptr = userPtr;
00047 return EPHIDGET_OK;
00048 }
00049
00050
00051
00052
00053
00054 int CPhidgetAttachEvent(CPhidgetHandle phid) {
00055 int result = 0;
00056 CPhidgetManagerList *trav2 = 0;
00057 TESTPTR(phid)
00058 result = CList_addToList((CListHandle *)&AttachedDevices, phid, CPhidget_areEqual);
00059 if(result == EPHIDGET_DUPLICATE)
00060 {
00061 return EPHIDGET_OK;
00062 }
00063 else if(result)
00064 {
00065 return result;
00066 }
00067
00068 for(trav2 = localPhidgetManagers; trav2; trav2 = trav2->next)
00069 {
00070 if (trav2->phidm->fptrAttachChange && trav2->phidm->state == PHIDGETMANAGER_ACTIVE)
00071 {
00072
00073 CThread_mutex_unlock(&attachedDevicesLock);
00074 trav2->phidm->fptrAttachChange((CPhidgetHandle)phid, trav2->phidm->fptrAttachChangeptr);
00075 CThread_mutex_lock(&attachedDevicesLock);
00076 }
00077 }
00078
00079 return findActiveDevice(phid);
00080 }
00081
00082 int CPhidgetDetachEvent(CPhidgetHandle phid) {
00083 int result = 0;
00084 CPhidgetList *trav = 0;
00085 CPhidgetManagerList *trav2 = 0;
00086 CPhidgetHandle travPhid = 0;
00087 TESTPTR(phid)
00088 CPhidget_clearStatusFlag(&phid->status, PHIDGET_ATTACHED_FLAG, NULL);
00089 CPhidget_setStatusFlag(&phid->status, PHIDGET_DETACHING_FLAG, NULL);
00090
00091 CList_removeFromList((CListHandle *)&AttachedDevices, phid, CPhidget_areExtraEqual, FALSE, NULL);
00092 for(trav2 = localPhidgetManagers; trav2; trav2 = trav2->next)
00093 {
00094 if (trav2->phidm->fptrDetachChange && trav2->phidm->state == PHIDGETMANAGER_ACTIVE)
00095 {
00096
00097 CThread_mutex_unlock(&attachedDevicesLock);
00098 trav2->phidm->fptrDetachChange((CPhidgetHandle)phid, trav2->phidm->fptrDetachChangeptr);
00099 CThread_mutex_lock(&attachedDevicesLock);
00100 }
00101 }
00102 CPhidget_clearStatusFlag(&phid->status, PHIDGET_DETACHING_FLAG, NULL);
00103
00104 CThread_mutex_lock(&activeDevicesLock);
00105 for (trav=ActiveDevices; trav; trav = trav->next)
00106 {
00107 if((CPhidget_areExtraEqual(phid, trav->phid) && CPhidget_statusFlagIsSet(trav->phid->status, PHIDGET_ATTACHED_FLAG))
00108 || CPhidgetHandle_areEqual(phid, trav->phid))
00109 {
00110 CPhidget_setStatusFlag(&trav->phid->status, PHIDGET_DETACHING_FLAG, &trav->phid->lock);
00111 if(trav->phid->specificDevice == PHIDGETOPEN_ANY_ATTACHED)
00112 trav->phid->specificDevice = PHIDGETOPEN_ANY;
00113
00114 trav->phid->writeStopFlag = PTRUE;
00115 CThread_set_event(&trav->phid->writeAvailableEvent);
00116
00117 result = CUSBCloseHandle(trav->phid);
00118 CThread_join(&trav->phid->writeThread);
00119 CThread_join(&trav->phid->readThread);
00120
00121
00122 travPhid = trav->phid;
00123 CThread_mutex_unlock(&activeDevicesLock);
00124 if (travPhid->fptrDetach)
00125 travPhid->fptrDetach((CPhidgetHandle)travPhid, travPhid->fptrDetachptr);
00126
00127 travPhid->deviceIDSpec = 0;
00128 travPhid->deviceUID = 0;
00129
00130 #if !defined(_MACOSX) && !defined(WINCE)
00131 CPhidgetFHandle_free(travPhid->CPhidgetFHandle);
00132 travPhid->CPhidgetFHandle = NULL;
00133 #endif
00134
00135 CPhidget_clearStatusFlag(&travPhid->status, PHIDGET_DETACHING_FLAG, &travPhid->lock);
00136 CPhidget_clearStatusFlag(&travPhid->status, PHIDGET_USB_ERROR_FLAG, &travPhid->lock);
00137 goto found_to_detach;
00138 }
00139
00140 }
00141 CThread_mutex_unlock(&activeDevicesLock);
00142
00143 found_to_detach:
00144 CPhidget_free(phid);
00145
00146 return result;
00147 }
00148
00149
00150 static int sendInitialEvents()
00151 {
00152 CPhidgetManagerList *managerList = 0;
00153 CPhidgetList *phidList = 0;
00154
00155 for(managerList = localPhidgetManagers; managerList; managerList = managerList->next)
00156 {
00157 if (managerList->phidm->state == PHIDGETMANAGER_ACTIVATING)
00158 {
00159 managerList->phidm->state = PHIDGETMANAGER_ACTIVE;
00160
00161 if (managerList->phidm->fptrAttachChange)
00162 {
00163 for (phidList=AttachedDevices; phidList; phidList = phidList->next)
00164 {
00165
00166 CThread_mutex_unlock(&attachedDevicesLock);
00167 managerList->phidm->fptrAttachChange((CPhidgetHandle)(phidList->phid), managerList->phidm->fptrAttachChangeptr);
00168 CThread_mutex_lock(&attachedDevicesLock);
00169 }
00170 }
00171 }
00172 }
00173
00174 return EPHIDGET_OK;
00175 }
00176
00177 int CPhidgetManager_poll()
00178 {
00179 CPhidgetList *curList = 0, *detachList = 0;
00180 CPhidgetList *trav = 0, *trav2 = 0;
00181 CPhidgetHandle foundPhidget;
00182
00183 if(!managerLockInitialized)
00184 {
00185 CThread_mutex_init(&managerLock);
00186 managerLockInitialized = PTRUE;
00187 }
00188
00189 CThread_mutex_lock(&managerLock);
00190 CThread_mutex_lock(&attachedDevicesLock);
00191
00192 sendInitialEvents();
00193
00194 CUSBBuildList(&curList);
00195
00196
00197 for (trav=AttachedDevices; trav; trav = trav->next)
00198 {
00199 if(CList_findInList((CListHandle)curList, trav->phid, CPhidget_areExtraEqual, NULL) == EPHIDGET_NOTFOUND)
00200 {
00201 CList_addToList((CListHandle *)&detachList, trav->phid, CPhidget_areEqual);
00202 }
00203 }
00204 for (trav=curList; trav; trav = trav->next)
00205 {
00206 if(CList_findInList((CListHandle)AttachedDevices, trav->phid, CPhidget_areExtraEqual, NULL) == EPHIDGET_NOTFOUND)
00207 {
00208 CPhidgetAttachEvent(trav->phid);
00209 }
00210
00211
00212
00213
00214 CThread_mutex_lock(&activeDevicesLock);
00215 if(CList_findInList((CListHandle)ActiveDevices, trav->phid, CPhidget_areEqual, (void **)&foundPhidget) == EPHIDGET_OK)
00216 {
00217 if(CPhidget_statusFlagIsSet(foundPhidget->status, PHIDGET_ATTACHED_FLAG)
00218 && CPhidget_statusFlagIsSet(foundPhidget->status, PHIDGET_USB_ERROR_FLAG))
00219 {
00220 LOG(PHIDGET_LOG_WARNING,"PHIDGET_USB_ERROR_FLAG is set - cycling device through a detach");
00221 CList_addToList((CListHandle *)&detachList, trav->phid, CPhidget_areEqual);
00222
00223
00224
00225 for (trav2=curList; trav2; trav2 = trav2->next)
00226 {
00227 if(trav->phid->serialNumber == trav2->phid->serialNumber
00228 && trav->phid->deviceDef->pdd_iid != trav2->phid->deviceDef->pdd_iid)
00229 {
00230 LOG(PHIDGET_LOG_WARNING,"PHIDGET_USB_ERROR_FLAG is set - cycling composite device 2nd interface through a detach");
00231 CList_addToList((CListHandle *)&detachList, trav2->phid, CPhidget_areEqual);
00232 }
00233 }
00234 }
00235 }
00236
00237
00238 CThread_mutex_unlock(&activeDevicesLock);
00239 }
00240 for (trav=detachList; trav; trav = trav->next)
00241 {
00242 CPhidgetDetachEvent(trav->phid);
00243 }
00244 CList_emptyList((CListHandle *)&detachList, FALSE, NULL);
00245 CList_emptyList((CListHandle *)&curList, FALSE, NULL);
00246
00247 CThread_mutex_unlock(&attachedDevicesLock);
00248 CThread_mutex_unlock(&managerLock);
00249 return EPHIDGET_OK;
00250 }
00251
00252 int CCONV CPhidgetManager_create(CPhidgetManagerHandle *phidm)
00253 {
00254 CPhidgetManagerHandle phidmtemp = 0;
00255
00256 TESTPTR(phidm)
00257 if(!(phidmtemp = (CPhidgetManagerHandle)malloc(sizeof(CPhidgetManager))))
00258 return EPHIDGET_NOMEMORY;
00259 ZEROMEM(phidmtemp, sizeof(CPhidgetManager));
00260
00261 phidmtemp->state = PHIDGETMANAGER_INACTIVE;
00262
00263 if(!managerLockInitialized)
00264 {
00265 CThread_mutex_init(&managerLock);
00266 managerLockInitialized = PTRUE;
00267 }
00268
00269 CThread_mutex_init(&phidmtemp->lock);
00270 CThread_mutex_init(&phidmtemp->openCloseLock);
00271
00272 *phidm = phidmtemp;
00273 return EPHIDGET_OK;
00274 }
00275
00276 int CCONV CPhidgetManager_close(CPhidgetManagerHandle phidm)
00277 {
00278 TESTPTR(phidm)
00279
00280 CThread_mutex_lock(&phidm->openCloseLock);
00281 if (!CPhidget_statusFlagIsSet(phidm->status, PHIDGET_OPENED_FLAG))
00282 {
00283 LOG(PHIDGET_LOG_WARNING, "Close was called on an already closed Manager handle.");
00284 CThread_mutex_unlock(&phidm->openCloseLock);
00285 return EPHIDGET_OK;
00286 }
00287
00288 if(phidm->state == PHIDGETMANAGER_ACTIVE || phidm->state == PHIDGETMANAGER_ACTIVATING)
00289 {
00290 phidm->state = PHIDGETMANAGER_INACTIVE;
00291 CPhidget_clearStatusFlag(&phidm->status, PHIDGET_ATTACHED_FLAG, &phidm->lock);
00292 if(CPhidget_statusFlagIsSet(phidm->status, PHIDGET_REMOTE_FLAG))
00293 {
00294
00295 int freeList = phidm->networkInfo->mdns ? PFALSE : PTRUE;
00296 unregisterRemoteManager(phidm);
00297
00298 CList_emptyList((CListHandle *)&phidm->AttachedPhidgets, freeList, CPhidget_free);
00299 }
00300 else
00301 {
00302 CThread_mutex_lock(&managerLock);
00303 ActivePhidgetManagers--;
00304 CList_removeFromList((CListHandle *)&localPhidgetManagers, phidm, CPhidgetManager_areEqual, PFALSE, NULL);
00305 CThread_mutex_unlock(&managerLock);
00306 }
00307 }
00308
00309
00310 if(!ActiveDevices && !ActivePhidgetManagers)
00311 {
00312 JoinCentralThread();
00313
00314 #if defined(_LINUX) && !defined(_ANDROID)
00315 CUSBUninit();
00316 #endif
00317 }
00318
00319 CPhidget_clearStatusFlag(&phidm->status, PHIDGET_OPENED_FLAG, &phidm->lock);
00320 CThread_mutex_unlock(&phidm->openCloseLock);
00321 return EPHIDGET_OK;
00322 }
00323
00324 int CCONV CPhidgetManager_delete(CPhidgetManagerHandle phidm)
00325 {
00326 CPhidgetManager_free(phidm);
00327 return EPHIDGET_OK;
00328 }
00329
00330 int CCONV CPhidgetManager_getServerID(CPhidgetManagerHandle phidm, const char **serverID)
00331 {
00332 return CPhidget_getServerID((CPhidgetHandle)phidm, serverID);
00333 }
00334 int CCONV CPhidgetManager_getServerAddress(CPhidgetManagerHandle phidm, const char **address, int *port)
00335 {
00336 return CPhidget_getServerAddress((CPhidgetHandle)phidm, address, port);
00337 }
00338 int CCONV CPhidgetManager_getServerStatus(CPhidgetManagerHandle phidm, int *status)
00339 {
00340 return CPhidget_getServerStatus((CPhidgetHandle)phidm, status);
00341 }
00342
00343 int CCONV CPhidgetManager_open(CPhidgetManagerHandle phidm)
00344 {
00345 int result = EPHIDGET_OK;
00346
00347 TESTPTR(phidm)
00348
00349 #if defined(_IPHONE)
00350 return EPHIDGET_UNSUPPORTED;
00351 #endif
00352
00353 #if defined(_ANDROID)
00354 if(!ANDROID_USB_GOOD)
00355 return EPHIDGET_UNSUPPORTED;
00356 #endif
00357
00358 CThread_mutex_lock(&phidm->openCloseLock);
00359 if (CPhidget_statusFlagIsSet(phidm->status, PHIDGET_OPENED_FLAG))
00360 {
00361 LOG(PHIDGET_LOG_WARNING, "Open was called on an already opened Manager handle.");
00362 CThread_mutex_unlock(&phidm->openCloseLock);
00363 return EPHIDGET_OK;
00364 }
00365
00366 if(!phidgetLocksInitialized)
00367 {
00368 CThread_mutex_init(&activeDevicesLock);
00369 CThread_mutex_init(&attachedDevicesLock);
00370 phidgetLocksInitialized = PTRUE;
00371 }
00372
00373 if(phidm->state == PHIDGETMANAGER_INACTIVE)
00374 {
00375 CThread_mutex_lock(&managerLock);
00376
00377 CList_addToList((CListHandle *)&localPhidgetManagers, phidm, CPhidgetManager_areEqual);
00378
00379 #ifdef _MACOSX
00380 phidm->state = PHIDGETMANAGER_ACTIVE;
00381 #else
00382 phidm->state = PHIDGETMANAGER_ACTIVATING;
00383 #endif
00384
00385 CPhidget_setStatusFlag(&phidm->status, PHIDGET_ATTACHED_FLAG, &phidm->lock);
00386
00387 ActivePhidgetManagers++;
00388
00389 CThread_mutex_unlock(&managerLock);
00390
00391 result = StartCentralThread();
00392 }
00393
00394 CPhidget_setStatusFlag(&phidm->status, PHIDGET_OPENED_FLAG, &phidm->lock);
00395 CThread_mutex_unlock(&phidm->openCloseLock);
00396 return result;
00397 }
00398
00399 int CCONV CPhidgetManager_set_OnAttach_Handler(CPhidgetManagerHandle phidm, int (CCONV *fptr)(CPhidgetHandle phid, void *userPtr), void *userPtr)
00400 {
00401 TESTPTR(phidm)
00402 phidm->fptrAttachChange = fptr;
00403 phidm->fptrAttachChangeptr = userPtr;
00404 return EPHIDGET_OK;
00405 }
00406 int CCONV CPhidgetManager_set_OnDetach_Handler(CPhidgetManagerHandle phidm, int (CCONV *fptr)(CPhidgetHandle phid, void *userPtr), void *userPtr)
00407 {
00408 TESTPTR(phidm)
00409 phidm->fptrDetachChange = fptr;
00410 phidm->fptrDetachChangeptr = userPtr;
00411 return EPHIDGET_OK;
00412 }
00413 int CCONV CPhidgetManager_set_OnServerConnect_Handler(CPhidgetManagerHandle phidm, int (CCONV *fptr)(CPhidgetManagerHandle phidm, void *userPtr), void *userPtr)
00414 {
00415 TESTPTR(phidm)
00416 phidm->fptrServerConnect = fptr;
00417 phidm->fptrServerConnectptr = userPtr;
00418 return EPHIDGET_OK;
00419 }
00420 int CCONV CPhidgetManager_set_OnServerDisconnect_Handler(CPhidgetManagerHandle phidm, int (CCONV *fptr)(CPhidgetManagerHandle phidm, void *userPtr), void *userPtr)
00421 {
00422 TESTPTR(phidm)
00423 phidm->fptrServerDisconnect = fptr;
00424 phidm->fptrServerDisconnectptr = userPtr;
00425 return EPHIDGET_OK;
00426 }
00427
00428 int CCONV CPhidgetManager_freeAttachedDevicesArray(CPhidgetHandle phidArray[])
00429 {
00430 if(!phidArray) return EPHIDGET_OK;
00431 free(phidArray); phidArray = NULL;
00432 return EPHIDGET_OK;
00433 }
00434
00435 int CCONV CPhidgetManager_getAttachedDevices(CPhidgetManagerHandle phidm, CPhidgetHandle *phidArray[], int *count)
00436 {
00437 CPhidgetList *trav = 0;
00438 int i = 0;
00439
00440 TESTPTRS(phidArray, count)
00441 TESTPTR(phidm)
00442
00443 *count = 0;
00444 if(CPhidget_statusFlagIsSet(phidm->status, PHIDGET_REMOTE_FLAG))
00445 {
00446 for (trav=phidm->AttachedPhidgets; trav; trav = trav->next)
00447 {
00448 if (CPhidget_statusFlagIsSet(trav->phid->status, PHIDGET_ATTACHED_FLAG))
00449 (*count)++;
00450 }
00451
00452 if(*count==0)
00453 {
00454 *phidArray = NULL;
00455 }
00456 else
00457 {
00458 *phidArray = (CPhidgetHandle *)malloc(sizeof(**phidArray) * *count);
00459 if (!*phidArray)
00460 return EPHIDGET_NOMEMORY;
00461 ZEROMEM(*phidArray, sizeof(**phidArray) * *count);
00462
00463 for (trav=phidm->AttachedPhidgets, i=0; trav; trav = trav->next)
00464 {
00465 if (CPhidget_statusFlagIsSet(trav->phid->status, PHIDGET_ATTACHED_FLAG))
00466 {
00467 (*phidArray)[i] = trav->phid;
00468 i++;
00469 }
00470 }
00471 }
00472 }
00473 else
00474 {
00475 CThread_mutex_lock(&attachedDevicesLock);
00476 for (trav=AttachedDevices; trav; trav = trav->next)
00477 {
00478 if (CPhidget_statusFlagIsSet(trav->phid->status, PHIDGET_ATTACHED_FLAG))
00479 (*count)++;
00480 }
00481 if(*count==0)
00482 {
00483 *phidArray = NULL;
00484 }
00485 else
00486 {
00487 *phidArray = (CPhidgetHandle *)malloc(sizeof(**phidArray) * *count);
00488 if (!*phidArray)
00489 {
00490 CThread_mutex_unlock(&attachedDevicesLock);
00491 return EPHIDGET_NOMEMORY;
00492 }
00493 ZEROMEM(*phidArray, sizeof(**phidArray) * *count);
00494
00495 for (trav=AttachedDevices, i=0; trav; trav = trav->next)
00496 {
00497 if (CPhidget_statusFlagIsSet(trav->phid->status, PHIDGET_ATTACHED_FLAG))
00498 {
00499 (*phidArray)[i] = trav->phid;
00500 i++;
00501 }
00502 }
00503 }
00504
00505 CThread_mutex_unlock(&attachedDevicesLock);
00506 }
00507 return EPHIDGET_OK;
00508 }