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

device_store.c

00001 /***************************************************************************
00002  * CVSID: $Id: device_store.c,v 1.14 2004/01/18 22:05:47 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 ds_init()
00096 {
00097     device_list_num = 0;
00098     device_list_head = NULL;
00099     temp_device_counter = 0;
00100 
00101     num_gdl_changed_cb = 0;
00102     num_new_capability_cb = 0;
00103     num_property_changed_cb = 1;
00104     property_changed_cb[0] = async_find_property_changed;
00105 }
00106 
00111 void ds_add_cb_newcap(HalDeviceNewCapabilityCallback cb)
00112 {
00113     if( num_property_changed_cb < MAX_CB_FUNCS )
00114         new_capability_cb[num_new_capability_cb++] = cb;
00115 }
00116 
00121 void ds_add_cb_property_changed(HalDevicePropertyChangedCallback cb)
00122 {
00123     if( num_property_changed_cb < MAX_CB_FUNCS )
00124         property_changed_cb[num_property_changed_cb++] = cb;
00125 }
00126 
00131 void ds_add_cb_gdl_changed(HalDeviceGDLChangedCallback cb)
00132 {
00133     if( num_gdl_changed_cb < MAX_CB_FUNCS )
00134         gdl_changed_cb[num_gdl_changed_cb++] = cb;
00135 }
00136 
00137 
00138 
00141 void ds_shutdown()
00142 {
00143 }
00144 
00149 void ds_print(HalDevice* device)
00150 {
00151     HalPropertyIterator iter;
00152 
00153     printf("device udi = %s    (%s)\n", ds_device_get_udi(device),
00154            device->in_gdl ? "in GDL" : "NOT in GDL");
00155 
00156     for(ds_property_iter_begin(device, &iter);
00157         ds_property_iter_has_more(&iter);
00158         ds_property_iter_next(&iter))
00159     {
00160         int type;
00161         HalProperty* p;
00162         const char* key;
00163 
00164         p = ds_property_iter_get(&iter);
00165 
00166         key = ds_property_iter_get_key(p);
00167         type = ds_property_iter_get_type(p);
00168 
00169         switch( type )
00170         {
00171         case DBUS_TYPE_STRING:
00172             printf("  %s = '%s'  (string)\n", key, 
00173                    ds_property_iter_get_string(p));
00174             break;
00175 
00176         case DBUS_TYPE_INT32:
00177             printf("  %s = %d  0x%x  (int)\n", key, 
00178                    ds_property_iter_get_int(p),
00179                    ds_property_iter_get_int(p));
00180             break;
00181 
00182         case DBUS_TYPE_DOUBLE:
00183             printf("  %s = %g  (double)\n", key, 
00184                    ds_property_iter_get_double(p));
00185             break;
00186 
00187         case DBUS_TYPE_BOOLEAN:
00188             printf("  %s = %s  (bool)\n", key, 
00189                    (ds_property_iter_get_bool(p) ? "true" : "false"));
00190             break;
00191 
00192         default:
00193             HAL_WARNING(("Unknown property type %d", type));
00194             break;
00195         }
00196     }
00197     printf("\n");
00198 }
00199 
00200 /**************************************************************************/
00201 
00208 HalDevice* ds_device_find(const char* udi)
00209 {
00210     HalDevice* it;
00211 
00212     for(it=device_list_head; it!=NULL; it=it->next)
00213     {
00214         if( strcmp(it->udi, udi)==0 )
00215             return it;
00216     }
00217     return NULL;
00218 }
00219 
00221 typedef struct DSDeviceAsyncFindStruct_s
00222 {
00223     char* key;                    
00224     char* value;                  
00226     dbus_bool_t only_gdl;         
00227     DSAsyncFindDeviceCB callback; 
00228     void* data1;                  
00229     void* data2;                  
00230     guint timeout_id;             
00232     struct DSDeviceAsyncFindStruct_s* next; 
00233 } DSDeviceAsyncFindStruct;
00234 
00236 static DSDeviceAsyncFindStruct* async_find_outstanding_head = NULL;
00237 
00243 static gboolean async_find_timeout_fn(gpointer data)
00244 {
00245     void* data1;
00246     void* data2;
00247     DSAsyncFindDeviceCB callback;
00248     DSDeviceAsyncFindStruct* i;
00249     DSDeviceAsyncFindStruct* prev;
00250     DSDeviceAsyncFindStruct* afs = (DSDeviceAsyncFindStruct*) data;
00251 
00252     /* Check if this is still in list */
00253     for(i=async_find_outstanding_head, prev=NULL; i!=NULL; i=i->next)
00254     {
00255         if( i==afs )
00256         {
00257             data1 = i->data1;
00258             data2 = i->data2;
00259             callback = i->callback;
00260             
00261             /* Remove element in list */
00262             if( prev!=NULL )
00263             {
00264                 prev->next = i->next;
00265             }
00266             else
00267             {
00268                 async_find_outstanding_head = i->next;
00269             }
00270 
00271             /* Clean up element */
00272             free(i->key);
00273             free(i->value);
00274             free(i);
00275 
00276             /* We need to be careful to remove the element prior to this
00277              * invocation as our use of it triggers a device addition and
00278              * thus an indirect invocation of code looking at this list
00279              */
00280             (*callback)(NULL, data1, data2);
00281 
00282             return FALSE; /* cancel timeout */
00283         }
00284 
00285         prev = i;
00286     }
00287     return FALSE; /* cancel timeout */
00288 }
00289 
00290 
00299 static void async_find_check_new_addition(HalDevice* device)
00300 {
00301     int type;
00302     void* data1;
00303     void* data2;
00304     DSAsyncFindDeviceCB callback;
00305     DSDeviceAsyncFindStruct* i;
00306     DSDeviceAsyncFindStruct* prev;
00307 
00308 check_list_again:
00309 
00310     /* Check if this is still in list */
00311     for(i=async_find_outstanding_head, prev=NULL; i!=NULL; i=i->next)
00312     {
00313         /*HAL_INFO(("   *** key='%s', value='%s'", i->key, i->value));*/
00314 
00315         type = ds_property_get_type(device, i->key);
00316         if( type==DBUS_TYPE_STRING )
00317         {
00318             if( strcmp(ds_property_get_string(device, i->key), i->value)==0 &&
00319                 ( (!(i->only_gdl)) || (i->only_gdl && device->in_gdl)) )
00320             {
00321 
00322                 /* Yay, a match! */
00323                 /*printf("new_add_match 0x%08x\n", i);*/
00324 
00325                 data1 = i->data1;
00326                 data2 = i->data2;
00327                 callback = i->callback;
00328             
00329                 /* Remove element in list */
00330                 if( prev!=NULL )
00331                 {
00332                     prev->next = i->next;
00333                 }
00334                 else
00335                 {
00336                     async_find_outstanding_head = i->next;
00337                 }
00338 
00339                 /* Clean up element */
00340                 free(i->key);
00341                 free(i->value);
00342                 free(i);
00343 
00344                 /* We need to be careful to remove the element prior to this
00345                  * invocation as our use of it triggers a device addition and
00346                  * thus an indirect invocation of code looking at this list
00347                  */
00348                 (*callback)(device, data1, data2);
00349 
00350                 /* Argh.. Ok, this call we just made may trigger modifications
00351                  * to the list (inserted at the head), or it may have trigger
00352                  * a device add (more sensible), hence an invocation of this
00353                  * function... again.. 
00354                  *
00355                  * *AND*, there may be more than one outstanding request
00356                  * for this newly added device.. 
00357                  *
00358                  * *THEREFORE*, we have to start comparing the list from the
00359                  * darn beginning all over again. 
00360                  *
00361                  * Sigh.. callbacks suck
00362                  */
00363                 goto check_list_again;
00364                 /*return;*/
00365             }
00366         }
00367         prev = i;
00368     }
00369 }
00370 
00380 static void async_find_property_changed(HalDevice* device,
00381                                         const char* key, 
00382                                         dbus_bool_t in_gdl, 
00383                                         dbus_bool_t removed,
00384                                         dbus_bool_t added)
00385 {
00386     if( !removed )
00387         async_find_check_new_addition(device);
00388 }
00389 
00390 
00416 void ds_device_async_find_by_key_value_string(const char* key, 
00417                                               const char* value,
00418                                               dbus_bool_t only_gdl,
00419                                               DSAsyncFindDeviceCB callback, 
00420                                               void* data1, 
00421                                               void* data2, 
00422                                               int timeout)
00423 {
00424     HalDevice* device;
00425     DSDeviceAsyncFindStruct* afs;
00426 
00427     assert( callback!=NULL );
00428 
00429     /* first, try to see if we can find it right away */
00430     device = ds_device_find_by_key_value_string(key, value, only_gdl);
00431     if( device!=NULL )
00432     {
00433         /* yay! */
00434         (*callback)(device, data1, data2 );
00435         return;
00436     }
00437 
00438     if( timeout==0 )
00439     {
00440         (*callback)(NULL, data1, data2 );
00441         return;
00442     }
00443 
00444     /* Nope; First, create a request with the neccessary data */
00445     afs = xmalloc(sizeof(DSDeviceAsyncFindStruct));
00446     afs->key   = xstrdup(key);
00447     afs->value = xstrdup(value);
00448     afs->only_gdl = only_gdl;
00449     afs->callback = callback;
00450     afs->data1 = data1;
00451     afs->data2 = data2;
00452 
00453     /* Second, setup a function to fire at timeout */
00454     afs->timeout_id = g_timeout_add(timeout, 
00455                                     async_find_timeout_fn, (gpointer)afs);
00456 
00457     afs->next = async_find_outstanding_head;
00458     async_find_outstanding_head = afs;
00459 
00460 }
00461 
00474 HalDevice** ds_device_find_multiple_by_key_value_string(const char* key, 
00475                                                         const char* value,
00476                                                         dbus_bool_t only_gdl,
00477                                                         int* num_results)
00478 {
00479     int type;
00480     int num_devices;
00481     HalDevice* device;
00482     HalDevice** devices;
00483     HalDeviceIterator iter_device;
00484 
00487     devices = xmalloc(sizeof(HalDevice*)*1024);
00488     num_devices = 0;
00489 
00490     for(ds_device_iter_begin(&iter_device);
00491         ds_device_iter_has_more(&iter_device);
00492         ds_device_iter_next(&iter_device))
00493     {
00494         device = ds_device_iter_get(&iter_device);
00495 
00496         if( only_gdl && !device->in_gdl )
00497             continue;
00498 
00499         type = ds_property_get_type(device, key);
00500         if( type==DBUS_TYPE_STRING )
00501         {
00502             if( strcmp(ds_property_get_string(device, key),
00503                        value)==0 )
00504                 devices[num_devices++] = device;
00505         }
00506     }
00507 
00508     if( num_devices==0 )
00509     {
00510         free(devices);
00511         return NULL;
00512     }
00513     else
00514     {
00515         if( num_results!=NULL )
00516             *num_results = num_devices;
00517         return devices;
00518     }
00519 }
00520 
00531 HalDevice* ds_device_find_by_key_value_string(const char* key, 
00532                                               const char* value,
00533                                               dbus_bool_t only_gdl)
00534 {
00535     int type;
00536     HalDevice* device;
00537     HalDeviceIterator iter_device;
00538 
00539     for(ds_device_iter_begin(&iter_device);
00540         ds_device_iter_has_more(&iter_device);
00541         ds_device_iter_next(&iter_device))
00542     {
00543         device = ds_device_iter_get(&iter_device);
00544 
00545         if( only_gdl && !device->in_gdl )
00546             continue;
00547 
00548         type = ds_property_get_type(device, key);
00549         if( type==DBUS_TYPE_STRING )
00550         {
00551             if( strcmp(ds_property_get_string(device, key),
00552                        value)==0 )
00553                 return device;
00554         }
00555     }
00556 
00557     return NULL;
00558 }
00559 
00566 HalDevice* ds_device_new()
00567 {
00568     char buf[128];
00569     HalDevice* obj;
00570 
00571     snprintf(buf, 128, "/org/freedesktop/Hal/devices/temp/%d", 
00572              temp_device_counter++);
00573 
00574     obj = (HalDevice*) xmalloc(sizeof(HalDevice));
00575 
00576     obj->udi            = xstrdup(buf);
00577     obj->in_gdl         = FALSE;
00578     obj->num_properties = 0;
00579     obj->prop_head      = NULL;
00580 
00581     obj->prev = NULL;
00582     obj->next = device_list_head;
00583     if( obj->next!=NULL )
00584         obj->next->prev = obj;
00585 
00586     device_list_head = obj;
00587     device_list_num++;
00588 
00589     return obj;
00590 }
00591 
00597 void ds_device_destroy(HalDevice* device)
00598 {
00599     int i;
00600     HalProperty* prop;
00601     HalProperty* prop_next;
00602 
00603     if( device->in_gdl )
00604     {
00605         for(i=0; i<num_gdl_changed_cb; i++)
00606             (*(gdl_changed_cb[i]))(device, FALSE);
00607     }
00608 
00609     // remove device from list
00610     if( device->next!=NULL )
00611         device->next->prev = device->prev;
00612     if( device->prev!=NULL )
00613         device->prev->next = device->next;
00614     if( device_list_head==device )
00615         device_list_head = device->next;
00616     --device_list_num;
00617 
00618     // free device
00619     for(prop=device->prop_head; prop!=NULL; prop=prop_next)
00620     {
00621         prop_next = prop->next;
00622         free(prop->key);
00623         if( prop->type==DBUS_TYPE_STRING )
00624             free(prop->str_value);
00625         free(prop);
00626     }
00627     free(device->udi);
00628     free(device);
00629 }
00630 
00631 /**************************************************************************/
00632 
00637 void ds_gdl_add(HalDevice* device)
00638 {
00639     int i;
00640     device->in_gdl = TRUE;
00641 
00642     for(i=0; i<num_gdl_changed_cb; i++)
00643         (*(gdl_changed_cb[i]))(device, TRUE);
00644 
00645     /* Ah, now check for the asynchronous outstanding finds whether this
00646      * device was the one someone is searching for
00647      */
00648     async_find_check_new_addition(device);
00649 }
00650 
00655 unsigned int ds_device_size()
00656 {
00657     return device_list_num;
00658 }
00659 
00664 void ds_device_iter_begin(HalDeviceIterator* iterator)
00665 {
00666     iterator->position = 0;
00667     iterator->cursor = device_list_head;
00668 }
00669 
00675 dbus_bool_t ds_device_iter_has_more(HalDeviceIterator* iterator)
00676 {
00677     return iterator->position<device_list_num;
00678 }
00679 
00686 void ds_device_iter_next(HalDeviceIterator* iterator)
00687 {
00688     iterator->position++;
00689     iterator->cursor = iterator->cursor->next;
00690 }
00691 
00697 HalDevice* ds_device_iter_get(HalDeviceIterator* iterator)
00698 {
00699     return iterator->cursor;
00700 }
00701 
00702 /**************************************************************************/
00703 
00709 const char* ds_device_get_udi(HalDevice* device)
00710 {
00711     return device->udi;
00712 }
00713 
00721 dbus_bool_t ds_device_set_udi(HalDevice* device, const char* udi)
00722 {
00723     if( ds_device_find(udi)!=NULL )
00724         return FALSE;
00725     free(device->udi);
00726     device->udi = xstrdup(udi);
00727     return TRUE;
00728 }
00729 
00730 
00731 /**************************************************************************/
00732 
00738 unsigned int ds_properties_size(HalDevice* device)
00739 {
00740     return device->num_properties;
00741 }
00742 
00749 dbus_bool_t ds_property_exists(HalDevice* device, const char* key)
00750 {
00751     return ds_property_find(device, key)!=NULL;
00752 }
00753 
00761 HalProperty* ds_property_find(HalDevice* device, const char* key)
00762 {
00763     HalProperty* prop;
00764 
00765     // check if property already exist
00766     for(prop=device->prop_head; prop!=NULL; prop=prop->next)
00767     {
00768         if( strcmp(prop->key, key)==0 )
00769         {
00770             return prop;
00771         }
00772     }
00773 
00774     return NULL;
00775 }
00776 
00782 void ds_property_iter_begin(HalDevice* device, HalPropertyIterator* iterator)
00783 {
00784     iterator->device = device;
00785     iterator->cursor = device->prop_head;
00786 }
00787 
00793 dbus_bool_t ds_property_iter_has_more(HalPropertyIterator* iterator)
00794 {
00795     return iterator->cursor!=NULL;
00796 }
00797 
00802 void ds_property_iter_next(HalPropertyIterator* iterator)
00803 {
00804     iterator->cursor = iterator->cursor->next;
00805 }
00806 
00812 HalProperty* ds_property_iter_get(HalPropertyIterator* iterator)
00813 {
00814     return iterator->cursor;
00815 }
00816 
00825 dbus_bool_t ds_property_set_string(HalDevice* device, const char* key, 
00826                                    const char* value)
00827 {
00828     int i;
00829     HalProperty* prop;
00830 
00831     // check if property already exist
00832     for(prop=device->prop_head; prop!=NULL; prop=prop->next)
00833     {
00834         if( strcmp(prop->key, key)==0 )
00835         {
00836             if( prop->type!=DBUS_TYPE_STRING )
00837                 return FALSE;
00838 
00839             // don't bother setting the same value
00840             if( value!=NULL && strcmp(prop->str_value, value)==0 )
00841             {
00842                 return TRUE;
00843             }
00844 
00845             free(prop->str_value);
00846             prop->str_value = (char*) xstrdup(value);
00847 
00848             // callback that the property changed
00849             for(i=0; i<num_property_changed_cb; i++)
00850                 (*(property_changed_cb[i]))(device, key, device->in_gdl, 
00851                                             FALSE, FALSE);
00852             return TRUE;
00853         }
00854     }
00855 
00856     // nope, have to create it
00857     //
00858     prop = (HalProperty*) malloc(sizeof(HalProperty));
00859     if( prop==NULL )
00860         return FALSE;
00861     prop->key = (char*) xstrdup(key);
00862     prop->str_value = (char*) xstrdup(value);
00863 
00864     prop->type = DBUS_TYPE_STRING;
00865 
00866     prop->next        = device->prop_head;
00867     prop->prev        = NULL;
00868     device->prop_head = prop;
00869     device->num_properties++;
00870     if( prop->next!=NULL )
00871         prop->next->prev = prop;
00872 
00873     // callback that the property have been added
00874     for(i=0; i<num_property_changed_cb; i++)
00875         (*(property_changed_cb[i]))(device, key, device->in_gdl, 
00876                                     FALSE, TRUE);
00877 
00878     return TRUE;
00879 }
00880 
00889 dbus_bool_t ds_property_set_int(HalDevice* device, const char* key, 
00890                                 dbus_int32_t value)
00891 {
00892     int i;
00893     HalProperty* prop;
00894 
00895     // check if property already exist
00896     for(prop=device->prop_head; prop!=NULL; prop=prop->next)
00897     {
00898         if( strcmp(prop->key, key)==0 )
00899         {
00900             if( prop->type!=DBUS_TYPE_INT32 )
00901                 return FALSE;
00902 
00903             // don't bother setting the same value
00904             if( prop->int_value==value )
00905                 return TRUE;
00906 
00907             prop->int_value = value;
00908 
00909             // callback that the property changed
00910             for(i=0; i<num_property_changed_cb; i++)
00911                 (*(property_changed_cb[i]))(device, key, device->in_gdl, 
00912                                             FALSE, FALSE);
00913             return TRUE;
00914         }
00915     }
00916 
00917     // nope, have to create it
00918     //
00919     prop = (HalProperty*) malloc(sizeof(HalProperty));
00920     if( prop==NULL )
00921         return FALSE;
00922     prop->key = (char*) xstrdup(key);
00923     prop->int_value = value;
00924 
00925     prop->type = DBUS_TYPE_INT32;
00926 
00927     prop->next        = device->prop_head;
00928     prop->prev        = NULL;
00929     device->prop_head = prop;
00930     device->num_properties++;
00931     if( prop->next!=NULL )
00932         prop->next->prev = prop;
00933 
00934     // callback that the property have been added
00935     for(i=0; i<num_property_changed_cb; i++)
00936         (*(property_changed_cb[i]))(device, key, device->in_gdl, 
00937                                     FALSE, TRUE);
00938 
00939     return TRUE;
00940 }
00941 
00950 dbus_bool_t ds_property_set_bool(HalDevice* device, const char* key, 
00951                                  dbus_bool_t value)
00952 {
00953     int i;
00954     HalProperty* prop;
00955 
00956     // check if property already exist
00957     for(prop=device->prop_head; prop!=NULL; prop=prop->next)
00958     {
00959         if( strcmp(prop->key, key)==0 )
00960         {
00961             if( prop->type!=DBUS_TYPE_BOOLEAN )
00962                 return FALSE;
00963 
00964             // don't bother setting the same value
00965             if( prop->bool_value==value )
00966                 return TRUE;
00967 
00968             prop->bool_value = value;
00969 
00970             // callback that the property changed
00971             for(i=0; i<num_property_changed_cb; i++)
00972                 (*(property_changed_cb[i]))(device, key, device->in_gdl, 
00973                                             FALSE, FALSE);
00974             return TRUE;
00975         }
00976     }
00977 
00978     // nope, have to create it
00979     //
00980     prop = (HalProperty*) malloc(sizeof(HalProperty));
00981     if( prop==NULL )
00982         return FALSE;
00983     prop->key = (char*) xstrdup(key);
00984     prop->bool_value = value;
00985 
00986     prop->type = DBUS_TYPE_BOOLEAN;
00987 
00988     prop->next        = device->prop_head;
00989     prop->prev        = NULL;
00990     device->prop_head = prop;
00991     device->num_properties++;
00992     if( prop->next!=NULL )
00993         prop->next->prev = prop;
00994 
00995     // callback that the property have been added
00996     for(i=0; i<num_property_changed_cb; i++)
00997         (*(property_changed_cb[i]))(device, key, device->in_gdl, 
00998                                     FALSE, TRUE);
00999 
01000     return TRUE;
01001 }
01002 
01011 dbus_bool_t ds_property_set_double(HalDevice* device, const char* key, 
01012                                    double value)
01013 {
01014     int i;
01015     HalProperty* prop;
01016 
01017     // check if property already exist
01018     for(prop=device->prop_head; prop!=NULL; prop=prop->next)
01019     {
01020         if( strcmp(prop->key, key)==0 )
01021         {
01022             if( prop->type!=DBUS_TYPE_DOUBLE )
01023                 return FALSE;
01024 
01025             // don't bother setting the same value
01026             if( prop->double_value==value )
01027                 return TRUE;
01028 
01029             prop->double_value = value;
01030 
01031             // callback that the property changed
01032             for(i=0; i<num_property_changed_cb; i++)
01033                 (*(property_changed_cb[i]))(device, key, device->in_gdl, 
01034                                             FALSE, FALSE);
01035             return TRUE;
01036         }
01037     }
01038 
01039     // nope, have to create it
01040     //
01041     prop = (HalProperty*) malloc(sizeof(HalProperty));
01042     if( prop==NULL )
01043         return FALSE;
01044     prop->key = (char*) xstrdup(key);
01045     prop->double_value = value;
01046 
01047     prop->type = DBUS_TYPE_DOUBLE;
01048 
01049     prop->next        = device->prop_head;
01050     prop->prev        = NULL;
01051     device->prop_head = prop;
01052     device->num_properties++;
01053     if( prop->next!=NULL )
01054         prop->next->prev = prop;
01055 
01056     // callback that the property have been added
01057     for(i=0; i<num_property_changed_cb; i++)
01058         (*(property_changed_cb[i]))(device, key, device->in_gdl, 
01059                                     FALSE, TRUE);
01060 
01061     return TRUE;
01062 }
01063 
01070 dbus_bool_t ds_property_remove(HalDevice* device, const char* key)
01071 {
01072     int i;
01073     int j;
01074     HalProperty* prop;
01075 
01076     i=0;
01077     // check if property already exist
01078     for(prop=device->prop_head; prop!=NULL; prop=prop->next, i++)
01079     {
01080         if( strcmp(prop->key, key)==0 )
01081         {
01082             switch( prop->type )
01083             {
01084             case DBUS_TYPE_STRING:
01085                 free( prop->str_value );
01086                 break;
01087             case DBUS_TYPE_INT32:
01088                 break;
01089             case DBUS_TYPE_DOUBLE:
01090                 break;
01091             case DBUS_TYPE_BOOLEAN:
01092                 break;
01093             }
01094 
01095             free(prop->key);
01096                 
01097             if( prop->prev==NULL )
01098             {
01099                 device->prop_head = prop->next;
01100                 if( prop->next!=NULL )
01101                     prop->next->prev = NULL;
01102             }
01103             else
01104             {
01105                 prop->prev->next = prop->next;
01106                 if( prop->next!=NULL )
01107                     prop->next->prev = prop->prev;
01108             }
01109             free(prop);
01110             device->num_properties--;
01111 
01112             for(j=0; j<num_property_changed_cb; j++)
01113                 (*(property_changed_cb[j]))(device, key, device->in_gdl, 
01114                                             TRUE, FALSE);
01115             
01116             return TRUE;
01117         }
01118     }
01119 
01120     return FALSE;
01121 }
01122 
01123 /**************************************************************************/
01124 
01130 const char* ds_property_iter_get_key(HalProperty* property)
01131 {
01132     return property->key;
01133 }
01134 
01141 int ds_property_iter_get_type(HalProperty* property)
01142 {
01143     return property->type;
01144 }
01145 
01146 
01153 const char* ds_property_iter_get_string(HalProperty* property)
01154 {
01155     if( property->type!=DBUS_TYPE_STRING )
01156         return NULL;
01157     return property->str_value;
01158 }
01159 
01165 dbus_int32_t ds_property_iter_get_int(HalProperty* property)
01166 {
01167     return property->int_value;
01168 }
01169 
01175 dbus_bool_t ds_property_iter_get_bool(HalProperty* property)
01176 {
01177     return property->bool_value;
01178 }
01179 
01185 double ds_property_iter_get_double(HalProperty* property)
01186 {
01187     return property->double_value;
01188 }
01189 
01200 void ds_device_merge(HalDevice* target, HalDevice* source)
01201 {
01202     const char* caps;
01203     HalPropertyIterator iter;
01204 
01205     property_atomic_update_begin();
01206 
01207     for(ds_property_iter_begin(source, &iter);
01208         ds_property_iter_has_more(&iter);
01209         ds_property_iter_next(&iter))
01210     {
01211         int type;
01212         int target_type;
01213         const char* key;
01214         HalProperty* p;
01215 
01216         p = ds_property_iter_get(&iter);
01217         key = ds_property_iter_get_key(p);
01218         type = ds_property_iter_get_type(p);
01219 
01220         /* handle info.capabilities in a special way */
01221         if( strcmp(key, "info.capabilities")==0 )
01222             continue;
01223 
01224         /* only remove target if it exists with different type */
01225         target_type = ds_property_get_type(target, key);
01226         if( target_type!=DBUS_TYPE_NIL && target_type!=type )
01227             ds_property_remove(target, key);
01228 
01229         switch( type )
01230         {
01231         case DBUS_TYPE_STRING:
01232             ds_property_set_string(target, key,ds_property_iter_get_string(p));
01233             break;
01234         case DBUS_TYPE_INT32:
01235             ds_property_set_int(target, key, ds_property_iter_get_int(p));
01236             break;
01237         case DBUS_TYPE_DOUBLE:
01238             ds_property_set_double(target, key,ds_property_iter_get_double(p));
01239             break;
01240         case DBUS_TYPE_BOOLEAN:
01241             ds_property_set_bool(target, key, ds_property_iter_get_bool(p));
01242             break;
01243         default:
01244             HAL_WARNING(("Unknown property type %d", type));
01245             break;
01246         }
01247     }    
01248 
01249     property_atomic_update_end();
01250 
01251     caps = ds_property_get_string(source, "info.capabilities");
01252     if( caps!=NULL )
01253     {
01254         int i;
01255         char* tok;
01256         char buf[256];
01257         char* bufp = buf;
01258     
01259         tok = strtok_r((char*)caps, " ", &bufp);
01260         while( tok!=NULL )
01261         {
01262             if( !ds_query_capability(target, tok) )
01263             {
01264                 ds_add_capability(target, tok);
01265             }
01266             tok = strtok_r(NULL, " ", &bufp);
01267         }
01268     }
01269 
01270 }
01271 
01280 int ds_property_get_type(HalDevice* device, const char* key)
01281 {
01282     HalProperty* prop;
01283 
01284     // check if property already exist
01285     for(prop=device->prop_head; prop!=NULL; prop=prop->next)
01286     {
01287         if( strcmp(prop->key, key)==0 )
01288         {
01289             return prop->type;
01290         }
01291     }
01292     return DBUS_TYPE_NIL;
01293 }
01294 
01302 const char* ds_property_get_string(HalDevice* device, const char* key)
01303 {
01304     HalProperty* prop;
01305 
01306     // check if property already exist
01307     for(prop=device->prop_head; prop!=NULL; prop=prop->next)
01308     {
01309         if( strcmp(prop->key, key)==0 )
01310         {
01311             if( prop->type!=DBUS_TYPE_STRING )
01312                 return NULL;
01313             return prop->str_value;
01314         }
01315     }
01316     return NULL;
01317 }
01318 
01325 dbus_int32_t ds_property_get_int(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     {
01332         if( strcmp(prop->key, key)==0 )
01333         {
01334             if( prop->type!=DBUS_TYPE_INT32 )
01335                 return -1;
01336             return prop->int_value;
01337         }
01338     }
01339     return -1;
01340 }
01341 
01348 dbus_bool_t ds_property_get_bool(HalDevice* device, const char* key)
01349 {
01350     HalProperty* prop;
01351 
01352     // check if property already exist
01353     for(prop=device->prop_head; prop!=NULL; prop=prop->next)
01354     {
01355         if( strcmp(prop->key, key)==0 )
01356         {
01357             if( prop->type!=DBUS_TYPE_BOOLEAN )
01358                 return -1;
01359             return prop->bool_value;
01360         }
01361     }
01362     return -1;
01363 }
01364 
01371 double ds_property_get_double(HalDevice* device, const char* key)
01372 {
01373     HalProperty* prop;
01374 
01375     // check if property already exist
01376     for(prop=device->prop_head; prop!=NULL; prop=prop->next)
01377     {
01378         if( strcmp(prop->key, key)==0 )
01379         {
01380             if( prop->type!=DBUS_TYPE_DOUBLE )
01381                 return -1.0;
01382             return prop->double_value;
01383         }
01384     }
01385     return -1.0;
01386 }
01387 
01388 
01407 dbus_bool_t ds_device_matches(HalDevice* device1, HalDevice* device2, 
01408                               const char* namespace)
01409 {
01410     int len;
01411     HalPropertyIterator iter;
01412 
01413     len = strlen(namespace);
01414 
01415     for(ds_property_iter_begin(device1, &iter);
01416         ds_property_iter_has_more(&iter);
01417         ds_property_iter_next(&iter))
01418     {
01419         int type;
01420         const char* key;
01421         HalProperty* p;
01422 
01423         p = ds_property_iter_get(&iter);
01424         key = ds_property_iter_get_key(p);
01425         type = ds_property_iter_get_type(p);
01426 
01427         if( strncmp(key, namespace, len)!=0 )
01428             continue;
01429 
01430         if( !ds_property_exists(device2, key) )
01431             return FALSE;
01432 
01433         switch( type )
01434         {
01435         case DBUS_TYPE_STRING:
01436             if( strcmp(ds_property_iter_get_string(p),
01437                        ds_property_get_string(device2, key))!=0 )
01438                 return FALSE;
01439             break;
01440         case DBUS_TYPE_INT32:
01441             if( ds_property_iter_get_int(p) !=
01442                 ds_property_get_int(device2, key) )
01443                 return FALSE;
01444             break;
01445         case DBUS_TYPE_DOUBLE:
01446             if( ds_property_iter_get_double(p) !=
01447                 ds_property_get_double(device2, key) )
01448                 return FALSE;
01449             break;
01450         case DBUS_TYPE_BOOLEAN:
01451             if( ds_property_iter_get_bool(p) !=
01452                 ds_property_get_bool(device2, key) )
01453                 return FALSE;
01454             break;
01455         default:
01456             HAL_WARNING(("Unknown property type %d", type));
01457             break;
01458         }
01459     }
01460 
01461     return TRUE;
01462 }
01463 
01464 
01466 #define MAX_CAP_SIZE 2048
01467 
01473 void ds_add_capability(HalDevice* device, const char* capability)
01474 {
01475     int i;
01476     const char* caps;
01477     char buf[MAX_CAP_SIZE];
01478 
01479     caps = ds_property_get_string(device, "info.capabilities");
01480     if( caps==NULL )
01481     {
01482         ds_property_set_string(device, "info.capabilities", capability);
01483     }
01484     else
01485     {
01486         if( ds_query_capability(device, capability) )
01487         {
01488             return;
01489         }
01490         else
01491         {
01492             snprintf(buf, MAX_CAP_SIZE, "%s %s", caps, capability);
01493             ds_property_set_string(device, "info.capabilities", buf);
01494         }
01495     }
01496 
01497     for(i=0; i<num_new_capability_cb; i++)
01498         (*(new_capability_cb[i]))(device, capability, device->in_gdl);
01499 }
01500 
01508 dbus_bool_t ds_query_capability(HalDevice* device, const char* capability)
01509 {
01510     const char* caps_orig;
01511     char* caps;
01512     char buf[256];
01513     char* bufp = buf;
01514     char* c;
01515 
01516     caps = NULL;
01517     caps_orig = ds_property_get_string(device, "info.capabilities");
01518     if( caps_orig!=NULL )
01519     {
01520         /* strtok_r destroys the string, so mae a copy */
01521         caps = xstrdup(caps_orig);
01522 
01523         for(c = strtok_r(caps, " ", &bufp); 
01524             c!=NULL; 
01525             c = strtok_r(NULL, " ", &bufp))
01526         {
01527             if( strcmp(c, capability)==0 )
01528             {
01529                 free(caps);
01530                 return TRUE;
01531             }
01532         }
01533         
01534         free(caps);
01535     }
01536     return FALSE;
01537 }
01538 
01539 

Generated on Sat Feb 7 22:11:46 2004 for HAL by doxygen 1.3.5