# 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: */