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);

	CList_removeFromList((CListHandle *)&AttachedDevices, phid, CPhidget_areExtraEqual, FALSE, NULL);
	for(trav2 = localPhidgetManagers; trav2; trav2 = trav2->next)
	{
		if (trav2->phidm->fptrDetachChange && trav2->phidm->state == PHIDGETMANAGER_ACTIVE)
		{
			//So we can access AttachedDevices from within the manager atach event
			CThread_mutex_unlock(&attachedDevicesLock);
			trav2->phidm->fptrDetachChange((CPhidgetHandle)phid, trav2->phidm->fptrDetachChangeptr);
			CThread_mutex_lock(&attachedDevicesLock);
		}
	}
	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 == PHIDGETOPEN_ANY_ATTACHED)
				trav->phid->specificDevice = PHIDGETOPEN_ANY;

			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;
			travPhid->deviceUID = 0;
			
#if !defined(_MACOSX) && !defined(WINCE)
			CPhidgetFHandle_free(travPhid->CPhidgetFHandle);
			travPhid->CPhidgetFHandle = NULL;
#endif
			
			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:
	CPhidget_free(phid);

	return result;
}
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;
}
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; 
}
Beispiel #4
0
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);
		}
	}
}
Beispiel #5
0
int InitializeZeroconf()
{
	DNSServiceErrorType error;
	CThread_mutex_lock(&zeroconfInitLock);
	if(!Dns_sdInitialized)
	{
	#ifdef ZEROCONF_RUNTIME_LINKING

	#ifdef _WINDOWS
		if(!(dllHandle = LoadLibrary(L"dnssd.dll")))
		{
			DWORD error = GetLastError();
			switch(error)
			{
			case ERROR_MOD_NOT_FOUND:
				LOG(PHIDGET_LOG_DEBUG,"LoadLibrary failed - module could not be found");
				break;
			default:
				LOG(PHIDGET_LOG_DEBUG,"LoadLibrary failed with error code: %d", error);
			}
			CThread_mutex_unlock(&zeroconfInitLock);
			return EPHIDGET_UNEXPECTED;
		}

		// If the handle is valid, try to get the function address. 
		if (NULL != dllHandle) 
		{ 
		  //Get pointers to our functions using GetProcAddress:
#ifdef WINCE
		  DNSServiceRegisterPtr = (DNSServiceRegisterType)GetProcAddress(dllHandle, L"DNSServiceRegister");
		  DNSServiceProcessResultPtr = (DNSServiceProcessResultType)GetProcAddress(dllHandle, L"DNSServiceProcessResult");
		  DNSServiceRefDeallocatePtr = (DNSServiceRefDeallocateType)GetProcAddress(dllHandle, L"DNSServiceRefDeallocate");
		  DNSServiceAddRecordPtr = (DNSServiceAddRecordType)GetProcAddress(dllHandle, L"DNSServiceAddRecord");
		  DNSServiceUpdateRecordPtr = (DNSServiceUpdateRecordType)GetProcAddress(dllHandle, L"DNSServiceUpdateRecord");
		  DNSServiceRemoveRecordPtr = (DNSServiceRemoveRecordType)GetProcAddress(dllHandle, L"DNSServiceRemoveRecord");
		  DNSServiceBrowsePtr = (DNSServiceBrowseType)GetProcAddress(dllHandle, L"DNSServiceBrowse");
		  DNSServiceResolvePtr = (DNSServiceResolveType)GetProcAddress(dllHandle, L"DNSServiceResolve");
		  DNSServiceQueryRecordPtr = (DNSServiceQueryRecordType)GetProcAddress(dllHandle, L"DNSServiceQueryRecord");
		  DNSServiceConstructFullNamePtr = (DNSServiceConstructFullNameType)GetProcAddress(dllHandle, L"DNSServiceConstructFullName");
		  DNSServiceRefSockFDPtr = (DNSServiceRefSockFDType)GetProcAddress(dllHandle, L"DNSServiceRefSockFD");
#else
		  DNSServiceRegisterPtr = (DNSServiceRegisterType)GetProcAddress(dllHandle, "DNSServiceRegister");
		  DNSServiceProcessResultPtr = (DNSServiceProcessResultType)GetProcAddress(dllHandle, "DNSServiceProcessResult");
		  DNSServiceRefDeallocatePtr = (DNSServiceRefDeallocateType)GetProcAddress(dllHandle, "DNSServiceRefDeallocate");
		  DNSServiceAddRecordPtr = (DNSServiceAddRecordType)GetProcAddress(dllHandle, "DNSServiceAddRecord");
		  DNSServiceUpdateRecordPtr = (DNSServiceUpdateRecordType)GetProcAddress(dllHandle, "DNSServiceUpdateRecord");
		  DNSServiceRemoveRecordPtr = (DNSServiceRemoveRecordType)GetProcAddress(dllHandle, "DNSServiceRemoveRecord");
		  DNSServiceBrowsePtr = (DNSServiceBrowseType)GetProcAddress(dllHandle, "DNSServiceBrowse");
		  DNSServiceResolvePtr = (DNSServiceResolveType)GetProcAddress(dllHandle, "DNSServiceResolve");
		  DNSServiceQueryRecordPtr = (DNSServiceQueryRecordType)GetProcAddress(dllHandle, "DNSServiceQueryRecord");
		  DNSServiceConstructFullNamePtr = (DNSServiceConstructFullNameType)GetProcAddress(dllHandle, "DNSServiceConstructFullName");
		  DNSServiceRefSockFDPtr = (DNSServiceRefSockFDType)GetProcAddress(dllHandle, "DNSServiceRefSockFD");
#endif

		  Dns_sdInitialized = (
			  NULL != DNSServiceRegisterPtr && 
			  NULL != DNSServiceProcessResultPtr &&
			  NULL != DNSServiceRefDeallocatePtr &&
			  NULL != DNSServiceAddRecordPtr &&
			  NULL != DNSServiceUpdateRecordPtr &&
			  NULL != DNSServiceRemoveRecordPtr &&
			  NULL != DNSServiceQueryRecordPtr &&
			  NULL != DNSServiceConstructFullNamePtr &&
			  NULL != DNSServiceRefSockFDPtr);
		}
		
		if(!Dns_sdInitialized)
		{
			LOG(PHIDGET_LOG_DEBUG,"InitializeZeroconf failed somehow...");
			CThread_mutex_unlock(&zeroconfInitLock);
			return EPHIDGET_UNSUPPORTED;
		}
		
	#elif _LINUX
		libHandle = dlopen("libdns_sd.so",RTLD_LAZY);
		if(!libHandle)
		{
			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;
		}
		
		//Get pointers to our functions using dlsym:
		if(!(DNSServiceRegisterPtr = (DNSServiceRegisterType)dlsym(libHandle, "DNSServiceRegister"))) goto dlsym_err;
		if(!(DNSServiceProcessResultPtr = (DNSServiceProcessResultType)dlsym(libHandle, "DNSServiceProcessResult"))) goto dlsym_err;
		if(!(DNSServiceRefDeallocatePtr = (DNSServiceRefDeallocateType)dlsym(libHandle, "DNSServiceRefDeallocate"))) goto dlsym_err;
		if(!(DNSServiceAddRecordPtr = (DNSServiceAddRecordType)dlsym(libHandle, "DNSServiceAddRecord"))) goto dlsym_err;
		if(!(DNSServiceUpdateRecordPtr = (DNSServiceUpdateRecordType)dlsym(libHandle, "DNSServiceUpdateRecord"))) goto dlsym_err;
		if(!(DNSServiceRemoveRecordPtr = (DNSServiceRemoveRecordType)dlsym(libHandle, "DNSServiceRemoveRecord"))) goto dlsym_err;
		if(!(DNSServiceBrowsePtr = (DNSServiceBrowseType)dlsym(libHandle, "DNSServiceBrowse"))) goto dlsym_err;
		if(!(DNSServiceResolvePtr = (DNSServiceResolveType)dlsym(libHandle, "DNSServiceResolve"))) goto dlsym_err;
		if(!(DNSServiceQueryRecordPtr = (DNSServiceQueryRecordType)dlsym(libHandle, "DNSServiceQueryRecord"))) goto dlsym_err;
		if(!(DNSServiceConstructFullNamePtr = (DNSServiceConstructFullNameType)dlsym(libHandle, "DNSServiceConstructFullName"))) goto dlsym_err;
		if(!(DNSServiceRefSockFDPtr = (DNSServiceRefSockFDType)dlsym(libHandle, "DNSServiceRefSockFD"))) goto dlsym_err;
		
		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;
		
	dlsym_good:
		Dns_sdInitialized = TRUE;
	#endif
		
	#else
		Dns_sdInitialized = TRUE;
	#endif
	   LOG(PHIDGET_LOG_DEBUG,"InitializeZeroconf - System supports zeroconf.");
	}
	if(!Dns_sdBrowsing)
	{
		error = DNSServiceBrowsePtr(&zeroconf_browse_ws_ref,
                            0,                // no flags
                            0,                // all network interfaces
                            "_phidget_ws._tcp",     // service type
                            "",               // default domains
                            DNSServiceBrowse_ws_CallBack, // call back function
                            NULL);            // no context
		if (error != kDNSServiceErr_NoError)
		{
			LOG(PHIDGET_LOG_ERROR,"DNSServiceBrowse on _phidget_ws._tcp failed: %d", error);
			CThread_mutex_unlock(&zeroconfInitLock);
			return EPHIDGET_TRYAGAIN;
		}

		error = DNSServiceBrowsePtr(&zeroconf_browse_sbc_ref,
                            0,                // no flags
                            0,                // all network interfaces
                            "_phidget_sbc._tcp",     // service type
                            "",               // default domains
                            DNSServiceBrowse_sbc_CallBack, // call back function
                            NULL);            // no context
		if (error != kDNSServiceErr_NoError)
		{
			LOG(PHIDGET_LOG_ERROR,"DNSServiceBrowse on _phidget_sbc._tcp failed: %d", error);
			CThread_mutex_unlock(&zeroconfInitLock);
			return EPHIDGET_TRYAGAIN;
		}

		error = DNSServiceBrowsePtr(&zeroconf_browse_phidget_ref,
                            0,                // no flags
                            0,                // all network interfaces
                            "_phidget._tcp",     // service type
                            "",               // default domains
                            DNSServiceBrowse_Phidget_CallBack, // call back function
                            NULL);            // no context
		if (error != kDNSServiceErr_NoError)
		{
			LOG(PHIDGET_LOG_ERROR,"DNSServiceBrowse on _phidget._tcp failed: %d", error);
			CThread_mutex_unlock(&zeroconfInitLock);
			return EPHIDGET_TRYAGAIN;
		}

		stopBrowsing = FALSE;
		pthread_create(&dns_thread, NULL, (void *(*)(void *))dns_callback_thread,NULL);

		Dns_sdBrowsing = PTRUE;
		LOG(PHIDGET_LOG_DEBUG,"InitializeZeroconf - Zeroconf browsing active.");
	}
	CThread_mutex_unlock(&zeroconfInitLock);
	return EPHIDGET_OK;
}
Beispiel #6
0
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;
    }
}
Beispiel #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);
		}
	}
}
Beispiel #8
0
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;
	
    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(!(avahi_service_name_join_ptr(fullname, AVAHI_DOMAIN_NAME_MAX, name, type, domain)))
                LOG(PHIDGET_LOG_ERROR, "Failed avahi_service_name_join_ptr '%s': %s", name, avahi_strerror_ptr(avahi_client_errno_ptr(client)));

			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;
			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);
		}
            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;
    }
}
/* 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)
		{
			//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);
		}
	}

	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;
}
Beispiel #11
0
//if outputting to a file, it is designed to be CSV compliant
//only print out debug logs in debug library
PHIDGET21_API int CCONV CPhidget_log(CPhidgetLog_level level, const char *msg, const char *fmt, ...)
{
	int threadID = 0;
	int logToStderr = (int)level & LOG_TO_STDERR;
	va_list va;
	level = level & 0xFF;
#ifdef DEBUG
	if(level <= logging_level || level == PHIDGET_LOG_DEBUG || logToStderr)
#else
	if((level <= logging_level && level != PHIDGET_LOG_DEBUG) || logToStderr)
#endif
	{
		if(!logLockInitialized)
		{
			CThread_mutex_init(&logLock);
			logLockInitialized = PTRUE;
		}
		CThread_mutex_lock(&logLock);
		if (!logFile)
			logFile = stdout;
#ifdef WINCE
		if(logToStderr)
			fprintf(stderr, "%s: ",logLevelToStr(level));
		else if(logFile==stdout)
			fprintf(logFile, "%s: ",logLevelToStr(level));
		else
			fprintf(logFile, "%d,\"%s\",%s,\"", threadID, msg, logLevelToStr(level));
		va_start(va, fmt);
		if(logToStderr)
		{
			vfprintf(stderr, fmt, va);
			va_end(va);
			fprintf(stderr, "\n");
			fflush(stderr);
		}
		else
		{
			vfprintf(logFile, fmt, va);
			va_end(va);
			if(logFile==stdout)
				fprintf(logFile, "\n");
			else
				fprintf(logFile, "\"\n");
			fflush(logFile);
		}
#else //!WINCE
		{
			char date[50];
			struct tm *tmp;
			time_t t;
			time(&t);
 #ifndef _WINDOWS
			struct tm tm;
			localtime_r(&t, &tm);
			tmp = &tm;
			threadID = (int)pthread_self();
 #else
			tmp = localtime(&t);
			threadID = (int)GetCurrentThreadId();
 #endif
			if (!strftime(date, sizeof (date), "%c", tmp))
				strncpy(date, "?", sizeof (date));
			if(logToStderr)
				fprintf(stderr, "%s: ",logLevelToStr(level));
			else if(logFile==stdout)
				fprintf(logFile, "%s: ",logLevelToStr(level));
			else
				fprintf(logFile, "%s,%d,\"%s\",%s,\"", date, threadID, msg, logLevelToStr(level));
			va_start(va, fmt);
			if(logToStderr)
			{
				vfprintf(stderr, fmt, va);
				va_end(va);
				fprintf(stderr, "\n");
				fflush(stderr);
			}
			else
			{
				vfprintf(logFile, fmt, va);
				va_end(va);
				if(logFile==stdout)
					fprintf(logFile, "\n");
				else
					fprintf(logFile, "\"\n");
				fflush(logFile);
			}
		}
#endif
		CThread_mutex_unlock(&logLock);
	}
	return EPHIDGET_OK;
}
Beispiel #12
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);
		}
	}
}