Exemple #1
0
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;
}
Exemple #3
0
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;
    }
}
Exemple #7
0
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);
		}
	}
}
Exemple #8
0
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);
		}
	}
}