/* 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); }
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; }
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); } }
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 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 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; }
void DNSServiceBrowse_sbc_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, "Dns_sbc_BrowseCallBack returned error: %d\n", errorCode); else { DNSServiceErrorType error; DNSServiceRef serviceRef; char fullname[kDNSServiceMaxDomainName]; CPhidgetSBCHandle sbc; CPhidgetSBCHandle found_sbc; CPhidgetSBCManagerList *trav; DNSServiceConstructFullNamePtr(fullname, name, type, domain); 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'; if(flags & kDNSServiceFlagsAdd) { LOG(PHIDGET_LOG_INFO, "DNSServiceBrowse_sbc_CallBack (Add): %s",name); error = DNSServiceQueryRecordPtr(&serviceRef, 0, interfaceIndex, fullname, kDNSServiceType_TXT, kDNSServiceClass_IN, DNSServiceQueryRecord_SBC_CallBack, sbc); if (error == kDNSServiceErr_NoError) { DNSServiceProcessResultPtr(serviceRef); DNSServiceRefDeallocatePtr(serviceRef); 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 { //make sure zeroconf_ref is not pending if(found_sbc->networkInfo) { CThread_mutex_lock(&found_sbc->networkInfo->zeroconf_ref_lock); if(found_sbc->networkInfo->zeroconf_ref) { DNSServiceRefDeallocatePtr((DNSServiceRef)found_sbc->networkInfo->zeroconf_ref); found_sbc->networkInfo->zeroconf_ref = NULL; } CThread_mutex_unlock(&found_sbc->networkInfo->zeroconf_ref_lock); } //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); } else LOG(PHIDGET_LOG_ERROR, "DNSServiceQueryRecordPtr returned error: %d\n", error); } else { LOG(PHIDGET_LOG_INFO, "DNSServiceBrowse_sbc_CallBack (Remove): %s",name); CThread_mutex_lock(&zeroconfSBCsLock); CThread_mutex_lock(&activeSBCManagersLock); //make sure zeroconf_ref is not pending if(sbc->networkInfo) { CThread_mutex_lock(&sbc->networkInfo->zeroconf_ref_lock); if(sbc->networkInfo->zeroconf_ref) { DNSServiceRefDeallocatePtr((DNSServiceRef)sbc->networkInfo->zeroconf_ref); sbc->networkInfo->zeroconf_ref = NULL; } CThread_mutex_unlock(&sbc->networkInfo->zeroconf_ref_lock); } 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); } } }
void DNSServiceBrowse_Phidget_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, "Dns_sd_BrowseCallBack returned error: %d\n", errorCode); else { DNSServiceErrorType error; DNSServiceRef serviceRef; char fullname[kDNSServiceMaxDomainName]; CPhidgetHandle phid; CPhidgetHandle found_phid; CPhidgetManagerList *trav; DNSServiceConstructFullNamePtr(fullname, name, type, domain); LOG(PHIDGET_LOG_INFO, "DNSServiceBrowse_Phidget_CallBack: %s",name); 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); if(flags & kDNSServiceFlagsAdd) { error = DNSServiceQueryRecordPtr(&serviceRef, 0, interfaceIndex, fullname, kDNSServiceType_TXT, kDNSServiceClass_IN, DNSServiceQueryRecord_Phidget_CallBack, phid); if (error == kDNSServiceErr_NoError) { DNSServiceProcessResultPtr(serviceRef); DNSServiceRefDeallocatePtr(serviceRef); 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); if(CList_findInList((CListHandle)zeroconfPhidgets, phid, CPhidget_areExtraEqual, (void **)&found_phid) == EPHIDGET_OK) { //Only do a detach/attach cycle if something's different if(found_phid->serialNumber == phid->serialNumber && found_phid->deviceVersion == phid->deviceVersion && !strcmp(found_phid->label, phid->label) && !strcmp(found_phid->networkInfo->zeroconf_server_id, phid->networkInfo->zeroconf_server_id)) { CPhidgetRemote_free(phid->networkInfo); CPhidget_free(phid); CThread_mutex_unlock(&activeRemoteManagersLock); CThread_mutex_unlock(&zeroconfPhidgetsLock); return; } //set detaching status CPhidget_clearStatusFlag(&found_phid->status, PHIDGET_ATTACHED_FLAG, &found_phid->lock); CPhidget_setStatusFlag(&found_phid->status, PHIDGET_DETACHING_FLAG, &found_phid->lock); //Remove from list - don't free until after detach event CList_removeFromList((CListHandle *)&zeroconfPhidgets, found_phid, CPhidget_areExtraEqual, FALSE, NULL); 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,found_phid->networkInfo->zeroconf_server_id))) { CList_removeFromList((CListHandle *)&trav->phidm->AttachedPhidgets, found_phid, CPhidget_areExtraEqual, PFALSE, NULL); if (trav->phidm->fptrDetachChange && trav->phidm->state == PHIDGETMANAGER_ACTIVE) trav->phidm->fptrDetachChange((CPhidgetHandle)found_phid, trav->phidm->fptrDetachChangeptr); } } CPhidgetRemote_free(found_phid->networkInfo); CPhidget_free(found_phid); } CPhidget_setStatusFlag(&phid->status, PHIDGET_SERVER_CONNECTED_FLAG, &phid->lock); //now add it CList_addToList((CListHandle *)&zeroconfPhidgets, phid, CPhidget_areExtraEqual); //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))) { CList_addToList((CListHandle *)&trav->phidm->AttachedPhidgets, phid, CPhidget_areExtraEqual); 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); } else LOG(PHIDGET_LOG_ERROR, "DNSServiceQueryRecordPtr returned error: %d\n", error); } else { //have to fill in phid manually from just the name int i; char *name_copy = strdup(name); for(i=0;i<(int)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); //we need to set this so it checks the serial numbers for a match phid->specificDevice = PHIDGETOPEN_SERIAL; for(i = 0;i<PHIDGET_DEVICE_COUNT;i++) if(!strcmp(name_copy, Phid_Device_Def[i].pdd_name)) break; phid->deviceDef = &Phid_Device_Def[i]; //phid->deviceIDSpec = Phid_Device_Def[i].pdd_sdid; phid->deviceIDSpec = 0; //Needs to be 0 because the name can be ambiguous (ie 1018/1200) - we will still match on serial/device class, which is enough for uniqueness 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); if(!CList_findInList((CListHandle)zeroconfPhidgets, phid, CPhidget_areEqual, (void **)&found_phid)) { CPhidget_clearStatusFlag(&found_phid->status, PHIDGET_ATTACHED_FLAG, &found_phid->lock); CPhidget_setStatusFlag(&found_phid->status, PHIDGET_DETACHING_FLAG, &found_phid->lock); CPhidget_setStatusFlag(&found_phid->status, PHIDGET_REMOTE_FLAG, &found_phid->lock); CPhidget_clearStatusFlag(&found_phid->status, PHIDGET_SERVER_CONNECTED_FLAG, &found_phid->lock); CList_removeFromList((CListHandle *)&zeroconfPhidgets, found_phid, CPhidget_areExtraEqual, FALSE, NULL); //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,found_phid->networkInfo->zeroconf_server_id))) { CList_removeFromList((CListHandle *)&trav->phidm->AttachedPhidgets, found_phid, CPhidget_areExtraEqual, PFALSE, NULL); if (trav->phidm->fptrDetachChange && trav->phidm->state == PHIDGETMANAGER_ACTIVE) trav->phidm->fptrDetachChange((CPhidgetHandle)found_phid, trav->phidm->fptrDetachChangeptr); } } CPhidget_clearStatusFlag(&found_phid->status, PHIDGET_DETACHING_FLAG, &found_phid->lock); CPhidgetRemote_free(found_phid->networkInfo); CPhidget_free(found_phid); } CPhidgetRemote_free(phid->networkInfo); CPhidget_free(phid); CThread_mutex_unlock(&activeRemoteManagersLock); CThread_mutex_unlock(&zeroconfPhidgetsLock); free(name_copy); } } }
void DNSServiceBrowse_Phidget_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, "Dns_sd_BrowseCallBack returned error: %d\n", errorCode); else { DNSServiceErrorType error; DNSServiceRef serviceRef; char fullname[kDNSServiceMaxDomainName]; CPhidgetHandle phid; CPhidgetManagerList *trav; DNSServiceConstructFullNamePtr(fullname, name, type, domain); LOG(PHIDGET_LOG_INFO, "DNSServiceBrowse_Phidget_CallBack: %s",name); 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); if(flags & kDNSServiceFlagsAdd) { error = DNSServiceQueryRecordPtr(&serviceRef, 0, interfaceIndex, fullname, kDNSServiceType_TXT, kDNSServiceClass_IN, DNSServiceQueryRecord_Phidget_CallBack, phid); if (error == kDNSServiceErr_NoError) { DNSServiceProcessResultPtr(serviceRef); DNSServiceRefDeallocatePtr(serviceRef); CThread_mutex_lock(&zeroconfPhidgetsLock); CThread_mutex_lock(&activeRemoteManagersLock); CPhidget_setStatusFlag(phid, PHIDGET_ATTACHED_FLAG); 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); } else LOG(PHIDGET_LOG_ERROR, "DNSServiceQueryRecordPtr returned error: %d\n", error); } else { //have to fill in phid manually from just the name int i; 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_DeviceSpecificName[i])) break; phid->deviceIDSpec = 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, PHIDGET_ATTACHED_FLAG); CPhidget_setStatusFlag(phid, PHIDGET_DETACHING_FLAG); if(!CList_findInList((CListHandle)zeroconfPhidgets, phid, CPhidget_areEqual, NULL)) { 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, PHIDGET_DETACHING_FLAG); CPhidget_free(phid); } CThread_mutex_unlock(&activeRemoteManagersLock); CThread_mutex_unlock(&zeroconfPhidgetsLock); free(name_copy); } } }