int CCONV CPhidgetDictionary_getKey(CPhidgetDictionaryHandle dict, const char *key, char *val, int vallen)
{
	int result, size;
	char err[1024], *keywrap;
	TESTPTRS(dict, key)
	TESTPTR(val)

	CThread_mutex_lock(&dict->lock);
	if(!CPhidget_statusFlagIsSet(dict->status, PHIDGET_SERVER_CONNECTED_FLAG))
	{
		CThread_mutex_unlock(&dict->lock);
		return EPHIDGET_NETWORK_NOTCONNECTED;
	}

	//The get command returns a list of keys - since we want just a single key, lets wrap in ^ and $
	//other reg exp tags are allowed and will be honoured
	size = (int)strlen(key);
	keywrap = (char *)malloc(size+3);
	snprintf(keywrap, size+3, "^%s$",key);

	CThread_mutex_lock(&dict->networkInfo->server->pdc_lock);
	result = pdc_get(dict->networkInfo->server->pdcs, keywrap, val, vallen, err, sizeof(err));
	CThread_mutex_unlock(&dict->networkInfo->server->pdc_lock);

	free(keywrap);

	CThread_mutex_unlock(&dict->lock);

	if(result == 0) return EPHIDGET_UNEXPECTED;
	return EPHIDGET_OK;
}
void DNSServiceQueryRecord_Phidget_CallBack
	(
	AvahiRecordBrowser *b, 
	AvahiIfIndex interface, 
	AvahiProtocol protocol, 
	AvahiBrowserEvent event, 
	const char *name, 
	uint16_t clazz, 
	uint16_t type, 
	const void *rdata, 
	size_t size, 
	AvahiLookupResultFlags flags, 
	void *userdata
	)
{
	CPhidgetHandle phid = (CPhidgetHandle)userdata;
	CPhidgetManagerList *trav;
	
	switch(event)
	{
	case AVAHI_BROWSER_NEW:
		PhidFromTXT(phid, size, rdata);
		LOG(PHIDGET_LOG_INFO, "DNSServiceQueryRecord_Phidget_CallBack: %s",name);
		CThread_mutex_lock(&zeroconfPhidgetsLock);
		CThread_mutex_lock(&activeRemoteManagersLock);
		
		CPhidget_setStatusFlag(&phid->status, PHIDGET_ATTACHED_FLAG, &phid->lock);
		CPhidget_setStatusFlag(&phid->status, PHIDGET_REMOTE_FLAG, &phid->lock);
		CPhidget_setStatusFlag(&phid->status, PHIDGET_SERVER_CONNECTED_FLAG, &phid->lock);

		if(CList_findInList((CListHandle)zeroconfPhidgets, phid, CPhidget_areEqual, NULL))
		{
			CList_addToList((CListHandle *)&zeroconfPhidgets, phid, CPhidget_areEqual);
			//managers
			for (trav=activeRemoteManagers; trav; trav = trav->next)
			{
				if(trav->phidm->networkInfo->requested_address==NULL
					&& (trav->phidm->networkInfo->requested_serverID == NULL || !strcmp(trav->phidm->networkInfo->requested_serverID,phid->networkInfo->zeroconf_server_id)))
				{
					if (trav->phidm->fptrAttachChange && trav->phidm->state == PHIDGETMANAGER_ACTIVE)
						trav->phidm->fptrAttachChange((CPhidgetHandle)phid, trav->phidm->fptrAttachChangeptr);
				}
			}
		}
		CThread_mutex_unlock(&activeRemoteManagersLock);
		CThread_mutex_unlock(&zeroconfPhidgetsLock);
		break;
	case AVAHI_BROWSER_FAILURE:
		LOG(PHIDGET_LOG_ERROR, "DNSServiceQueryRecord_Phidget_CallBack returned error: %s", avahi_strerror_ptr(avahi_client_errno_ptr(client)));
		break;
	case AVAHI_BROWSER_ALL_FOR_NOW:
		avahi_record_browser_free_ptr(b);
	case AVAHI_BROWSER_CACHE_EXHAUSTED:
		LOG(PHIDGET_LOG_INFO, "DNSServiceQueryRecord_Phidget_CallBack %s", event == AVAHI_BROWSER_CACHE_EXHAUSTED ? "CACHE_EXHAUSTED" : "ALL_FOR_NOW");
		break;
	case AVAHI_BROWSER_REMOVE:
		break;
	}
}
예제 #3
0
int CCONV CPhidgetDictionary_set_OnKeyChange_Handler(CPhidgetDictionaryHandle dict, CPhidgetDictionaryListenerHandle *dictlistener, const char *pattern, 
	int(CCONV *fptr)(CPhidgetDictionaryHandle dict, void *userPtr, const char *key, const char *val, CPhidgetDictionary_keyChangeReason reason),
	void *userPtr)
{
	CPhidgetDictionaryListenerHandle dict_listener;
	char errdesc[1024];
	int result;

	TESTPTRS(dict, pattern)
	TESTPTR(dictlistener)

	CThread_mutex_lock(&dict->lock);
	if(!CPhidget_statusFlagIsSet(dict->status, PHIDGET_SERVER_CONNECTED_FLAG))
	{
		CThread_mutex_unlock(&dict->lock);
		return EPHIDGET_NETWORK_NOTCONNECTED;
	}
		
	if(!(dict_listener = malloc(sizeof(CPhidgetDictionaryListener))))
	{
		CThread_mutex_unlock(&dict->lock);
		return EPHIDGET_NOMEMORY;
	}
	ZEROMEM(dict_listener, sizeof(CPhidgetDictionaryListener));
	
	dict_listener->dict = dict;
	dict_listener->fptr = fptr;
	dict_listener->userPtr = userPtr;
	
	CThread_mutex_lock(&dict->networkInfo->server->pdc_lock);
	if (!(dict_listener->listen_id = pdc_listen(dict->networkInfo->server->pdcs, pattern, dict_event_handler, dict_listener, errdesc, sizeof (errdesc))))
	{
		LOG(PHIDGET_LOG_DEBUG,"pdc_listen: %s", errdesc);
		free(dict_listener);
		CThread_mutex_unlock(&dict->networkInfo->server->pdc_lock);
		CThread_mutex_unlock(&dict->lock);
		return EPHIDGET_UNEXPECTED;
	}
	CThread_mutex_unlock(&dict->networkInfo->server->pdc_lock);
	
	CThread_mutex_lock(&dict->listenersLock);
	if((result = CList_addToList((CListHandle *)&dict->listeners, dict_listener, CPhidgetDictionaryListener_areEqual)))
	{
		CThread_mutex_unlock(&dict->listenersLock);
		CThread_mutex_lock(&dict->networkInfo->server->pdc_lock);
		pdc_ignore(dict->networkInfo->server->pdcs, dict_listener->listen_id, NULL, 0);
		CThread_mutex_unlock(&dict->networkInfo->server->pdc_lock);
		free(dict_listener);
		CThread_mutex_unlock(&dict->lock);
		return result;
	}
	CThread_mutex_unlock(&dict->listenersLock);
	CThread_mutex_unlock(&dict->lock);

	*dictlistener = dict_listener;
	
	return EPHIDGET_OK;
}
int CCONV CPhidgetManager_open(CPhidgetManagerHandle phidm)
{
	int result = EPHIDGET_OK;
	
	TESTPTR(phidm)
	
#if defined(_IPHONE)
	return EPHIDGET_UNSUPPORTED;
#endif
	
#if defined(_ANDROID)
	if(!ANDROID_USB_GOOD)
		return EPHIDGET_UNSUPPORTED;
#endif
	
	CThread_mutex_lock(&phidm->openCloseLock);
	if (CPhidget_statusFlagIsSet(phidm->status, PHIDGET_OPENED_FLAG))
	{
		LOG(PHIDGET_LOG_WARNING, "Open was called on an already opened Manager handle.");
		CThread_mutex_unlock(&phidm->openCloseLock);
		return EPHIDGET_OK;
	}

	if(!phidgetLocksInitialized)
	{
		CThread_mutex_init(&activeDevicesLock);
		CThread_mutex_init(&attachedDevicesLock);
		phidgetLocksInitialized = PTRUE;
	}

	if(phidm->state == PHIDGETMANAGER_INACTIVE)
	{
		CThread_mutex_lock(&managerLock);
	
		CList_addToList((CListHandle *)&localPhidgetManagers, phidm, CPhidgetManager_areEqual);
		
#ifdef _MACOSX
		phidm->state = PHIDGETMANAGER_ACTIVE;
#else
		phidm->state = PHIDGETMANAGER_ACTIVATING;
#endif
		
		CPhidget_setStatusFlag(&phidm->status, PHIDGET_ATTACHED_FLAG, &phidm->lock);

		ActivePhidgetManagers++;

		CThread_mutex_unlock(&managerLock);

		result = StartCentralThread();
	}

	CPhidget_setStatusFlag(&phidm->status, PHIDGET_OPENED_FLAG, &phidm->lock);
	CThread_mutex_unlock(&phidm->openCloseLock);
	return result;
}
// sends out any initial attach events for new managers
static int sendInitialEvents()
{
	CPhidgetManagerList *managerList = 0;
	CPhidgetList *phidList = 0;
	
	for(managerList = localPhidgetManagers; managerList; managerList = managerList->next)
	{
		if (managerList->phidm->state == PHIDGETMANAGER_ACTIVATING)
		{
			managerList->phidm->state = PHIDGETMANAGER_ACTIVE;
			
			if (managerList->phidm->fptrAttachChange)
			{
				for (phidList=AttachedDevices; phidList; phidList = phidList->next) 
				{
					//So we can access AttachedDevices from within the manager atach event
					CThread_mutex_unlock(&attachedDevicesLock);
					managerList->phidm->fptrAttachChange((CPhidgetHandle)(phidList->phid), managerList->phidm->fptrAttachChangeptr);
					CThread_mutex_lock(&attachedDevicesLock);
				}
			}
		}
	}

	return EPHIDGET_OK;
}
/* The internal event handlers for PhidgetManager - these should be called directly from the usb functions...
 * these run in the context of the central thread
 * if AddDevice returns EPHIDGET_DUPLICATE, the user callback is not run (good)
 */
int CPhidgetAttachEvent(CPhidgetHandle phid) {
	int result = 0;
	CPhidgetManagerList *trav2 = 0;
	TESTPTR(phid)
	result = CList_addToList((CListHandle *)&AttachedDevices, phid, CPhidget_areEqual);
	if(result == EPHIDGET_DUPLICATE)
	{
		return EPHIDGET_OK;
	}
	else if(result) 
	{
		return result;
	}
	
	for(trav2 = localPhidgetManagers; trav2; trav2 = trav2->next)
	{
		if (trav2->phidm->fptrAttachChange && trav2->phidm->state == PHIDGETMANAGER_ACTIVE)
		{
			//So we can access AttachedDevices from within the manager atach event
			CThread_mutex_unlock(&attachedDevicesLock);
			trav2->phidm->fptrAttachChange((CPhidgetHandle)phid, trav2->phidm->fptrAttachChangeptr);
			CThread_mutex_lock(&attachedDevicesLock);
		}
	}

	return findActiveDevice(phid);
}
예제 #7
0
int getZeroconfHostPort(CPhidgetRemoteHandle networkInfo)
{
	DNSServiceErrorType error;
	//already a lookup pending? cancel it and start a new one...
	CThread_mutex_lock(&networkInfo->zeroconf_ref_lock);
	if(networkInfo->zeroconf_ref != NULL)
	{
		DNSServiceRefDeallocatePtr((DNSServiceRef)networkInfo->zeroconf_ref);
		networkInfo->zeroconf_ref = NULL;
	}
	error = DNSServiceResolvePtr((DNSServiceRef *)&networkInfo->zeroconf_ref,
							   0,  // no flags
							   0,  // all network interfaces
							   networkInfo->zeroconf_name, //name
							   networkInfo->zeroconf_type, // service type
							   networkInfo->zeroconf_domain, //domain
							   DNSServiceResolve_CallBack,
							   networkInfo);     // no context
	if (error != kDNSServiceErr_NoError)
	{
		LOG(PHIDGET_LOG_ERROR, "getZeroconfHostPort returned error: %d\n", error);
		networkInfo->zeroconf_ref = NULL;
		CThread_mutex_unlock(&networkInfo->zeroconf_ref_lock);
		return EPHIDGET_NETWORK;
	}
	else
	{
		DNSServiceProcessResultPtr((DNSServiceRef)networkInfo->zeroconf_ref);
		DNSServiceRefDeallocatePtr((DNSServiceRef)networkInfo->zeroconf_ref);
		networkInfo->zeroconf_ref = NULL;
		CThread_mutex_unlock(&networkInfo->zeroconf_ref_lock);
		return EPHIDGET_OK;
	}
}
int CCONV CPhidgetManager_close(CPhidgetManagerHandle phidm)
{
	TESTPTR(phidm)

	CThread_mutex_lock(&phidm->openCloseLock);
	if (!CPhidget_statusFlagIsSet(phidm->status, PHIDGET_OPENED_FLAG))
	{
		LOG(PHIDGET_LOG_WARNING, "Close was called on an already closed Manager handle.");
		CThread_mutex_unlock(&phidm->openCloseLock);
		return EPHIDGET_OK;
	}

	if(phidm->state == PHIDGETMANAGER_ACTIVE || phidm->state == PHIDGETMANAGER_ACTIVATING)
	{
		phidm->state = PHIDGETMANAGER_INACTIVE;
		CPhidget_clearStatusFlag(&phidm->status, PHIDGET_ATTACHED_FLAG, &phidm->lock);
		if(CPhidget_statusFlagIsSet(phidm->status, PHIDGET_REMOTE_FLAG))
		{
			//Only free the list phidgets if this is an openRemoteIP - not for openRemote
			int freeList = phidm->networkInfo->mdns ? PFALSE : PTRUE;
			unregisterRemoteManager(phidm);

			CList_emptyList((CListHandle *)&phidm->AttachedPhidgets, freeList, CPhidget_free);
		}
		else
		{
			CThread_mutex_lock(&managerLock);
			ActivePhidgetManagers--;
			CList_removeFromList((CListHandle *)&localPhidgetManagers, phidm, CPhidgetManager_areEqual, PFALSE, NULL);
			CThread_mutex_unlock(&managerLock);
		}
	}
	
	//if there are no more active phidgets or managers, wait for the central thread to exit
	if(!ActiveDevices && !ActivePhidgetManagers)
	{
		JoinCentralThread();
		//Shut down USB
#if defined(_LINUX) && !defined(_ANDROID)
		CUSBUninit();
#endif
	}

	CPhidget_clearStatusFlag(&phidm->status, PHIDGET_OPENED_FLAG, &phidm->lock);
	CThread_mutex_unlock(&phidm->openCloseLock);
	return EPHIDGET_OK;
}
예제 #9
0
int UninitializeZeroconf()
{
	void *status;
	CThread_mutex_lock(&zeroconfInitLock);
	if(Dns_sdBrowsing)
	{
		stopBrowsing = TRUE;
		if(dns_thread)
		{
			pthread_join(dns_thread, &status);
			dns_thread = NULL;
		}

		if(zeroconf_browse_ws_ref)
		{
			DNSServiceRefDeallocatePtr(zeroconf_browse_ws_ref);
			zeroconf_browse_ws_ref = NULL;
		}
		if(zeroconf_browse_sbc_ref)
		{
			DNSServiceRefDeallocatePtr(zeroconf_browse_sbc_ref);
			zeroconf_browse_sbc_ref = NULL;
		}
		if(zeroconf_browse_phidget_ref)
		{
			DNSServiceRefDeallocatePtr(zeroconf_browse_phidget_ref);
			zeroconf_browse_phidget_ref = NULL;
		}
		
		CThread_mutex_lock(&zeroconfPhidgetsLock);
		CList_emptyList((CListHandle *)&zeroconfPhidgets, FALSE, NULL);
		CThread_mutex_unlock(&zeroconfPhidgetsLock);
		
		CThread_mutex_lock(&zeroconfSBCsLock);
		CList_emptyList((CListHandle *)&zeroconfSBCs, FALSE, NULL);
		CThread_mutex_unlock(&zeroconfSBCsLock);
		
		CThread_mutex_lock(&zeroconfServersLock);
		CList_emptyList((CListHandle *)&zeroconfServers, FALSE, NULL);
		CThread_mutex_unlock(&zeroconfServersLock);

		Dns_sdBrowsing = FALSE;
	}
	CThread_mutex_unlock(&zeroconfInitLock);
	return EPHIDGET_OK;
}
예제 #10
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 CPhidgetDictionary_removeKey(CPhidgetDictionaryHandle dict, const char *pattern)
{
	int result;
	char err[1024];
	TESTPTRS(dict, pattern)

	CThread_mutex_lock(&dict->lock);
	if(!CPhidget_statusFlagIsSet(dict->status, PHIDGET_SERVER_CONNECTED_FLAG))
	{
		CThread_mutex_unlock(&dict->lock);
		return EPHIDGET_NETWORK_NOTCONNECTED;
	}

	CThread_mutex_lock(&dict->networkInfo->server->pdc_lock);
	result = pdc_remove(dict->networkInfo->server->pdcs, pattern, err, sizeof(err));
	CThread_mutex_unlock(&dict->networkInfo->server->pdc_lock);

	CThread_mutex_unlock(&dict->lock);

	if(result == 0) return EPHIDGET_UNEXPECTED;
	return EPHIDGET_OK;
}
예제 #12
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;
}
예제 #13
0
//This can be called even when not connected to a server
int CCONV CPhidgetDictionary_remove_OnKeyChange_Handler(CPhidgetDictionaryListenerHandle keylistener)
{
	int result = 0;
	char errdesc[1024];
	CPhidgetDictionaryHandle dict;

	TESTPTR(keylistener)
	dict = keylistener->dict;

	CThread_mutex_lock(&dict->lock);

	if(CPhidget_statusFlagIsSet(dict->status, PHIDGET_SERVER_CONNECTED_FLAG))
	{
		CThread_mutex_lock(&dict->networkInfo->server->pdc_lock);
		if(!(result = pdc_ignore(dict->networkInfo->server->pdcs, keylistener->listen_id, errdesc, sizeof (errdesc))))
		{
			LOG(PHIDGET_LOG_WARNING,"pdc_ignore: %s",errdesc);
			CThread_mutex_unlock(&dict->networkInfo->server->pdc_lock);
			CThread_mutex_unlock(&dict->lock);
			return EPHIDGET_UNEXPECTED;
		}
		CThread_mutex_unlock(&dict->networkInfo->server->pdc_lock);
	}

	CThread_mutex_lock(&dict->listenersLock);
	if((result = CList_removeFromList((CListHandle *)&dict->listeners, keylistener, 
		CPhidgetDictionaryListener_areEqual, PTRUE, CPhidgetDictionaryListener_free)))
	{
		CThread_mutex_unlock(&dict->listenersLock);
		CThread_mutex_unlock(&dict->lock);
		return result;
	}
	CThread_mutex_unlock(&dict->listenersLock);
	CThread_mutex_unlock(&dict->lock);

	return EPHIDGET_OK;
}
예제 #14
0
PHIDGET21_API int CCONV CPhidget_disableLogging()
{
	if(!logLockInitialized)
	{
		CThread_mutex_init(&logLock);
		logLockInitialized = PTRUE;
	}
	LOG(PHIDGET_LOG_INFO, "Disabling logging");
	CThread_mutex_lock(&logLock);
	if(logFile!=NULL && logFile!=stdout && logFile!=stderr)
		fclose(logFile);
	logFile = NULL;
	logging_level = 0;
	CThread_mutex_unlock(&logLock);
	return EPHIDGET_OK;
}
예제 #15
0
void CPhidgetDictionary_free(void *arg)
{
	CPhidgetDictionaryHandle dict = arg;
	
	if(!dict)
		return;
	
	CThread_mutex_lock(&dict->listenersLock);
	CList_emptyList((CListHandle *)&dict->listeners, PTRUE, CPhidgetDictionaryListener_free);
	CThread_mutex_unlock(&dict->listenersLock);

	CThread_mutex_destroy(&dict->lock);
	CThread_mutex_destroy(&dict->listenersLock);
	CThread_mutex_destroy(&dict->openCloseLock);

	free(dict); dict = NULL;
}
예제 #16
0
PHIDGET21_API int CCONV CPhidget_enableLogging(CPhidgetLog_level level, const char *outputFile)
{	
	if(!logLockInitialized)
	{
		CThread_mutex_init(&logLock);
		logLockInitialized = PTRUE;
	}
	CThread_mutex_lock(&logLock);
	if(outputFile == NULL)
		logFile = NULL;
	else
		logFile = fopen(outputFile,"a");
	logging_level = level;
	CThread_mutex_unlock(&logLock);
	LOG(PHIDGET_LOG_INFO, "Enabling logging");
	return EPHIDGET_OK;
}
예제 #17
0
/* Async add - errors returned to a registered error handler */
int CCONV CPhidgetDictionary_addKey(CPhidgetDictionaryHandle dict, const char *key, const char *val, int persistent)
{
	TESTPTR(dict)
	TESTPTRS(key, val)

	CThread_mutex_lock(&dict->lock);
	if(!CPhidget_statusFlagIsSet(dict->status, PHIDGET_SERVER_CONNECTED_FLAG))
	{
		CThread_mutex_unlock(&dict->lock);
		return EPHIDGET_NETWORK_NOTCONNECTED;
	}

	pdc_async_set(dict->networkInfo->server->pdcs, key, val, (int)strlen(val), persistent?0:1, internal_async_network_error_handler, dict);

	CThread_mutex_unlock(&dict->lock);

	return EPHIDGET_OK;
}
예제 #18
0
void DNSServiceBrowse_ws_CallBack(DNSServiceRef service,
                DNSServiceFlags flags,
                uint32_t interfaceIndex,
                DNSServiceErrorType errorCode,
                const char * name,
                const char * type,
                const char * domain,
                void * context)
{
	if (errorCode != kDNSServiceErr_NoError)
		LOG(PHIDGET_LOG_ERROR, "DNSServiceBrowse_ws_CallBack returned error: %d\n", errorCode);
	else
	{
		char fullname[kDNSServiceMaxDomainName];

		CPhidgetRemoteHandle networkInfo;
		if((CPhidgetRemote_create(&networkInfo))) return;

		networkInfo->zeroconf_name = strdup(name);
		networkInfo->zeroconf_server_id = strdup(name);
		networkInfo->zeroconf_type = strdup(type);
		networkInfo->zeroconf_domain = strdup(domain);

		DNSServiceConstructFullNamePtr(fullname, name, type, domain);

		LOG(PHIDGET_LOG_INFO, "DNSServiceBrowse_ws_CallBack: %s",name);

		CThread_mutex_lock(&zeroconfServersLock);
		if(flags & kDNSServiceFlagsAdd)
		{
			if(CList_addToList((CListHandle *)&zeroconfServers, networkInfo, CPhidgetRemote_areEqual) != EPHIDGET_OK)
				CPhidgetRemote_free(networkInfo);
		}
		else
		{
			CList_removeFromList((CListHandle *)&zeroconfServers, networkInfo, CPhidgetRemote_areEqual, TRUE, CPhidgetRemote_free);
		}
		CThread_mutex_unlock(&zeroconfServersLock);
	}
}
int UninitializeZeroconf()
{
	int ret;
    /* Cleanup things */
	CThread_mutex_lock(&zeroconfInitLock);
	if(Dns_sdInitialized)
	{
		if (threaded_poll)
		{
			if((ret = avahi_threaded_poll_stop_ptr(threaded_poll)) == -1)
				LOG(PHIDGET_LOG_WARNING, "avahi_threaded_poll_stop failed",ret);
			avahi_client_free_ptr(client);
			avahi_threaded_poll_free_ptr(threaded_poll);
			threaded_poll = NULL;
			client = NULL;
		}
	}
		
	Dns_sdInitialized = FALSE;
	CThread_mutex_unlock(&zeroconfInitLock);
	return EPHIDGET_OK;
}
예제 #20
0
int refreshZeroconf(CPhidgetRemoteHandle networkInfo, DNSServiceQueryRecordReply callBack, void *userPtr)
{
	DNSServiceErrorType error;
	char fullname[kDNSServiceMaxDomainName];

	//already a lookup pending? cancel it and start a new one...
	CThread_mutex_lock(&networkInfo->zeroconf_ref_lock);
	
	DNSServiceConstructFullNamePtr(fullname, networkInfo->zeroconf_name, networkInfo->zeroconf_type, networkInfo->zeroconf_domain);

	if(networkInfo->zeroconf_ref != NULL)
	{
		DNSServiceRefDeallocatePtr((DNSServiceRef)networkInfo->zeroconf_ref);
		networkInfo->zeroconf_ref = NULL;
	}
	error = DNSServiceQueryRecordPtr((DNSServiceRef *)&networkInfo->zeroconf_ref,
							   0,  // no flags
							   0,  // all network interfaces
							   fullname, //name
							   kDNSServiceType_TXT, // service type
							   kDNSServiceClass_IN, // service class
							   callBack,
							   userPtr);
	if (error != kDNSServiceErr_NoError)
	{
		LOG(PHIDGET_LOG_ERROR, "getZeroconfHostPort returned error: %d\n", error);
		networkInfo->zeroconf_ref = NULL;
		CThread_mutex_unlock(&networkInfo->zeroconf_ref_lock);
		return EPHIDGET_NETWORK;
	}
	else
	{
		DNSServiceProcessResultPtr((DNSServiceRef)networkInfo->zeroconf_ref);
		DNSServiceRefDeallocatePtr((DNSServiceRef)networkInfo->zeroconf_ref);
		networkInfo->zeroconf_ref = NULL;
		CThread_mutex_unlock(&networkInfo->zeroconf_ref_lock);
		return EPHIDGET_OK;
	}
}
예제 #21
0
int CCONV CPhidgetDictionary_close(CPhidgetDictionaryHandle dict)
{
	int result = EPHIDGET_OK;
	TESTPTR(dict)

	CThread_mutex_lock(&dict->openCloseLock);
	if (!CPhidget_statusFlagIsSet(dict->status, PHIDGET_OPENED_FLAG))
	{
		LOG(PHIDGET_LOG_WARNING, "Close was called on an already closed Dictionary handle.");
		CThread_mutex_unlock(&dict->openCloseLock);
		return EPHIDGET_OK;
	}

	if((result = unregisterRemoteDictionary(dict)) != EPHIDGET_OK)
	{
		CThread_mutex_unlock(&dict->openCloseLock);
		return result;
	}

	CPhidget_clearStatusFlag(&dict->status, PHIDGET_OPENED_FLAG, &dict->lock);
	CThread_mutex_unlock(&dict->openCloseLock);
	return EPHIDGET_OK;
}
int InitializeZeroconf()
{
    int error;
    //int ret = 1;
	int timeout = 50; //500ms
	const char *avahiVersion;
	
	CThread_mutex_lock(&zeroconfInitLock);
	if(Dns_sdInitialized) 
	{
		CThread_mutex_unlock(&zeroconfInitLock);
		return EPHIDGET_OK;
	}
	
#ifdef ZEROCONF_RUNTIME_LINKING

	avahiLibHandle = dlopen("libavahi-client.so",RTLD_LAZY);
	if(!avahiLibHandle)
	{
		avahiLibHandle = dlopen("libavahi-client.so.3",RTLD_LAZY);
	}
	if(!avahiLibHandle)
	{
		LOG(PHIDGET_LOG_WARNING, "dlopen failed with error: %s", dlerror());
		LOG(PHIDGET_LOG_WARNING, "Assuming that zeroconf is not supported on this machine.");
		CThread_mutex_unlock(&zeroconfInitLock);
		return EPHIDGET_UNSUPPORTED;
	}

	//These are always in Avahi
	if(!(avahi_client_get_version_string_ptr = (avahi_client_get_version_string_type)dlsym(avahiLibHandle, "avahi_client_get_version_string"))) goto dlsym_err;
	if(!(avahi_service_browser_new_ptr = (avahi_service_browser_new_type)dlsym(avahiLibHandle, "avahi_service_browser_new"))) goto dlsym_err;
	if(!(avahi_service_resolver_new_ptr = (avahi_service_resolver_new_type)dlsym(avahiLibHandle, "avahi_service_resolver_new"))) goto dlsym_err;
	if(!(avahi_service_resolver_free_ptr = (avahi_service_resolver_free_type)dlsym(avahiLibHandle, "avahi_service_resolver_free"))) goto dlsym_err;
	if(!(avahi_record_browser_new_ptr = (avahi_record_browser_new_type)dlsym(avahiLibHandle, "avahi_record_browser_new"))) goto dlsym_err;
	if(!(avahi_record_browser_free_ptr = (avahi_record_browser_free_type)dlsym(avahiLibHandle, "avahi_record_browser_free"))) goto dlsym_err;
	if(!(avahi_service_name_join_ptr = (avahi_service_name_join_type)dlsym(avahiLibHandle, "avahi_service_name_join"))) goto dlsym_err;
	if(!(avahi_client_new_ptr = (avahi_client_new_type)dlsym(avahiLibHandle, "avahi_client_new"))) goto dlsym_err;
	if(!(avahi_client_free_ptr = (avahi_client_free_type)dlsym(avahiLibHandle, "avahi_client_free"))) goto dlsym_err;
	if(!(avahi_strerror_ptr = (avahi_strerror_type)dlsym(avahiLibHandle, "avahi_strerror"))) goto dlsym_err;
	if(!(avahi_client_errno_ptr = (avahi_client_errno_type)dlsym(avahiLibHandle, "avahi_client_errno"))) goto dlsym_err;
	
	//These are in Avahi > 0.6.4
	if(!(avahi_threaded_poll_new_ptr = (avahi_threaded_poll_new_type)dlsym(avahiLibHandle, "avahi_threaded_poll_new"))) goto dlsym_err2;
	if(!(avahi_threaded_poll_free_ptr = (avahi_threaded_poll_free_type)dlsym(avahiLibHandle, "avahi_threaded_poll_free"))) goto dlsym_err2;
	if(!(avahi_threaded_poll_get_ptr = (avahi_threaded_poll_get_type)dlsym(avahiLibHandle, "avahi_threaded_poll_get"))) goto dlsym_err2;
	if(!(avahi_threaded_poll_start_ptr = (avahi_threaded_poll_start_type)dlsym(avahiLibHandle, "avahi_threaded_poll_start"))) goto dlsym_err2;
	if(!(avahi_threaded_poll_stop_ptr = (avahi_threaded_poll_stop_type)dlsym(avahiLibHandle, "avahi_threaded_poll_stop"))) goto dlsym_err2;
	if(!(avahi_threaded_poll_quit_ptr = (avahi_threaded_poll_quit_type)dlsym(avahiLibHandle, "avahi_threaded_poll_quit"))) goto dlsym_err2;
	if(!(avahi_threaded_poll_lock_ptr = (avahi_threaded_poll_lock_type)dlsym(avahiLibHandle, "avahi_threaded_poll_lock"))) goto dlsym_err2;
	if(!(avahi_threaded_poll_unlock_ptr = (avahi_threaded_poll_unlock_type)dlsym(avahiLibHandle, "avahi_threaded_poll_unlock"))) goto dlsym_err2;
	
	goto dlsym_good;
	
dlsym_err:
	LOG(PHIDGET_LOG_WARNING, "dlsym failed with error: %s", dlerror());
	LOG(PHIDGET_LOG_WARNING, "Assuming that zeroconf is not supported on this machine.");
	CThread_mutex_unlock(&zeroconfInitLock);
	return EPHIDGET_UNSUPPORTED;
	
	//Old avahi didn't have the thread functions
dlsym_err2:
	LOG(PHIDGET_LOG_WARNING, "dlsym failed with error: %s", dlerror());
	LOG(PHIDGET_LOG_WARNING, "Avahi is too old, upgrade to at least version 0.6.4.");
	LOG(PHIDGET_LOG_WARNING, "Zeroconf will not be used on this machine.");
	CThread_mutex_unlock(&zeroconfInitLock);
	return EPHIDGET_UNSUPPORTED;
	
dlsym_good:
		
#endif

    /* Allocate main loop object */
    if (!(threaded_poll = avahi_threaded_poll_new_ptr())) {
        LOG(PHIDGET_LOG_ERROR, "Failed to create threaded poll object.");
		CThread_mutex_unlock(&zeroconfInitLock);
        return EPHIDGET_UNEXPECTED;
    }
	
    /* Allocate a new client */
    client = avahi_client_new_ptr(avahi_threaded_poll_get_ptr(threaded_poll), 0, client_callback, NULL, &error);

    /* Check wether creating the client object succeeded */
    if (!client) {
        LOG(PHIDGET_LOG_ERROR, "Failed to create client: %s", avahi_strerror_ptr(error));
		CThread_mutex_unlock(&zeroconfInitLock);
        return EPHIDGET_UNEXPECTED;
    }
	
	//get version
	avahiVersion = avahi_client_get_version_string_ptr(client);
	
	/* Create the service browsers */
    if (!(zeroconf_browse_ws_ref = avahi_service_browser_new_ptr(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "_phidget_ws._tcp", NULL, 0, DNSServiceBrowse_ws_CallBack, client))) {
        LOG(PHIDGET_LOG_ERROR, "Failed to create service browser: %s", avahi_strerror_ptr(avahi_client_errno_ptr(client)));
		CThread_mutex_unlock(&zeroconfInitLock);
        return EPHIDGET_UNEXPECTED;
    }
    if (!(zeroconf_browse_phidget_ref = avahi_service_browser_new_ptr(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "_phidget._tcp", NULL, 0, DNSServiceBrowse_Phidget_CallBack, client))) {
        LOG(PHIDGET_LOG_ERROR, "Failed to create service browser: %s", avahi_strerror_ptr(avahi_client_errno_ptr(client)));
		CThread_mutex_unlock(&zeroconfInitLock);
        return EPHIDGET_UNEXPECTED;
    }
    if (!(zeroconf_browse_sbc_ref = avahi_service_browser_new_ptr(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "_phidget_sbc._tcp", NULL, 0, DNSServiceBrowse_SBC_CallBack, client))) {
        LOG(PHIDGET_LOG_ERROR, "Failed to create service browser: %s", avahi_strerror_ptr(avahi_client_errno_ptr(client)));
		CThread_mutex_unlock(&zeroconfInitLock);
        return EPHIDGET_UNEXPECTED;
    }
	
	if(avahi_threaded_poll_start_ptr(threaded_poll))
	{
		LOG(PHIDGET_LOG_ERROR, "avahi_threaded_poll_start_ptr failed");
		CThread_mutex_unlock(&zeroconfInitLock);
        return EPHIDGET_UNEXPECTED;
	}
	//Thread is started successfully
	else
	{
		//There is a bug in at least Avahi 0.6.16 (Debian Etch default) where thread_running is not set, so quit doesn't work!!!???!?!?!?!?!?!
		//This is fixed in 0.6.24
		//So I'll set it myself here
		if(strcmp(avahiVersion, "avahi 0.6.24") < 0)
		{
			LOG(PHIDGET_LOG_INFO, "Fixing thread_running bug in avahi < 0.6.24");
			threaded_poll->thread_running = 1;
		}
	}
	
	while(!Dns_sdInitialized)
	{
		usleep(10000);
		timeout--;
		if(!timeout)
		{
			UninitializeZeroconf();
			LOG(PHIDGET_LOG_ERROR, "InitializeZeroconf Seems bad... Dns_sdInitialized wasn't set to true.");
			CThread_mutex_unlock(&zeroconfInitLock);
			return EPHIDGET_UNEXPECTED;
		}
	}
	
	LOG(PHIDGET_LOG_INFO, "InitializeZeroconf Seems good... (%s)",avahiVersion);
	
	CThread_mutex_unlock(&zeroconfInitLock);
	return EPHIDGET_OK;
	
}
void DNSServiceBrowse_ws_CallBack(
    AvahiServiceBrowser *b,
    AvahiIfIndex interface,
    AvahiProtocol protocol,
    AvahiBrowserEvent event,
    const char *name,
    const char *type,
    const char *domain,
    AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
    void* userdata) 
{

    switch (event) {

        case AVAHI_BROWSER_FAILURE:
            
            LOG(PHIDGET_LOG_ERROR, "(Browser) %s", avahi_strerror_ptr(avahi_client_errno_ptr(client)));
            //avahi_threaded_poll_quit_ptr(threaded_poll);
            return;

        case AVAHI_BROWSER_NEW:
		{
			CPhidgetRemoteHandle networkInfo;
			if((CPhidgetRemote_create(&networkInfo))) return;

			networkInfo->zeroconf_name = strdup(name);
			networkInfo->zeroconf_server_id = strdup(name);
			networkInfo->zeroconf_type = strdup(type);
			networkInfo->zeroconf_domain = strdup(domain);
			
            LOG(PHIDGET_LOG_INFO, "(Browser) NEW: service '%s' of type '%s' in domain '%s'", name, type, domain);

			CThread_mutex_lock(&zeroconfServersLock);
			CList_addToList((CListHandle *)&zeroconfServers, networkInfo, CPhidgetRemote_areEqual);
			CThread_mutex_unlock(&zeroconfServersLock);
		}
            break;

        case AVAHI_BROWSER_REMOVE:
		{
			CPhidgetRemoteHandle networkInfo;
			if((CPhidgetRemote_create(&networkInfo))) return;

			networkInfo->zeroconf_name = strdup(name);
			networkInfo->zeroconf_server_id = strdup(name);
			networkInfo->zeroconf_type = strdup(type);
			networkInfo->zeroconf_domain = strdup(domain);
            LOG(PHIDGET_LOG_INFO, "(Browser) REMOVE: service '%s' of type '%s' in domain '%s'", name, type, domain);

			CThread_mutex_lock(&zeroconfServersLock);
			CList_removeFromList((CListHandle *)&zeroconfServers, networkInfo, CPhidgetRemote_areEqual, TRUE, CPhidgetRemote_free);
			CThread_mutex_unlock(&zeroconfServersLock);
		}
            break;

        case AVAHI_BROWSER_ALL_FOR_NOW:
        case AVAHI_BROWSER_CACHE_EXHAUSTED:
            LOG(PHIDGET_LOG_INFO, "(Browser) %s", event == AVAHI_BROWSER_CACHE_EXHAUSTED ? "CACHE_EXHAUSTED" : "ALL_FOR_NOW");
            break;
    }
}
void DNSServiceBrowse_SBC_CallBack(
									   AvahiServiceBrowser *b,
									   AvahiIfIndex interface,
									   AvahiProtocol protocol,
									   AvahiBrowserEvent event,
									   const char *name,
									   const char *type,
									   const char *domain,
									   AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
									   void* userdata) 
{
	
	CPhidgetSBCHandle sbc, found_sbc;
	CPhidgetSBCManagerList *trav;
	int ret;
	
    switch (event) {
			
        case AVAHI_BROWSER_FAILURE:
            
            LOG(PHIDGET_LOG_WARNING, "(Browser) %s", avahi_strerror_ptr(avahi_client_errno_ptr(client)));
            avahi_threaded_poll_quit_ptr(threaded_poll);
            return;
			
        case AVAHI_BROWSER_NEW:
		{
			char fullname[AVAHI_DOMAIN_NAME_MAX];
			
			if((CPhidgetSBC_create(&sbc))) return;
			if((CPhidgetRemote_create(&sbc->networkInfo))) return;
			
			sbc->networkInfo->zeroconf_name = strdup(name);
			sbc->networkInfo->zeroconf_type = strdup(type);
			sbc->networkInfo->zeroconf_domain = strdup(domain);
			sbc->networkInfo->mdns = PTRUE;
			
			strncpy(sbc->mac, name+12, 18); //name == 'PhidgetSBC (??:??:??:??:??:??)'
			sbc->mac[17] = '\0';
			
            LOG(PHIDGET_LOG_INFO, "(Browser) NEW: service '%s' of type '%s' in domain '%s'", name, type, domain);
			
			if((ret = avahi_service_name_join_ptr(fullname, AVAHI_DOMAIN_NAME_MAX, name, type, domain)) != AVAHI_OK)
                LOG(PHIDGET_LOG_ERROR, "Failed avahi_service_name_join_ptr '%s': %s", name, avahi_strerror_ptr(ret));
			
			if(!(avahi_record_browser_new_ptr(client, interface, protocol, fullname, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_TXT, 0, DNSServiceQueryRecord_SBC_CallBack, sbc)))
                LOG(PHIDGET_LOG_ERROR, "Failed to resolve service '%s': %s", name, avahi_strerror_ptr(avahi_client_errno_ptr(client)));
			//gets added to list in callback
		}
            break;
			
        case AVAHI_BROWSER_REMOVE:
		{
			if((CPhidgetSBC_create(&sbc))) return;
			if((CPhidgetRemote_create(&sbc->networkInfo))) return;
			
			sbc->networkInfo->zeroconf_name = strdup(name);
			sbc->networkInfo->zeroconf_type = strdup(type);
			sbc->networkInfo->zeroconf_domain = strdup(domain);
			sbc->networkInfo->mdns = PTRUE;
			
			strncpy(sbc->mac, name+12, 18); //name == 'PhidgetSBC (??:??:??:??:??:??)'
			sbc->mac[17] = '\0';
			
            LOG(PHIDGET_LOG_INFO, "(Browser) REMOVE: service '%s' of type '%s' in domain '%s'", name, type, domain);
			
			
			CThread_mutex_lock(&zeroconfSBCsLock);
			CThread_mutex_lock(&activeSBCManagersLock);
			
			if(CList_findInList((CListHandle)zeroconfSBCs, sbc, CPhidgetSBC_areEqual, (void **)&found_sbc) == EPHIDGET_OK)
			{
				CList_removeFromList((CListHandle *)&zeroconfSBCs, found_sbc, CPhidgetSBC_areEqual, PFALSE, NULL);
				//managers
				for (trav=activeSBCManagers; trav; trav = trav->next)
				{
					if (trav->sbcm->fptrDetachChange && trav->sbcm->state == PHIDGETMANAGER_ACTIVE)
						trav->sbcm->fptrDetachChange((CPhidgetSBCHandle)found_sbc, trav->sbcm->fptrDetachChangeptr);
				}
				CPhidgetSBC_free(found_sbc);
			}
			
			CThread_mutex_unlock(&activeSBCManagersLock);
			CThread_mutex_unlock(&zeroconfSBCsLock);
			
			CPhidgetSBC_free(sbc);
		}
            break;
			
        case AVAHI_BROWSER_ALL_FOR_NOW:
        case AVAHI_BROWSER_CACHE_EXHAUSTED:
            LOG(PHIDGET_LOG_INFO, "(Browser) %s", event == AVAHI_BROWSER_CACHE_EXHAUSTED ? "CACHE_EXHAUSTED" : "ALL_FOR_NOW");
            break;
    }
}
void DNSServiceBrowse_Phidget_CallBack(
    AvahiServiceBrowser *b,
    AvahiIfIndex interface,
    AvahiProtocol protocol,
    AvahiBrowserEvent event,
    const char *name,
    const char *type,
    const char *domain,
    AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
    void* userdata) 
{

	CPhidgetHandle phid;
	CPhidgetManagerList *trav;
	
	int ret;
	
    switch (event) {

        case AVAHI_BROWSER_FAILURE:
            
            LOG(PHIDGET_LOG_WARNING, "(Browser) %s", avahi_strerror_ptr(avahi_client_errno_ptr(client)));
            avahi_threaded_poll_quit_ptr(threaded_poll);
            return;

        case AVAHI_BROWSER_NEW:
		{
			char fullname[AVAHI_DOMAIN_NAME_MAX];
			
			if((CPhidget_create(&phid))) return;
			if((CPhidgetRemote_create(&phid->networkInfo))) return;

			phid->networkInfo->zeroconf_name = strdup(name);
			phid->networkInfo->zeroconf_type = strdup(type);
			phid->networkInfo->zeroconf_domain = strdup(domain);
			
            LOG(PHIDGET_LOG_INFO, "(Browser) NEW: service '%s' of type '%s' in domain '%s'", name, type, domain);
			
			if((ret = avahi_service_name_join_ptr(fullname, AVAHI_DOMAIN_NAME_MAX, name, type, domain)) != AVAHI_OK)
                LOG(PHIDGET_LOG_ERROR, "Failed avahi_service_name_join_ptr '%s': %s", name, avahi_strerror_ptr(ret));

			if(!(avahi_record_browser_new_ptr(client, interface, protocol, fullname, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_TXT, 0, DNSServiceQueryRecord_Phidget_CallBack, phid)))
                LOG(PHIDGET_LOG_ERROR, "Failed to resolve service '%s': %s", name, avahi_strerror_ptr(avahi_client_errno_ptr(client)));
			//gets added to list in callback
		}
            break;

        case AVAHI_BROWSER_REMOVE:
		{
			if((CPhidget_create(&phid))) return;
			if((CPhidgetRemote_create(&phid->networkInfo))) return;

			phid->networkInfo->zeroconf_name = strdup(name);
			phid->networkInfo->zeroconf_type = strdup(type);
			phid->networkInfo->zeroconf_domain = strdup(domain);
			
            LOG(PHIDGET_LOG_INFO, "(Browser) REMOVE: service '%s' of type '%s' in domain '%s'", name, type, domain);

			//have to fill in phid manually from just the name
			int i;
			CPhidgetHandle found_phid;
			char *name_copy = strdup(name);
			for(i=0;i<strlen(name_copy);i++)
				if(name_copy[i] == '(') break;
			if(i<=1) return;
			name_copy[strlen(name_copy)-1]='\0';
			name_copy[i-1] = '\0';
			phid->serialNumber = strtol(name_copy+i+1, NULL, 10);
			phid->specificDevice = PTRUE;
			for(i = 0;i<PHIDGET_DEVICE_COUNT;i++)
				if(!strcmp(name_copy, Phid_Device_Def[i].pdd_name)) break;
			phid->deviceIDSpec = 0;
			phid->deviceDef = &Phid_Device_Def[i];
			phid->attr = Phid_Device_Def[i].pdd_attr;
			phid->deviceID = Phid_Device_Def[i].pdd_did;
			phid->deviceType = Phid_DeviceName[phid->deviceID];
			phid->networkInfo->mdns = PTRUE;

			CThread_mutex_lock(&zeroconfPhidgetsLock);
			CThread_mutex_lock(&activeRemoteManagersLock);

			CPhidget_clearStatusFlag(&phid->status, PHIDGET_ATTACHED_FLAG, &phid->lock);
			CPhidget_setStatusFlag(&phid->status, PHIDGET_DETACHING_FLAG, &phid->lock);
			CPhidget_setStatusFlag(&phid->status, PHIDGET_REMOTE_FLAG, &phid->lock);
			CPhidget_clearStatusFlag(&phid->status, PHIDGET_SERVER_CONNECTED_FLAG, &phid->lock);

			if(!CList_findInList((CListHandle)zeroconfPhidgets, phid, CPhidget_areEqual, (void **)&found_phid))
			{
				strcpy(phid->label, found_phid->label);
				phid->deviceVersion = found_phid->deviceVersion;
				CList_removeFromList((CListHandle *)&zeroconfPhidgets, phid, CPhidget_areExtraEqual, TRUE, CPhidget_free);
				//managers
				for (trav=activeRemoteManagers; trav; trav = trav->next)
				{
					if(trav->phidm->networkInfo->requested_address==NULL
						&& (trav->phidm->networkInfo->requested_serverID == NULL || !strcmp(trav->phidm->networkInfo->requested_serverID,phid->networkInfo->zeroconf_server_id)))
					{
						if (trav->phidm->fptrDetachChange && trav->phidm->state == PHIDGETMANAGER_ACTIVE)
							trav->phidm->fptrDetachChange((CPhidgetHandle)phid, trav->phidm->fptrDetachChangeptr);
					}
				}
				CPhidget_clearStatusFlag(&phid->status, PHIDGET_DETACHING_FLAG, &phid->lock);
				CPhidget_free(phid);
			}
			CThread_mutex_unlock(&activeRemoteManagersLock);
			CThread_mutex_unlock(&zeroconfPhidgetsLock);
			free(name_copy);
		}
            break;

        case AVAHI_BROWSER_ALL_FOR_NOW:
        case AVAHI_BROWSER_CACHE_EXHAUSTED:
            LOG(PHIDGET_LOG_INFO, "(Browser) %s", event == AVAHI_BROWSER_CACHE_EXHAUSTED ? "CACHE_EXHAUSTED" : "ALL_FOR_NOW");
            break;
    }
}
void DNSServiceQueryRecord_SBC_CallBack
(
 AvahiRecordBrowser *b, 
 AvahiIfIndex interface, 
 AvahiProtocol protocol, 
 AvahiBrowserEvent event, 
 const char *name, 
 uint16_t clazz, 
 uint16_t type, 
 const void *rdata, 
 size_t size, 
 AvahiLookupResultFlags flags, 
 void *userdata
 )
{
	CPhidgetSBCHandle sbc = (CPhidgetSBCHandle)userdata, found_sbc;
	CPhidgetSBCManagerList *trav;
	
	switch(event)
	{
		case AVAHI_BROWSER_NEW:
			SBCFromTXT(sbc, size, rdata);
			LOG(PHIDGET_LOG_INFO, "DNSServiceQueryRecord_SBC_CallBack: %s",name);
			CThread_mutex_lock(&zeroconfSBCsLock);
			CThread_mutex_lock(&activeSBCManagersLock);
			
			//Check if it's in the list and if it's different, remove it to make way for the new one
			// (Sometimes, we don't get a proper detach notification)
			if(CList_findInList((CListHandle)zeroconfSBCs, sbc, CPhidgetSBC_areEqual, (void **)&found_sbc) == EPHIDGET_OK)
			{
				if(CPhidgetSBC_areExtraEqual(found_sbc, sbc) != PTRUE) //A version number has changed
				{
					//Remove from list - don't free until after detach event
					CList_removeFromList((CListHandle *)&zeroconfSBCs, found_sbc, CPhidgetSBC_areEqual, PFALSE, NULL);
					
					for (trav=activeSBCManagers; trav; trav = trav->next)
					{
						if (trav->sbcm->fptrDetachChange && trav->sbcm->state == PHIDGETMANAGER_ACTIVE)
							trav->sbcm->fptrDetachChange((CPhidgetSBCHandle)found_sbc, trav->sbcm->fptrDetachChangeptr);
					}
					
					CPhidgetSBC_free(found_sbc);
					
					//now we fall through and add back to new one
				}
				else //Nothing has changed, we didn't remove, don't add
				{
					CPhidgetSBC_free(sbc);
					goto dontadd;
				}
			}
			
			//now add it
			CList_addToList((CListHandle *)&zeroconfSBCs, sbc, CPhidgetSBC_areEqual);
			
			//send out events
			for (trav=activeSBCManagers; trav; trav = trav->next)
			{
				if (trav->sbcm->fptrAttachChange && trav->sbcm->state == PHIDGETMANAGER_ACTIVE)
					trav->sbcm->fptrAttachChange((CPhidgetSBCHandle)sbc, trav->sbcm->fptrAttachChangeptr);
				
			}
		dontadd:
			
			CThread_mutex_unlock(&activeSBCManagersLock);
			CThread_mutex_unlock(&zeroconfSBCsLock);
			break;
		case AVAHI_BROWSER_FAILURE:
			LOG(PHIDGET_LOG_ERROR, "DNSServiceQueryRecord_SBC_CallBack returned error: %s", avahi_strerror_ptr(avahi_client_errno_ptr(client)));
			break;
		case AVAHI_BROWSER_ALL_FOR_NOW:
			avahi_record_browser_free_ptr(b);
		case AVAHI_BROWSER_CACHE_EXHAUSTED:
			LOG(PHIDGET_LOG_INFO, "DNSServiceQueryRecord_SBC_CallBack %s", event == AVAHI_BROWSER_CACHE_EXHAUSTED ? "CACHE_EXHAUSTED" : "ALL_FOR_NOW");
			break;
		case AVAHI_BROWSER_REMOVE:
			break;
	}
}
예제 #27
0
/* 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;
}
예제 #28
0
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; 
}
예제 #29
0
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;
}
예제 #30
0
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;
}