# device.c

Go to the documentation of this file.

    00001
    00011 /* $Progeny$
    00012  *
    00013  * Copyright 2001, 2002 Progeny Linux Systems, Inc.
    00014  * Copyright 2002 Hewlett-Packard Company
    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
    00035 #include "config.h"
    00036
    00037 #include <sys/types.h>
    00038
    00039 #include <assert.h>
    00040 #include <stdbool.h>
    00041 #include <string.h>
    00042
    00043 #include <discover/discover.h>
    00044 #include <discover/discover-conf.h>
    00045 #include <discover/discover-xml.h>
    00046
    00047 #include <discover/device.h>
    00048 #include <discover/utils.h>
    00049
    00062 discover_device_t *
    00063 discover_device_find(char *discover_class, discover_error_t *status)
    00064 {
    00065     discover_device_t *result, *device, *last, *new_device;
    00066     discover_xml_busclass_t *busclasses;
    00067     discover_bus_map_t *busmap;
    00068     int i;
    00069
    00070     assert(discover_class);
    00071
    00072     result = last = NULL;
    00073
    00074     busmap = discover_conf_get_full_bus_map(status);
    00075     if (status->code != 0) {
    00076         return NULL;
    00077     }
    00078
    00079     for (i = 0; busmap[i].name; i++) {
    00080         if (!busmap[i].scan_default) {
    00081             continue;
    00082         }
    00083
    00084         busclasses = discover_xml_get_busclasses(i, status);
    00085         if (status->code != 0) {
    00086             return result;
    00087         }
    00088         for (device = discover_get_devices(i, status);
    00089              device;
    00090              device = discover_device_get_next(device)) {
    00091             if (!device->busclass) {
    00092                 /* This is a device about which we know nothing. */
    00093                 continue;
    00094             }
    00095             if (discover_xml_busclass_cmp(device->busclass, discover_class,
    00096                                           busclasses) == 0) {
    00097                 new_device = discover_device_new();
    00098                 discover_device_copy(device, new_device);
    00099                 new_device->next = NULL;
    00100
    00101                 if (last) {
    00102                     last->next = new_device;
    00103                     last = new_device;
    00104                 } else {
    00105                     result = last = new_device;
    00106                 }
    00107             }
    00108         }
    00109
    00110         if (status->code != 0) {
    00111             return result;
    00112         }
    00113     }
    00114
    00115     if (result) {
    00116         status->code = DISCOVER_SUCCESS;
    00117     } else {
    00118         char *message = _discover_xmalloc(100);
    00119         snprintf(message, 100, "Device \"%s\" not found",
    00120                     discover_class);
    00121         status->code = DISCOVER_EDEVICENOTFOUND;
    00122         status->create_message(&status, message);
    00123     }
    00124
    00125     return result;
    00126 }
    00127
    00128 static discover_data_t *
    00129 scan_data_list(discover_data_t *node, char *discover_class, char **version,
    00130                discover_error_t *status)
    00131 {
    00132     discover_data_t *result = NULL;
    00133     int cmp;
    00134
    00135     for ( ; node != NULL; node = node->next) {
    00136         if (strcmp(node->discover_class, discover_class) == 0) {
    00137             if (*version && node->version) {
    00138                 cmp = discover_xml_version_cmp(node->version,
    00139                                                *version, status);
    00140
    00141                 if (status->code != 0) {
    00142                     return result;
    00143                 }
    00144                 if (cmp) {
    00145                     result = node;
    00146                     /* The version is no longer relevant for nested data
    00147                      * elements.
    00148                      */
    00149                     *version = NULL;
    00150                     break;
    00151                 }
    00152             } else {
    00153                 result = node;
    00154                 break;
    00155             }
    00156         }
    00157     }
    00158     return result;
    00159 }
    00160
    00161
    00162 static discover_data_t *
    00163 get_data(discover_device_t *device, char *discover_class, char **version,
    00164          discover_error_t *status)
    00165 {
    00166     assert(device != NULL);
    00167     assert(discover_class != NULL);
    00168
    00169     return scan_data_list(device->data, discover_class, version, status);
    00170 }
    00171
    00172 static discover_data_t *
    00173 get_child_data(discover_data_t *data, char *discover_class, char **version,
    00174                discover_error_t *status)
    00175 {
    00176     assert(data != NULL);
    00177     assert(discover_class != NULL);
    00178
    00179     return scan_data_list(data->child, discover_class, version, status);
    00180 }
    00181
    00203 char *
    00204 discover_device_get_data(discover_device_t *device, char *discover_class,
    00205                          char *version, discover_error_t *status)
    00206 {
    00207     discover_data_t *data;
    00208     char *result, *tmp, *tmp_orig, **argv, *block;
    00209     size_t argv_len;
    00210     int i;
    00211
    00212     assert(device != NULL);
    00213     assert(discover_class != NULL);
    00214     assert(status != NULL);
    00215
    00216     status->code = 0;
    00217
    00218     data = NULL;
    00219     result = NULL;
    00220     tmp_orig = tmp = _discover_xstrdup(discover_class);
    00221     argv = NULL;
    00222     argv_len = 0;
    00223
    00224     while ((block = strsep(&tmp, "/"))) {
    00225         argv_len++;
    00226         argv = _discover_xrealloc(argv, sizeof(char *) * argv_len);
    00227         argv[argv_len - 1] = block;
    00228     }
    00229
    00230
    00231     while(!data && device) {
    00232         data = get_data(device, argv[0], &version, status);
    00233
    00234         if (data) {
    00235             for (i = 1; i < argv_len; i++) {
    00236                 data = get_child_data(data, argv[i], &version, status);
    00237                 if (status->code != 0) {
    00238                     goto out;
    00239                 }
    00240                 if (!data) {
    00241                     break;
    00242                 }
    00243             }
    00244         }
    00245
    00246         device = device->extra;
    00247     }
    00248
    00249     if (data) {
    00250         result = data->text;
    00251     }
    00252
    00253 out:
    00254
    00255     free(tmp_orig);
    00256     free(argv);
    00257
    00258     return result;
    00259 }
    00260
    00267 void
    00268 discover_device_copy(discover_device_t *src, discover_device_t *dst)
    00269 {
    00270     assert(src != NULL);
    00271     assert(dst != NULL);
    00272
    00273     if (src->busclass) {
    00274         dst->busclass = _discover_xstrdup(src->busclass);
    00275     }
    00276
    00277     if (src->model_id) {
    00278         dst->model_id = _discover_xstrdup(src->model_id);
    00279     }
    00280
    00281     if (src->model_name) {
    00282         dst->model_name = _discover_xstrdup(src->model_name);
    00283     }
    00284
    00285     if (src->vendor_id) {
    00286         dst->vendor_id = _discover_xstrdup(src->vendor_id);
    00287     }
    00288
    00289     if (src->vendor_name) {
    00290         dst->vendor_name = _discover_xstrdup(src->vendor_name);
    00291     }
    00292
    00293     dst->busclasses = src->busclasses;
    00294     dst->vendors = src->vendors;
    00295     dst->data = src->data;
    00296     dst->extra = src->extra;
    00297     dst->next = src->next;
    00298 }
    00299
    00300 /******************************************************************************
    00301  * Data accessors
    00302  */
    00303
    00307 char *
    00308 discover_data_get_class(discover_data_t *data)
    00309 {
    00310     assert(data != NULL);
    00311
    00312     return data->discover_class;
    00313 }
    00314
    00318 char *
    00319 discover_data_get_text(discover_data_t *data)
    00320 {
    00321     assert(data != NULL);
    00322
    00323     return data->text;
    00324 }
    00325
    00329 discover_data_t *
    00330 discover_data_get_parent(discover_data_t *data)
    00331 {
    00332     assert(data != NULL);
    00333
    00334     return data->parent;
    00335 }
    00336
    00340 discover_data_t *
    00341 discover_data_get_child(discover_data_t *data)
    00342 {
    00343     assert(data != NULL);
    00344
    00345     return data->child;
    00346 }
    00347
    00351 discover_data_t *
    00352 discover_data_get_next(discover_data_t *data)
    00353 {
    00354     assert(data != NULL);
    00355
    00356     return data->next;
    00357 }
    00358
    00362 discover_data_t *
    00363 discover_data_get_prev(discover_data_t *data)
    00364 {
    00365     assert(data != NULL);
    00366
    00367     return data->prev;
    00368 }
    00369
    00373 discover_data_t *
    00374 discover_data_get_first(discover_data_t *data)
    00375 {
    00376     int i = 1;
    00377
    00378     if (data == NULL) {
    00379         return NULL;
    00380     }
    00381
    00382     while(i) {
    00383         if(data->prev) {
    00384             data = data->prev;
    00385         } else if(data->parent) {
    00386             data = data->parent;
    00387         } else {
    00388             i = 0;
    00389         }
    00390     }
    00391 /*
    00392
    00393     for (;
    00394          data->prev;
    00395          data = data->prev)
    00396     ;
    00397     for (;
    00398          data->parent;
    00399          data = data->parent)
    00400     ;
    00401 */
    00402     return data;
    00403 }
    00404
    00408 discover_data_t *
    00409 discover_data_new(void)
    00410 {
    00411     discover_data_t *new;
    00412
    00413     new = _discover_xmalloc(sizeof(discover_data_t));
    00414
    00415     new->discover_class = NULL;
    00416     new->version = NULL;
    00417     new->text = NULL;
    00418     new->parent = NULL;
    00419     new->child = NULL;
    00420     new->next = NULL;
    00421     new->prev = NULL;
    00422
    00423     return new;
    00424 }
    00425
    00435 void
    00436 discover_data_free(discover_data_t *data_tree)
    00437 {
    00438     discover_data_t *data, *last;
    00439
    00440     last = NULL;
    00441
    00442     if (data_tree) {
    00443         for (data = data_tree->next;
    00444              data;
    00445              data = data->next) {
    00446             discover_data_free(data);
    00447
    00448             if (last) {
    00449                 free(last);
    00450             }
    00451             last = data;
    00452         }
    00453
    00454         if (last) {
    00455             free(last);
    00456         }
    00457
    00458         if (data_tree->child) {
    00459             discover_data_free(data_tree->child);
    00460             free(data_tree->child);
    00461         }
    00462
    00463         if (data_tree->discover_class) {
    00464             free(data_tree->discover_class);
    00465         }
    00466
    00467         if (data_tree->version) {
    00468             free(data_tree->version);
    00469         }
    00470
    00471         if (data_tree->text) {
    00472             free(data_tree->text);
    00473         }
    00474     }
    00475 }
    00476
    00477 /******************************************************************************
    00478  * Device accessors
    00479  */
    00480
    00484 char *
    00485 discover_device_get_busclass(discover_device_t *device)
    00486 {
    00487     assert(device != NULL);
    00488
    00489     return device->busclass;
    00490 }
    00491
    00495 char *
    00496 discover_device_get_model_id(discover_device_t *device)
    00497 {
    00498     assert(device != NULL);
    00499
    00500     return device->model_id;
    00501 }
    00502
    00506 char *
    00507 discover_device_get_model_name(discover_device_t *device)
    00508 {
    00509     assert(device != NULL);
    00510
    00511     return device->model_name;
    00512 }
    00513
    00517 char *
    00518 discover_device_get_vendor_id(discover_device_t *device)
    00519 {
    00520     assert(device != NULL);
    00521
    00522     return device->vendor_id;
    00523 }
    00524
    00528 char *
    00529 discover_device_get_vendor_name(discover_device_t *device)
    00530 {
    00531     assert(device != NULL);
    00532
    00533     return device->vendor_name;
    00534 }
    00535
    00539 discover_data_t *
    00540 discover_device_get_data_struct(discover_device_t *device)
    00541 {
    00542     assert(device != NULL);
    00543
    00544     return device->data;
    00545 }
    00546
    00550 discover_device_t *
    00551 discover_device_get_next(discover_device_t *device)
    00552 {
    00553     assert(device != NULL);
    00554
    00555     return device->next;
    00556 }
    00557
    00561 discover_device_t *
    00562 discover_device_new(void)
    00563 {
    00564     discover_device_t *new;
    00565
    00566     new = _discover_xmalloc(sizeof(discover_device_t));
    00567
    00568     new->busclass = NULL;
    00569     new->model_id = NULL;
    00570     new->model_name = NULL;
    00571     new->vendor_id = NULL;
    00572     new->vendor_name = NULL;
    00573     new->busclasses = NULL;
    00574     new->vendors = NULL;
    00575     new->data = NULL;
    00576     new->next = NULL;
    00577     new->extra = NULL;
    00578
    00579     return new;
    00580 }
    00581
    00591 void
    00592 discover_device_free(discover_device_t *devices, int free_data)
    00593 {
    00594     discover_device_t *device, *last;
    00595
    00596     last = NULL;
    00597
    00598     for (device = devices;
    00599          device;
    00600          device = device->next) {
    00601         if (device->busclass) {
    00602             free(device->busclass);
    00603         }
    00604
    00605         if (device->model_id) {
    00606             free(device->model_id);
    00607         }
    00608
    00609         if (device->model_name) {
    00610             free(device->model_name);
    00611         }
    00612
    00613         if (device->vendor_id) {
    00614             free(device->vendor_id);
    00615         }
    00616
    00617         if (device->vendor_name) {
    00618             free(device->vendor_name);
    00619         }
    00620
    00621         if (free_data && device->data) {
    00622             discover_data_free(device->data);
    00623             free(device->data);
    00624         }
    00625
    00626         if (last) {
    00627             free(last);
    00628         }
    00629         last = device;
    00630     }
    00631
    00632     if (last) {
    00633         free(last);
    00634     }
    00635 }
    00636
    00639 /*
    00640  * Local variables:
    00641  * c-file-style: "progeny"
    00642  * indent-tabs-mode: nil
    00643  * End:
    00644  */
    00645 /* vim: set cin fo=tcroq sw=4 et sts=4 tw=75: */