2 * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
4 * Copyright (c) 2006-2008, Thomas Bernard
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * * The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
34 #include "getifaddr.h"
35 #include "upnpdescgen.h"
36 #include "minidlnapath.h"
37 #include "upnpglobalvars.h"
38 #include "upnpdescstrings.h"
42 static const char * const upnptypes
[] =
54 static const char * const upnpdefaultvalues
[] =
60 static const char * const upnpallowedvalues
[] =
76 "Unconfigured", /* 14 */
80 "Unconfigured", /* 18 */
87 "ERROR_NONE", /* 25 */
90 "ContentFormatMismatch",
91 "InsufficientBandwidth",
98 "BrowseMetadata", /* 36 */
99 "BrowseDirectChildren",
101 "COMPLETED", /* 39 */
106 RESOURCE_PROTOCOL_INFO_VALUES
, /* 44 */
114 static const char xmlver
[] =
115 "<?xml version=\"1.0\"?>\r\n";
116 static const char root_service
[] =
117 "scpd xmlns=\"urn:schemas-upnp-org:service-1-0\"";
118 static const char root_device
[] =
119 "root xmlns=\"urn:schemas-upnp-org:device-1-0\""
121 " xmlns:pnpx=\"http://schemas.microsoft.com/windows/pnpx/2005/11\""
122 " xmlns:df=\"http://schemas.microsoft.com/windows/2008/09/devicefoundation\""
126 /* root Description of the UPnP Device */
127 static const struct XMLElt rootDesc
[] =
129 {root_device
, INITHELPER(1,2)},
130 {"specVersion", INITHELPER(3,2)},
131 {"device", INITHELPER(5,(14+PNPX
))},
134 {"/deviceType", "urn:schemas-upnp-org:device:MediaServer:1"},
136 {"/pnpx:X_hardwareId", pnpx_hwid
},
137 {"/pnpx:X_compatibleId", "MS_DigitalMediaDeviceClass_DMS_V001"},
138 {"/pnpx:X_deviceCategory", "MediaDevices"},
139 {"/df:X_deviceCategory", "Multimedia.DMS"},
140 {"/microsoft:magicPacketWakeSupported xmlns:microsoft=\"urn:schemas-microsoft-com:WMPNSS-1-0\"", "0"},
142 {"/friendlyName", friendly_name
}, /* required */
143 {"/manufacturer", ROOTDEV_MANUFACTURER
}, /* required */
144 {"/manufacturerURL", ROOTDEV_MANUFACTURERURL
}, /* optional */
145 {"/modelDescription", ROOTDEV_MODELDESCRIPTION
}, /* recommended */
146 {"/modelName", modelname
}, /* required */
147 {"/modelNumber", modelnumber
},
148 {"/modelURL", ROOTDEV_MODELURL
},
149 {"/serialNumber", serialnumber
},
150 {"/UDN", uuidvalue
}, /* required */
151 {"/dlna:X_DLNADOC xmlns:dlna=\"urn:schemas-dlna-org:device-1-0\"", "DMS-1.50"},
152 {"/presentationURL", presentationurl
}, /* recommended */
153 {"iconList", INITHELPER((19+PNPX
),4)},
154 {"serviceList", INITHELPER((43+PNPX
),3)},
155 {"icon", INITHELPER((23+PNPX
),5)},
156 {"icon", INITHELPER((28+PNPX
),5)},
157 {"icon", INITHELPER((33+PNPX
),5)},
158 {"icon", INITHELPER((38+PNPX
),5)},
159 {"/mimetype", "image/png"},
163 {"/url", "/icons/sm.png"},
164 {"/mimetype", "image/png"},
168 {"/url", "/icons/lrg.png"},
169 {"/mimetype", "image/jpeg"},
173 {"/url", "/icons/sm.jpg"},
174 {"/mimetype", "image/jpeg"},
178 {"/url", "/icons/lrg.jpg"},
179 {"service", INITHELPER((46+PNPX
),5)},
180 {"service", INITHELPER((51+PNPX
),5)},
181 {"service", INITHELPER((56+PNPX
),5)},
182 {"/serviceType", "urn:schemas-upnp-org:service:ContentDirectory:1"},
183 {"/serviceId", "urn:upnp-org:serviceId:ContentDirectory"},
184 {"/controlURL", CONTENTDIRECTORY_CONTROLURL
},
185 {"/eventSubURL", CONTENTDIRECTORY_EVENTURL
},
186 {"/SCPDURL", CONTENTDIRECTORY_PATH
},
187 {"/serviceType", "urn:schemas-upnp-org:service:ConnectionManager:1"},
188 {"/serviceId", "urn:upnp-org:serviceId:ConnectionManager"},
189 {"/controlURL", CONNECTIONMGR_CONTROLURL
},
190 {"/eventSubURL", CONNECTIONMGR_EVENTURL
},
191 {"/SCPDURL", CONNECTIONMGR_PATH
},
192 {"/serviceType", "urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1"},
193 {"/serviceId", "urn:microsoft.com:serviceId:X_MS_MediaReceiverRegistrar"},
194 {"/controlURL", X_MS_MEDIARECEIVERREGISTRAR_CONTROLURL
},
195 {"/eventSubURL", X_MS_MEDIARECEIVERREGISTRAR_EVENTURL
},
196 {"/SCPDURL", X_MS_MEDIARECEIVERREGISTRAR_PATH
},
200 /* For ConnectionManager */
201 static const struct argument GetProtocolInfoArgs
[] =
208 static const struct argument PrepareForConnectionArgs
[] =
210 {"RemoteProtocolInfo", 1, 6},
211 {"PeerConnectionManager", 1, 4},
212 {"PeerConnectionID", 1, 7},
214 {"ConnectionID", 2, 7},
215 {"AVTransportID", 2, 8},
220 static const struct argument ConnectionCompleteArgs
[] =
222 {"ConnectionID", 1, 7},
226 static const struct argument GetCurrentConnectionIDsArgs
[] =
228 {"ConnectionIDs", 2, 2},
232 static const struct argument GetCurrentConnectionInfoArgs
[] =
234 {"ConnectionID", 1, 7},
236 {"AVTransportID", 2, 8},
237 {"ProtocolInfo", 2, 6},
238 {"PeerConnectionManager", 2, 4},
239 {"PeerConnectionID", 2, 7},
245 static const struct action ConnectionManagerActions
[] =
247 {"GetProtocolInfo", GetProtocolInfoArgs
}, /* R */
248 //OPTIONAL {"PrepareForConnection", PrepareForConnectionArgs}, /* R */
249 //OPTIONAL {"ConnectionComplete", ConnectionCompleteArgs}, /* R */
250 {"GetCurrentConnectionIDs", GetCurrentConnectionIDsArgs
}, /* R */
251 {"GetCurrentConnectionInfo", GetCurrentConnectionInfoArgs
}, /* R */
255 static const struct stateVar ConnectionManagerVars
[] =
257 {"SourceProtocolInfo", 0|EVENTED
, 0, 0, 44}, /* required */
258 {"SinkProtocolInfo", 0|EVENTED
, 0, 0, 48}, /* required */
259 {"CurrentConnectionIDs", 0|EVENTED
, 0, 0, 46}, /* required */
260 {"A_ARG_TYPE_ConnectionStatus", 0, 0, 27}, /* required */
261 {"A_ARG_TYPE_ConnectionManager", 0, 0}, /* required */
262 {"A_ARG_TYPE_Direction", 0, 0, 33}, /* required */
263 {"A_ARG_TYPE_ProtocolInfo", 0, 0}, /* required */
264 {"A_ARG_TYPE_ConnectionID", 4, 0}, /* required */
265 {"A_ARG_TYPE_AVTransportID", 4, 0}, /* required */
266 {"A_ARG_TYPE_RcsID", 4, 0}, /* required */
270 static const struct argument GetSearchCapabilitiesArgs
[] =
272 {"SearchCaps", 2, 10},
276 static const struct argument GetSortCapabilitiesArgs
[] =
282 static const struct argument GetSystemUpdateIDArgs
[] =
288 static const struct argument BrowseArgs
[] =
291 {"BrowseFlag", 1, 4},
293 {"StartingIndex", 1, 7},
294 {"RequestedCount", 1, 8},
295 {"SortCriteria", 1, 6},
297 {"NumberReturned", 2, 8},
298 {"TotalMatches", 2, 8},
303 static const struct argument SearchArgs
[] =
305 {"ContainerID", 1, 1},
306 {"SearchCriteria", 1, 3},
308 {"StartingIndex", 1, 7},
309 {"RequestedCount", 1, 8},
310 {"SortCriteria", 1, 6},
312 {"NumberReturned", 2, 8},
313 {"TotalMatches", 2, 8},
318 static const struct action ContentDirectoryActions
[] =
320 {"GetSearchCapabilities", GetSearchCapabilitiesArgs
}, /* R */
321 {"GetSortCapabilities", GetSortCapabilitiesArgs
}, /* R */
322 {"GetSystemUpdateID", GetSystemUpdateIDArgs
}, /* R */
323 {"Browse", BrowseArgs
}, /* R */
324 {"Search", SearchArgs
}, /* O */
325 #if 0 // Not implementing optional features yet...
326 {"CreateObject", CreateObjectArgs
}, /* O */
327 {"DestroyObject", DestroyObjectArgs
}, /* O */
328 {"UpdateObject", UpdateObjectArgs
}, /* O */
329 {"ImportResource", ImportResourceArgs
}, /* O */
330 {"ExportResource", ExportResourceArgs
}, /* O */
331 {"StopTransferResource", StopTransferResourceArgs
}, /* O */
332 {"GetTransferProgress", GetTransferProgressArgs
}, /* O */
333 {"DeleteResource", DeleteResourceArgs
}, /* O */
334 {"CreateReference", CreateReferenceArgs
}, /* O */
339 static const struct stateVar ContentDirectoryVars
[] =
341 {"TransferIDs", 0|EVENTED
, 0, 0, 48}, /* 0 */
342 {"A_ARG_TYPE_ObjectID", 0, 0},
343 {"A_ARG_TYPE_Result", 0, 0},
344 {"A_ARG_TYPE_SearchCriteria", 0, 0},
345 {"A_ARG_TYPE_BrowseFlag", 0, 0, 36},
346 /* Allowed Values : BrowseMetadata / BrowseDirectChildren */
347 {"A_ARG_TYPE_Filter", 0, 0}, /* 5 */
348 {"A_ARG_TYPE_SortCriteria", 0, 0},
349 {"A_ARG_TYPE_Index", 3, 0},
350 {"A_ARG_TYPE_Count", 3, 0},
351 {"A_ARG_TYPE_UpdateID", 3, 0},
352 {"SearchCapabilities", 0, 0},
353 {"SortCapabilities", 0, 0},
354 {"SystemUpdateID", 3|EVENTED
, 0, 0, 255},
358 static const struct argument GetIsAuthorizedArgs
[] =
365 static const struct argument GetIsValidatedArgs
[] =
372 static const struct argument GetRegisterDeviceArgs
[] =
374 {"RegistrationReqMsg", 1, 1},
375 {"RegistrationRespMsg", 2, 2},
379 static const struct action X_MS_MediaReceiverRegistrarActions
[] =
381 {"IsAuthorized", GetIsAuthorizedArgs
}, /* R */
382 {"IsValidated", GetIsValidatedArgs
}, /* R */
383 {"RegisterDevice", GetRegisterDeviceArgs
},
387 static const struct stateVar X_MS_MediaReceiverRegistrarVars
[] =
389 {"A_ARG_TYPE_DeviceID", 0, 0},
390 {"A_ARG_TYPE_RegistrationReqMsg", 7, 0},
391 {"A_ARG_TYPE_RegistrationRespMsg", 7, 0},
392 {"A_ARG_TYPE_Result", 6, 0},
393 {"AuthorizationDeniedUpdateID", 3|EVENTED
, 0},
394 {"AuthorizationGrantedUpdateID", 3|EVENTED
, 0},
395 {"ValidationRevokedUpdateID", 3|EVENTED
, 0},
396 {"ValidationSucceededUpdateID", 3|EVENTED
, 0},
400 static const struct serviceDesc scpdContentDirectory
=
401 { ContentDirectoryActions
, ContentDirectoryVars
};
403 static const struct serviceDesc scpdConnectionManager
=
404 { ConnectionManagerActions
, ConnectionManagerVars
};
406 static const struct serviceDesc scpdX_MS_MediaReceiverRegistrar
=
407 { X_MS_MediaReceiverRegistrarActions
, X_MS_MediaReceiverRegistrarVars
};
410 * concatenate the string and use realloc to increase the
411 * memory buffer if needed. */
413 strcat_str(char * str
, int * len
, int * tmplen
, const char * s2
)
417 s2len
= (int)strlen(s2
);
418 if(*tmplen
<= (*len
+ s2len
))
423 *tmplen
+= s2len
+ 1;
424 p
= realloc(str
, *tmplen
);
430 *tmplen
-= s2len
+ 1;
436 /*strcpy(str + *len, s2); */
437 memcpy(str
+ *len
, s2
, s2len
+ 1);
443 * concatenate a character and use realloc to increase the
444 * size of the memory buffer if needed */
446 strcat_char(char * str
, int * len
, int * tmplen
, char c
)
449 if(*tmplen
<= (*len
+ 1))
452 p
= (char *)realloc(str
, *tmplen
);
466 /* iterative subroutine using a small stack
467 * This way, the progam stack usage is kept low */
469 genXML(char * str
, int * len
, int * tmplen
,
470 const struct XMLElt
* p
)
474 const char * eltname
, *s
;
480 const char * eltname
;
481 } pile
[16]; /* stack */
483 i
= 0; /* current node */
484 j
= 1; /* i + number of nodes*/
487 eltname
= p
[i
].eltname
;
490 if(eltname
[0] == '/')
493 printf("DBG: <%s>%s<%s>\n", eltname
+1, p
[i
].data
, eltname
);
495 str
= strcat_char(str
, len
, tmplen
, '<');
496 str
= strcat_str(str
, len
, tmplen
, eltname
+1);
497 str
= strcat_char(str
, len
, tmplen
, '>');
498 str
= strcat_str(str
, len
, tmplen
, p
[i
].data
);
499 str
= strcat_char(str
, len
, tmplen
, '<');
500 sscanf(eltname
, "%s", element
);
501 str
= strcat_str(str
, len
, tmplen
, element
);
502 str
= strcat_char(str
, len
, tmplen
, '>');
510 printf("DBG: pile[%d]\t%d %d\n", top
, i
, j
);
515 printf("DBG: i==j, </%s>\n", pile
[top
].eltname
);
517 str
= strcat_char(str
, len
, tmplen
, '<');
518 str
= strcat_char(str
, len
, tmplen
, '/');
519 s
= pile
[top
].eltname
;
520 for(c
= *s
; c
> ' '; c
= *(++s
))
521 str
= strcat_char(str
, len
, tmplen
, c
);
522 str
= strcat_char(str
, len
, tmplen
, '>');
532 printf("DBG: [%d] <%s>\n", i
, eltname
);
534 str
= strcat_char(str
, len
, tmplen
, '<');
535 str
= strcat_str(str
, len
, tmplen
, eltname
);
536 str
= strcat_char(str
, len
, tmplen
, '>');
539 /*j = i + p[k].nchild; */
540 i
= (unsigned long)p
[k
].data
& 0xffff;
541 j
= i
+ ((unsigned long)p
[k
].data
>> 16);
544 printf("DBG: +pile[%d]\t%d %d\n", top
, i
, j
);
548 pile
[top
].eltname
= eltname
;
554 * - Generate the root description of the UPnP device.
555 * - the len argument is used to return the length of
556 * the returned string.
557 * - tmp_uuid argument is used to build the uuid string */
559 genRootDesc(int * len
)
564 str
= (char *)malloc(tmplen
);
567 * len
= strlen(xmlver
);
568 memcpy(str
, xmlver
, *len
+ 1);
569 str
= genXML(str
, len
, &tmplen
, rootDesc
);
575 genRootDescSamsung(int * len
)
579 struct XMLElt samsungRootDesc
[sizeof(rootDesc
)/sizeof(struct XMLElt
)];
581 str
= (char *)malloc(tmplen
);
584 * len
= strlen(xmlver
);
585 memcpy(str
, xmlver
, *len
+ 1);
586 /* Replace the optional modelURL and manufacturerURL fields with Samsung foo */
587 memcpy(&samsungRootDesc
, &rootDesc
, sizeof(rootDesc
));
588 samsungRootDesc
[8+PNPX
].eltname
= "/sec:ProductCap";
589 samsungRootDesc
[8+PNPX
].data
= "smi,DCM10,getMediaInfo.sec,getCaptionInfo.sec";
590 samsungRootDesc
[12+PNPX
].eltname
= "/sec:X_ProductCap";
591 samsungRootDesc
[12+PNPX
].data
= "smi,DCM10,getMediaInfo.sec,getCaptionInfo.sec";
592 str
= genXML(str
, len
, &tmplen
, samsungRootDesc
);
597 /* genServiceDesc() :
598 * Generate service description with allowed methods and
599 * related variables. */
601 genServiceDesc(int * len
, const struct serviceDesc
* s
)
604 const struct action
* acts
;
605 const struct stateVar
* vars
;
606 const struct argument
* args
;
611 str
= (char *)malloc(tmplen
);
614 /*strcpy(str, xmlver); */
615 *len
= strlen(xmlver
);
616 memcpy(str
, xmlver
, *len
+ 1);
618 acts
= s
->actionList
;
619 vars
= s
->serviceStateTable
;
621 str
= strcat_char(str
, len
, &tmplen
, '<');
622 str
= strcat_str(str
, len
, &tmplen
, root_service
);
623 str
= strcat_char(str
, len
, &tmplen
, '>');
625 str
= strcat_str(str
, len
, &tmplen
,
626 "<specVersion><major>1</major><minor>0</minor></specVersion>");
629 str
= strcat_str(str
, len
, &tmplen
, "<actionList>");
632 str
= strcat_str(str
, len
, &tmplen
, "<action><name>");
633 str
= strcat_str(str
, len
, &tmplen
, acts
[i
].name
);
634 str
= strcat_str(str
, len
, &tmplen
, "</name>");
639 str
= strcat_str(str
, len
, &tmplen
, "<argumentList>");
643 str
= strcat_str(str
, len
, &tmplen
, "<argument><name>");
644 p
= vars
[args
[j
].relatedVar
].name
;
645 str
= strcat_str(str
, len
, &tmplen
, (args
[j
].name
? args
[j
].name
: p
));
646 str
= strcat_str(str
, len
, &tmplen
, "</name><direction>");
647 str
= strcat_str(str
, len
, &tmplen
, args
[j
].dir
==1?"in":"out");
648 str
= strcat_str(str
, len
, &tmplen
,
649 "</direction><relatedStateVariable>");
650 str
= strcat_str(str
, len
, &tmplen
, p
);
651 str
= strcat_str(str
, len
, &tmplen
,
652 "</relatedStateVariable></argument>");
655 str
= strcat_str(str
, len
, &tmplen
,"</argumentList>");
657 str
= strcat_str(str
, len
, &tmplen
, "</action>");
658 /*str = strcat_char(str, len, &tmplen, '\n'); // TEMP ! */
661 str
= strcat_str(str
, len
, &tmplen
, "</actionList><serviceStateTable>");
665 str
= strcat_str(str
, len
, &tmplen
,
666 "<stateVariable sendEvents=\"");
667 str
= strcat_str(str
, len
, &tmplen
, (vars
[i
].itype
& EVENTED
)?"yes":"no");
668 str
= strcat_str(str
, len
, &tmplen
, "\"><name>");
669 str
= strcat_str(str
, len
, &tmplen
, vars
[i
].name
);
670 str
= strcat_str(str
, len
, &tmplen
, "</name><dataType>");
671 str
= strcat_str(str
, len
, &tmplen
, upnptypes
[vars
[i
].itype
& 0x0f]);
672 str
= strcat_str(str
, len
, &tmplen
, "</dataType>");
673 if(vars
[i
].iallowedlist
)
675 str
= strcat_str(str
, len
, &tmplen
, "<allowedValueList>");
676 for(j
=vars
[i
].iallowedlist
; upnpallowedvalues
[j
]; j
++)
678 str
= strcat_str(str
, len
, &tmplen
, "<allowedValue>");
679 str
= strcat_str(str
, len
, &tmplen
, upnpallowedvalues
[j
]);
680 str
= strcat_str(str
, len
, &tmplen
, "</allowedValue>");
682 str
= strcat_str(str
, len
, &tmplen
, "</allowedValueList>");
684 /*if(vars[i].defaultValue) */
687 str
= strcat_str(str
, len
, &tmplen
, "<defaultValue>");
688 /*str = strcat_str(str, len, &tmplen, vars[i].defaultValue); */
689 str
= strcat_str(str
, len
, &tmplen
, upnpdefaultvalues
[vars
[i
].idefault
]);
690 str
= strcat_str(str
, len
, &tmplen
, "</defaultValue>");
692 str
= strcat_str(str
, len
, &tmplen
, "</stateVariable>");
693 /*str = strcat_char(str, len, &tmplen, '\n'); // TEMP ! */
696 str
= strcat_str(str
, len
, &tmplen
, "</serviceStateTable></scpd>");
701 /* genContentDirectory() :
702 * Generate the ContentDirectory xml description */
704 genContentDirectory(int * len
)
706 return genServiceDesc(len
, &scpdContentDirectory
);
709 /* genConnectionManager() :
710 * Generate the ConnectionManager xml description */
712 genConnectionManager(int * len
)
714 return genServiceDesc(len
, &scpdConnectionManager
);
717 /* genX_MS_MediaReceiverRegistrar() :
718 * Generate the X_MS_MediaReceiverRegistrar xml description */
720 genX_MS_MediaReceiverRegistrar(int * len
)
722 return genServiceDesc(len
, &scpdX_MS_MediaReceiverRegistrar
);
726 genEventVars(int * len
, const struct serviceDesc
* s
, const char * servns
)
728 const struct stateVar
* v
;
733 str
= (char *)malloc(tmplen
);
737 v
= s
->serviceStateTable
;
738 snprintf(buf
, sizeof(buf
), "<e:propertyset xmlns:e=\"urn:schemas-upnp-org:event-1-0\" xmlns:s=\"%s\">", servns
);
739 str
= strcat_str(str
, len
, &tmplen
, buf
);
741 if(v
->itype
& EVENTED
) {
742 snprintf(buf
, sizeof(buf
), "<e:property><%s>", v
->name
);
743 str
= strcat_str(str
, len
, &tmplen
, buf
);
744 //printf("<e:property><s:%s>", v->name);
745 switch(v
->ieventvalue
) {
748 case 255: /* Magical values should go around here */
749 if( strcmp(v
->name
, "SystemUpdateID") == 0 )
751 snprintf(buf
, sizeof(buf
), "%d", updateID
);
752 str
= strcat_str(str
, len
, &tmplen
, buf
);
756 str
= strcat_str(str
, len
, &tmplen
, upnpallowedvalues
[v
->ieventvalue
]);
757 //printf("%s", upnpallowedvalues[v->ieventvalue]);
759 snprintf(buf
, sizeof(buf
), "</%s></e:property>", v
->name
);
760 str
= strcat_str(str
, len
, &tmplen
, buf
);
761 //printf("</s:%s></e:property>\n", v->name);
765 str
= strcat_str(str
, len
, &tmplen
, "</e:propertyset>");
766 //printf("</e:propertyset>\n");
768 //printf("%d\n", tmplen);
774 getVarsContentDirectory(int * l
)
776 return genEventVars(l
,
777 &scpdContentDirectory
,
778 "urn:schemas-upnp-org:service:ContentDirectory:1");
782 getVarsConnectionManager(int * l
)
784 return genEventVars(l
,
785 &scpdConnectionManager
,
786 "urn:schemas-upnp-org:service:ConnectionManager:1");
790 getVarsX_MS_MediaReceiverRegistrar(int * l
)
792 return genEventVars(l
,
793 &scpdX_MS_MediaReceiverRegistrar
,
794 "urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1");