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 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 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; }
int CCONV CPhidget_create(CPhidgetHandle *phid) { CPhidgetHandle temp_phid; TESTPTR(phid) if(!(temp_phid = malloc(sizeof(CPhidget)))) return EPHIDGET_NOMEMORY; ZEROMEM(temp_phid, sizeof(CPhidget)); CThread_mutex_init(&temp_phid->lock); CThread_mutex_init(&temp_phid->openCloseLock); CThread_mutex_init(&temp_phid->writelock); CThread_mutex_init(&temp_phid->outputLock); CThread_create_event(&temp_phid->writeAvailableEvent); CThread_create_event(&temp_phid->writtenEvent); CPhidget_clearStatusFlag(&temp_phid->status, PHIDGET_ATTACHED_FLAG, &temp_phid->lock); *phid = temp_phid; 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; }
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 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); } } }