1/* 2 Copyright 2004, Broadcom Corporation 3 All Rights Reserved. 4 5 THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY 6 KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM 7 SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS 8 FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. 9*/ 10 11#include <stdarg.h> 12 13#include "upnp_dbg.h" 14#include "upnp_osl.h" 15#include "upnp.h" 16 17extern char *getsvcval(PService psvc, int i); 18extern void soap_response(UFILE*, const char *, const char *, const char *, pvar_entry_t, int); 19 20PService init_service(PServiceTemplate svctmpl, PDevice pdev) 21{ 22 PService psvc; 23 PFSVCINIT func; 24 int i, table_size; 25 26 UPNP_TRACE(("Initializing service \"%s\".\r\n", svctmpl->name)); 27 28 if (svctmpl->schema == NULL) 29 svctmpl->schema = "schemas-upnp-org"; 30 31 psvc = (PService) malloc(sizeof(Service)); 32 memset(psvc, 0, sizeof(Service)); 33 34 // store pointers to the template and the device into the service. 35 psvc->template = svctmpl; 36 psvc->device = pdev; 37 psvc->instance = ++svctmpl->count; 38 39 // allocate and initialize the service's state variables. 40 table_size = svctmpl->nvariables * sizeof(StateVar); 41 psvc->vars = (StateVar *) malloc(table_size); 42 memset(psvc->vars, 0, table_size); 43 44 for (i = 0; i < svctmpl->nvariables; i++) { 45 strcpy(psvc->vars[i].value, svctmpl->variables[i].value); 46 psvc->vars[i].flags = svctmpl->variables[i].flags; 47 assert((psvc->vars[i].flags & VAR_CHANGED) == 0); 48 } 49 50 // call the service's intialization function, if defined. 51 if ((func = svctmpl->svcinit) != NULL) { 52 (*func)(psvc, SERVICE_CREATE); 53 } 54 55 return psvc; 56} 57 58void destroy_service(PService psvc) 59{ 60 PFSVCINIT func; 61 62 UPNP_TRACE(("Destroying service \"%s\".\r\n", psvc->template->name)); 63 64 // call the service's intialization function, if defined. 65 if ((func = psvc->template->svcinit) != NULL) { 66 (*func)(psvc, SERVICE_DESTROY); 67 } 68 69 free(psvc->vars); 70 free(psvc); 71} 72 73 74void mark_changed(PService psvc, int varindex) 75{ 76 assert(varindex >= 0 && varindex <= psvc->template->nvariables); 77 78 psvc->vars[varindex].flags |= VAR_CHANGED; 79 psvc->flags |= VAR_CHANGED; 80} 81 82 83/* Print an XML device description for a device and all its subdevices. 84 We used to just print the static XML device description from a file, but now that the 85 IGD is more dynamic and can adjust to different gateway configurations, 86 we must dynamically generate the XML. 87 */ 88void service_xml(PService psvc, UFILE *up) 89{ 90 const char *type2str(vartype_t type); 91 PFSVCXML func; 92 PVarTemplate pv; 93 PAction *ac; 94 PParam pa; 95 char *tstr; 96 97 uprintf(up, 98 "<?xml version=\"1.0\"?>\r\n" 99 "<scpd xmlns=\"urn:schemas-upnp-org:service-1-0\">\r\n" 100 " <specVersion>\r\n" 101 " <major>1</major>\r\n" 102 " <minor>0</minor>\r\n" 103 " </specVersion>\r\n"); 104 105 // call the service's xml function, if defined. 106 if ((func = psvc->template->svcxml) != NULL) { 107 (*func)(psvc, up); 108 } 109 110 uprintf(up, "<actionList>\r\n"); 111 if (psvc->template->actions) { 112 for (ac = psvc->template->actions; *ac; ac++) { 113 uprintf(up, "<action>\r\n"); 114 uprintf(up, "<name>%s</name>\r\n", (*ac)->name); 115 116 /* don't print any <argumentList> if there are no args. */ 117 if ((pa = (*ac)->params) && pa->name) { 118 uprintf(up, "<argumentList>\r\n"); 119 while (pa->name) { 120 uprintf(up, "<argument>\r\n"); 121 uprintf(up, "<name>%s</name>\r\n", pa->name); 122 uprintf(up, "<relatedStateVariable>%s</relatedStateVariable>\r\n", 123 psvc->template->variables[pa->related].name); 124 uprintf(up, "<direction>%s</direction>\r\n", 125 (pa->flags == VAR_OUT ? "out" : "in")); 126 uprintf(up, "</argument>\r\n"); 127 128 pa++; 129 } 130 uprintf(up, "</argumentList>\r\n"); 131 } 132 uprintf(up, "</action>\r\n"); 133 } 134 } 135 uprintf(up, "</actionList>\r\n"); 136 137 uprintf(up, "<serviceStateTable>\r\n"); 138 for (pv = psvc->template->variables; pv->name; pv++) { 139 uprintf(up, "<stateVariable sendEvents=\"%s\">\r\n", 140 (pv->flags & VAR_EVENTED ? "yes" : "no")); 141 uprintf(up, " <name>%s</name>\r\n", pv->name); 142 tstr = type2str(pv->flags&VAR_TYPE_MASK); 143 if (tstr == NULL) { 144 UPNP_ERROR(("unknown type - %s \"%s\"\r\n", 145 psvc->template->name, pv->name)); 146 } else { 147 uprintf(up, " <dataType>%s</dataType>\r\n", tstr); 148 } 149 150 if ((pv->flags & VAR_LIST) && pv->allowed.list ) { 151 char ** avl; 152 uprintf(up, " <allowedValueList>\r\n"); 153 for (avl = pv->allowed.list; *avl; avl++) { 154 uprintf(up, " <allowedValue>%s</allowedValue>\r\n", *avl); 155 } 156 uprintf(up, " </allowedValueList>\r\n"); 157 } else if ((pv->flags & VAR_RANGE) && pv->allowed.range ) { 158 PallowedValueRange avr = pv->allowed.range; 159 uprintf(up, " <allowedValueRange>\r\n"); 160 uprintf(up, " <minimum>%s</minimum>\r\n", avr->minimum); 161 uprintf(up, " <maximum>%s</maximum>\r\n", avr->minimum); 162 uprintf(up, " <step>%s</step>\r\n", avr->step); 163 uprintf(up, " </allowedValueRange>\r\n"); 164 } 165 166 uprintf(up, "</stateVariable>\r\n"); 167 } 168 uprintf(up, "</serviceStateTable>\r\n"); 169 170 171 uprintf(up, "</scpd>\r\n"); 172} 173 174 175const char *type2str(vartype_t type) 176{ 177 char *str; 178 179 switch (type) { 180 case VAR_UBYTE: 181 str = "ui1"; 182 break; 183 case VAR_USHORT: 184 str = "ui2"; 185 break; 186 case VAR_ULONG: 187 str = "ui4"; 188 break; 189 case VAR_BYTE: 190 str = "i1"; 191 break; 192 case VAR_SHORT: 193 str = "i2"; 194 break; 195 case VAR_LONG: 196 str = "i4"; 197 break; 198 case VAR_STRING: 199 str = "string"; 200 break; 201 case VAR_BOOL: 202 str = "boolean"; 203 break; 204 default: 205 str = NULL; 206 } 207 return str; 208} 209 210 211 212// NOT IMPLEMENTED 213int NotImplemented(UFILE *up, PService psvc, PAction ac, pvar_entry_t args, int nargs) 214{ 215 UPNP_ERROR(("Action \"%s\" not implemented, svc \"%s\"\r\n", ac->name, psvc->template->name)); 216 217 soap_error( up, SOAP_INVALID_ACTION ); 218 219 /* indicate that we have already handled the response. 220 (see the handling of return code from 'func' in invoke(). */ 221 return FALSE; 222} 223 224 225 226/* The default action is to reflect the contents of the related variables to all OUT parameters. 227 That is, if an action has an OUT param, return the value of the <relatedVariable> for that param. 228 Do the same for any other out params. 229 230 The value of related variables is obtained by calling getsvcval(). 231*/ 232int DefaultAction(UFILE *up, PService psvc, PAction ac, 233 pvar_entry_t args, int nargs) 234{ 235 PParam pa; 236 237 for (pa = ac->params; pa->name; pa++) { 238 if (pa->flags & VAR_OUT) { 239 pa->value = getsvcval(psvc, pa->related); 240 } 241 } 242 243 return TRUE; 244} 245