Main Page | Modules | Data Structures | Directories | File List | Data Fields | Globals

sysdep.c

Go to the documentation of this file.
00001 
00010 /* $Progeny$
00011  *
00012  * AUTHOR: John R. Daily <jdaily@progeny.com>
00013  *
00014  * Copyright 2002 Progeny Linux Systems, Inc.
00015  *
00016  * Permission is hereby granted, free of charge, to any person obtaining a
00017  * copy of this software and associated documentation files (the "Software"),
00018  * to deal in the Software without restriction, including without limitation
00019  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00020  * and/or sell copies of the Software, and to permit persons to whom the
00021  * Software is furnished to do so, subject to the following conditions:
00022  *
00023  * The above copyright notice and this permission notice shall be included in
00024  * all copies or substantial portions of the Software.
00025  *
00026  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00027  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00028  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
00029  * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00030  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
00031  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
00032  * DEALINGS IN THE SOFTWARE.
00033  */
00034 #include <assert.h>
00035 
00036 #include <stdio.h>
00037 #include <string.h>
00038 
00039 #include <discover/discover.h>
00040 #include <discover/discover-conf.h>
00041 #include <discover/discover-xml.h>
00042 #include <discover/sysdep.h>
00043 
00044 #include <discover/device.h>
00045 #include <discover/utils.h>
00046 
00047 
00049 typedef discover_sysdep_data_t *(raw_sysdep_function_t)(void);
00050 
00051 static raw_sysdep_function_t *raw_map[] = {
00052     _discover_get_ata_raw,
00053     _discover_get_pci_raw,
00054     _discover_get_pcmcia_raw,
00055     _discover_get_scsi_raw,
00056     _discover_get_usb_raw
00057 };
00058 
00059 
00060 /*
00061  * Utility functions
00062  */
00063 
00065 discover_sysdep_data_t *
00066 _discover_sysdep_data_new(void)
00067 {
00068     discover_sysdep_data_t *node =
00069         _discover_xmalloc(sizeof(discover_sysdep_data_t));
00070     node->busclass = NULL;
00071     node->vendor = NULL;
00072     node->model = NULL;
00073     node->data = NULL;
00074     node->next = NULL;
00075     return node;
00076 }
00077 
00079 discover_sysdep_device_data_t *
00080 _discover_sysdep_device_data_new(void)
00081 {
00082     discover_sysdep_device_data_t *node =
00083         _discover_xmalloc(sizeof(discover_sysdep_device_data_t));
00084     node->path = NULL;
00085     node->value = NULL;
00086     node->next = NULL;
00087     return node;
00088 }
00089 
00091 void
00092 _discover_free_sysdep_data(discover_sysdep_data_t *head)
00093 {
00094     discover_sysdep_data_t *node;
00095 
00096     while (head) {
00097         node = head->next;
00098         if (head->vendor) {
00099             free(head->vendor);
00100         }
00101         if (head->model) {
00102             free(head->model);
00103         }
00104         if (head->busclass) {
00105             free(head->busclass);
00106         }
00107         if (head->data) {
00108             _discover_free_sysdep_device_data(head->data);
00109         }
00110         free(head);
00111         head = node;
00112     }
00113 }
00114 
00116 void
00117 _discover_free_sysdep_device_data(discover_sysdep_device_data_t *head)
00118 {
00119     discover_sysdep_device_data_t *node;
00120     while (head) {
00121         node = head->next;
00122         if (head->path) {
00123             free(head->path);
00124         }
00125         if (head->value) {
00126             free(head->value);
00127         }
00128         free(head);
00129         head = node;
00130     }
00131 }
00132 
00134 discover_data_t *
00135 _discover_convert_device_data(discover_sysdep_device_data_t *head)
00136 {
00137     discover_data_t *data_head, *data_current, *data_new;
00138     discover_sysdep_device_data_t *node;
00139     char *buffer, *path, *token;
00140 
00142     data_head = discover_data_new();
00143     data_head->discover_class = _discover_xstrdup("device");
00144 
00145     /*
00146      * Step through the device data nodes returned by the sysdeps.
00147      * Each node will have a path relative to the "device" toplevel,
00148      * separated by slashes, as well as a value.  We need to set
00149      * each one up to look like it came from the XML data.
00150      */
00151     for (node = head; node; node = head->next) {
00153         data_current = NULL;
00154 
00156         path = _discover_xstrdup(node->path);
00157         buffer = _discover_xstrdup(node->path);
00158 
00160         for (token = strtok_r(path, "/", &buffer); token;
00161              token = strtok_r(NULL, "/", &buffer)) {
00163             data_new = discover_data_new();
00164             data_new->discover_class = _discover_xstrdup(token);
00165 
00167             if (data_current == NULL) {
00169                 if (data_head->child == NULL) {
00170                     data_head->child = data_new;
00171                 } else {
00172                     data_current = data_head->child;
00173                     while (data_current->next)
00174                         data_current = data_current->next;
00175                     data_current->next = data_new;
00176                 }
00177             } else {
00179                 data_current->child = data_new;
00180                 data_new->parent = data_current;
00181             }
00182 
00183             data_current = data_new;
00184         }
00185 
00186         /*
00187          * We've gotten to the very last path element; set the 
00188          * node's value here.
00189          */
00190         data_current->text = _discover_xstrdup(node->value);
00191 
00193         free(path);
00194         free(buffer);
00195     }
00196 
00197     return data_head;
00198 }
00199 
00200 /*
00201  * Functions that access the sysdeps
00202  */
00203 static discover_device_t *devices[BUS_COUNT];
00204 
00205 discover_device_t *
00206 discover_get_devices(discover_bus_t bus, discover_error_t *status)
00207 {
00208     discover_device_t *device, *last;
00209     discover_device_t *xml_devices;
00210     discover_bus_map_t *busmap;
00211     discover_sysdep_data_t *head, *node;
00212     discover_data_t *data_head, *data_node;
00213 
00214     assert(status);
00215 
00216     status->code = DISCOVER_SUCCESS;
00217     device = last = NULL;
00218 
00219     busmap = discover_conf_get_bus_map(bus, status);
00220     if (status->code != 0) {
00221         return NULL;
00222     }
00223 
00224     if (busmap->scan_never) {
00225         status->code = DISCOVER_EBUSDISABLED;
00226         return NULL;
00227     }
00228 
00229     if (devices[bus]) {
00230         return devices[bus];
00231     }
00232 
00233     xml_devices = discover_xml_get_devices(bus, status);
00234     if (!xml_devices) {
00235         return NULL;
00236     }
00237 
00238     /*
00239      * Allow overrides of this function.
00240      */
00241     if (busmap->get_raw) {
00242         head = node = busmap->get_raw();
00243     } else {
00244         head = node = raw_map[bus]();
00245     }
00246 
00247     while (node) {
00248         /*
00249          * The variable names are ambiguous:
00250          *   node   -  Hardware data retrieved from the OS
00251          *   device -  Matching hardware data from our database
00252          */
00253         device =
00254             discover_xml_get_matching_devices(xml_devices, node->vendor,
00255                                               node->model, status);
00256 
00257         if (!device) {
00258             device = discover_device_new();
00259             device->model_id = strdup(node->model);
00260             device->vendor_id = strdup(node->vendor);
00261         }
00262 
00263         /*
00264          * If we get a busclass from the hardware, treat it as
00265          * canonical.
00266          */
00267         if (node->busclass != NULL) {
00268             if (device->busclass != NULL) {
00269                 free(device->busclass);
00270             }
00271             device->busclass = strdup(node->busclass);
00272         }
00273 
00274         /* Add sysdep data to the data nodes. */
00275         if (node->data != NULL) {
00276             data_head = _discover_convert_device_data(node->data);
00277             if (data_head != NULL) {
00278                 for (data_node = data_head; data_node->next != NULL; 
00279                      data_node = data_node->next) ;
00280                 data_node->next = device->data;
00281                 device->data = data_head;
00282             }
00283         }
00284 
00285         if (last) {
00286             last->next = device;
00287             last = device;
00288         } else {
00289             devices[bus] = last = device;
00290         }
00291 
00292         node = node->next;
00293     }
00294 
00295     _discover_free_sysdep_data(head);
00296 
00297     return devices[bus];
00298 }
00299 
00300 void
00301 discover_free_devices(void)
00302 {
00303     int i;
00304 
00305     for (i = 0; i < BUS_COUNT; i++) {
00306         discover_device_free(devices[i], 0);
00307         devices[i] = NULL;
00308     }
00309 }
00310 
00311 /*
00312  * Local variables:
00313  * c-file-style: "progeny"
00314  * indent-tabs-mode: nil
00315  * End:
00316  */
00317 /* vim: set cin fo=tcroq sw=4 et sts=4 tw=75: */

Generated on Thu Jul 28 03:38:00 2005 for discover by  doxygen 1.4.2