Beispiel #1
0
/********************************************************************************
 * TvCtrlPointGetVar
 *
 * Description: 
 *       Send a GetVar request to the specified service of a device.
 *
 * Parameters:
 *   service -- The service
 *   devnum -- The number of the device (order in the list,
 *             starting with 1)
 *   varname -- The name of the variable to request.
 *
 ********************************************************************************/
int TvCtrlPointGetVar(int service, int devnum, const char *varname)
{
	struct TvDeviceNode *devnode;
	int rc;

	ithread_mutex_lock(&DeviceListMutex);

	rc = TvCtrlPointGetDevice(devnum, &devnode);

	if (TV_SUCCESS == rc) {
		rc = UpnpGetServiceVarStatusAsync(
			ctrlpt_handle,
			devnode->device.TvService[service].ControlURL,
			varname,
			TvCtrlPointCallbackEventHandler,
			NULL);
		if (rc != UPNP_E_SUCCESS) {
			SampleUtil_Print(
				"Error in UpnpGetServiceVarStatusAsync -- %d\n",
				rc);
			rc = TV_ERROR;
		}
	}

	ithread_mutex_unlock(&DeviceListMutex);

	return rc;
}
Beispiel #2
0
/********************************************************************************
 * upnp_igd_get_var
 *
 * Description:
 *       Send a GetVar request to the specified service of a device.
 *
 * Parameters:
 *   igd_ctxt    -- The upnp igd context
 *   device_node -- The device
 *   service     -- The service
 *   variable    -- The variable to request.
 *   fun         -- Callback function
 *   cookie      -- Callback cookie
 *
 ********************************************************************************/
int upnp_igd_get_var(upnp_igd_context* igd_ctxt, upnp_igd_device_node *device_node, int service, int variable,
		Upnp_FunPtr fun, const void *cookie) {
	int ret;
	upnp_igd_print(igd_ctxt, UPNP_IGD_DEBUG, "Get %s.%s from IGD device %s[%s]",
			IGDServiceName[service],
			IGDVarName[service][variable],
			device_node->device.friendly_name,
			device_node->device.udn);

	ret = UpnpGetServiceVarStatusAsync(igd_ctxt->upnp_handle,
			device_node->device.services[service].control_url,
			IGDVarName[service][variable],
			fun,
			cookie);
	if (ret != UPNP_E_SUCCESS) {
		upnp_igd_print(igd_ctxt, UPNP_IGD_ERROR, "Error in UpnpGetServiceVarStatusAsync -- %d", ret);
		ret = -1;
	}

	return 0;
}
/********************************************************************************
 * WscUPnPCPHandleEvent
 *
 * Description: 
 *       Handle a UPnP event that was received.  Process the event and update
 *       the appropriate service state table.
 *
 * Parameters:
 *   sid -- The subscription id for the event
 *   eventkey -- The eventkey number for the event
 *   changes -- The DOM document representing the changes
 *
 * Return:
 *   None 
 ********************************************************************************/
void WscUPnPCPHandleEvent(
	IN Upnp_SID sid,
	IN int evntkey,
	IN IXML_Document * changes)
{
	struct upnpDeviceNode *devNode;
	char *inStr = NULL, *pWscU2KMsg = NULL;
	unsigned char *decodeStr = NULL;
	int decodeLen, wscU2KMsgLen;
	unsigned int UPnPDevIP = 0;
	
	devNode = WscDeviceList;
	while (devNode) 
	{
		if(strcmp(devNode->device.services.SID, sid) == 0) 
		{
			devNode->device.timeCount = devNode->device.AdvrTimeOut;
			UPnPDevIP = devNode->device.ipAddr;
			
			DBGPRINTF(RT_DBG_INFO, "Received WscService Event: %d for SID %s\n", evntkey, sid);
			WscStateVarUpdate(devNode, changes);

			inStr = devNode->device.services.StateVarVal[WSC_EVENT_WLANEVENT];
			if (inStr)
			{
#define WSC_EVENT_WLANEVENT_MSG_LEN_MIN		18	// The first byte is the msg type, the next 17 bytes is the MAC address in xx:xx format

				DBGPRINTF(RT_DBG_INFO, "\tWLANEvent=%s!\n", devNode->device.services.StateVarVal[WSC_EVENT_WLANEVENT]);
				decodeLen = ILibBase64Decode((unsigned char *)inStr, strlen(inStr), &decodeStr);

				if((decodeLen > WSC_EVENT_WLANEVENT_MSG_LEN_MIN) && (ioctl_sock >= 0))
				{
					RTMP_WSC_U2KMSG_HDR *msgHdr;
					WscEnvelope *msgEnvelope;
					int msgQIdx = -1;
			 
					
			 		decodeLen -= WSC_EVENT_WLANEVENT_MSG_LEN_MIN;
					
					/* Prepare the msg buffers */
					wscU2KMsgLen = wscU2KMsgCreate(&pWscU2KMsg, (char *)(decodeStr + WSC_EVENT_WLANEVENT_MSG_LEN_MIN), 
													decodeLen, EAP_FRAME_TYPE_WSC);
					if (wscU2KMsgLen == 0)
						goto done;

					/* Prepare the msg envelope */
					if ((msgEnvelope = wscEnvelopeCreate()) == NULL)
						goto done;
					msgEnvelope->callBack = wscCPPutMessage;
			
					/* Lock the msgQ and check if we can get a valid mailbox to insert our request! */
					if (wscMsgQInsert(msgEnvelope, &msgQIdx) != WSC_SYS_SUCCESS)
						goto done;

					// Fill the session ID to the U2KMsg buffer header.
					msgHdr = (RTMP_WSC_U2KMSG_HDR *)pWscU2KMsg;
					msgHdr->envID = msgEnvelope->envID;

					// copy the Addr1 & Addr2
					memcpy(msgHdr->Addr1, HostMacAddr, MAC_ADDR_LEN);
					memcpy(msgHdr->Addr2, &UPnPDevIP, sizeof(unsigned int));

					// Now send the msg to kernel space.
					DBGPRINTF(RT_DBG_INFO, "(%s):Ready to send pWscU2KMsg(len=%d) to kernel by ioctl(%d)!\n", __FUNCTION__, wscU2KMsgLen, ioctl_sock);
					//wsc_hexdump("U2KMsg", pWscU2KMsg, wscU2KMsgLen);
	
					if(wsc_set_oid(RT_OID_WSC_EAPMSG, pWscU2KMsg, wscU2KMsgLen) != 0)
						wscEnvelopeRemove(msgEnvelope, msgQIdx);
				}
			}
			if (devNode->device.services.StateVarVal[WSC_EVENT_APSTATUS] != NULL)
				DBGPRINTF(RT_DBG_INFO, "\tAPStatus=%s!\n", devNode->device.services.StateVarVal[WSC_EVENT_APSTATUS]);
			if (devNode->device.services.StateVarVal[WSC_EVENT_STASTATUS] != NULL)
				DBGPRINTF(RT_DBG_INFO, "\tSTAStatus=%s!\n", devNode->device.services.StateVarVal[WSC_EVENT_STASTATUS]);
			break;
		}
		devNode = devNode->next;
	}
	
done:

}


/********************************************************************************
 * WscUPnPCPHandleSubscribeUpdate
 *
 * Description: 
 *       Handle a UPnP subscription update that was received.  Find the 
 *       service the update belongs to, and update its subscription
 *       timeout.
 *
 * Parameters:
 *   eventURL -- The event URL for the subscription
 *   sid -- The subscription id for the subscription
 *   timeout  -- The new timeout for the subscription
 *
 * Return:
 *    None
 ********************************************************************************/
void WscUPnPCPHandleSubscribeUpdate(
	IN char *eventURL,
	IN Upnp_SID sid,
	IN int timeout)
{
	struct upnpDeviceNode *tmpdevnode;

	tmpdevnode = WscDeviceList;
	while (tmpdevnode) 
	{
		if( strcmp(tmpdevnode->device.services.EventURL, eventURL) == 0) 
		{
			DBGPRINTF(RT_DBG_INFO, "Received WscService Event Renewal for eventURL %s\n", eventURL);
			strcpy(tmpdevnode->device.services.SID, sid);
			break;
		}

		tmpdevnode = tmpdevnode->next;
	}
}



/********************************************************************************
 * WscUPnPCPDeviceHandler
 *
 * Description: 
 *       The callback handler registered with the SDK while registering the Control Point.
 *       This callback funtion detects the type of callback, and passes the request on to 
 *       the appropriate function.
 *
 * Parameters:
 *   EventType -- The type of callback event
 *   Event -- Data structure containing event data
 *   Cookie -- Optional data specified during callback registration
 *
 * Return:
 *    Always zero 
 ********************************************************************************/
int
WscUPnPCPDeviceHandler(
	IN Upnp_EventType EventType,
	IN void *Event,
	IN void *Cookie)
{
    //wsc_PrintEvent( EventType, Event );

	switch (EventType) 
	{
		/*
			SSDP Stuff 
		*/
		case UPNP_DISCOVERY_ADVERTISEMENT_ALIVE:
		case UPNP_DISCOVERY_SEARCH_RESULT:
			{
				struct Upnp_Discovery *d_event = (struct Upnp_Discovery *)Event;
				unsigned int ipAddr = 0;
				if (d_event->ErrCode != UPNP_E_SUCCESS)
				{
					DBGPRINTF(RT_DBG_ERROR, "Error in Discovery Adv Callback -- %d\n", d_event->ErrCode);
				}
				else 
				{
					if (strcmp(d_event->DeviceType, WscDeviceTypeStr) == 0)
					{	//We just need to take care about the WscDeviceTypeStr
						DBGPRINTF(RT_DBG_INFO, "Receive a Advertisement from a WFADevice(URL=%s)\n", d_event->Location);
						if (WscUPnPCPAddDevice(WscDeviceTypeStr, d_event, &ipAddr) == WSC_SYS_SUCCESS)
						{
							WscUPnPCPDumpList(); // Printing the Wsc Device List for debug
							WscUPnPCPSendAction(ipAddr,"GetDeviceInfo", NULL, NULL, 0);
						}
					}
				}
				break;
			}

		case UPNP_DISCOVERY_SEARCH_TIMEOUT:
			// Nothing to do here..
			break;

		case UPNP_DISCOVERY_ADVERTISEMENT_BYEBYE:
			{
				struct Upnp_Discovery *d_event = (struct Upnp_Discovery *)Event;

				if (d_event->ErrCode != UPNP_E_SUCCESS)
				{
					DBGPRINTF(RT_DBG_ERROR, "Error in Discovery ByeBye Callback -- %d\n", d_event->ErrCode);
				}
				else
				{
					DBGPRINTF(RT_DBG_INFO, "Received ByeBye for Device: %s\n", d_event->DeviceId);
	                WscUPnPCPRemoveDevice(d_event->DeviceId);
					//Dump it for debug
					WscUPnPCPDumpList();
				}

				break;
			}

		/*
			SOAP Stuff 
		*/
		case UPNP_CONTROL_ACTION_COMPLETE:
			{
				struct Upnp_Action_Complete *a_event = (struct Upnp_Action_Complete *)Event;

				if (a_event->ErrCode != UPNP_E_SUCCESS)
					DBGPRINTF(RT_DBG_ERROR, "Error in  Action Complete Callback -- %d\n", a_event->ErrCode);
				else 
				{
					DBGPRINTF(RT_DBG_INFO, "Get event:UPNP_CONTROL_ACTION_COMPLETE!\n");
					WscUPnPCPHandleActionResponse(a_event);
				}
				break;
			}

		case UPNP_CONTROL_GET_VAR_COMPLETE:
			{
				struct Upnp_State_Var_Complete *sv_event = (struct Upnp_State_Var_Complete *)Event;

				if (sv_event->ErrCode != UPNP_E_SUCCESS)
				{
					DBGPRINTF(RT_DBG_ERROR, "Error in Get Var Complete Callback -- %d\n", sv_event->ErrCode);
                } else {
					WscUPnPCPHandleGetVar(sv_event->CtrlUrl, sv_event->StateVarName, sv_event->CurrentVal);
				}

				break;
			}

		/*
			GENA Stuff 
		*/
		case UPNP_EVENT_RECEIVED:
			{
				struct Upnp_Event *e_event = (struct Upnp_Event *)Event;
				
				DBGPRINTF(RT_DBG_INFO, "Get event:UPNP_EVENT_RECEIVED!\n");
				
				WscUPnPCPHandleEvent(e_event->Sid, e_event->EventKey, e_event->ChangedVariables);
				break;
			}

		case UPNP_EVENT_SUBSCRIBE_COMPLETE:
		case UPNP_EVENT_UNSUBSCRIBE_COMPLETE:
		case UPNP_EVENT_RENEWAL_COMPLETE:
			{
				struct Upnp_Event_Subscribe *es_event = (struct Upnp_Event_Subscribe *)Event;

				if (es_event->ErrCode != UPNP_E_SUCCESS) 
				{
					DBGPRINTF(RT_DBG_ERROR, "Error in Event Subscribe Callback -- %d\n", es_event->ErrCode);
				} else {
					WscUPnPCPHandleSubscribeUpdate(es_event->PublisherUrl, es_event->Sid, es_event->TimeOut);
                }

				break;
			}

		case UPNP_EVENT_AUTORENEWAL_FAILED:
		case UPNP_EVENT_SUBSCRIPTION_EXPIRED:
			{
				int TimeOut = DEF_SUBSCRIPTION_TIMEOUT;
				Upnp_SID newSID;
				int ret;

				struct Upnp_Event_Subscribe *es_event = (struct Upnp_Event_Subscribe *)Event;

				ret = UpnpSubscribe(WscCPHandle, es_event->PublisherUrl, &TimeOut, newSID);

				if (ret == UPNP_E_SUCCESS) 
				{
					DBGPRINTF(RT_DBG_INFO, "Subscribed to EventURL with SID=%s\n", newSID);
					WscUPnPCPHandleSubscribeUpdate(es_event->PublisherUrl, newSID, TimeOut);
				} else {
					DBGPRINTF(RT_DBG_ERROR, "Error Subscribing to EventURL -- %d\n", ret);
				}
				break;
			}

			/*
				Ignore these cases, since this is not a device 
			*/
		case UPNP_EVENT_SUBSCRIPTION_REQUEST:
		case UPNP_CONTROL_GET_VAR_REQUEST:
		case UPNP_CONTROL_ACTION_REQUEST:
			break;
	}

	return 0;
}


/********************************************************************************
 * WscUPnPCPGetVar
 *
 * Description: 
 *       Send a GetVar request to the specified service of a device.
 *
 * Parameters:
 *   ipAddr -- The IP address of the device.
 *   varname -- The name of the variable to request.
 *
 * Return:
 *    UPNP_E_SUCCESS - if success
 *    WSC_SYS_ERROR  - if failure
 ********************************************************************************/
int
WscUPnPCPGetVar(
	IN uint32 ipAddr,
	IN char *varname)
{
	struct upnpDeviceNode *devnode;
	int rc;

	rc = WscUPnPCPGetDevice(ipAddr, &devnode);

	if (rc == WSC_SYS_SUCCESS)
	{
		rc = UpnpGetServiceVarStatusAsync( WscCPHandle, devnode->device.services.ControlURL,
                                           varname, WscUPnPCPDeviceHandler, NULL);
		if( rc != UPNP_E_SUCCESS )
		{
			DBGPRINTF(RT_DBG_ERROR, "Error in UpnpGetServiceVarStatusAsync -- %d\n", rc);
			rc = WSC_SYS_ERROR;
		}
	}

	return rc;
}


#if 0
int WscUPnPCPGetVarSampleCode(
	IN int devnum)
{
    return WscUPnPCPGetVar(devnum, "Power");
}
#endif


/********************************************************************************
 * WscUPnPCPVerifyTimeouts
 *
 * Description: 
 *       Checks the advertisement each device in the global device list. 
 *		 If an advertisement expires, the device is removed from the list.
 *		 If an advertisement is about to expire, a search request is sent 
 *		 for that device.  
 *
 * Parameters:
 *    incr -- The increment to subtract from the timeouts each time the
 *            function is called.
 *
 * Return:
 *    None
 ********************************************************************************/
void WscUPnPCPVerifyTimeouts(int incr)
{
	struct upnpDeviceNode *prevdevnode, *curdevnode;
	int ret, timeLeft;

	prevdevnode = NULL;
	curdevnode = WscDeviceList;

	while (curdevnode)
	{
		curdevnode->device.timeCount += incr;
		timeLeft = curdevnode->device.AdvrTimeOut - curdevnode->device.timeCount;
		
		if (timeLeft <= 0)
		{
			/* This advertisement has expired, so we should remove the device from the list */
			if (WscDeviceList == curdevnode)
				WscDeviceList = curdevnode->next;
			else
				prevdevnode->next = curdevnode->next;
			DBGPRINTF(RT_DBG_INFO, "%s(), delete the node(ipAddr=0x%08x)!\n", __FUNCTION__, curdevnode->device.ipAddr);
			WscUPnPCPDeleteNode(curdevnode);
			curdevnode = prevdevnode ? prevdevnode->next : WscDeviceList;
		} else {
			if (timeLeft < 3 * incr)
			{
				/*
					This advertisement is about to expire, so send out a search request for this 
					device UDN to try to renew
				*/
				ret = UpnpSearchAsync(WscCPHandle, incr, curdevnode->device.UDN, NULL);
				if (ret != UPNP_E_SUCCESS)
					DBGPRINTF(RT_DBG_ERROR, "Err sending SearchReq for Device UDN: %s -- err = %d\n", curdevnode->device.UDN, ret);
			}

			prevdevnode = curdevnode;
			curdevnode = curdevnode->next;
		}

	}
}


/********************************************************************************
 * WscUPnPCPHouseKeep
 *
 * Description: 
 *       Function that runs in its own thread and monitors advertisement
 *       and subscription timeouts for devices in the global device list.
 *
 * Parameters:
 *    None
 *  
 * Return:
 *    UPNP_E_SUCCESS - if success
 *    WSC_SYS_ERROR  - if failure
 ********************************************************************************/
void *WscUPnPCPHouseKeep(void *args)
{
	int incr = 30;              // how often to verify the timeouts, in seconds

	while(1)
	{
		sleep(incr);
		WscUPnPCPVerifyTimeouts(incr);
	}
}