int CCONV CPhidgetDictionary_getKey(CPhidgetDictionaryHandle dict, const char *key, char *val, int vallen) { int result, size; char err[1024], *keywrap; TESTPTRS(dict, key) TESTPTR(val) CThread_mutex_lock(&dict->lock); if(!CPhidget_statusFlagIsSet(dict->status, PHIDGET_SERVER_CONNECTED_FLAG)) { CThread_mutex_unlock(&dict->lock); return EPHIDGET_NETWORK_NOTCONNECTED; } //The get command returns a list of keys - since we want just a single key, lets wrap in ^ and $ //other reg exp tags are allowed and will be honoured size = (int)strlen(key); keywrap = (char *)malloc(size+3); snprintf(keywrap, size+3, "^%s$",key); CThread_mutex_lock(&dict->networkInfo->server->pdc_lock); result = pdc_get(dict->networkInfo->server->pdcs, keywrap, val, vallen, err, sizeof(err)); CThread_mutex_unlock(&dict->networkInfo->server->pdc_lock); free(keywrap); CThread_mutex_unlock(&dict->lock); if(result == 0) return EPHIDGET_UNEXPECTED; return EPHIDGET_OK; }
void DNSServiceQueryRecord_Phidget_CallBack ( AvahiRecordBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *name, uint16_t clazz, uint16_t type, const void *rdata, size_t size, AvahiLookupResultFlags flags, void *userdata ) { CPhidgetHandle phid = (CPhidgetHandle)userdata; CPhidgetManagerList *trav; switch(event) { case AVAHI_BROWSER_NEW: PhidFromTXT(phid, size, rdata); LOG(PHIDGET_LOG_INFO, "DNSServiceQueryRecord_Phidget_CallBack: %s",name); CThread_mutex_lock(&zeroconfPhidgetsLock); CThread_mutex_lock(&activeRemoteManagersLock); CPhidget_setStatusFlag(&phid->status, PHIDGET_ATTACHED_FLAG, &phid->lock); CPhidget_setStatusFlag(&phid->status, PHIDGET_REMOTE_FLAG, &phid->lock); CPhidget_setStatusFlag(&phid->status, PHIDGET_SERVER_CONNECTED_FLAG, &phid->lock); if(CList_findInList((CListHandle)zeroconfPhidgets, phid, CPhidget_areEqual, NULL)) { CList_addToList((CListHandle *)&zeroconfPhidgets, phid, CPhidget_areEqual); //managers for (trav=activeRemoteManagers; trav; trav = trav->next) { if(trav->phidm->networkInfo->requested_address==NULL && (trav->phidm->networkInfo->requested_serverID == NULL || !strcmp(trav->phidm->networkInfo->requested_serverID,phid->networkInfo->zeroconf_server_id))) { if (trav->phidm->fptrAttachChange && trav->phidm->state == PHIDGETMANAGER_ACTIVE) trav->phidm->fptrAttachChange((CPhidgetHandle)phid, trav->phidm->fptrAttachChangeptr); } } } CThread_mutex_unlock(&activeRemoteManagersLock); CThread_mutex_unlock(&zeroconfPhidgetsLock); break; case AVAHI_BROWSER_FAILURE: LOG(PHIDGET_LOG_ERROR, "DNSServiceQueryRecord_Phidget_CallBack returned error: %s", avahi_strerror_ptr(avahi_client_errno_ptr(client))); break; case AVAHI_BROWSER_ALL_FOR_NOW: avahi_record_browser_free_ptr(b); case AVAHI_BROWSER_CACHE_EXHAUSTED: LOG(PHIDGET_LOG_INFO, "DNSServiceQueryRecord_Phidget_CallBack %s", event == AVAHI_BROWSER_CACHE_EXHAUSTED ? "CACHE_EXHAUSTED" : "ALL_FOR_NOW"); break; case AVAHI_BROWSER_REMOVE: break; } }
int CCONV CPhidgetDictionary_set_OnKeyChange_Handler(CPhidgetDictionaryHandle dict, CPhidgetDictionaryListenerHandle *dictlistener, const char *pattern, int(CCONV *fptr)(CPhidgetDictionaryHandle dict, void *userPtr, const char *key, const char *val, CPhidgetDictionary_keyChangeReason reason), void *userPtr) { CPhidgetDictionaryListenerHandle dict_listener; char errdesc[1024]; int result; TESTPTRS(dict, pattern) TESTPTR(dictlistener) CThread_mutex_lock(&dict->lock); if(!CPhidget_statusFlagIsSet(dict->status, PHIDGET_SERVER_CONNECTED_FLAG)) { CThread_mutex_unlock(&dict->lock); return EPHIDGET_NETWORK_NOTCONNECTED; } if(!(dict_listener = malloc(sizeof(CPhidgetDictionaryListener)))) { CThread_mutex_unlock(&dict->lock); return EPHIDGET_NOMEMORY; } ZEROMEM(dict_listener, sizeof(CPhidgetDictionaryListener)); dict_listener->dict = dict; dict_listener->fptr = fptr; dict_listener->userPtr = userPtr; CThread_mutex_lock(&dict->networkInfo->server->pdc_lock); if (!(dict_listener->listen_id = pdc_listen(dict->networkInfo->server->pdcs, pattern, dict_event_handler, dict_listener, errdesc, sizeof (errdesc)))) { LOG(PHIDGET_LOG_DEBUG,"pdc_listen: %s", errdesc); free(dict_listener); CThread_mutex_unlock(&dict->networkInfo->server->pdc_lock); CThread_mutex_unlock(&dict->lock); return EPHIDGET_UNEXPECTED; } CThread_mutex_unlock(&dict->networkInfo->server->pdc_lock); CThread_mutex_lock(&dict->listenersLock); if((result = CList_addToList((CListHandle *)&dict->listeners, dict_listener, CPhidgetDictionaryListener_areEqual))) { CThread_mutex_unlock(&dict->listenersLock); CThread_mutex_lock(&dict->networkInfo->server->pdc_lock); pdc_ignore(dict->networkInfo->server->pdcs, dict_listener->listen_id, NULL, 0); CThread_mutex_unlock(&dict->networkInfo->server->pdc_lock); free(dict_listener); CThread_mutex_unlock(&dict->lock); return result; } CThread_mutex_unlock(&dict->listenersLock); CThread_mutex_unlock(&dict->lock); *dictlistener = dict_listener; return EPHIDGET_OK; }
int CCONV CPhidgetManager_open(CPhidgetManagerHandle phidm) { int result = EPHIDGET_OK; TESTPTR(phidm) #if defined(_IPHONE) return EPHIDGET_UNSUPPORTED; #endif #if defined(_ANDROID) if(!ANDROID_USB_GOOD) return EPHIDGET_UNSUPPORTED; #endif CThread_mutex_lock(&phidm->openCloseLock); if (CPhidget_statusFlagIsSet(phidm->status, PHIDGET_OPENED_FLAG)) { LOG(PHIDGET_LOG_WARNING, "Open was called on an already opened Manager handle."); CThread_mutex_unlock(&phidm->openCloseLock); return EPHIDGET_OK; } if(!phidgetLocksInitialized) { CThread_mutex_init(&activeDevicesLock); CThread_mutex_init(&attachedDevicesLock); phidgetLocksInitialized = PTRUE; } if(phidm->state == PHIDGETMANAGER_INACTIVE) { CThread_mutex_lock(&managerLock); CList_addToList((CListHandle *)&localPhidgetManagers, phidm, CPhidgetManager_areEqual); #ifdef _MACOSX phidm->state = PHIDGETMANAGER_ACTIVE; #else phidm->state = PHIDGETMANAGER_ACTIVATING; #endif CPhidget_setStatusFlag(&phidm->status, PHIDGET_ATTACHED_FLAG, &phidm->lock); ActivePhidgetManagers++; CThread_mutex_unlock(&managerLock); result = StartCentralThread(); } CPhidget_setStatusFlag(&phidm->status, PHIDGET_OPENED_FLAG, &phidm->lock); CThread_mutex_unlock(&phidm->openCloseLock); return result; }
// sends out any initial attach events for new managers static int sendInitialEvents() { CPhidgetManagerList *managerList = 0; CPhidgetList *phidList = 0; for(managerList = localPhidgetManagers; managerList; managerList = managerList->next) { if (managerList->phidm->state == PHIDGETMANAGER_ACTIVATING) { managerList->phidm->state = PHIDGETMANAGER_ACTIVE; if (managerList->phidm->fptrAttachChange) { for (phidList=AttachedDevices; phidList; phidList = phidList->next) { //So we can access AttachedDevices from within the manager atach event CThread_mutex_unlock(&attachedDevicesLock); managerList->phidm->fptrAttachChange((CPhidgetHandle)(phidList->phid), managerList->phidm->fptrAttachChangeptr); CThread_mutex_lock(&attachedDevicesLock); } } } } return EPHIDGET_OK; }
/* The internal event handlers for PhidgetManager - these should be called directly from the usb functions... * these run in the context of the central thread * if AddDevice returns EPHIDGET_DUPLICATE, the user callback is not run (good) */ int CPhidgetAttachEvent(CPhidgetHandle phid) { int result = 0; CPhidgetManagerList *trav2 = 0; TESTPTR(phid) result = CList_addToList((CListHandle *)&AttachedDevices, phid, CPhidget_areEqual); if(result == EPHIDGET_DUPLICATE) { return EPHIDGET_OK; } else if(result) { return result; } for(trav2 = localPhidgetManagers; trav2; trav2 = trav2->next) { if (trav2->phidm->fptrAttachChange && trav2->phidm->state == PHIDGETMANAGER_ACTIVE) { //So we can access AttachedDevices from within the manager atach event CThread_mutex_unlock(&attachedDevicesLock); trav2->phidm->fptrAttachChange((CPhidgetHandle)phid, trav2->phidm->fptrAttachChangeptr); CThread_mutex_lock(&attachedDevicesLock); } } return findActiveDevice(phid); }
int getZeroconfHostPort(CPhidgetRemoteHandle networkInfo) { DNSServiceErrorType error; //already a lookup pending? cancel it and start a new one... CThread_mutex_lock(&networkInfo->zeroconf_ref_lock); if(networkInfo->zeroconf_ref != NULL) { DNSServiceRefDeallocatePtr((DNSServiceRef)networkInfo->zeroconf_ref); networkInfo->zeroconf_ref = NULL; } error = DNSServiceResolvePtr((DNSServiceRef *)&networkInfo->zeroconf_ref, 0, // no flags 0, // all network interfaces networkInfo->zeroconf_name, //name networkInfo->zeroconf_type, // service type networkInfo->zeroconf_domain, //domain DNSServiceResolve_CallBack, networkInfo); // no context if (error != kDNSServiceErr_NoError) { LOG(PHIDGET_LOG_ERROR, "getZeroconfHostPort returned error: %d\n", error); networkInfo->zeroconf_ref = NULL; CThread_mutex_unlock(&networkInfo->zeroconf_ref_lock); return EPHIDGET_NETWORK; } else { DNSServiceProcessResultPtr((DNSServiceRef)networkInfo->zeroconf_ref); DNSServiceRefDeallocatePtr((DNSServiceRef)networkInfo->zeroconf_ref); networkInfo->zeroconf_ref = NULL; CThread_mutex_unlock(&networkInfo->zeroconf_ref_lock); return EPHIDGET_OK; } }
int CCONV CPhidgetManager_close(CPhidgetManagerHandle phidm) { TESTPTR(phidm) CThread_mutex_lock(&phidm->openCloseLock); if (!CPhidget_statusFlagIsSet(phidm->status, PHIDGET_OPENED_FLAG)) { LOG(PHIDGET_LOG_WARNING, "Close was called on an already closed Manager handle."); CThread_mutex_unlock(&phidm->openCloseLock); return EPHIDGET_OK; } if(phidm->state == PHIDGETMANAGER_ACTIVE || phidm->state == PHIDGETMANAGER_ACTIVATING) { phidm->state = PHIDGETMANAGER_INACTIVE; CPhidget_clearStatusFlag(&phidm->status, PHIDGET_ATTACHED_FLAG, &phidm->lock); if(CPhidget_statusFlagIsSet(phidm->status, PHIDGET_REMOTE_FLAG)) { //Only free the list phidgets if this is an openRemoteIP - not for openRemote int freeList = phidm->networkInfo->mdns ? PFALSE : PTRUE; unregisterRemoteManager(phidm); CList_emptyList((CListHandle *)&phidm->AttachedPhidgets, freeList, CPhidget_free); } else { CThread_mutex_lock(&managerLock); ActivePhidgetManagers--; CList_removeFromList((CListHandle *)&localPhidgetManagers, phidm, CPhidgetManager_areEqual, PFALSE, NULL); CThread_mutex_unlock(&managerLock); } } //if there are no more active phidgets or managers, wait for the central thread to exit if(!ActiveDevices && !ActivePhidgetManagers) { JoinCentralThread(); //Shut down USB #if defined(_LINUX) && !defined(_ANDROID) CUSBUninit(); #endif } CPhidget_clearStatusFlag(&phidm->status, PHIDGET_OPENED_FLAG, &phidm->lock); CThread_mutex_unlock(&phidm->openCloseLock); return EPHIDGET_OK; }
int UninitializeZeroconf() { void *status; CThread_mutex_lock(&zeroconfInitLock); if(Dns_sdBrowsing) { stopBrowsing = TRUE; if(dns_thread) { pthread_join(dns_thread, &status); dns_thread = NULL; } if(zeroconf_browse_ws_ref) { DNSServiceRefDeallocatePtr(zeroconf_browse_ws_ref); zeroconf_browse_ws_ref = NULL; } if(zeroconf_browse_sbc_ref) { DNSServiceRefDeallocatePtr(zeroconf_browse_sbc_ref); zeroconf_browse_sbc_ref = NULL; } if(zeroconf_browse_phidget_ref) { DNSServiceRefDeallocatePtr(zeroconf_browse_phidget_ref); zeroconf_browse_phidget_ref = NULL; } CThread_mutex_lock(&zeroconfPhidgetsLock); CList_emptyList((CListHandle *)&zeroconfPhidgets, FALSE, NULL); CThread_mutex_unlock(&zeroconfPhidgetsLock); CThread_mutex_lock(&zeroconfSBCsLock); CList_emptyList((CListHandle *)&zeroconfSBCs, FALSE, NULL); CThread_mutex_unlock(&zeroconfSBCsLock); CThread_mutex_lock(&zeroconfServersLock); CList_emptyList((CListHandle *)&zeroconfServers, FALSE, NULL); CThread_mutex_unlock(&zeroconfServersLock); Dns_sdBrowsing = FALSE; } CThread_mutex_unlock(&zeroconfInitLock); return EPHIDGET_OK; }
int CPhidgetDetachEvent(CPhidgetHandle phid) { int result = 0; CPhidgetList *trav = 0; CPhidgetManagerList *trav2 = 0; CPhidgetHandle travPhid = 0; TESTPTR(phid) CPhidget_clearStatusFlag(&phid->status, PHIDGET_ATTACHED_FLAG, NULL); CPhidget_setStatusFlag(&phid->status, PHIDGET_DETACHING_FLAG, NULL); for(trav2 = localPhidgetManagers; trav2; trav2 = trav2->next) { if (trav2->phidm->fptrDetachChange && trav2->phidm->state == PHIDGETMANAGER_ACTIVE) trav2->phidm->fptrDetachChange((CPhidgetHandle)phid, trav2->phidm->fptrDetachChangeptr); } CPhidget_clearStatusFlag(&phid->status, PHIDGET_DETACHING_FLAG, NULL); CThread_mutex_lock(&activeDevicesLock); for (trav=ActiveDevices; trav; trav = trav->next) { if((CPhidget_areExtraEqual(phid, trav->phid) && CPhidget_statusFlagIsSet(trav->phid->status, PHIDGET_ATTACHED_FLAG)) || CPhidgetHandle_areEqual(phid, trav->phid)) { CPhidget_setStatusFlag(&trav->phid->status, PHIDGET_DETACHING_FLAG, &trav->phid->lock); if(trav->phid->specificDevice == 2) trav->phid->specificDevice = 0; trav->phid->writeStopFlag = PTRUE; CThread_set_event(&trav->phid->writeAvailableEvent); //if it's waiting on this event - signal NOW result = CUSBCloseHandle(trav->phid); CThread_join(&trav->phid->writeThread); CThread_join(&trav->phid->readThread); //because trav can be freed during the detach call, don't use it in or after the call travPhid = trav->phid; CThread_mutex_unlock(&activeDevicesLock); if (travPhid->fptrDetach) travPhid->fptrDetach((CPhidgetHandle)travPhid, travPhid->fptrDetachptr); travPhid->deviceIDSpec = 0; CPhidgetFHandle_free(travPhid->CPhidgetFHandle); travPhid->CPhidgetFHandle = NULL; CPhidget_clearStatusFlag(&travPhid->status, PHIDGET_DETACHING_FLAG, &travPhid->lock); CPhidget_clearStatusFlag(&travPhid->status, PHIDGET_USB_ERROR_FLAG, &travPhid->lock); goto found_to_detach; } } CThread_mutex_unlock(&activeDevicesLock); found_to_detach: result = CList_removeFromList((CListHandle *)&AttachedDevices, phid, CPhidget_areExtraEqual, TRUE, CPhidget_free); return result; }
int CCONV CPhidgetDictionary_removeKey(CPhidgetDictionaryHandle dict, const char *pattern) { int result; char err[1024]; TESTPTRS(dict, pattern) CThread_mutex_lock(&dict->lock); if(!CPhidget_statusFlagIsSet(dict->status, PHIDGET_SERVER_CONNECTED_FLAG)) { CThread_mutex_unlock(&dict->lock); return EPHIDGET_NETWORK_NOTCONNECTED; } CThread_mutex_lock(&dict->networkInfo->server->pdc_lock); result = pdc_remove(dict->networkInfo->server->pdcs, pattern, err, sizeof(err)); CThread_mutex_unlock(&dict->networkInfo->server->pdc_lock); CThread_mutex_unlock(&dict->lock); if(result == 0) return EPHIDGET_UNEXPECTED; return EPHIDGET_OK; }
int CCONV CPhidgetManager_close(CPhidgetManagerHandle phidm) { TESTPTR(phidm) CThread_mutex_lock(&phidm->openCloseLock); if (!CPhidget_statusFlagIsSet(phidm->status, PHIDGET_OPENED_FLAG)) { LOG(PHIDGET_LOG_WARNING, "Close was called on an already closed Manager handle."); CThread_mutex_unlock(&phidm->openCloseLock); return EPHIDGET_OK; } if(phidm->state == PHIDGETMANAGER_ACTIVE || phidm->state == PHIDGETMANAGER_ACTIVATING) { phidm->state = PHIDGETMANAGER_INACTIVE; CPhidget_clearStatusFlag(&phidm->status, PHIDGET_ATTACHED_FLAG, &phidm->lock); if(CPhidget_statusFlagIsSet(phidm->status, PHIDGET_REMOTE_FLAG)) { unregisterRemoteManager(phidm); } else { CThread_mutex_lock(&managerLock); ActivePhidgetManagers--; CList_removeFromList((CListHandle *)&localPhidgetManagers, phidm, CPhidgetManager_areEqual, PFALSE, NULL); CThread_mutex_unlock(&managerLock); } } //if there are no more active phidgets or managers, wait for the central thread to exit if(!ActiveDevices && !ActivePhidgetManagers) { JoinCentralThread(); } CPhidget_clearStatusFlag(&phidm->status, PHIDGET_OPENED_FLAG, &phidm->lock); CThread_mutex_unlock(&phidm->openCloseLock); return EPHIDGET_OK; }
//This can be called even when not connected to a server int CCONV CPhidgetDictionary_remove_OnKeyChange_Handler(CPhidgetDictionaryListenerHandle keylistener) { int result = 0; char errdesc[1024]; CPhidgetDictionaryHandle dict; TESTPTR(keylistener) dict = keylistener->dict; CThread_mutex_lock(&dict->lock); if(CPhidget_statusFlagIsSet(dict->status, PHIDGET_SERVER_CONNECTED_FLAG)) { CThread_mutex_lock(&dict->networkInfo->server->pdc_lock); if(!(result = pdc_ignore(dict->networkInfo->server->pdcs, keylistener->listen_id, errdesc, sizeof (errdesc)))) { LOG(PHIDGET_LOG_WARNING,"pdc_ignore: %s",errdesc); CThread_mutex_unlock(&dict->networkInfo->server->pdc_lock); CThread_mutex_unlock(&dict->lock); return EPHIDGET_UNEXPECTED; } CThread_mutex_unlock(&dict->networkInfo->server->pdc_lock); } CThread_mutex_lock(&dict->listenersLock); if((result = CList_removeFromList((CListHandle *)&dict->listeners, keylistener, CPhidgetDictionaryListener_areEqual, PTRUE, CPhidgetDictionaryListener_free))) { CThread_mutex_unlock(&dict->listenersLock); CThread_mutex_unlock(&dict->lock); return result; } CThread_mutex_unlock(&dict->listenersLock); CThread_mutex_unlock(&dict->lock); return EPHIDGET_OK; }
PHIDGET21_API int CCONV CPhidget_disableLogging() { if(!logLockInitialized) { CThread_mutex_init(&logLock); logLockInitialized = PTRUE; } LOG(PHIDGET_LOG_INFO, "Disabling logging"); CThread_mutex_lock(&logLock); if(logFile!=NULL && logFile!=stdout && logFile!=stderr) fclose(logFile); logFile = NULL; logging_level = 0; CThread_mutex_unlock(&logLock); return EPHIDGET_OK; }
void CPhidgetDictionary_free(void *arg) { CPhidgetDictionaryHandle dict = arg; if(!dict) return; CThread_mutex_lock(&dict->listenersLock); CList_emptyList((CListHandle *)&dict->listeners, PTRUE, CPhidgetDictionaryListener_free); CThread_mutex_unlock(&dict->listenersLock); CThread_mutex_destroy(&dict->lock); CThread_mutex_destroy(&dict->listenersLock); CThread_mutex_destroy(&dict->openCloseLock); free(dict); dict = NULL; }
PHIDGET21_API int CCONV CPhidget_enableLogging(CPhidgetLog_level level, const char *outputFile) { if(!logLockInitialized) { CThread_mutex_init(&logLock); logLockInitialized = PTRUE; } CThread_mutex_lock(&logLock); if(outputFile == NULL) logFile = NULL; else logFile = fopen(outputFile,"a"); logging_level = level; CThread_mutex_unlock(&logLock); LOG(PHIDGET_LOG_INFO, "Enabling logging"); return EPHIDGET_OK; }
/* Async add - errors returned to a registered error handler */ int CCONV CPhidgetDictionary_addKey(CPhidgetDictionaryHandle dict, const char *key, const char *val, int persistent) { TESTPTR(dict) TESTPTRS(key, val) CThread_mutex_lock(&dict->lock); if(!CPhidget_statusFlagIsSet(dict->status, PHIDGET_SERVER_CONNECTED_FLAG)) { CThread_mutex_unlock(&dict->lock); return EPHIDGET_NETWORK_NOTCONNECTED; } pdc_async_set(dict->networkInfo->server->pdcs, key, val, (int)strlen(val), persistent?0:1, internal_async_network_error_handler, dict); CThread_mutex_unlock(&dict->lock); return EPHIDGET_OK; }
void DNSServiceBrowse_ws_CallBack(DNSServiceRef service, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char * name, const char * type, const char * domain, void * context) { if (errorCode != kDNSServiceErr_NoError) LOG(PHIDGET_LOG_ERROR, "DNSServiceBrowse_ws_CallBack returned error: %d\n", errorCode); else { char fullname[kDNSServiceMaxDomainName]; CPhidgetRemoteHandle networkInfo; if((CPhidgetRemote_create(&networkInfo))) return; networkInfo->zeroconf_name = strdup(name); networkInfo->zeroconf_server_id = strdup(name); networkInfo->zeroconf_type = strdup(type); networkInfo->zeroconf_domain = strdup(domain); DNSServiceConstructFullNamePtr(fullname, name, type, domain); LOG(PHIDGET_LOG_INFO, "DNSServiceBrowse_ws_CallBack: %s",name); CThread_mutex_lock(&zeroconfServersLock); if(flags & kDNSServiceFlagsAdd) { if(CList_addToList((CListHandle *)&zeroconfServers, networkInfo, CPhidgetRemote_areEqual) != EPHIDGET_OK) CPhidgetRemote_free(networkInfo); } else { CList_removeFromList((CListHandle *)&zeroconfServers, networkInfo, CPhidgetRemote_areEqual, TRUE, CPhidgetRemote_free); } CThread_mutex_unlock(&zeroconfServersLock); } }
int UninitializeZeroconf() { int ret; /* Cleanup things */ CThread_mutex_lock(&zeroconfInitLock); if(Dns_sdInitialized) { if (threaded_poll) { if((ret = avahi_threaded_poll_stop_ptr(threaded_poll)) == -1) LOG(PHIDGET_LOG_WARNING, "avahi_threaded_poll_stop failed",ret); avahi_client_free_ptr(client); avahi_threaded_poll_free_ptr(threaded_poll); threaded_poll = NULL; client = NULL; } } Dns_sdInitialized = FALSE; CThread_mutex_unlock(&zeroconfInitLock); return EPHIDGET_OK; }
int refreshZeroconf(CPhidgetRemoteHandle networkInfo, DNSServiceQueryRecordReply callBack, void *userPtr) { DNSServiceErrorType error; char fullname[kDNSServiceMaxDomainName]; //already a lookup pending? cancel it and start a new one... CThread_mutex_lock(&networkInfo->zeroconf_ref_lock); DNSServiceConstructFullNamePtr(fullname, networkInfo->zeroconf_name, networkInfo->zeroconf_type, networkInfo->zeroconf_domain); if(networkInfo->zeroconf_ref != NULL) { DNSServiceRefDeallocatePtr((DNSServiceRef)networkInfo->zeroconf_ref); networkInfo->zeroconf_ref = NULL; } error = DNSServiceQueryRecordPtr((DNSServiceRef *)&networkInfo->zeroconf_ref, 0, // no flags 0, // all network interfaces fullname, //name kDNSServiceType_TXT, // service type kDNSServiceClass_IN, // service class callBack, userPtr); if (error != kDNSServiceErr_NoError) { LOG(PHIDGET_LOG_ERROR, "getZeroconfHostPort returned error: %d\n", error); networkInfo->zeroconf_ref = NULL; CThread_mutex_unlock(&networkInfo->zeroconf_ref_lock); return EPHIDGET_NETWORK; } else { DNSServiceProcessResultPtr((DNSServiceRef)networkInfo->zeroconf_ref); DNSServiceRefDeallocatePtr((DNSServiceRef)networkInfo->zeroconf_ref); networkInfo->zeroconf_ref = NULL; CThread_mutex_unlock(&networkInfo->zeroconf_ref_lock); return EPHIDGET_OK; } }
int CCONV CPhidgetDictionary_close(CPhidgetDictionaryHandle dict) { int result = EPHIDGET_OK; TESTPTR(dict) CThread_mutex_lock(&dict->openCloseLock); if (!CPhidget_statusFlagIsSet(dict->status, PHIDGET_OPENED_FLAG)) { LOG(PHIDGET_LOG_WARNING, "Close was called on an already closed Dictionary handle."); CThread_mutex_unlock(&dict->openCloseLock); return EPHIDGET_OK; } if((result = unregisterRemoteDictionary(dict)) != EPHIDGET_OK) { CThread_mutex_unlock(&dict->openCloseLock); return result; } CPhidget_clearStatusFlag(&dict->status, PHIDGET_OPENED_FLAG, &dict->lock); CThread_mutex_unlock(&dict->openCloseLock); return EPHIDGET_OK; }
int InitializeZeroconf() { int error; //int ret = 1; int timeout = 50; //500ms const char *avahiVersion; CThread_mutex_lock(&zeroconfInitLock); if(Dns_sdInitialized) { CThread_mutex_unlock(&zeroconfInitLock); return EPHIDGET_OK; } #ifdef ZEROCONF_RUNTIME_LINKING avahiLibHandle = dlopen("libavahi-client.so",RTLD_LAZY); if(!avahiLibHandle) { avahiLibHandle = dlopen("libavahi-client.so.3",RTLD_LAZY); } if(!avahiLibHandle) { LOG(PHIDGET_LOG_WARNING, "dlopen failed with error: %s", dlerror()); LOG(PHIDGET_LOG_WARNING, "Assuming that zeroconf is not supported on this machine."); CThread_mutex_unlock(&zeroconfInitLock); return EPHIDGET_UNSUPPORTED; } //These are always in Avahi if(!(avahi_client_get_version_string_ptr = (avahi_client_get_version_string_type)dlsym(avahiLibHandle, "avahi_client_get_version_string"))) goto dlsym_err; if(!(avahi_service_browser_new_ptr = (avahi_service_browser_new_type)dlsym(avahiLibHandle, "avahi_service_browser_new"))) goto dlsym_err; if(!(avahi_service_resolver_new_ptr = (avahi_service_resolver_new_type)dlsym(avahiLibHandle, "avahi_service_resolver_new"))) goto dlsym_err; if(!(avahi_service_resolver_free_ptr = (avahi_service_resolver_free_type)dlsym(avahiLibHandle, "avahi_service_resolver_free"))) goto dlsym_err; if(!(avahi_record_browser_new_ptr = (avahi_record_browser_new_type)dlsym(avahiLibHandle, "avahi_record_browser_new"))) goto dlsym_err; if(!(avahi_record_browser_free_ptr = (avahi_record_browser_free_type)dlsym(avahiLibHandle, "avahi_record_browser_free"))) goto dlsym_err; if(!(avahi_service_name_join_ptr = (avahi_service_name_join_type)dlsym(avahiLibHandle, "avahi_service_name_join"))) goto dlsym_err; if(!(avahi_client_new_ptr = (avahi_client_new_type)dlsym(avahiLibHandle, "avahi_client_new"))) goto dlsym_err; if(!(avahi_client_free_ptr = (avahi_client_free_type)dlsym(avahiLibHandle, "avahi_client_free"))) goto dlsym_err; if(!(avahi_strerror_ptr = (avahi_strerror_type)dlsym(avahiLibHandle, "avahi_strerror"))) goto dlsym_err; if(!(avahi_client_errno_ptr = (avahi_client_errno_type)dlsym(avahiLibHandle, "avahi_client_errno"))) goto dlsym_err; //These are in Avahi > 0.6.4 if(!(avahi_threaded_poll_new_ptr = (avahi_threaded_poll_new_type)dlsym(avahiLibHandle, "avahi_threaded_poll_new"))) goto dlsym_err2; if(!(avahi_threaded_poll_free_ptr = (avahi_threaded_poll_free_type)dlsym(avahiLibHandle, "avahi_threaded_poll_free"))) goto dlsym_err2; if(!(avahi_threaded_poll_get_ptr = (avahi_threaded_poll_get_type)dlsym(avahiLibHandle, "avahi_threaded_poll_get"))) goto dlsym_err2; if(!(avahi_threaded_poll_start_ptr = (avahi_threaded_poll_start_type)dlsym(avahiLibHandle, "avahi_threaded_poll_start"))) goto dlsym_err2; if(!(avahi_threaded_poll_stop_ptr = (avahi_threaded_poll_stop_type)dlsym(avahiLibHandle, "avahi_threaded_poll_stop"))) goto dlsym_err2; if(!(avahi_threaded_poll_quit_ptr = (avahi_threaded_poll_quit_type)dlsym(avahiLibHandle, "avahi_threaded_poll_quit"))) goto dlsym_err2; if(!(avahi_threaded_poll_lock_ptr = (avahi_threaded_poll_lock_type)dlsym(avahiLibHandle, "avahi_threaded_poll_lock"))) goto dlsym_err2; if(!(avahi_threaded_poll_unlock_ptr = (avahi_threaded_poll_unlock_type)dlsym(avahiLibHandle, "avahi_threaded_poll_unlock"))) goto dlsym_err2; goto dlsym_good; dlsym_err: LOG(PHIDGET_LOG_WARNING, "dlsym failed with error: %s", dlerror()); LOG(PHIDGET_LOG_WARNING, "Assuming that zeroconf is not supported on this machine."); CThread_mutex_unlock(&zeroconfInitLock); return EPHIDGET_UNSUPPORTED; //Old avahi didn't have the thread functions dlsym_err2: LOG(PHIDGET_LOG_WARNING, "dlsym failed with error: %s", dlerror()); LOG(PHIDGET_LOG_WARNING, "Avahi is too old, upgrade to at least version 0.6.4."); LOG(PHIDGET_LOG_WARNING, "Zeroconf will not be used on this machine."); CThread_mutex_unlock(&zeroconfInitLock); return EPHIDGET_UNSUPPORTED; dlsym_good: #endif /* Allocate main loop object */ if (!(threaded_poll = avahi_threaded_poll_new_ptr())) { LOG(PHIDGET_LOG_ERROR, "Failed to create threaded poll object."); CThread_mutex_unlock(&zeroconfInitLock); return EPHIDGET_UNEXPECTED; } /* Allocate a new client */ client = avahi_client_new_ptr(avahi_threaded_poll_get_ptr(threaded_poll), 0, client_callback, NULL, &error); /* Check wether creating the client object succeeded */ if (!client) { LOG(PHIDGET_LOG_ERROR, "Failed to create client: %s", avahi_strerror_ptr(error)); CThread_mutex_unlock(&zeroconfInitLock); return EPHIDGET_UNEXPECTED; } //get version avahiVersion = avahi_client_get_version_string_ptr(client); /* Create the service browsers */ if (!(zeroconf_browse_ws_ref = avahi_service_browser_new_ptr(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "_phidget_ws._tcp", NULL, 0, DNSServiceBrowse_ws_CallBack, client))) { LOG(PHIDGET_LOG_ERROR, "Failed to create service browser: %s", avahi_strerror_ptr(avahi_client_errno_ptr(client))); CThread_mutex_unlock(&zeroconfInitLock); return EPHIDGET_UNEXPECTED; } if (!(zeroconf_browse_phidget_ref = avahi_service_browser_new_ptr(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "_phidget._tcp", NULL, 0, DNSServiceBrowse_Phidget_CallBack, client))) { LOG(PHIDGET_LOG_ERROR, "Failed to create service browser: %s", avahi_strerror_ptr(avahi_client_errno_ptr(client))); CThread_mutex_unlock(&zeroconfInitLock); return EPHIDGET_UNEXPECTED; } if (!(zeroconf_browse_sbc_ref = avahi_service_browser_new_ptr(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "_phidget_sbc._tcp", NULL, 0, DNSServiceBrowse_SBC_CallBack, client))) { LOG(PHIDGET_LOG_ERROR, "Failed to create service browser: %s", avahi_strerror_ptr(avahi_client_errno_ptr(client))); CThread_mutex_unlock(&zeroconfInitLock); return EPHIDGET_UNEXPECTED; } if(avahi_threaded_poll_start_ptr(threaded_poll)) { LOG(PHIDGET_LOG_ERROR, "avahi_threaded_poll_start_ptr failed"); CThread_mutex_unlock(&zeroconfInitLock); return EPHIDGET_UNEXPECTED; } //Thread is started successfully else { //There is a bug in at least Avahi 0.6.16 (Debian Etch default) where thread_running is not set, so quit doesn't work!!!???!?!?!?!?!?! //This is fixed in 0.6.24 //So I'll set it myself here if(strcmp(avahiVersion, "avahi 0.6.24") < 0) { LOG(PHIDGET_LOG_INFO, "Fixing thread_running bug in avahi < 0.6.24"); threaded_poll->thread_running = 1; } } while(!Dns_sdInitialized) { usleep(10000); timeout--; if(!timeout) { UninitializeZeroconf(); LOG(PHIDGET_LOG_ERROR, "InitializeZeroconf Seems bad... Dns_sdInitialized wasn't set to true."); CThread_mutex_unlock(&zeroconfInitLock); return EPHIDGET_UNEXPECTED; } } LOG(PHIDGET_LOG_INFO, "InitializeZeroconf Seems good... (%s)",avahiVersion); CThread_mutex_unlock(&zeroconfInitLock); return EPHIDGET_OK; }
void DNSServiceBrowse_ws_CallBack( AvahiServiceBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *name, const char *type, const char *domain, AVAHI_GCC_UNUSED AvahiLookupResultFlags flags, void* userdata) { switch (event) { case AVAHI_BROWSER_FAILURE: LOG(PHIDGET_LOG_ERROR, "(Browser) %s", avahi_strerror_ptr(avahi_client_errno_ptr(client))); //avahi_threaded_poll_quit_ptr(threaded_poll); return; case AVAHI_BROWSER_NEW: { CPhidgetRemoteHandle networkInfo; if((CPhidgetRemote_create(&networkInfo))) return; networkInfo->zeroconf_name = strdup(name); networkInfo->zeroconf_server_id = strdup(name); networkInfo->zeroconf_type = strdup(type); networkInfo->zeroconf_domain = strdup(domain); LOG(PHIDGET_LOG_INFO, "(Browser) NEW: service '%s' of type '%s' in domain '%s'", name, type, domain); CThread_mutex_lock(&zeroconfServersLock); CList_addToList((CListHandle *)&zeroconfServers, networkInfo, CPhidgetRemote_areEqual); CThread_mutex_unlock(&zeroconfServersLock); } break; case AVAHI_BROWSER_REMOVE: { CPhidgetRemoteHandle networkInfo; if((CPhidgetRemote_create(&networkInfo))) return; networkInfo->zeroconf_name = strdup(name); networkInfo->zeroconf_server_id = strdup(name); networkInfo->zeroconf_type = strdup(type); networkInfo->zeroconf_domain = strdup(domain); LOG(PHIDGET_LOG_INFO, "(Browser) REMOVE: service '%s' of type '%s' in domain '%s'", name, type, domain); CThread_mutex_lock(&zeroconfServersLock); CList_removeFromList((CListHandle *)&zeroconfServers, networkInfo, CPhidgetRemote_areEqual, TRUE, CPhidgetRemote_free); CThread_mutex_unlock(&zeroconfServersLock); } break; case AVAHI_BROWSER_ALL_FOR_NOW: case AVAHI_BROWSER_CACHE_EXHAUSTED: LOG(PHIDGET_LOG_INFO, "(Browser) %s", event == AVAHI_BROWSER_CACHE_EXHAUSTED ? "CACHE_EXHAUSTED" : "ALL_FOR_NOW"); break; } }
void DNSServiceBrowse_SBC_CallBack( AvahiServiceBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *name, const char *type, const char *domain, AVAHI_GCC_UNUSED AvahiLookupResultFlags flags, void* userdata) { CPhidgetSBCHandle sbc, found_sbc; CPhidgetSBCManagerList *trav; int ret; switch (event) { case AVAHI_BROWSER_FAILURE: LOG(PHIDGET_LOG_WARNING, "(Browser) %s", avahi_strerror_ptr(avahi_client_errno_ptr(client))); avahi_threaded_poll_quit_ptr(threaded_poll); return; case AVAHI_BROWSER_NEW: { char fullname[AVAHI_DOMAIN_NAME_MAX]; if((CPhidgetSBC_create(&sbc))) return; if((CPhidgetRemote_create(&sbc->networkInfo))) return; sbc->networkInfo->zeroconf_name = strdup(name); sbc->networkInfo->zeroconf_type = strdup(type); sbc->networkInfo->zeroconf_domain = strdup(domain); sbc->networkInfo->mdns = PTRUE; strncpy(sbc->mac, name+12, 18); //name == 'PhidgetSBC (??:??:??:??:??:??)' sbc->mac[17] = '\0'; LOG(PHIDGET_LOG_INFO, "(Browser) NEW: service '%s' of type '%s' in domain '%s'", name, type, domain); if((ret = avahi_service_name_join_ptr(fullname, AVAHI_DOMAIN_NAME_MAX, name, type, domain)) != AVAHI_OK) LOG(PHIDGET_LOG_ERROR, "Failed avahi_service_name_join_ptr '%s': %s", name, avahi_strerror_ptr(ret)); if(!(avahi_record_browser_new_ptr(client, interface, protocol, fullname, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_TXT, 0, DNSServiceQueryRecord_SBC_CallBack, sbc))) LOG(PHIDGET_LOG_ERROR, "Failed to resolve service '%s': %s", name, avahi_strerror_ptr(avahi_client_errno_ptr(client))); //gets added to list in callback } break; case AVAHI_BROWSER_REMOVE: { if((CPhidgetSBC_create(&sbc))) return; if((CPhidgetRemote_create(&sbc->networkInfo))) return; sbc->networkInfo->zeroconf_name = strdup(name); sbc->networkInfo->zeroconf_type = strdup(type); sbc->networkInfo->zeroconf_domain = strdup(domain); sbc->networkInfo->mdns = PTRUE; strncpy(sbc->mac, name+12, 18); //name == 'PhidgetSBC (??:??:??:??:??:??)' sbc->mac[17] = '\0'; LOG(PHIDGET_LOG_INFO, "(Browser) REMOVE: service '%s' of type '%s' in domain '%s'", name, type, domain); CThread_mutex_lock(&zeroconfSBCsLock); CThread_mutex_lock(&activeSBCManagersLock); if(CList_findInList((CListHandle)zeroconfSBCs, sbc, CPhidgetSBC_areEqual, (void **)&found_sbc) == EPHIDGET_OK) { CList_removeFromList((CListHandle *)&zeroconfSBCs, found_sbc, CPhidgetSBC_areEqual, PFALSE, NULL); //managers for (trav=activeSBCManagers; trav; trav = trav->next) { if (trav->sbcm->fptrDetachChange && trav->sbcm->state == PHIDGETMANAGER_ACTIVE) trav->sbcm->fptrDetachChange((CPhidgetSBCHandle)found_sbc, trav->sbcm->fptrDetachChangeptr); } CPhidgetSBC_free(found_sbc); } CThread_mutex_unlock(&activeSBCManagersLock); CThread_mutex_unlock(&zeroconfSBCsLock); CPhidgetSBC_free(sbc); } break; case AVAHI_BROWSER_ALL_FOR_NOW: case AVAHI_BROWSER_CACHE_EXHAUSTED: LOG(PHIDGET_LOG_INFO, "(Browser) %s", event == AVAHI_BROWSER_CACHE_EXHAUSTED ? "CACHE_EXHAUSTED" : "ALL_FOR_NOW"); break; } }
void DNSServiceBrowse_Phidget_CallBack( AvahiServiceBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *name, const char *type, const char *domain, AVAHI_GCC_UNUSED AvahiLookupResultFlags flags, void* userdata) { CPhidgetHandle phid; CPhidgetManagerList *trav; int ret; switch (event) { case AVAHI_BROWSER_FAILURE: LOG(PHIDGET_LOG_WARNING, "(Browser) %s", avahi_strerror_ptr(avahi_client_errno_ptr(client))); avahi_threaded_poll_quit_ptr(threaded_poll); return; case AVAHI_BROWSER_NEW: { char fullname[AVAHI_DOMAIN_NAME_MAX]; if((CPhidget_create(&phid))) return; if((CPhidgetRemote_create(&phid->networkInfo))) return; phid->networkInfo->zeroconf_name = strdup(name); phid->networkInfo->zeroconf_type = strdup(type); phid->networkInfo->zeroconf_domain = strdup(domain); LOG(PHIDGET_LOG_INFO, "(Browser) NEW: service '%s' of type '%s' in domain '%s'", name, type, domain); if((ret = avahi_service_name_join_ptr(fullname, AVAHI_DOMAIN_NAME_MAX, name, type, domain)) != AVAHI_OK) LOG(PHIDGET_LOG_ERROR, "Failed avahi_service_name_join_ptr '%s': %s", name, avahi_strerror_ptr(ret)); if(!(avahi_record_browser_new_ptr(client, interface, protocol, fullname, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_TXT, 0, DNSServiceQueryRecord_Phidget_CallBack, phid))) LOG(PHIDGET_LOG_ERROR, "Failed to resolve service '%s': %s", name, avahi_strerror_ptr(avahi_client_errno_ptr(client))); //gets added to list in callback } break; case AVAHI_BROWSER_REMOVE: { if((CPhidget_create(&phid))) return; if((CPhidgetRemote_create(&phid->networkInfo))) return; phid->networkInfo->zeroconf_name = strdup(name); phid->networkInfo->zeroconf_type = strdup(type); phid->networkInfo->zeroconf_domain = strdup(domain); LOG(PHIDGET_LOG_INFO, "(Browser) REMOVE: service '%s' of type '%s' in domain '%s'", name, type, domain); //have to fill in phid manually from just the name int i; CPhidgetHandle found_phid; char *name_copy = strdup(name); for(i=0;i<strlen(name_copy);i++) if(name_copy[i] == '(') break; if(i<=1) return; name_copy[strlen(name_copy)-1]='\0'; name_copy[i-1] = '\0'; phid->serialNumber = strtol(name_copy+i+1, NULL, 10); phid->specificDevice = PTRUE; for(i = 0;i<PHIDGET_DEVICE_COUNT;i++) if(!strcmp(name_copy, Phid_Device_Def[i].pdd_name)) break; phid->deviceIDSpec = 0; phid->deviceDef = &Phid_Device_Def[i]; phid->attr = Phid_Device_Def[i].pdd_attr; phid->deviceID = Phid_Device_Def[i].pdd_did; phid->deviceType = Phid_DeviceName[phid->deviceID]; phid->networkInfo->mdns = PTRUE; CThread_mutex_lock(&zeroconfPhidgetsLock); CThread_mutex_lock(&activeRemoteManagersLock); CPhidget_clearStatusFlag(&phid->status, PHIDGET_ATTACHED_FLAG, &phid->lock); CPhidget_setStatusFlag(&phid->status, PHIDGET_DETACHING_FLAG, &phid->lock); CPhidget_setStatusFlag(&phid->status, PHIDGET_REMOTE_FLAG, &phid->lock); CPhidget_clearStatusFlag(&phid->status, PHIDGET_SERVER_CONNECTED_FLAG, &phid->lock); if(!CList_findInList((CListHandle)zeroconfPhidgets, phid, CPhidget_areEqual, (void **)&found_phid)) { strcpy(phid->label, found_phid->label); phid->deviceVersion = found_phid->deviceVersion; CList_removeFromList((CListHandle *)&zeroconfPhidgets, phid, CPhidget_areExtraEqual, TRUE, CPhidget_free); //managers for (trav=activeRemoteManagers; trav; trav = trav->next) { if(trav->phidm->networkInfo->requested_address==NULL && (trav->phidm->networkInfo->requested_serverID == NULL || !strcmp(trav->phidm->networkInfo->requested_serverID,phid->networkInfo->zeroconf_server_id))) { if (trav->phidm->fptrDetachChange && trav->phidm->state == PHIDGETMANAGER_ACTIVE) trav->phidm->fptrDetachChange((CPhidgetHandle)phid, trav->phidm->fptrDetachChangeptr); } } CPhidget_clearStatusFlag(&phid->status, PHIDGET_DETACHING_FLAG, &phid->lock); CPhidget_free(phid); } CThread_mutex_unlock(&activeRemoteManagersLock); CThread_mutex_unlock(&zeroconfPhidgetsLock); free(name_copy); } break; case AVAHI_BROWSER_ALL_FOR_NOW: case AVAHI_BROWSER_CACHE_EXHAUSTED: LOG(PHIDGET_LOG_INFO, "(Browser) %s", event == AVAHI_BROWSER_CACHE_EXHAUSTED ? "CACHE_EXHAUSTED" : "ALL_FOR_NOW"); break; } }
void DNSServiceQueryRecord_SBC_CallBack ( AvahiRecordBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *name, uint16_t clazz, uint16_t type, const void *rdata, size_t size, AvahiLookupResultFlags flags, void *userdata ) { CPhidgetSBCHandle sbc = (CPhidgetSBCHandle)userdata, found_sbc; CPhidgetSBCManagerList *trav; switch(event) { case AVAHI_BROWSER_NEW: SBCFromTXT(sbc, size, rdata); LOG(PHIDGET_LOG_INFO, "DNSServiceQueryRecord_SBC_CallBack: %s",name); CThread_mutex_lock(&zeroconfSBCsLock); CThread_mutex_lock(&activeSBCManagersLock); //Check if it's in the list and if it's different, remove it to make way for the new one // (Sometimes, we don't get a proper detach notification) if(CList_findInList((CListHandle)zeroconfSBCs, sbc, CPhidgetSBC_areEqual, (void **)&found_sbc) == EPHIDGET_OK) { if(CPhidgetSBC_areExtraEqual(found_sbc, sbc) != PTRUE) //A version number has changed { //Remove from list - don't free until after detach event CList_removeFromList((CListHandle *)&zeroconfSBCs, found_sbc, CPhidgetSBC_areEqual, PFALSE, NULL); for (trav=activeSBCManagers; trav; trav = trav->next) { if (trav->sbcm->fptrDetachChange && trav->sbcm->state == PHIDGETMANAGER_ACTIVE) trav->sbcm->fptrDetachChange((CPhidgetSBCHandle)found_sbc, trav->sbcm->fptrDetachChangeptr); } CPhidgetSBC_free(found_sbc); //now we fall through and add back to new one } else //Nothing has changed, we didn't remove, don't add { CPhidgetSBC_free(sbc); goto dontadd; } } //now add it CList_addToList((CListHandle *)&zeroconfSBCs, sbc, CPhidgetSBC_areEqual); //send out events for (trav=activeSBCManagers; trav; trav = trav->next) { if (trav->sbcm->fptrAttachChange && trav->sbcm->state == PHIDGETMANAGER_ACTIVE) trav->sbcm->fptrAttachChange((CPhidgetSBCHandle)sbc, trav->sbcm->fptrAttachChangeptr); } dontadd: CThread_mutex_unlock(&activeSBCManagersLock); CThread_mutex_unlock(&zeroconfSBCsLock); break; case AVAHI_BROWSER_FAILURE: LOG(PHIDGET_LOG_ERROR, "DNSServiceQueryRecord_SBC_CallBack returned error: %s", avahi_strerror_ptr(avahi_client_errno_ptr(client))); break; case AVAHI_BROWSER_ALL_FOR_NOW: avahi_record_browser_free_ptr(b); case AVAHI_BROWSER_CACHE_EXHAUSTED: LOG(PHIDGET_LOG_INFO, "DNSServiceQueryRecord_SBC_CallBack %s", event == AVAHI_BROWSER_CACHE_EXHAUSTED ? "CACHE_EXHAUSTED" : "ALL_FOR_NOW"); break; case AVAHI_BROWSER_REMOVE: break; } }
/* The internal event handlers for PhidgetManager - these should be called directly from the usb functions... * these run in the context of the central thread * if AddDevice returns EPHIDGET_DUPLICATE, the user callback is not run (good) */ int CPhidgetAttachEvent(CPhidgetHandle phid) { int result = 0; CPhidgetList *trav = 0; CPhidgetManagerList *trav2 = 0; CPhidgetHandle travPhid = 0; TESTPTR(phid) result = CList_addToList((CListHandle *)&AttachedDevices, phid, CPhidget_areEqual); if(result == EPHIDGET_DUPLICATE) { return EPHIDGET_OK; } else if(result) { return result; } for(trav2 = localPhidgetManagers; trav2; trav2 = trav2->next) { if (trav2->phidm->fptrAttachChange && trav2->phidm->state == PHIDGETMANAGER_ACTIVE) trav2->phidm->fptrAttachChange((CPhidgetHandle)phid, trav2->phidm->fptrAttachChangeptr); } result = EPHIDGET_OK; CThread_mutex_lock(&activeDevicesLock); //first look for this specific device for (trav=ActiveDevices; trav; trav = trav->next) { if((trav->phid->serialNumber == phid->serialNumber) && (trav->phid->deviceID == phid->deviceID) && !CPhidget_statusFlagIsSet(trav->phid->status, PHIDGET_ATTACHED_FLAG)) { travPhid = trav->phid; CThread_mutex_unlock(&activeDevicesLock); //Prevent close from being called during attachActiveDevice CThread_mutex_lock(&travPhid->openCloseLock); result = attachActiveDevice(travPhid, phid); CThread_mutex_unlock(&travPhid->openCloseLock); return result; } } //second look for a general device for (trav=ActiveDevices; trav; trav = trav->next) { if(CPhidget_areEqual(trav->phid, phid) && !CPhidget_statusFlagIsSet(trav->phid->status, PHIDGET_ATTACHED_FLAG)) { travPhid = trav->phid; CThread_mutex_unlock(&activeDevicesLock); //Prevent close from being called during attachActiveDevice CThread_mutex_lock(&travPhid->openCloseLock); result = attachActiveDevice(travPhid, phid); CThread_mutex_unlock(&travPhid->openCloseLock); //If one doesn't work, try the next one - this would happen if the first one in opened elsewhere if(result != EPHIDGET_OK) { CThread_mutex_lock(&activeDevicesLock); continue; } return result; } } CThread_mutex_unlock(&activeDevicesLock); return result; }
int CCONV CPhidgetManager_getAttachedDevices(CPhidgetManagerHandle phidm, CPhidgetHandle *phidArray[], int *count) { CPhidgetList *trav = 0; int i = 0; TESTPTRS(phidArray, count) TESTPTR(phidm) *count = 0; if(CPhidget_statusFlagIsSet(phidm->status, PHIDGET_REMOTE_FLAG)) { for (trav=phidm->AttachedPhidgets; trav; trav = trav->next) { if (CPhidget_statusFlagIsSet(trav->phid->status, PHIDGET_ATTACHED_FLAG)) (*count)++; } if(*count==0) { *phidArray = NULL; } else { *phidArray = (CPhidgetHandle *)malloc(sizeof(**phidArray) * *count); if (!*phidArray) return EPHIDGET_NOMEMORY; ZEROMEM(*phidArray, sizeof(**phidArray) * *count); for (trav=phidm->AttachedPhidgets, i=0; trav; trav = trav->next) { if (CPhidget_statusFlagIsSet(trav->phid->status, PHIDGET_ATTACHED_FLAG)) { (*phidArray)[i] = trav->phid; i++; } } } } else { CThread_mutex_lock(&attachedDevicesLock); for (trav=AttachedDevices; trav; trav = trav->next) { if (CPhidget_statusFlagIsSet(trav->phid->status, PHIDGET_ATTACHED_FLAG)) (*count)++; } if(*count==0) { *phidArray = NULL; } else { *phidArray = (CPhidgetHandle *)malloc(sizeof(**phidArray) * *count); if (!*phidArray) { CThread_mutex_unlock(&attachedDevicesLock); return EPHIDGET_NOMEMORY; } ZEROMEM(*phidArray, sizeof(**phidArray) * *count); for (trav=AttachedDevices, i=0; trav; trav = trav->next) { if (CPhidget_statusFlagIsSet(trav->phid->status, PHIDGET_ATTACHED_FLAG)) { (*phidArray)[i] = trav->phid; i++; } } } CThread_mutex_unlock(&attachedDevicesLock); } return EPHIDGET_OK; }
int CPhidgetManager_poll() { CPhidgetList *curList = 0, *detachList = 0; CPhidgetList *trav = 0; CPhidgetHandle foundPhidget; if(!managerLockInitialized) { CThread_mutex_init(&managerLock); managerLockInitialized = PTRUE; } CThread_mutex_lock(&managerLock); CThread_mutex_lock(&attachedDevicesLock); sendInitialEvents(); CUSBBuildList(&curList); for (trav=AttachedDevices; trav; trav = trav->next) { if(CList_findInList((CListHandle)curList, trav->phid, CPhidget_areExtraEqual, NULL) == EPHIDGET_NOTFOUND) { CList_addToList((CListHandle *)&detachList, trav->phid, CPhidget_areEqual); } } for (trav=curList; trav; trav = trav->next) { if(CList_findInList((CListHandle)AttachedDevices, trav->phid, CPhidget_areExtraEqual, NULL) == EPHIDGET_NOTFOUND) { CPhidgetAttachEvent(trav->phid); } //if PHIDGET_USB_ERROR_FLAG is set, cycle device through a detach //if it's ok, it will re-attach //this can't yet handle unexpected timeouts (because we don't have a definitive list of expected timeouts) if(CList_findInList((CListHandle)ActiveDevices, trav->phid, CPhidget_areEqual, (void **)&foundPhidget) == EPHIDGET_OK) { if(CPhidget_statusFlagIsSet(foundPhidget->status, PHIDGET_ATTACHED_FLAG)) { if(CPhidget_statusFlagIsSet(foundPhidget->status, PHIDGET_USB_ERROR_FLAG)) { LOG(PHIDGET_LOG_WARNING,"PHIDGET_USB_ERROR_FLAG is set - cycling device through a detach"); CList_addToList((CListHandle *)&detachList, trav->phid, CPhidget_areEqual); } } } } for (trav=detachList; trav; trav = trav->next) { CPhidgetDetachEvent(trav->phid); } CList_emptyList((CListHandle *)&detachList, FALSE, NULL); CList_emptyList((CListHandle *)&curList, FALSE, NULL); CThread_mutex_unlock(&attachedDevicesLock); CThread_mutex_unlock(&managerLock); return EPHIDGET_OK; }
int CPhidgetManager_poll() { CPhidgetList *curList = 0, *detachList = 0; CPhidgetList *trav = 0, *trav2 = 0; CPhidgetHandle foundPhidget; if(!managerLockInitialized) { CThread_mutex_init(&managerLock); managerLockInitialized = PTRUE; } CThread_mutex_lock(&managerLock); CThread_mutex_lock(&attachedDevicesLock); sendInitialEvents(); CUSBBuildList(&curList); for (trav=AttachedDevices; trav; trav = trav->next) { if(CList_findInList((CListHandle)curList, trav->phid, CPhidget_areExtraEqual, NULL) == EPHIDGET_NOTFOUND) { CList_addToList((CListHandle *)&detachList, trav->phid, CPhidget_areEqual); } } for (trav=curList; trav; trav = trav->next) { if(CList_findInList((CListHandle)AttachedDevices, trav->phid, CPhidget_areExtraEqual, NULL) == EPHIDGET_NOTFOUND) { CPhidgetAttachEvent(trav->phid); } //if PHIDGET_USB_ERROR_FLAG is set, cycle device through a detach //if it's ok, it will re-attach CThread_mutex_lock(&activeDevicesLock); if(CList_findInList((CListHandle)ActiveDevices, trav->phid, CPhidget_areEqual, (void **)&foundPhidget) == EPHIDGET_OK) { if(CPhidget_statusFlagIsSet(foundPhidget->status, PHIDGET_ATTACHED_FLAG) && CPhidget_statusFlagIsSet(foundPhidget->status, PHIDGET_USB_ERROR_FLAG)) { LOG(PHIDGET_LOG_WARNING,"PHIDGET_USB_ERROR_FLAG is set - cycling device through a detach"); CList_addToList((CListHandle *)&detachList, trav->phid, CPhidget_areEqual); //if this is a composite device, we must find it's pair and detach that as well. //same serial, but different interface num for (trav2=curList; trav2; trav2 = trav2->next) { if(trav->phid->serialNumber == trav2->phid->serialNumber && trav->phid->deviceDef->pdd_iid != trav2->phid->deviceDef->pdd_iid) { LOG(PHIDGET_LOG_WARNING,"PHIDGET_USB_ERROR_FLAG is set - cycling composite device 2nd interface through a detach"); CList_addToList((CListHandle *)&detachList, trav2->phid, CPhidget_areEqual); } } } } CThread_mutex_unlock(&activeDevicesLock); } for (trav=detachList; trav; trav = trav->next) { CPhidgetDetachEvent(trav->phid); } CList_emptyList((CListHandle *)&detachList, FALSE, NULL); CList_emptyList((CListHandle *)&curList, FALSE, NULL); CThread_mutex_unlock(&attachedDevicesLock); CThread_mutex_unlock(&managerLock); return EPHIDGET_OK; }