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 static const struct argument AddPortMappingArgs
[] =
213 static const struct argument DeletePortMappingArgs
[] =
221 static const struct argument SetConnectionTypeArgs
[] =
227 static const struct argument GetConnectionTypeInfoArgs
[] =
234 static const struct argument GetNATRSIPStatusArgs
[] =
241 static const struct argument GetGenericPortMappingEntryArgs
[] =
255 static const struct argument GetSpecificPortMappingEntryArgs
[] =
268 /* For ConnectionManager */
269 static const struct argument GetProtocolInfoArgs
[] =
276 static const struct argument PrepareForConnectionArgs
[] =
278 {"RemoteProtocolInfo", 1, 6},
279 {"PeerConnectionManager", 1, 4},
280 {"PeerConnectionID", 1, 7},
282 {"ConnectionID", 2, 7},
283 {"AVTransportID", 2, 8},
288 static const struct argument ConnectionCompleteArgs
[] =
290 {"ConnectionID", 1, 7},
294 static const struct argument GetCurrentConnectionIDsArgs
[] =
296 {"ConnectionIDs", 2, 2},
300 static const struct argument GetCurrentConnectionInfoArgs
[] =
302 {"ConnectionID", 1, 7},
304 {"AVTransportID", 2, 8},
305 {"ProtocolInfo", 2, 6},
306 {"PeerConnectionManager", 2, 4},
307 {"PeerConnectionID", 2, 7},
313 static const struct action ConnectionManagerActions
[] =
315 {"GetProtocolInfo", GetProtocolInfoArgs
}, /* R */
316 //OPTIONAL {"PrepareForConnection", PrepareForConnectionArgs}, /* R */
317 //OPTIONAL {"ConnectionComplete", ConnectionCompleteArgs}, /* R */
318 {"GetCurrentConnectionIDs", GetCurrentConnectionIDsArgs
}, /* R */
319 {"GetCurrentConnectionInfo", GetCurrentConnectionInfoArgs
}, /* R */
323 static const struct stateVar ConnectionManagerVars
[] =
325 {"SourceProtocolInfo", 1<<7, 0, 0, 44}, /* required */
326 {"SinkProtocolInfo", 1<<7, 0, 0, 48}, /* required */
327 {"CurrentConnectionIDs", 1<<7, 0, 0, 46}, /* required */
328 {"A_ARG_TYPE_ConnectionStatus", 0, 0, 27}, /* required */
329 {"A_ARG_TYPE_ConnectionManager", 0, 0}, /* required */
330 {"A_ARG_TYPE_Direction", 0, 0, 33}, /* required */
331 {"A_ARG_TYPE_ProtocolInfo", 0, 0}, /* required */
332 {"A_ARG_TYPE_ConnectionID", 4, 0}, /* required */
333 {"A_ARG_TYPE_AVTransportID", 4, 0}, /* required */
334 {"A_ARG_TYPE_RcsID", 4, 0}, /* required */
338 static const struct argument GetSearchCapabilitiesArgs
[] =
340 {"SearchCaps", 2, 10},
344 static const struct argument GetSortCapabilitiesArgs
[] =
350 static const struct argument GetSystemUpdateIDArgs
[] =
356 static const struct argument BrowseArgs
[] =
359 {"BrowseFlag", 1, 4},
361 {"StartingIndex", 1, 7},
362 {"RequestedCount", 1, 8},
363 {"SortCriteria", 1, 6},
365 {"NumberReturned", 2, 8},
366 {"TotalMatches", 2, 8},
371 static const struct argument SearchArgs
[] =
373 {"ContainerID", 1, 1},
374 {"SearchCriteria", 1, 3},
376 {"StartingIndex", 1, 7},
377 {"RequestedCount", 1, 8},
378 {"SortCriteria", 1, 6},
380 {"NumberReturned", 2, 8},
381 {"TotalMatches", 2, 8},
386 static const struct action ContentDirectoryActions
[] =
388 {"GetSearchCapabilities", GetSearchCapabilitiesArgs
}, /* R */
389 {"GetSortCapabilities", GetSortCapabilitiesArgs
}, /* R */
390 {"GetSystemUpdateID", GetSystemUpdateIDArgs
}, /* R */
391 {"Browse", BrowseArgs
}, /* R */
392 {"Search", SearchArgs
}, /* O */
393 #if 0 // Not implementing optional features yet...
394 {"CreateObject", CreateObjectArgs
}, /* O */
395 {"DestroyObject", DestroyObjectArgs
}, /* O */
396 {"UpdateObject", UpdateObjectArgs
}, /* O */
397 {"ImportResource", ImportResourceArgs
}, /* O */
398 {"ExportResource", ExportResourceArgs
}, /* O */
399 {"StopTransferResource", StopTransferResourceArgs
}, /* O */
400 {"GetTransferProgress", GetTransferProgressArgs
}, /* O */
401 {"DeleteResource", DeleteResourceArgs
}, /* O */
402 {"CreateReference", CreateReferenceArgs
}, /* O */
407 static const struct stateVar ContentDirectoryVars
[] =
409 {"TransferIDs", 1<<7, 0, 0, 48}, /* 0 */
410 {"A_ARG_TYPE_ObjectID", 0, 0},
411 {"A_ARG_TYPE_Result", 0, 0},
412 {"A_ARG_TYPE_SearchCriteria", 0, 0},
413 {"A_ARG_TYPE_BrowseFlag", 0, 0, 36},
414 /* Allowed Values : BrowseMetadata / BrowseDirectChildren */
415 {"A_ARG_TYPE_Filter", 0, 0}, /* 5 */
416 {"A_ARG_TYPE_SortCriteria", 0, 0},
417 {"A_ARG_TYPE_Index", 3, 0},
418 {"A_ARG_TYPE_Count", 3, 0},
419 {"A_ARG_TYPE_UpdateID", 3, 0},
420 //JM{"A_ARG_TYPE_TransferID", 3, 0}, /* 10 */
421 //JM{"A_ARG_TYPE_TransferStatus", 0, 0, 39},
422 /* Allowed Values : COMPLETED / ERROR / IN_PROGRESS / STOPPED */
423 //JM{"A_ARG_TYPE_TransferLength", 0, 0},
424 //JM{"A_ARG_TYPE_TransferTotal", 0, 0},
425 //JM{"A_ARG_TYPE_TagValueList", 0, 0},
426 //JM{"A_ARG_TYPE_URI", 5, 0}, /* 15 */
427 {"SearchCapabilities", 0, 0},
428 {"SortCapabilities", 0, 0},
429 {"SystemUpdateID", 3|0x80, 0, 0, 255},
430 //{"ContainerUpdateIDs", 0, 0},
434 static const struct argument GetIsAuthorizedArgs
[] =
441 static const struct argument GetIsValidatedArgs
[] =
448 static const struct argument GetRegisterDeviceArgs
[] =
450 {"RegistrationReqMsg", 1, 1},
451 {"RegistrationRespMsg", 2, 2},
455 static const struct action X_MS_MediaReceiverRegistrarActions
[] =
457 {"IsAuthorized", GetIsAuthorizedArgs
}, /* R */
458 {"IsValidated", GetIsValidatedArgs
}, /* R */
459 #if 0 // Not needed? WMP12 still works. Need to check with 360 and WMP11.
460 {"RegisterDevice", GetRegisterDeviceArgs
}, /* R */
465 static const struct stateVar X_MS_MediaReceiverRegistrarVars
[] =
467 {"A_ARG_TYPE_DeviceID", 0, 0},
468 {"A_ARG_TYPE_RegistrationReqMsg", 7, 0},
469 {"A_ARG_TYPE_RegistrationRespMsg", 7, 0},
470 {"A_ARG_TYPE_Result", 6, 0},
471 {"AuthorizationDeniedUpdateID", 3, 0},
472 {"AuthorizationGrantedUpdateID", 3, 0},
473 {"ValidationRevokedUpdateID", 3, 0},
474 {"ValidationSucceededUpdateID", 3, 0},
479 /* See UPnP_IGD_WANCommonInterfaceConfig 1.0.pdf */
481 static const struct argument GetCommonLinkPropertiesArgs
[] =
490 static const struct argument GetTotalBytesSentArgs
[] =
496 static const struct argument GetTotalBytesReceivedArgs
[] =
502 static const struct argument GetTotalPacketsSentArgs
[] =
508 static const struct argument GetTotalPacketsReceivedArgs
[] =
514 static const struct serviceDesc scpdContentDirectory
=
515 { ContentDirectoryActions
, ContentDirectoryVars
};
517 static const struct serviceDesc scpdConnectionManager
=
518 { ConnectionManagerActions
, ConnectionManagerVars
};
520 static const struct serviceDesc scpdX_MS_MediaReceiverRegistrar
=
521 { X_MS_MediaReceiverRegistrarActions
, X_MS_MediaReceiverRegistrarVars
};
524 * concatenate the string and use realloc to increase the
525 * memory buffer if needed. */
527 strcat_str(char * str
, int * len
, int * tmplen
, const char * s2
)
531 s2len
= (int)strlen(s2
);
532 if(*tmplen
<= (*len
+ s2len
))
537 *tmplen
+= s2len
+ 1;
538 p
= realloc(str
, *tmplen
);
544 *tmplen
-= s2len
+ 1;
550 /*strcpy(str + *len, s2); */
551 memcpy(str
+ *len
, s2
, s2len
+ 1);
557 * concatenate a character and use realloc to increase the
558 * size of the memory buffer if needed */
560 strcat_char(char * str
, int * len
, int * tmplen
, char c
)
563 if(*tmplen
<= (*len
+ 1))
566 p
= (char *)realloc(str
, *tmplen
);
580 /* iterative subroutine using a small stack
581 * This way, the progam stack usage is kept low */
583 genXML(char * str
, int * len
, int * tmplen
,
584 const struct XMLElt
* p
)
588 const char * eltname
, *s
;
594 const char * eltname
;
595 } pile
[16]; /* stack */
597 i
= 0; /* current node */
598 j
= 1; /* i + number of nodes*/
601 eltname
= p
[i
].eltname
;
604 if(eltname
[0] == '/')
607 printf("DBG: <%s>%s<%s>\n", eltname
+1, p
[i
].data
, eltname
);
609 str
= strcat_char(str
, len
, tmplen
, '<');
610 str
= strcat_str(str
, len
, tmplen
, eltname
+1);
611 str
= strcat_char(str
, len
, tmplen
, '>');
612 str
= strcat_str(str
, len
, tmplen
, p
[i
].data
);
613 str
= strcat_char(str
, len
, tmplen
, '<');
614 sscanf(eltname
, "%s", element
);
615 str
= strcat_str(str
, len
, tmplen
, element
);
616 str
= strcat_char(str
, len
, tmplen
, '>');
624 printf("DBG: pile[%d]\t%d %d\n", top
, i
, j
);
629 printf("DBG: i==j, </%s>\n", pile
[top
].eltname
);
631 str
= strcat_char(str
, len
, tmplen
, '<');
632 str
= strcat_char(str
, len
, tmplen
, '/');
633 s
= pile
[top
].eltname
;
634 for(c
= *s
; c
> ' '; c
= *(++s
))
635 str
= strcat_char(str
, len
, tmplen
, c
);
636 str
= strcat_char(str
, len
, tmplen
, '>');
646 printf("DBG: [%d] <%s>\n", i
, eltname
);
648 str
= strcat_char(str
, len
, tmplen
, '<');
649 str
= strcat_str(str
, len
, tmplen
, eltname
);
650 str
= strcat_char(str
, len
, tmplen
, '>');
653 /*j = i + p[k].nchild; */
654 i
= (unsigned long)p
[k
].data
& 0xffff;
655 j
= i
+ ((unsigned long)p
[k
].data
>> 16);
658 printf("DBG: +pile[%d]\t%d %d\n", top
, i
, j
);
662 pile
[top
].eltname
= eltname
;
668 * - Generate the root description of the UPnP device.
669 * - the len argument is used to return the length of
670 * the returned string.
671 * - tmp_uuid argument is used to build the uuid string */
673 genRootDesc(int * len
)
678 str
= (char *)malloc(tmplen
);
681 * len
= strlen(xmlver
);
682 memcpy(str
, xmlver
, *len
+ 1);
683 str
= genXML(str
, len
, &tmplen
, rootDesc
);
689 genRootDescSamsung(int * len
)
693 struct XMLElt samsungRootDesc
[sizeof(rootDesc
)/sizeof(struct XMLElt
)];
695 str
= (char *)malloc(tmplen
);
698 * len
= strlen(xmlver
);
699 memcpy(str
, xmlver
, *len
+ 1);
700 /* Replace the optional modelURL and manufacturerURL fields with Samsung foo */
701 memcpy(&samsungRootDesc
, &rootDesc
, sizeof(rootDesc
));
702 samsungRootDesc
[8+PNPX
].eltname
= "/sec:ProductCap";
703 samsungRootDesc
[8+PNPX
].data
= "smi,DCM10,getMediaInfo.sec,getCaptionInfo.sec";
704 samsungRootDesc
[12+PNPX
].eltname
= "/sec:X_ProductCap";
705 samsungRootDesc
[12+PNPX
].data
= "smi,DCM10,getMediaInfo.sec,getCaptionInfo.sec";
706 str
= genXML(str
, len
, &tmplen
, samsungRootDesc
);
711 /* genServiceDesc() :
712 * Generate service description with allowed methods and
713 * related variables. */
715 genServiceDesc(int * len
, const struct serviceDesc
* s
)
718 const struct action
* acts
;
719 const struct stateVar
* vars
;
720 const struct argument
* args
;
725 str
= (char *)malloc(tmplen
);
728 /*strcpy(str, xmlver); */
729 *len
= strlen(xmlver
);
730 memcpy(str
, xmlver
, *len
+ 1);
732 acts
= s
->actionList
;
733 vars
= s
->serviceStateTable
;
735 str
= strcat_char(str
, len
, &tmplen
, '<');
736 str
= strcat_str(str
, len
, &tmplen
, root_service
);
737 str
= strcat_char(str
, len
, &tmplen
, '>');
739 str
= strcat_str(str
, len
, &tmplen
,
740 "<specVersion><major>1</major><minor>0</minor></specVersion>");
743 str
= strcat_str(str
, len
, &tmplen
, "<actionList>");
746 str
= strcat_str(str
, len
, &tmplen
, "<action><name>");
747 str
= strcat_str(str
, len
, &tmplen
, acts
[i
].name
);
748 str
= strcat_str(str
, len
, &tmplen
, "</name>");
753 str
= strcat_str(str
, len
, &tmplen
, "<argumentList>");
757 str
= strcat_str(str
, len
, &tmplen
, "<argument><name>");
758 p
= vars
[args
[j
].relatedVar
].name
;
759 str
= strcat_str(str
, len
, &tmplen
, (args
[j
].name
? args
[j
].name
: p
));
760 str
= strcat_str(str
, len
, &tmplen
, "</name><direction>");
761 str
= strcat_str(str
, len
, &tmplen
, args
[j
].dir
==1?"in":"out");
762 str
= strcat_str(str
, len
, &tmplen
,
763 "</direction><relatedStateVariable>");
764 str
= strcat_str(str
, len
, &tmplen
, p
);
765 str
= strcat_str(str
, len
, &tmplen
,
766 "</relatedStateVariable></argument>");
769 str
= strcat_str(str
, len
, &tmplen
,"</argumentList>");
771 str
= strcat_str(str
, len
, &tmplen
, "</action>");
772 /*str = strcat_char(str, len, &tmplen, '\n'); // TEMP ! */
775 str
= strcat_str(str
, len
, &tmplen
, "</actionList><serviceStateTable>");
779 str
= strcat_str(str
, len
, &tmplen
,
780 "<stateVariable sendEvents=\"");
781 str
= strcat_str(str
, len
, &tmplen
, (vars
[i
].itype
& 0x80)?"yes":"no");
782 str
= strcat_str(str
, len
, &tmplen
, "\"><name>");
783 str
= strcat_str(str
, len
, &tmplen
, vars
[i
].name
);
784 str
= strcat_str(str
, len
, &tmplen
, "</name><dataType>");
785 str
= strcat_str(str
, len
, &tmplen
, upnptypes
[vars
[i
].itype
& 0x0f]);
786 str
= strcat_str(str
, len
, &tmplen
, "</dataType>");
787 if(vars
[i
].iallowedlist
)
789 str
= strcat_str(str
, len
, &tmplen
, "<allowedValueList>");
790 for(j
=vars
[i
].iallowedlist
; upnpallowedvalues
[j
]; j
++)
792 str
= strcat_str(str
, len
, &tmplen
, "<allowedValue>");
793 str
= strcat_str(str
, len
, &tmplen
, upnpallowedvalues
[j
]);
794 str
= strcat_str(str
, len
, &tmplen
, "</allowedValue>");
796 str
= strcat_str(str
, len
, &tmplen
, "</allowedValueList>");
798 /*if(vars[i].defaultValue) */
801 str
= strcat_str(str
, len
, &tmplen
, "<defaultValue>");
802 /*str = strcat_str(str, len, &tmplen, vars[i].defaultValue); */
803 str
= strcat_str(str
, len
, &tmplen
, upnpdefaultvalues
[vars
[i
].idefault
]);
804 str
= strcat_str(str
, len
, &tmplen
, "</defaultValue>");
806 str
= strcat_str(str
, len
, &tmplen
, "</stateVariable>");
807 /*str = strcat_char(str, len, &tmplen, '\n'); // TEMP ! */
810 str
= strcat_str(str
, len
, &tmplen
, "</serviceStateTable></scpd>");
815 /* genContentDirectory() :
816 * Generate the ContentDirectory xml description */
818 genContentDirectory(int * len
)
820 return genServiceDesc(len
, &scpdContentDirectory
);
823 /* genConnectionManager() :
824 * Generate the ConnectionManager xml description */
826 genConnectionManager(int * len
)
828 return genServiceDesc(len
, &scpdConnectionManager
);
831 /* genX_MS_MediaReceiverRegistrar() :
832 * Generate the X_MS_MediaReceiverRegistrar xml description */
834 genX_MS_MediaReceiverRegistrar(int * len
)
836 return genServiceDesc(len
, &scpdX_MS_MediaReceiverRegistrar
);
840 genEventVars(int * len
, const struct serviceDesc
* s
, const char * servns
)
842 const struct stateVar
* v
;
847 str
= (char *)malloc(tmplen
);
851 v
= s
->serviceStateTable
;
852 snprintf(buf
, sizeof(buf
), "<e:propertyset xmlns:e=\"urn:schemas-upnp-org:event-1-0\" xmlns:s=\"%s\">", servns
);
853 str
= strcat_str(str
, len
, &tmplen
, buf
);
855 if(v
->itype
& 0x80) {
856 snprintf(buf
, sizeof(buf
), "<e:property><%s>", v
->name
);
857 str
= strcat_str(str
, len
, &tmplen
, buf
);
858 //printf("<e:property><s:%s>", v->name);
859 switch(v
->ieventvalue
) {
862 case 255: /* Magical values should go around here */
863 if( strcmp(v
->name
, "SystemUpdateID") == 0 )
865 snprintf(buf
, sizeof(buf
), "%d", updateID
);
866 str
= strcat_str(str
, len
, &tmplen
, buf
);
870 str
= strcat_str(str
, len
, &tmplen
, upnpallowedvalues
[v
->ieventvalue
]);
871 //printf("%s", upnpallowedvalues[v->ieventvalue]);
873 snprintf(buf
, sizeof(buf
), "</%s></e:property>", v
->name
);
874 str
= strcat_str(str
, len
, &tmplen
, buf
);
875 //printf("</s:%s></e:property>\n", v->name);
879 str
= strcat_str(str
, len
, &tmplen
, "</e:propertyset>");
880 //printf("</e:propertyset>\n");
882 //printf("%d\n", tmplen);
888 getVarsContentDirectory(int * l
)
890 return genEventVars(l
,
891 &scpdContentDirectory
,
892 "urn:schemas-upnp-org:service:ContentDirectory:1");
896 getVarsConnectionManager(int * l
)
898 return genEventVars(l
,
899 &scpdConnectionManager
,
900 "urn:schemas-upnp-org:service:ConnectionManager:1");
904 getVarsX_MS_MediaReceiverRegistrar(int * l
)
906 return genEventVars(l
,
907 &scpdX_MS_MediaReceiverRegistrar
,
908 "urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1");