cphidgetmanager.c
Go to the documentation of this file.
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 /* A list of local Phidget Managers */
00011 CPhidgetManagerListHandle localPhidgetManagers = NULL;
00012 int ActivePhidgetManagers = 0;
00013 
00014 /* Protects localPhidgetManagers */
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 /* The internal event handlers for PhidgetManager - these should be called directly from the usb functions...
00051  * these run in the context of the central thread
00052  * if AddDevice returns EPHIDGET_DUPLICATE, the user callback is not run (good)
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                         //So we can access AttachedDevices from within the manager atach event
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                         //So we can access AttachedDevices from within the manager atach event
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); //if it's waiting on this event - signal NOW
00116 
00117                         result = CUSBCloseHandle(trav->phid);
00118                         CThread_join(&trav->phid->writeThread);
00119                         CThread_join(&trav->phid->readThread);
00120 
00121                         //because trav can be freed during the detach call, don't use it in or after the call
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 // sends out any initial attach events for new managers
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                                         //So we can access AttachedDevices from within the manager atach event
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                 //if PHIDGET_USB_ERROR_FLAG is set, cycle device through a detach
00212                 //if it's ok, it will re-attach
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                                 //if this is a composite device, we must find it's pair and detach that as well.
00224                                 //same serial, but different interface num
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                         //Only free the list phidgets if this is an openRemoteIP - not for openRemote
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         //if there are no more active phidgets or managers, wait for the central thread to exit
00310         if(!ActiveDevices && !ActivePhidgetManagers)
00311         {
00312                 JoinCentralThread();
00313                 //Shut down USB
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 }


pedal_monitor
Author(s): Pedro Mendes
autogenerated on Fri Jun 6 2014 18:37:20