Main Page | Modules | Data Structures | File List | Data Fields | Related Pages

device_store.c

00001 /***************************************************************************
00002  * CVSID: $Id: device_store.c,v 1.15 2004/03/03 17:56:56 david Exp $
00003  *
00004  * device_store.c : device store interface
00005  *
00006  * Copyright (C) 2003 David Zeuthen, <david@fubar.dk>
00007  *
00008  * Licensed under the Academic Free License version 2.0
00009  *
00010  * This program is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version.
00014  *
00015  * This program is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License
00021  * along with this program; if not, write to the Free Software
00022  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00023  *
00024  **************************************************************************/
00025 
00026 
00027 #ifdef HAVE_CONFIG_H
00028 #  include <config.h>
00029 #endif
00030 
00031 #include <assert.h>
00032 #include <stdio.h>
00033 #include <stdlib.h>
00034 #include <string.h>
00035 #include <dbus/dbus.h>
00036 #include <dbus/dbus-glib.h>
00037 
00038 #include "logger.h"
00039 #include "hald.h"
00040 #include "device_store.h"
00041 
00054 /* fwd decl */
00055 static void async_find_property_changed (HalDevice * device,
00056                      const char *key,
00057                      dbus_bool_t in_gdl,
00058                      dbus_bool_t removed,
00059                      dbus_bool_t added);
00060 
00062 #define MAX_CB_FUNCS 32
00063 
00065 static HalDevicePropertyChangedCallback property_changed_cb[MAX_CB_FUNCS];
00066 
00068 static HalDeviceGDLChangedCallback gdl_changed_cb[MAX_CB_FUNCS];
00069 
00071 static HalDeviceNewCapabilityCallback new_capability_cb[MAX_CB_FUNCS];
00072 
00074 static int num_property_changed_cb = 0;
00075 
00077 static int num_gdl_changed_cb = 0;
00078 
00080 static int num_new_capability_cb = 0;
00081 
00082 
00084 static unsigned int device_list_num = 0;
00085 
00087 unsigned int temp_device_counter = 0;
00088 
00090 static HalDevice *device_list_head = NULL;
00091 
00095 void
00096 ds_init ()
00097 {
00098     device_list_num = 0;
00099     device_list_head = NULL;
00100     temp_device_counter = 0;
00101 
00102     num_gdl_changed_cb = 0;
00103     num_new_capability_cb = 0;
00104     num_property_changed_cb = 1;
00105     property_changed_cb[0] = async_find_property_changed;
00106 }
00107 
00112 void
00113 ds_add_cb_newcap (HalDeviceNewCapabilityCallback cb)
00114 {
00115     if (num_property_changed_cb < MAX_CB_FUNCS)
00116         new_capability_cb[num_new_capability_cb++] = cb;
00117 }
00118 
00123 void
00124 ds_add_cb_property_changed (HalDevicePropertyChangedCallback cb)
00125 {
00126     if (num_property_changed_cb < MAX_CB_FUNCS)
00127         property_changed_cb[num_property_changed_cb++] = cb;
00128 }
00129 
00134 void
00135 ds_add_cb_gdl_changed (HalDeviceGDLChangedCallback cb)
00136 {
00137     if (num_gdl_changed_cb < MAX_CB_FUNCS)
00138         gdl_changed_cb[num_gdl_changed_cb++] = cb;
00139 }
00140 
00141 
00142 
00145 void
00146 ds_shutdown ()
00147 {
00148 }
00149 
00154 void
00155 ds_print (HalDevice * device)
00156 {
00157     HalPropertyIterator iter;
00158 
00159     printf ("device udi = %s    (%s)\n", ds_device_get_udi (device),
00160         device->in_gdl ? "in GDL" : "NOT in GDL");
00161 
00162     for (ds_property_iter_begin (device, &iter);
00163          ds_property_iter_has_more (&iter);
00164          ds_property_iter_next (&iter)) {
00165         int type;
00166         HalProperty *p;
00167         const char *key;
00168 
00169         p = ds_property_iter_get (&iter);
00170 
00171         key = ds_property_iter_get_key (p);
00172         type = ds_property_iter_get_type (p);
00173 
00174         switch (type) {
00175         case DBUS_TYPE_STRING:
00176             printf ("  %s = '%s'  (string)\n", key,
00177                 ds_property_iter_get_string (p));
00178             break;
00179 
00180         case DBUS_TYPE_INT32:
00181             printf ("  %s = %d  0x%x  (int)\n", key,
00182                 ds_property_iter_get_int (p),
00183                 ds_property_iter_get_int (p));
00184             break;
00185 
00186         case DBUS_TYPE_DOUBLE:
00187             printf ("  %s = %g  (double)\n", key,
00188                 ds_property_iter_get_double (p));
00189             break;
00190 
00191         case DBUS_TYPE_BOOLEAN:
00192             printf ("  %s = %s  (bool)\n", key,
00193                 (ds_property_iter_get_bool (p) ? "true" :
00194                  "false"));
00195             break;
00196 
00197         default:
00198             HAL_WARNING (("Unknown property type %d", type));
00199             break;
00200         }
00201     }
00202     printf ("\n");
00203 }
00204 
00205 /**************************************************************************/
00206 
00213 HalDevice *
00214 ds_device_find (const char *udi)
00215 {
00216     HalDevice *it;
00217 
00218     for (it = device_list_head; it != NULL; it = it->next) {
00219         if (strcmp (it->udi, udi) == 0)
00220             return it;
00221     }
00222     return NULL;
00223 }
00224 
00226 typedef struct DSDeviceAsyncFindStruct_s {
00227     char *key;        
00228     char *value;          
00230     dbus_bool_t only_gdl;     
00231     DSAsyncFindDeviceCB callback;
00233     void *data1;          
00234     void *data2;          
00235     guint timeout_id;     
00237     struct DSDeviceAsyncFindStruct_s *next;
00239 } DSDeviceAsyncFindStruct;
00240 
00242 static DSDeviceAsyncFindStruct *async_find_outstanding_head = NULL;
00243 
00249 static gboolean
00250 async_find_timeout_fn (gpointer data)
00251 {
00252     void *data1;
00253     void *data2;
00254     DSAsyncFindDeviceCB callback;
00255     DSDeviceAsyncFindStruct *i;
00256     DSDeviceAsyncFindStruct *prev;
00257     DSDeviceAsyncFindStruct *afs = (DSDeviceAsyncFindStruct *) data;
00258 
00259     /* Check if this is still in list */
00260     for (i = async_find_outstanding_head, prev = NULL; i != NULL;
00261          i = i->next) {
00262         if (i == afs) {
00263             data1 = i->data1;
00264             data2 = i->data2;
00265             callback = i->callback;
00266 
00267             /* Remove element in list */
00268             if (prev != NULL) {
00269                 prev->next = i->next;
00270             } else {
00271                 async_find_outstanding_head = i->next;
00272             }
00273 
00274             /* Clean up element */
00275             free (i->key);
00276             free (i->value);
00277             free (i);
00278 
00279             /* We need to be careful to remove the element prior
00280              * to this invocation as our use of it triggers a 
00281              * device addition and thus an indirect invocation 
00282              * of code looking at this list
00283              */
00284 
00285             (*callback) (NULL, data1, data2);
00286 
00287             return FALSE;   /* cancel timeout */
00288         }
00289 
00290         prev = i;
00291     }
00292     return FALSE;       /* cancel timeout */
00293 }
00294 
00295 
00304 static void
00305 async_find_check_new_addition (HalDevice * device)
00306 {
00307     int type;
00308     void *data1;
00309     void *data2;
00310     DSAsyncFindDeviceCB callback;
00311     DSDeviceAsyncFindStruct *i;
00312     DSDeviceAsyncFindStruct *prev;
00313 
00314 check_list_again:
00315 
00316     /* Check if this is still in list */
00317     for (i = async_find_outstanding_head, prev = NULL; i != NULL;
00318          i = i->next) {
00319         /*HAL_INFO(("*** key='%s', value='%s'", i->key, i->value)); */
00320 
00321         type = ds_property_get_type (device, i->key);
00322         if (type == DBUS_TYPE_STRING) {
00323             if (strcmp
00324                 (ds_property_get_string (device, i->key),
00325                  i->value) == 0 && ((!(i->only_gdl))
00326                         || (i->only_gdl
00327                             && device->in_gdl))) {
00328 
00329                 /* Yay, a match! */
00330                 /*printf("new_add_match 0x%08x\n", i); */
00331 
00332                 data1 = i->data1;
00333                 data2 = i->data2;
00334                 callback = i->callback;
00335 
00336                 /* Remove element in list */
00337                 if (prev != NULL) {
00338                     prev->next = i->next;
00339                 } else {
00340                     async_find_outstanding_head =
00341                         i->next;
00342                 }
00343 
00344                 /* Clean up element */
00345                 free (i->key);
00346                 free (i->value);
00347                 free (i);
00348 
00349                 /* We need to be careful to remove the element
00350                  * prior to this invocation as our use of it
00351                  * triggers a device addition and thus an 
00352                  * indirect invocation of code looking at 
00353                  * this list
00354                  */
00355                 (*callback) (device, data1, data2);
00356 
00357                 /* Argh.. Ok, this call we just made may 
00358                  * trigger modifications to the list (inserted
00359                  * at the head), or it may have trigger a 
00360                  * device add (more sensible), hence an 
00361                  * invocation of this function... again.. 
00362                  *
00363                  * *AND*, there may be more than one 
00364                  * outstanding request for this newly added 
00365                  * device.. 
00366                  *
00367                  * *THEREFORE*, we have to start comparing 
00368                  * the list from the darn beginning all over 
00369                  * again. 
00370                  *
00371                  * Sigh.. callbacks suck
00372                  */
00373                 goto check_list_again;
00374                 /*return; */
00375             }
00376         }
00377         prev = i;
00378     }
00379 }
00380 
00390 static void
00391 async_find_property_changed (HalDevice * device,
00392                  const char *key,
00393                  dbus_bool_t in_gdl,
00394                  dbus_bool_t removed, dbus_bool_t added)
00395 {
00396     if (!removed)
00397         async_find_check_new_addition (device);
00398 }
00399 
00400 
00426 void
00427 ds_device_async_find_by_key_value_string (const char *key,
00428                       const char *value,
00429                       dbus_bool_t only_gdl,
00430                       DSAsyncFindDeviceCB callback,
00431                       void *data1,
00432                       void *data2, int timeout)
00433 {
00434     HalDevice *device;
00435     DSDeviceAsyncFindStruct *afs;
00436 
00437     assert (callback != NULL);
00438 
00439     /* first, try to see if we can find it right away */
00440     device = ds_device_find_by_key_value_string (key, value, only_gdl);
00441     if (device != NULL) {
00442         /* yay! */
00443         (*callback) (device, data1, data2);
00444         return;
00445     }
00446 
00447     if (timeout == 0) {
00448         (*callback) (NULL, data1, data2);
00449         return;
00450     }
00451 
00452     /* Nope; First, create a request with the neccessary data */
00453     afs = xmalloc (sizeof (DSDeviceAsyncFindStruct));
00454     afs->key = xstrdup (key);
00455     afs->value = xstrdup (value);
00456     afs->only_gdl = only_gdl;
00457     afs->callback = callback;
00458     afs->data1 = data1;
00459     afs->data2 = data2;
00460 
00461     /* Second, setup a function to fire at timeout */
00462     afs->timeout_id = g_timeout_add (timeout,
00463                      async_find_timeout_fn,
00464                      (gpointer) afs);
00465 
00466     afs->next = async_find_outstanding_head;
00467     async_find_outstanding_head = afs;
00468 
00469 }
00470 
00483 HalDevice **
00484 ds_device_find_multiple_by_key_value_string (const char *key,
00485                          const char *value,
00486                          dbus_bool_t only_gdl,
00487                          int *num_results)
00488 {
00489     int type;
00490     int num_devices;
00491     HalDevice *device;
00492     HalDevice **devices;
00493     HalDeviceIterator iter_device;
00494 
00498     devices = xmalloc (sizeof (HalDevice *) * 1024);
00499     num_devices = 0;
00500 
00501     for (ds_device_iter_begin (&iter_device);
00502          ds_device_iter_has_more (&iter_device);
00503          ds_device_iter_next (&iter_device)) {
00504         device = ds_device_iter_get (&iter_device);
00505 
00506         if (only_gdl && !device->in_gdl)
00507             continue;
00508 
00509         type = ds_property_get_type (device, key);
00510         if (type == DBUS_TYPE_STRING) {
00511             if (strcmp (ds_property_get_string (device, key),
00512                     value) == 0)
00513                 devices[num_devices++] = device;
00514         }
00515     }
00516 
00517     if (num_devices == 0) {
00518         free (devices);
00519         return NULL;
00520     } else {
00521         if (num_results != NULL)
00522             *num_results = num_devices;
00523         return devices;
00524     }
00525 }
00526 
00537 HalDevice *
00538 ds_device_find_by_key_value_string (const char *key,
00539                     const char *value,
00540                     dbus_bool_t only_gdl)
00541 {
00542     int type;
00543     HalDevice *device;
00544     HalDeviceIterator iter_device;
00545 
00546     for (ds_device_iter_begin (&iter_device);
00547          ds_device_iter_has_more (&iter_device);
00548          ds_device_iter_next (&iter_device)) {
00549         device = ds_device_iter_get (&iter_device);
00550 
00551         if (only_gdl && !device->in_gdl)
00552             continue;
00553 
00554         type = ds_property_get_type (device, key);
00555         if (type == DBUS_TYPE_STRING) {
00556             if (strcmp (ds_property_get_string (device, key),
00557                     value) == 0)
00558                 return device;
00559         }
00560     }
00561 
00562     return NULL;
00563 }
00564 
00571 HalDevice *
00572 ds_device_new ()
00573 {
00574     char buf[128];
00575     HalDevice *obj;
00576 
00577     snprintf (buf, 128, "/org/freedesktop/Hal/devices/temp/%d",
00578           temp_device_counter++);
00579 
00580     obj = (HalDevice *) xmalloc (sizeof (HalDevice));
00581 
00582     obj->udi = xstrdup (buf);
00583     obj->in_gdl = FALSE;
00584     obj->num_properties = 0;
00585     obj->prop_head = NULL;
00586 
00587     obj->prev = NULL;
00588     obj->next = device_list_head;
00589     if (obj->next != NULL)
00590         obj->next->prev = obj;
00591 
00592     device_list_head = obj;
00593     device_list_num++;
00594 
00595     return obj;
00596 }
00597 
00603 void
00604 ds_device_destroy (HalDevice * device)
00605 {
00606     int i;
00607     HalProperty *prop;
00608     HalProperty *prop_next;
00609 
00610     if (device->in_gdl) {
00611         for (i = 0; i < num_gdl_changed_cb; i++)
00612             (*(gdl_changed_cb[i])) (device, FALSE);
00613     }
00614     /* remove device from list */
00615     if (device->next != NULL)
00616         device->next->prev = device->prev;
00617     if (device->prev != NULL)
00618         device->prev->next = device->next;
00619     if (device_list_head == device)
00620         device_list_head = device->next;
00621     --device_list_num;
00622 
00623     /* free device */
00624     for (prop = device->prop_head; prop != NULL; prop = prop_next) {
00625         prop_next = prop->next;
00626         free (prop->key);
00627         if (prop->type == DBUS_TYPE_STRING)
00628             free (prop->str_value);
00629         free (prop);
00630     }
00631     free (device->udi);
00632     free (device);
00633 }
00634 
00635 /**************************************************************************/
00636 
00641 void
00642 ds_gdl_add (HalDevice * device)
00643 {
00644     int i;
00645     device->in_gdl = TRUE;
00646 
00647     for (i = 0; i < num_gdl_changed_cb; i++)
00648         (*(gdl_changed_cb[i])) (device, TRUE);
00649 
00650     /* Ah, now check for the asynchronous outstanding finds whether this
00651      * device was the one someone is searching for
00652      */
00653     async_find_check_new_addition (device);
00654 }
00655 
00660 unsigned int
00661 ds_device_size ()
00662 {
00663     return device_list_num;
00664 }
00665 
00670 void
00671 ds_device_iter_begin (HalDeviceIterator * iterator)
00672 {
00673     iterator->position = 0;
00674     iterator->cursor = device_list_head;
00675 }
00676 
00682 dbus_bool_t
00683 ds_device_iter_has_more (HalDeviceIterator * iterator)
00684 {
00685     return iterator->position < device_list_num;
00686 }
00687 
00694 void
00695 ds_device_iter_next (HalDeviceIterator * iterator)
00696 {
00697     iterator->position++;
00698     iterator->cursor = iterator->cursor->next;
00699 }
00700 
00706 HalDevice *
00707 ds_device_iter_get (HalDeviceIterator * iterator)
00708 {
00709     return iterator->cursor;
00710 }
00711 
00712 /**************************************************************************/
00713 
00719 const char *
00720 ds_device_get_udi (HalDevice * device)
00721 {
00722     return device->udi;
00723 }
00724 
00732 dbus_bool_t
00733 ds_device_set_udi (HalDevice * device, const char *udi)
00734 {
00735     if (ds_device_find (udi) != NULL)
00736         return FALSE;
00737     free (device->udi);
00738     device->udi = xstrdup (udi);
00739     return TRUE;
00740 }
00741 
00742 
00743 /**************************************************************************/
00744 
00750 unsigned int
00751 ds_properties_size (HalDevice * device)
00752 {
00753     return device->num_properties;
00754 }
00755 
00762 dbus_bool_t
00763 ds_property_exists (HalDevice * device, const char *key)
00764 {
00765     return ds_property_find (device, key) != NULL;
00766 }
00767 
00775 HalProperty *
00776 ds_property_find (HalDevice * device, const char *key)
00777 {
00778     HalProperty *prop;
00779 
00780     /* check if property already exist */
00781     for (prop = device->prop_head; prop != NULL; prop = prop->next) {
00782         if (strcmp (prop->key, key) == 0) {
00783             return prop;
00784         }
00785     }
00786 
00787     return NULL;
00788 }
00789 
00795 void
00796 ds_property_iter_begin (HalDevice * device, HalPropertyIterator * iterator)
00797 {
00798     iterator->device = device;
00799     iterator->cursor = device->prop_head;
00800 }
00801 
00807 dbus_bool_t
00808 ds_property_iter_has_more (HalPropertyIterator * iterator)
00809 {
00810     return iterator->cursor != NULL;
00811 }
00812 
00817 void
00818 ds_property_iter_next (HalPropertyIterator * iterator)
00819 {
00820     iterator->cursor = iterator->cursor->next;
00821 }
00822 
00828 HalProperty *
00829 ds_property_iter_get (HalPropertyIterator * iterator)
00830 {
00831     return iterator->cursor;
00832 }
00833 
00842 dbus_bool_t
00843 ds_property_set_string (HalDevice * device, const char *key,
00844             const char *value)
00845 {
00846     int i;
00847     HalProperty *prop;
00848 
00849     /* check if property already exist */
00850     for (prop = device->prop_head; prop != NULL; prop = prop->next) {
00851         if (strcmp (prop->key, key) == 0) {
00852             if (prop->type != DBUS_TYPE_STRING)
00853                 return FALSE;
00854 
00855             /* don't bother setting the same value */
00856             if (value != NULL
00857                 && strcmp (prop->str_value, value) == 0) {
00858                 return TRUE;
00859             }
00860 
00861             free (prop->str_value);
00862             prop->str_value = (char *) xstrdup (value);
00863 
00864             /* callback that the property changed */
00865             for (i = 0; i < num_property_changed_cb; i++)
00866                 (*(property_changed_cb[i])) (device, key,
00867                                  device->
00868                                  in_gdl, FALSE,
00869                                  FALSE);
00870             return TRUE;
00871         }
00872     }
00873 
00874     /* nope, have to create it */
00875     prop = (HalProperty *) malloc (sizeof (HalProperty));
00876     if (prop == NULL)
00877         return FALSE;
00878     prop->key = (char *) xstrdup (key);
00879     prop->str_value = (char *) xstrdup (value);
00880 
00881     prop->type = DBUS_TYPE_STRING;
00882 
00883     prop->next = device->prop_head;
00884     prop->prev = NULL;
00885     device->prop_head = prop;
00886     device->num_properties++;
00887     if (prop->next != NULL)
00888         prop->next->prev = prop;
00889 
00890     /* callback that the property have been added */
00891     for (i = 0; i < num_property_changed_cb; i++)
00892         (*(property_changed_cb[i])) (device, key, device->in_gdl,
00893                          FALSE, TRUE);
00894 
00895     return TRUE;
00896 }
00897 
00906 dbus_bool_t
00907 ds_property_set_int (HalDevice * device, const char *key,
00908              dbus_int32_t value)
00909 {
00910     int i;
00911     HalProperty *prop;
00912 
00913     /* check if property already exist */
00914     for (prop = device->prop_head; prop != NULL; prop = prop->next) {
00915         if (strcmp (prop->key, key) == 0) {
00916             if (prop->type != DBUS_TYPE_INT32)
00917                 return FALSE;
00918 
00919             /* don't bother setting the same value */
00920             if (prop->int_value == value)
00921                 return TRUE;
00922 
00923             prop->int_value = value;
00924 
00925             /* callback that the property changed */
00926             for (i = 0; i < num_property_changed_cb; i++)
00927                 (*(property_changed_cb[i])) (device, key,
00928                                  device->
00929                                  in_gdl, FALSE,
00930                                  FALSE);
00931             return TRUE;
00932         }
00933     }
00934 
00935     /* nope, have to create it */
00936     prop = (HalProperty *) malloc (sizeof (HalProperty));
00937     if (prop == NULL)
00938         return FALSE;
00939     prop->key = (char *) xstrdup (key);
00940     prop->int_value = value;
00941 
00942     prop->type = DBUS_TYPE_INT32;
00943 
00944     prop->next = device->prop_head;
00945     prop->prev = NULL;
00946     device->prop_head = prop;
00947     device->num_properties++;
00948     if (prop->next != NULL)
00949         prop->next->prev = prop;
00950 
00951     /* callback that the property have been added */
00952     for (i = 0; i < num_property_changed_cb; i++)
00953         (*(property_changed_cb[i])) (device, key, device->in_gdl,
00954                          FALSE, TRUE);
00955 
00956     return TRUE;
00957 }
00958 
00967 dbus_bool_t
00968 ds_property_set_bool (HalDevice * device, const char *key,
00969               dbus_bool_t value)
00970 {
00971     int i;
00972     HalProperty *prop;
00973 
00974     /* check if property already exist */
00975     for (prop = device->prop_head; prop != NULL; prop = prop->next) {
00976         if (strcmp (prop->key, key) == 0) {
00977             if (prop->type != DBUS_TYPE_BOOLEAN)
00978                 return FALSE;
00979 
00980             /* don't bother setting the same value */
00981             if (prop->bool_value == value)
00982                 return TRUE;
00983 
00984             prop->bool_value = value;
00985 
00986             /* callback that the property changed */
00987             for (i = 0; i < num_property_changed_cb; i++)
00988                 (*(property_changed_cb[i])) (device, key,
00989                                  device->
00990                                  in_gdl, FALSE,
00991                                  FALSE);
00992             return TRUE;
00993         }
00994     }
00995 
00996     /* nope, have to create it */
00997     prop = (HalProperty *) malloc (sizeof (HalProperty));
00998     if (prop == NULL)
00999         return FALSE;
01000     prop->key = (char *) xstrdup (key);
01001     prop->bool_value = value;
01002 
01003     prop->type = DBUS_TYPE_BOOLEAN;
01004 
01005     prop->next = device->prop_head;
01006     prop->prev = NULL;
01007     device->prop_head = prop;
01008     device->num_properties++;
01009     if (prop->next != NULL)
01010         prop->next->prev = prop;
01011 
01012     /* callback that the property have been added */
01013     for (i = 0; i < num_property_changed_cb; i++)
01014         (*(property_changed_cb[i])) (device, key, device->in_gdl,
01015                          FALSE, TRUE);
01016 
01017     return TRUE;
01018 }
01019 
01028 dbus_bool_t
01029 ds_property_set_double (HalDevice * device, const char *key, double value)
01030 {
01031     int i;
01032     HalProperty *prop;
01033 
01034     /* check if property already exist */
01035     for (prop = device->prop_head; prop != NULL; prop = prop->next) {
01036         if (strcmp (prop->key, key) == 0) {
01037             if (prop->type != DBUS_TYPE_DOUBLE)
01038                 return FALSE;
01039 
01040             /* don't bother setting the same value */
01041             if (prop->double_value == value)
01042                 return TRUE;
01043 
01044             prop->double_value = value;
01045 
01046             /* callback that the property changed */
01047             for (i = 0; i < num_property_changed_cb; i++)
01048                 (*(property_changed_cb[i])) (device, key,
01049                                  device->
01050                                  in_gdl, FALSE,
01051                                  FALSE);
01052             return TRUE;
01053         }
01054     }
01055 
01056     /* nope, have to create it */
01057     prop = (HalProperty *) malloc (sizeof (HalProperty));
01058     if (prop == NULL)
01059         return FALSE;
01060     prop->key = (char *) xstrdup (key);
01061     prop->double_value = value;
01062 
01063     prop->type = DBUS_TYPE_DOUBLE;
01064 
01065     prop->next = device->prop_head;
01066     prop->prev = NULL;
01067     device->prop_head = prop;
01068     device->num_properties++;
01069     if (prop->next != NULL)
01070         prop->next->prev = prop;
01071 
01072     /* callback that the property have been added */
01073     for (i = 0; i < num_property_changed_cb; i++)
01074         (*(property_changed_cb[i])) (device, key, device->in_gdl,
01075                          FALSE, TRUE);
01076 
01077     return TRUE;
01078 }
01079 
01086 dbus_bool_t
01087 ds_property_remove (HalDevice * device, const char *key)
01088 {
01089     int i;
01090     int j;
01091     HalProperty *prop;
01092 
01093     i = 0;
01094     /* check if property already exist */
01095     for (prop = device->prop_head; prop != NULL;
01096          prop = prop->next, i++) {
01097         if (strcmp (prop->key, key) == 0) {
01098             switch (prop->type) {
01099             case DBUS_TYPE_STRING:
01100                 free (prop->str_value);
01101                 break;
01102             case DBUS_TYPE_INT32:
01103                 break;
01104             case DBUS_TYPE_DOUBLE:
01105                 break;
01106             case DBUS_TYPE_BOOLEAN:
01107                 break;
01108             }
01109 
01110             free (prop->key);
01111 
01112             if (prop->prev == NULL) {
01113                 device->prop_head = prop->next;
01114                 if (prop->next != NULL)
01115                     prop->next->prev = NULL;
01116             } else {
01117                 prop->prev->next = prop->next;
01118                 if (prop->next != NULL)
01119                     prop->next->prev = prop->prev;
01120             }
01121             free (prop);
01122             device->num_properties--;
01123 
01124             for (j = 0; j < num_property_changed_cb; j++)
01125                 (*(property_changed_cb[j])) (device, key,
01126                                  device->
01127                                  in_gdl, TRUE,
01128                                  FALSE);
01129 
01130             return TRUE;
01131         }
01132     }
01133 
01134     return FALSE;
01135 }
01136 
01137 /**************************************************************************/
01138 
01144 const char *
01145 ds_property_iter_get_key (HalProperty * property)
01146 {
01147     return property->key;
01148 }
01149 
01156 int
01157 ds_property_iter_get_type (HalProperty * property)
01158 {
01159     return property->type;
01160 }
01161 
01162 
01169 const char *
01170 ds_property_iter_get_string (HalProperty * property)
01171 {
01172     if (property->type != DBUS_TYPE_STRING)
01173         return NULL;
01174     return property->str_value;
01175 }
01176 
01182 dbus_int32_t
01183 ds_property_iter_get_int (HalProperty * property)
01184 {
01185     return property->int_value;
01186 }
01187 
01193 dbus_bool_t
01194 ds_property_iter_get_bool (HalProperty * property)
01195 {
01196     return property->bool_value;
01197 }
01198 
01204 double
01205 ds_property_iter_get_double (HalProperty * property)
01206 {
01207     return property->double_value;
01208 }
01209 
01220 void
01221 ds_device_merge (HalDevice * target, HalDevice * source)
01222 {
01223     const char *caps;
01224     HalPropertyIterator iter;
01225 
01226     property_atomic_update_begin ();
01227 
01228     for (ds_property_iter_begin (source, &iter);
01229          ds_property_iter_has_more (&iter);
01230          ds_property_iter_next (&iter)) {
01231         int type;
01232         int target_type;
01233         const char *key;
01234         HalProperty *p;
01235 
01236         p = ds_property_iter_get (&iter);
01237         key = ds_property_iter_get_key (p);
01238         type = ds_property_iter_get_type (p);
01239 
01240         /* handle info.capabilities in a special way */
01241         if (strcmp (key, "info.capabilities") == 0)
01242             continue;
01243 
01244         /* only remove target if it exists with different type */
01245         target_type = ds_property_get_type (target, key);
01246         if (target_type != DBUS_TYPE_NIL && target_type != type)
01247             ds_property_remove (target, key);
01248 
01249         switch (type) {
01250         case DBUS_TYPE_STRING:
01251             ds_property_set_string (target, key,
01252                         ds_property_iter_get_string
01253                         (p));
01254             break;
01255         case DBUS_TYPE_INT32:
01256             ds_property_set_int (target, key,
01257                          ds_property_iter_get_int (p));
01258             break;
01259         case DBUS_TYPE_DOUBLE:
01260             ds_property_set_double (target, key,
01261                         ds_property_iter_get_double
01262                         (p));
01263             break;
01264         case DBUS_TYPE_BOOLEAN:
01265             ds_property_set_bool (target, key,
01266                           ds_property_iter_get_bool
01267                           (p));
01268             break;
01269         default:
01270             HAL_WARNING (("Unknown property type %d", type));
01271             break;
01272         }
01273     }
01274 
01275     property_atomic_update_end ();
01276 
01277     caps = ds_property_get_string (source, "info.capabilities");
01278     if (caps != NULL) {
01279         int i;
01280         char *tok;
01281         char buf[256];
01282         char *bufp = buf;
01283 
01284         tok = strtok_r ((char *) caps, " ", &bufp);
01285         while (tok != NULL) {
01286             if (!ds_query_capability (target, tok)) {
01287                 ds_add_capability (target, tok);
01288             }
01289             tok = strtok_r (NULL, " ", &bufp);
01290         }
01291     }
01292 
01293 }
01294 
01303 int
01304 ds_property_get_type (HalDevice * device, const char *key)
01305 {
01306     HalProperty *prop;
01307 
01308     /* check if property already exist */
01309     for (prop = device->prop_head; prop != NULL; prop = prop->next) {
01310         if (strcmp (prop->key, key) == 0) {
01311             return prop->type;
01312         }
01313     }
01314     return DBUS_TYPE_NIL;
01315 }
01316 
01324 const char *
01325 ds_property_get_string (HalDevice * device, const char *key)
01326 {
01327     HalProperty *prop;
01328 
01329     /* check if property already exist */
01330     for (prop = device->prop_head; prop != NULL; prop = prop->next) {
01331         if (strcmp (prop->key, key) == 0) {
01332             if (prop->type != DBUS_TYPE_STRING)
01333                 return NULL;
01334             return prop->str_value;
01335         }
01336     }
01337     return NULL;
01338 }
01339 
01346 dbus_int32_t
01347 ds_property_get_int (HalDevice * device, const char *key)
01348 {
01349     HalProperty *prop;
01350 
01351     /* check if property already exist */
01352     for (prop = device->prop_head; prop != NULL; prop = prop->next) {
01353         if (strcmp (prop->key, key) == 0) {
01354             if (prop->type != DBUS_TYPE_INT32)
01355                 return -1;
01356             return prop->int_value;
01357         }
01358     }
01359     return -1;
01360 }
01361 
01368 dbus_bool_t
01369 ds_property_get_bool (HalDevice * device, const char *key)
01370 {
01371     HalProperty *prop;
01372 
01373     /* check if property already exist */
01374     for (prop = device->prop_head; prop != NULL; prop = prop->next) {
01375         if (strcmp (prop->key, key) == 0) {
01376             if (prop->type != DBUS_TYPE_BOOLEAN)
01377                 return -1;
01378             return prop->bool_value;
01379         }
01380     }
01381     return -1;
01382 }
01383 
01390 double
01391 ds_property_get_double (HalDevice * device, const char *key)
01392 {
01393     HalProperty *prop;
01394 
01395     /* check if property already exist */
01396     for (prop = device->prop_head; prop != NULL; prop = prop->next) {
01397         if (strcmp (prop->key, key) == 0) {
01398             if (prop->type != DBUS_TYPE_DOUBLE)
01399                 return -1.0;
01400             return prop->double_value;
01401         }
01402     }
01403     return -1.0;
01404 }
01405 
01406 
01425 dbus_bool_t
01426 ds_device_matches (HalDevice * device1, HalDevice * device2,
01427            const char *namespace)
01428 {
01429     int len;
01430     HalPropertyIterator iter;
01431 
01432     len = strlen (namespace);
01433 
01434     for (ds_property_iter_begin (device1, &iter);
01435          ds_property_iter_has_more (&iter);
01436          ds_property_iter_next (&iter)) {
01437         int type;
01438         const char *key;
01439         HalProperty *p;
01440 
01441         p = ds_property_iter_get (&iter);
01442         key = ds_property_iter_get_key (p);
01443         type = ds_property_iter_get_type (p);
01444 
01445         if (strncmp (key, namespace, len) != 0)
01446             continue;
01447 
01448         if (!ds_property_exists (device2, key))
01449             return FALSE;
01450 
01451         switch (type) {
01452         case DBUS_TYPE_STRING:
01453             if (strcmp (ds_property_iter_get_string (p),
01454                     ds_property_get_string (device2,
01455                                 key)) != 0)
01456                 return FALSE;
01457             break;
01458         case DBUS_TYPE_INT32:
01459             if (ds_property_iter_get_int (p) !=
01460                 ds_property_get_int (device2, key))
01461                 return FALSE;
01462             break;
01463         case DBUS_TYPE_DOUBLE:
01464             if (ds_property_iter_get_double (p) !=
01465                 ds_property_get_double (device2, key))
01466                 return FALSE;
01467             break;
01468         case DBUS_TYPE_BOOLEAN:
01469             if (ds_property_iter_get_bool (p) !=
01470                 ds_property_get_bool (device2, key))
01471                 return FALSE;
01472             break;
01473         default:
01474             HAL_WARNING (("Unknown property type %d", type));
01475             break;
01476         }
01477     }
01478 
01479     return TRUE;
01480 }
01481 
01482 
01484 #define MAX_CAP_SIZE 2048
01485 
01491 void
01492 ds_add_capability (HalDevice * device, const char *capability)
01493 {
01494     int i;
01495     const char *caps;
01496     char buf[MAX_CAP_SIZE];
01497 
01498     caps = ds_property_get_string (device, "info.capabilities");
01499     if (caps == NULL) {
01500         ds_property_set_string (device, "info.capabilities",
01501                     capability);
01502     } else {
01503         if (ds_query_capability (device, capability)) {
01504             return;
01505         } else {
01506             snprintf (buf, MAX_CAP_SIZE, "%s %s", caps,
01507                   capability);
01508             ds_property_set_string (device,
01509                         "info.capabilities", buf);
01510         }
01511     }
01512 
01513     for (i = 0; i < num_new_capability_cb; i++)
01514         (*(new_capability_cb[i])) (device, capability,
01515                        device->in_gdl);
01516 }
01517 
01525 dbus_bool_t
01526 ds_query_capability (HalDevice * device, const char *capability)
01527 {
01528     const char *caps_orig;
01529     char *caps;
01530     char buf[256];
01531     char *bufp = buf;
01532     char *c;
01533 
01534     caps = NULL;
01535     caps_orig = ds_property_get_string (device, "info.capabilities");
01536     if (caps_orig != NULL) {
01537         /* strtok_r destroys the string, so mae a copy */
01538         caps = xstrdup (caps_orig);
01539 
01540         for (c = strtok_r (caps, " ", &bufp);
01541              c != NULL; c = strtok_r (NULL, " ", &bufp)) {
01542             if (strcmp (c, capability) == 0) {
01543                 free (caps);
01544                 return TRUE;
01545             }
01546         }
01547 
01548         free (caps);
01549     }
01550     return FALSE;
01551 }
01552 
01553 

Generated on Thu Mar 11 21:32:22 2004 for HAL by doxygen 1.3.6-20040222