root/src/tools/upnp/upnp/device.c

Revision 11400, 8.1 kB (checked in by BrainSlayer, 10 months ago)

lanport from nvram

  • Property svn:executable set to
Line 
1 /*
2     Copyright 2007, 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_osl.h"
14 #include "upnp_dbg.h"
15 #include "upnp.h"
16 #include <osl.h>
17 #include <sbutils.h>
18 #include <bcmnvram.h>
19 #include <wlioctl.h>
20 #include <wlutils.h>
21 #include <cyutils.h>
22 /*
23 #define DEV_MFR         "Broadcom"
24 #define DEV_MFR_URL     "http://www.broadcom.com/"
25 #define DEV_MODEL_DESCRIPTION  "Residential Gateway Device"
26 #define DEV_MODEL  "Wireless Base Station"
27 #define DEV_MODEL_NO  "MN-500"
28 #define DEV_MODEL_URL     "http://www.broadcom.com/"
29 */
30
31 extern PService init_service(PServiceTemplate svctmpl, PDevice pdev);
32 extern void destroy_service(PService);
33
34 void device_devicelist(PDevice pdev, UFILE *up);
35 void device_servicelist(PDevice pdev, UFILE *up);
36
37 PDevice root_devices = NULL;
38
39 /* recursive routine to initialize a device, and all its subdevices.
40    Also all services within a device are intialized by calling their
41    specific initialization function, if available.  */
42 PDevice init_device(PDevice parent, PDeviceTemplate pdevtmpl, ...)
43 {
44     static int indent = 0;
45     int i;
46     PFDEVINIT func;
47     PDevice pdev, subdev;
48     PService psvc;
49     va_list ap;
50
51     UPNP_TRACE(("%*sInitializing %sdevice \"%s\".\r\n", indent, "", (parent ? "" : "root "), pdevtmpl->type));
52
53     if (pdevtmpl->schema == NULL)
54         pdevtmpl->schema = "schemas-upnp-org";
55
56     pdev = (Device *) malloc(sizeof(Device));
57     memset(pdev, 0, sizeof(Device));
58     pdev->parent = parent;
59     pdev->template = pdevtmpl;
60
61     // call the device's intialization function, if defined.
62     if ((func = pdevtmpl->devinit) != NULL) {
63         va_start( ap, pdevtmpl);
64         (*func)(pdev, DEVICE_CREATE, ap);
65         va_end( ap);
66     }
67
68     // we do a top down, depth-first traversal of the device heirarchy.
69     // sub-devices will be initialized before we complete initialization of the root device.
70     //
71     for (i = 0; i < pdevtmpl->ndevices; i++) {
72         indent += 4;
73         subdev = init_device(pdev, &(pdevtmpl->devicelist[i]));
74         indent -= 4;
75         subdev->next = pdev->subdevs;
76         pdev->subdevs = subdev;
77     }
78
79     // Initialize each service in this device.
80     //
81     for (i = 0; i < pdevtmpl->nservices; i++) {
82         psvc = init_service(pdevtmpl->services[i], pdev);
83        
84         psvc->next = pdev->services;
85         pdev->services = psvc;
86     }
87
88     if (ISROOT(pdev)) {
89         pdev->next = root_devices;
90         root_devices = pdev;
91     }
92
93     return pdev;
94 }
95
96 void destroy_device(PDevice pdev)
97 {
98     static int indent = 0;
99     PFDEVINIT func;
100     PDevice psubdev, nextdev, *ppdev;
101     PService psvc, nextsvc;
102
103     UPNP_TRACE(("%*sDestroying %sdevice \"%s\".\r\n", indent, "", (ISROOT(pdev) ? "root " : ""), pdev->template->type));
104
105     // destroy all subdevices in this device.
106     if (pdev->subdevs) {
107         for (psubdev = pdev->subdevs; psubdev; psubdev = nextdev) {
108             nextdev = psubdev->next;
109             indent += 4;
110             destroy_device(psubdev);
111             indent -= 4;
112         }
113     }
114    
115     // destroy all service in this device.
116     if (pdev->services) {
117         for (psvc = pdev->services; psvc; psvc = nextsvc) {
118             nextsvc = psvc->next;
119             destroy_service(psvc);
120         }
121     }
122
123     // call this device's destroy function, if defined.
124     if ((func = pdev->template->devinit) != NULL) {
125         (*func)(pdev, DEVICE_DESTROY, (va_list) NULL );
126     }
127
128     // remove the device from the root device list
129     if (ISROOT(pdev)) {
130         for (ppdev = &root_devices; *ppdev; ppdev = &(*ppdev)->next) {
131             if (*ppdev == pdev) {
132                 *ppdev = (*ppdev)->next;
133                 break;
134             }
135         }
136     }
137
138     // finally, free the memory allocated in init_device();
139     free(pdev);
140 }
141
142
143 /* Print an XML device description for a device and all its subdevices.
144    We used to just print the static XML device description from a file, but now that the
145    IGD is more dynamic and can adjust to different gateway configurations,
146    we must dynamically generate the XML.
147  */
148 void device_xml(PDevice pdev, UFILE *up)
149 {
150     PFDEVXML func;
151     char *friendlyname;
152     char *model_no = NULL;
153
154     // call the device's xml function, if defined.
155     if ((func = pdev->template->devxml) != NULL) {
156         (*func)(pdev, up);
157         return;
158     }
159
160     if (ISROOT(pdev)) {
161         uprintf(up,
162                 "<?xml version=\"1.0\"?>\r\n"
163                 "<root xmlns=\"urn:schemas-upnp-org:device-1-0\">\r\n"
164                 "<specVersion>\r\n"
165                 "<major>1</major>\r\n"
166                 "<minor>0</minor>\r\n"
167                 "</specVersion>\r\n"
168                 );
169         uprintf(up, "<URLBase>http://%s:%s</URLBase>\r\n", nvram_safe_get("lan_ipaddr"), nvram_safe_get("http_lanport"));
170     }
171
172     if (pdev->friendlyname)
173         friendlyname = pdev->friendlyname;
174     else {
175         friendlyname = pdev->template->type;
176     }
177
178     model_no = nvram_get("DD_BOARD");
179     if (!model_no || strlen(model_no) == 0) {
180         model_no = DEV_MODEL_NO;
181     }
182
183     uprintf(up, "<device>\r\n");
184     uprintf(up, "<deviceType>%s</deviceType>\r\n", pdev->template->type);
185     if (ISROOT(pdev)) {
186         uprintf(up, "<presentationURL>/index.asp</presentationURL>\r\n");
187     }
188     uprintf(up, "<friendlyName>%s</friendlyName>\r\n", friendlyname);
189     uprintf(up, "<manufacturer>%s</manufacturer>\r\n", DEV_MFR);
190     uprintf(up, "<manufacturerURL>%s</manufacturerURL>\r\n", DEV_MFR_URL);
191     uprintf(up, "<modelDescription>%s</modelDescription>\r\n", DEV_MODEL_DESCRIPTION);
192     uprintf(up, "<modelName>%s</modelName>\r\n", DEV_MODEL);
193     uprintf(up, "<modelNumber>%s</modelNumber>\r\n", model_no);
194     uprintf(up, "<modelURL>%s</modelURL>\r\n", DEV_MODEL_URL);
195     uprintf(up, "<UDN>%s</UDN>\r\n", pdev->udn);
196
197     // generate XML for any services in this device.
198     device_servicelist(pdev, up);
199
200     // generate XML for any subdevices in this device.
201     device_devicelist(pdev, up);
202        
203     uprintf(up, "</device>\r\n");
204
205     if (ISROOT(pdev)) {
206         uprintf(up, "</root>\r\n");
207     }
208 }
209    
210    
211 void device_devicelist(PDevice pdev, UFILE *up)
212 {
213     PDevice  psubdev;
214
215     // generate XML for any subdevices in this device.
216     if (pdev->subdevs) {
217         uprintf(up, "<deviceList>\r\n");
218         for (psubdev = pdev->subdevs; psubdev; psubdev = psubdev->next)
219             device_xml(psubdev, up);
220         uprintf(up, "</deviceList>\r\n");
221     }
222 }
223
224
225 void device_servicelist(PDevice pdev, UFILE *up)
226 {
227     char svcurl[200];
228     PService psvc;
229
230     // generate XML for any services in this device.
231     if (pdev->services) {
232         uprintf(up, "<serviceList>\r\n");
233         forall_services(pdev, psvc) {
234             snprintf(svcurl, sizeof(svcurl), "/%s/%s", pdev->udn, psvc->template->name);
235
236             uprintf(up, "<service>\r\n");
237             uprintf(up, "<serviceType>urn:%s:service:%s</serviceType>\r\n",
238                     psvc->template->schema, psvc->template->name);
239             if (psvc->template->serviceid) {
240                 uprintf(up, "<serviceId>%s%d</serviceId>\r\n",
241                         psvc->template->serviceid, psvc->instance);
242             } else {
243                 uprintf(up, "<serviceId>urn:upnp-org:serviceId:%s%d</serviceId>\r\n",
244                         psvc->template->name, psvc->instance);
245             }
246             uprintf(up, "<controlURL>/%s/%s</controlURL>\r\n", pdev->udn, psvc->template->name);
247             uprintf(up, "<eventSubURL>/%s/%s</eventSubURL>\r\n", pdev->udn, psvc->template->name);
248             uprintf(up, "<SCPDURL>/dynsvc/%s.xml</SCPDURL>\r\n", psvc->template->name);
249             uprintf(up, "</service>\r\n");
250         }
251         uprintf(up, "</serviceList>\r\n");
252     }
253 }
254
255
256 /* Given a device pointer, return the root device for that device. */
257 PDevice rootdev(PDevice pdev)
258 {
259     while (pdev->parent)
260         pdev = pdev->parent;
261     return pdev;
262 }
263
264
265 /* Device iterator used by the forall_devices() macro.
266    
267    The first call to device_iterator() should have NULL as its argument. 
268    Subsequent calls will return the next device in depth first, pre-order. 
269 */
270 PDevice device_iterator(PDevice pdev)
271 {
272     PDevice nextdev;
273
274     if (pdev == NULL) {
275         nextdev = root_devices;
276     } else {
277         if (pdev->subdevs) {
278             nextdev = pdev->subdevs;
279         } else {
280             nextdev = pdev;
281             while (nextdev) {
282                 if (nextdev->next) {
283                     nextdev = nextdev->next;
284                     break;
285                 } else {
286                     nextdev = nextdev->parent;
287                 }
288             }
289         }
290     }
291
292     return nextdev;
293 }
294
295
296
Note: See TracBrowser for help on using the browser.