libupnp/upnp/sample/common/sample_util.c
Marcelo Roberto Jimenez 6fb2655086 White spaces.
git-svn-id: https://pupnp.svn.sourceforge.net/svnroot/pupnp/trunk@404 119443c7-1b9e-41f8-b6fc-b9c35fce742c
2008-06-03 15:19:00 +00:00

813 lines
28 KiB
C

/*******************************************************************************
*
* Copyright (c) 2000-2003 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************/
#include "sample_util.h"
#include <stdarg.h>
#if !UPNP_HAVE_TOOLS
# error "Need upnptools.h to compile samples ; try ./configure --enable-tools"
#endif
/*
Function pointer to use for displaying formatted
strings. Set on Initialization of device.
*/
int initialize = 1;
print_string gPrintFun = NULL;
state_update gStateUpdateFun = NULL;
/*! mutex to control displaying of events */
ithread_mutex_t display_mutex;
/********************************************************************************
* SampleUtil_Initialize
*
* Description:
* Initializes the sample util. Must be called before any sample util
* functions. May be called multiple times.
*
* Parameters:
* print_function - print function to use in SampleUtil_Print
*
********************************************************************************/
int
SampleUtil_Initialize( print_string print_function )
{
if( initialize ) {
ithread_mutexattr_t attr;
gPrintFun = print_function;
ithread_mutexattr_init( &attr );
ithread_mutexattr_setkind_np( &attr, ITHREAD_MUTEX_RECURSIVE_NP );
ithread_mutex_init( &display_mutex, &attr );
ithread_mutexattr_destroy( &attr );
initialize = 0;
}
return UPNP_E_SUCCESS;
}
/********************************************************************************
* SampleUtil_RegisterUpdateFunction
*
* Description:
*
* Parameters:
*
********************************************************************************/
int
SampleUtil_RegisterUpdateFunction( state_update update_function )
{
static int initialize = 1; //only intialize once
if( initialize ) {
gStateUpdateFun = update_function;
initialize = 0;
}
return UPNP_E_SUCCESS;
}
/********************************************************************************
* SampleUtil_Finish
*
* Description:
* Releases Resources held by sample util.
*
* Parameters:
*
********************************************************************************/
int
SampleUtil_Finish()
{
ithread_mutex_destroy( &display_mutex );
gPrintFun = NULL;
initialize = 1;
return UPNP_E_SUCCESS;
}
/********************************************************************************
* SampleUtil_GetElementValue
*
* Description:
* Given a DOM node such as <Channel>11</Channel>, this routine
* extracts the value (e.g., 11) from the node and returns it as
* a string. The string must be freed by the caller using
* free.
*
* Parameters:
* node -- The DOM node from which to extract the value
*
********************************************************************************/
char *
SampleUtil_GetElementValue( IN IXML_Element * element )
{
IXML_Node *child = ixmlNode_getFirstChild( ( IXML_Node * ) element );
char *temp = NULL;
if( ( child != 0 ) && ( ixmlNode_getNodeType( child ) == eTEXT_NODE ) ) {
temp = strdup( ixmlNode_getNodeValue( child ) );
}
return temp;
}
/********************************************************************************
* SampleUtil_GetFirstServiceList
*
* Description:
* Given a DOM node representing a UPnP Device Description Document,
* this routine parses the document and finds the first service list
* (i.e., the service list for the root device). The service list
* is returned as a DOM node list.
*
* Parameters:
* node -- The DOM node from which to extract the service list
*
********************************************************************************/
IXML_NodeList *
SampleUtil_GetFirstServiceList( IN IXML_Document * doc )
{
IXML_NodeList *ServiceList = NULL;
IXML_NodeList *servlistnodelist = NULL;
IXML_Node *servlistnode = NULL;
servlistnodelist =
ixmlDocument_getElementsByTagName( doc, "serviceList" );
if( servlistnodelist && ixmlNodeList_length( servlistnodelist ) ) {
/*
we only care about the first service list, from the root device
*/
servlistnode = ixmlNodeList_item( servlistnodelist, 0 );
/*
create as list of DOM nodes
*/
ServiceList =
ixmlElement_getElementsByTagName( ( IXML_Element * )
servlistnode, "service" );
}
if( servlistnodelist )
ixmlNodeList_free( servlistnodelist );
return ServiceList;
}
/********************************************************************************
* SampleUtil_GetFirstDocumentItem
*
* Description:
* Given a document node, this routine searches for the first element
* named by the input string item, and returns its value as a string.
* String must be freed by caller using free.
* Parameters:
* doc -- The DOM document from which to extract the value
* item -- The item to search for
*
********************************************************************************/
char *
SampleUtil_GetFirstDocumentItem( IN IXML_Document * doc,
IN const char *item )
{
IXML_NodeList *nodeList = NULL;
IXML_Node *textNode = NULL;
IXML_Node *tmpNode = NULL;
char *ret = NULL;
nodeList = ixmlDocument_getElementsByTagName( doc, ( char * )item );
if( nodeList ) {
if( ( tmpNode = ixmlNodeList_item( nodeList, 0 ) ) ) {
textNode = ixmlNode_getFirstChild( tmpNode );
ret = strdup( ixmlNode_getNodeValue( textNode ) );
}
}
if( nodeList )
ixmlNodeList_free( nodeList );
return ret;
}
/********************************************************************************
* SampleUtil_GetFirstElementItem
*
* Description:
* Given a DOM element, this routine searches for the first element
* named by the input string item, and returns its value as a string.
* The string must be freed using free.
* Parameters:
* node -- The DOM element from which to extract the value
* item -- The item to search for
*
********************************************************************************/
char *
SampleUtil_GetFirstElementItem( IN IXML_Element * element,
IN const char *item )
{
IXML_NodeList *nodeList = NULL;
IXML_Node *textNode = NULL;
IXML_Node *tmpNode = NULL;
char *ret = NULL;
nodeList = ixmlElement_getElementsByTagName( element, ( char * )item );
if( nodeList == NULL ) {
SampleUtil_Print( "Error finding %s in XML Node\n", item );
return NULL;
}
if( ( tmpNode = ixmlNodeList_item( nodeList, 0 ) ) == NULL ) {
SampleUtil_Print( "Error finding %s value in XML Node\n", item );
ixmlNodeList_free( nodeList );
return NULL;
}
textNode = ixmlNode_getFirstChild( tmpNode );
ret = strdup( ixmlNode_getNodeValue( textNode ) );
if( !ret ) {
SampleUtil_Print( "Error allocating memory for %s in XML Node\n",
item );
ixmlNodeList_free( nodeList );
return NULL;
}
ixmlNodeList_free( nodeList );
return ret;
}
/********************************************************************************
* SampleUtil_PrintEventType
*
* Description:
* Prints a callback event type as a string.
*
* Parameters:
* S -- The callback event
*
********************************************************************************/
void
SampleUtil_PrintEventType( IN Upnp_EventType S )
{
switch ( S ) {
case UPNP_DISCOVERY_ADVERTISEMENT_ALIVE:
SampleUtil_Print( "UPNP_DISCOVERY_ADVERTISEMENT_ALIVE\n" );
break;
case UPNP_DISCOVERY_ADVERTISEMENT_BYEBYE:
SampleUtil_Print( "UPNP_DISCOVERY_ADVERTISEMENT_BYEBYE\n" );
break;
case UPNP_DISCOVERY_SEARCH_RESULT:
SampleUtil_Print( "UPNP_DISCOVERY_SEARCH_RESULT\n" );
break;
case UPNP_DISCOVERY_SEARCH_TIMEOUT:
SampleUtil_Print( "UPNP_DISCOVERY_SEARCH_TIMEOUT\n" );
break;
/*
SOAP Stuff
*/
case UPNP_CONTROL_ACTION_REQUEST:
SampleUtil_Print( "UPNP_CONTROL_ACTION_REQUEST\n" );
break;
case UPNP_CONTROL_ACTION_COMPLETE:
SampleUtil_Print( "UPNP_CONTROL_ACTION_COMPLETE\n" );
break;
case UPNP_CONTROL_GET_VAR_REQUEST:
SampleUtil_Print( "UPNP_CONTROL_GET_VAR_REQUEST\n" );
break;
case UPNP_CONTROL_GET_VAR_COMPLETE:
SampleUtil_Print( "UPNP_CONTROL_GET_VAR_COMPLETE\n" );
break;
/*
GENA Stuff
*/
case UPNP_EVENT_SUBSCRIPTION_REQUEST:
SampleUtil_Print( "UPNP_EVENT_SUBSCRIPTION_REQUEST\n" );
break;
case UPNP_EVENT_RECEIVED:
SampleUtil_Print( "UPNP_EVENT_RECEIVED\n" );
break;
case UPNP_EVENT_RENEWAL_COMPLETE:
SampleUtil_Print( "UPNP_EVENT_RENEWAL_COMPLETE\n" );
break;
case UPNP_EVENT_SUBSCRIBE_COMPLETE:
SampleUtil_Print( "UPNP_EVENT_SUBSCRIBE_COMPLETE\n" );
break;
case UPNP_EVENT_UNSUBSCRIBE_COMPLETE:
SampleUtil_Print( "UPNP_EVENT_UNSUBSCRIBE_COMPLETE\n" );
break;
case UPNP_EVENT_AUTORENEWAL_FAILED:
SampleUtil_Print( "UPNP_EVENT_AUTORENEWAL_FAILED\n" );
break;
case UPNP_EVENT_SUBSCRIPTION_EXPIRED:
SampleUtil_Print( "UPNP_EVENT_SUBSCRIPTION_EXPIRED\n" );
break;
}
}
/********************************************************************************
* SampleUtil_PrintEvent
*
* Description:
* Prints callback event structure details.
*
* Parameters:
* EventType -- The type of callback event
* Event -- The callback event structure
*
********************************************************************************/
int
SampleUtil_PrintEvent( IN Upnp_EventType EventType,
IN void *Event )
{
ithread_mutex_lock( &display_mutex );
SampleUtil_Print
( "\n\n\n======================================================================\n" );
SampleUtil_Print
( "----------------------------------------------------------------------\n" );
SampleUtil_PrintEventType( EventType );
switch ( EventType ) {
/*
SSDP
*/
case UPNP_DISCOVERY_ADVERTISEMENT_ALIVE:
case UPNP_DISCOVERY_ADVERTISEMENT_BYEBYE:
case UPNP_DISCOVERY_SEARCH_RESULT:
{
UpnpDiscovery *d_event = (UpnpDiscovery *)Event;
SampleUtil_Print(
"ErrCode = %d\n"
"Expires = %d\n"
"DeviceId = %s\n"
"DeviceType = %s\n"
"ServiceType = %s\n"
"ServiceVer = %s\n"
"Location = %s\n"
"OS = %s\n"
"Date = %s\n"
"Ext = %s\n",
UpnpDiscovery_get_ErrCode(d_event),
UpnpDiscovery_get_Expires(d_event),
UpnpString_get_String(UpnpDiscovery_get_DeviceID(d_event)),
UpnpString_get_String(UpnpDiscovery_get_DeviceType(d_event)),
UpnpString_get_String(UpnpDiscovery_get_ServiceType(d_event)),
UpnpString_get_String(UpnpDiscovery_get_ServiceVer(d_event)),
UpnpString_get_String(UpnpDiscovery_get_Location(d_event)),
UpnpString_get_String(UpnpDiscovery_get_Os(d_event)),
UpnpString_get_String(UpnpDiscovery_get_Date(d_event)),
UpnpString_get_String(UpnpDiscovery_get_Ext(d_event)));
}
break;
case UPNP_DISCOVERY_SEARCH_TIMEOUT:
// Nothing to print out here
break;
/*
SOAP
*/
case UPNP_CONTROL_ACTION_REQUEST:
{
UpnpActionRequest *a_event = (UpnpActionRequest *)Event;
IXML_Document *actionRequestDoc = NULL;
IXML_Document *actionResultDoc = NULL;
char *xmlbuff = NULL;
SampleUtil_Print(
"ErrCode = %d\n"
"ErrStr = %s\n"
"ActionName = %s\n"
"UDN = %s\n"
"ServiceID = %s\n",
UpnpActionRequest_get_ErrCode(a_event),
UpnpString_get_String(UpnpActionRequest_get_ErrStr(a_event)),
UpnpString_get_String(UpnpActionRequest_get_ActionName(a_event)),
UpnpString_get_String(UpnpActionRequest_get_DevUDN(a_event)),
UpnpString_get_String(UpnpActionRequest_get_ServiceID(a_event)));
actionRequestDoc = UpnpActionRequest_get_ActionRequest(a_event);
if ( actionRequestDoc ) {
xmlbuff = ixmlPrintNode( (IXML_Node *)actionRequestDoc );
if ( xmlbuff ) {
SampleUtil_Print( "ActRequest = %s\n", xmlbuff );
ixmlFreeDOMString( xmlbuff );
}
xmlbuff = NULL;
} else {
SampleUtil_Print( "ActRequest = (null)\n" );
}
actionResultDoc = UpnpActionRequest_get_ActionResult(a_event);
if ( actionResultDoc ) {
xmlbuff = ixmlPrintNode( (IXML_Node *)actionResultDoc );
if ( xmlbuff ) {
SampleUtil_Print( "ActResult = %s\n", xmlbuff );
ixmlFreeDOMString( xmlbuff );
}
xmlbuff = NULL;
} else {
SampleUtil_Print( "ActResult = (null)\n" );
}
}
break;
case UPNP_CONTROL_ACTION_COMPLETE:
{
UpnpActionComplete *a_event = (UpnpActionComplete *)Event;
char *xmlbuff = NULL;
int errCode = UpnpActionComplete_get_ErrCode(a_event);
const char *ctrlURL = UpnpString_get_String(
UpnpActionComplete_get_CtrlUrl(a_event));
IXML_Document *actionRequest =
UpnpActionComplete_get_ActionRequest(a_event);
IXML_Document *actionResult =
UpnpActionComplete_get_ActionResult(a_event);
SampleUtil_Print(
"ErrCode = %d\n"
"CtrlUrl = %s\n",
errCode, ctrlURL);
if( actionRequest ) {
xmlbuff = ixmlPrintNode((IXML_Node *)actionRequest);
if( xmlbuff ) {
SampleUtil_Print( "ActRequest = %s\n", xmlbuff );
ixmlFreeDOMString( xmlbuff );
}
xmlbuff = NULL;
} else {
SampleUtil_Print( "ActRequest = (null)\n" );
}
if( actionResult ) {
xmlbuff = ixmlPrintNode((IXML_Node *)actionResult);
if( xmlbuff ) {
SampleUtil_Print( "ActResult = %s\n", xmlbuff );
ixmlFreeDOMString( xmlbuff );
}
xmlbuff = NULL;
} else {
SampleUtil_Print( "ActResult = (null)\n" );
}
}
break;
case UPNP_CONTROL_GET_VAR_REQUEST:
{
UpnpStateVarRequest *sv_event = (UpnpStateVarRequest *)Event;
SampleUtil_Print(
"ErrCode = %d\n"
"ErrStr = %s\n"
"UDN = %s\n"
"ServiceID = %s\n"
"StateVarName= %s\n"
"CurrentVal = %s\n",
UpnpStateVarRequest_get_ErrCode(sv_event),
UpnpString_get_String(UpnpStateVarRequest_get_ErrStr(sv_event)),
UpnpString_get_String(UpnpStateVarRequest_get_DevUDN(sv_event)),
UpnpString_get_String(UpnpStateVarRequest_get_ServiceID(sv_event)),
UpnpString_get_String(UpnpStateVarRequest_get_StateVarName(sv_event)),
UpnpStateVarRequest_get_CurrentVal(sv_event));
}
break;
case UPNP_CONTROL_GET_VAR_COMPLETE:
{
UpnpStateVarComplete *sv_event = (UpnpStateVarComplete *)Event;
SampleUtil_Print(
"ErrCode = %d\n"
"CtrlUrl = %s\n"
"StateVarName= %s\n"
"CurrentVal = %s\n",
UpnpStateVarComplete_get_ErrCode(sv_event),
UpnpString_get_String(UpnpStateVarComplete_get_CtrlUrl(sv_event)),
UpnpString_get_String(UpnpStateVarComplete_get_StateVarName(sv_event)),
UpnpStateVarComplete_get_CurrentVal(sv_event));
}
break;
/*
GENA
*/
case UPNP_EVENT_SUBSCRIPTION_REQUEST:
{
UpnpSubscriptionRequest *sr_event = (UpnpSubscriptionRequest *)Event;
SampleUtil_Print(
"ServiceID = %s\n"
"UDN = %s\n"
"SID = %s\n",
UpnpString_get_String(UpnpSubscriptionRequest_get_ServiceId(sr_event)),
UpnpString_get_String(UpnpSubscriptionRequest_get_UDN(sr_event)),
UpnpString_get_String(UpnpSubscriptionRequest_get_SID(sr_event)));
}
break;
case UPNP_EVENT_RECEIVED:
{
UpnpEvent *e_event = (UpnpEvent *)Event;
char *xmlbuff = NULL;
xmlbuff = ixmlPrintNode(
(IXML_Node *) UpnpEvent_get_ChangedVariables(e_event));
SampleUtil_Print(
"SID = %s\n"
"EventKey = %d\n"
"ChangedVars = %s\n",
UpnpString_get_String(UpnpEvent_get_SID(e_event)),
UpnpEvent_get_EventKey(e_event),
xmlbuff);
ixmlFreeDOMString(xmlbuff);
}
break;
case UPNP_EVENT_RENEWAL_COMPLETE:
{
UpnpEventSubscribe *es_event = (UpnpEventSubscribe *)Event;
SampleUtil_Print(
"SID = %s\n"
"ErrCode = %d\n"
"TimeOut = %d\n",
UpnpString_get_String(UpnpEventSubscribe_get_SID(es_event)),
UpnpEventSubscribe_get_ErrCode(es_event),
UpnpEventSubscribe_get_TimeOut(es_event));
}
break;
case UPNP_EVENT_SUBSCRIBE_COMPLETE:
case UPNP_EVENT_UNSUBSCRIBE_COMPLETE:
{
UpnpEventSubscribe *es_event = (UpnpEventSubscribe *)Event;
SampleUtil_Print(
"SID = %s\n"
"ErrCode = %d\n"
"PublisherURL= %s\n"
"TimeOut = %d\n",
UpnpString_get_String(UpnpEventSubscribe_get_SID(es_event)),
UpnpEventSubscribe_get_ErrCode(es_event),
UpnpString_get_String(UpnpEventSubscribe_get_PublisherUrl(es_event)),
UpnpEventSubscribe_get_TimeOut(es_event));
}
break;
case UPNP_EVENT_AUTORENEWAL_FAILED:
case UPNP_EVENT_SUBSCRIPTION_EXPIRED:
{
UpnpEventSubscribe *es_event = (UpnpEventSubscribe *)Event;
SampleUtil_Print(
"SID = %s\n"
"ErrCode = %d\n"
"PublisherURL= %s\n"
"TimeOut = %d\n",
UpnpString_get_String(UpnpEventSubscribe_get_SID(es_event)),
UpnpEventSubscribe_get_ErrCode(es_event),
UpnpString_get_String(UpnpEventSubscribe_get_PublisherUrl(es_event)),
UpnpEventSubscribe_get_TimeOut(es_event));
}
break;
}
SampleUtil_Print(
"----------------------------------------------------------------------\n"
"======================================================================\n\n\n\n" );
ithread_mutex_unlock( &display_mutex );
return 0;
}
/********************************************************************************
* SampleUtil_FindAndParseService
*
* Description:
* This routine finds the first occurance of a service in a DOM representation
* of a description document and parses it.
*
* Parameters:
* DescDoc -- The DOM description document
* location -- The location of the description document
* serviceSearchType -- The type of service to search for
* serviceId -- OUT -- The service ID
* eventURL -- OUT -- The event URL for the service
* controlURL -- OUT -- The control URL for the service
*
********************************************************************************/
int
SampleUtil_FindAndParseService( IN IXML_Document * DescDoc,
IN const char *location,
IN char *serviceType,
OUT char **serviceId,
OUT char **eventURL,
OUT char **controlURL )
{
int i,
length,
found = 0;
int ret;
char *tempServiceType = NULL;
char *baseURL = NULL;
const char *base = NULL;
char *relcontrolURL = NULL,
*releventURL = NULL;
IXML_NodeList *serviceList = NULL;
IXML_Element *service = NULL;
baseURL = SampleUtil_GetFirstDocumentItem( DescDoc, "URLBase" );
if (baseURL) {
base = baseURL;
} else {
base = location;
}
serviceList = SampleUtil_GetFirstServiceList( DescDoc );
length = ixmlNodeList_length( serviceList );
for( i = 0; i < length; i++ ) {
service = ( IXML_Element * ) ixmlNodeList_item( serviceList, i );
tempServiceType =
SampleUtil_GetFirstElementItem( ( IXML_Element * ) service,
"serviceType" );
if( strcmp( tempServiceType, serviceType ) == 0 ) {
SampleUtil_Print( "Found service: %s\n", serviceType );
*serviceId =
SampleUtil_GetFirstElementItem( service, "serviceId" );
SampleUtil_Print( "serviceId: %s\n", ( *serviceId ) );
relcontrolURL =
SampleUtil_GetFirstElementItem( service, "controlURL" );
releventURL =
SampleUtil_GetFirstElementItem( service, "eventSubURL" );
*controlURL =
malloc( strlen( base ) + strlen( relcontrolURL ) + 1 );
if( *controlURL ) {
ret = UpnpResolveURL( base, relcontrolURL, *controlURL );
if( ret != UPNP_E_SUCCESS )
SampleUtil_Print
( "Error generating controlURL from %s + %s\n",
base, relcontrolURL );
}
*eventURL =
malloc( strlen( base ) + strlen( releventURL ) + 1 );
if( *eventURL ) {
ret = UpnpResolveURL( base, releventURL, *eventURL );
if( ret != UPNP_E_SUCCESS )
SampleUtil_Print
( "Error generating eventURL from %s + %s\n", base,
releventURL );
}
if( relcontrolURL )
free( relcontrolURL );
if( releventURL )
free( releventURL );
relcontrolURL = releventURL = NULL;
found = 1;
break;
}
if( tempServiceType )
free( tempServiceType );
tempServiceType = NULL;
}
if( tempServiceType )
free( tempServiceType );
if( serviceList )
ixmlNodeList_free( serviceList );
if( baseURL )
free( baseURL );
return ( found );
}
// printf wrapper for portable code
int
uprint1( char *fmt,
... )
{
va_list ap;
char *buf = NULL;
int size;
va_start( ap, fmt );
size = vsnprintf( buf, 0, fmt, ap );
va_end( ap );
if( size > 0 ) {
buf = ( char * )malloc( size + 1 );
if( vsnprintf( buf, size + 1, fmt, ap ) != size ) {
free( buf );
buf = NULL;
}
}
if( buf ) {
ithread_mutex_lock( &display_mutex );
if( gPrintFun )
gPrintFun( buf );
ithread_mutex_unlock( &display_mutex );
free( buf );
}
return size;
}
/********************************************************************************
* SampleUtil_Print
*
* Description:
* Provides platform-specific print functionality. This function should be
* called when you want to print content suitable for console output (i.e.,
* in a large text box or on a screen). If your device/operating system is
* not supported here, you should add a port.
*
* Parameters:
* Same as printf()
*
********************************************************************************/
int SampleUtil_Print(char *fmt, ...)
{
#define MAX_BUF 1024
va_list ap;
static char buf[MAX_BUF];
int rc;
/* Protect both the display and the static buffer with the mutex */
ithread_mutex_lock(&display_mutex);
va_start(ap, fmt);
rc = vsnprintf(buf, MAX_BUF, fmt, ap);
va_end(ap);
if (gPrintFun) {
gPrintFun(buf);
}
ithread_mutex_unlock(&display_mutex);
return rc;
}
/********************************************************************************
* SampleUtil_StateUpdate
*
* Description:
*
* Parameters:
*
********************************************************************************/
void
SampleUtil_StateUpdate( const char *varName,
const char *varValue,
const char *UDN,
eventType type )
{
if( gStateUpdateFun )
gStateUpdateFun( varName, varValue, UDN, type );
// TBD: Add mutex here?
}