00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifdef HAVE_CONFIG_H
00027 # include <config.h>
00028 #endif
00029
00030 #define _GNU_SOURCE 1
00031
00032 #include <ctype.h>
00033 #include <stdio.h>
00034 #include <stdlib.h>
00035 #include <string.h>
00036 #include <getopt.h>
00037 #include <assert.h>
00038 #include <unistd.h>
00039 #include <stdarg.h>
00040 #include <limits.h>
00041
00042 #include <libhal/libhal.h>
00043
00044 #include "../logger.h"
00045 #include "../device_store.h"
00046 #include "../device_info.h"
00047 #include "linux_common.h"
00048
00062 double parse_double(const char* str)
00063 {
00065 return atof(str);
00066 }
00067
00074 dbus_int32_t parse_dec(const char* str)
00075 {
00076 dbus_int32_t value;
00077 value = strtol(str, NULL, 10);
00079 return value;
00080 }
00081
00089 dbus_int32_t parse_hex(const char* str)
00090 {
00091 dbus_int32_t value;
00092 value = strtol(str, NULL, 16);
00094 return value;
00095 }
00096
00108 long int find_num(char* pre, char* s, int base)
00109 {
00110 char* where;
00111 int result;
00112
00113 where = strstr(s, pre);
00114 if( where==NULL )
00115 {
00116
00117 return LONG_MAX;
00118 }
00119 where += strlen(pre);
00120
00121 result = strtol(where, NULL, base);
00123
00124
00125
00126
00127
00128 return result;
00129 }
00130
00141 double find_double(char* pre, char* s)
00142 {
00143 char* where;
00144 double result;
00145
00146 where = strstr(s, pre);
00148 if( where==NULL )
00149 DIE(("Didn't find '%s' in '%s'", pre, s));
00150 where += strlen(pre);
00151
00152 result = atof(where);
00153
00154 return result;
00155 }
00156
00167 int find_bcd2(char* pre, char* s)
00168 {
00169 int i;
00170 char c;
00171 int digit;
00172 int left, right, result;
00173 int len;
00174 char* str;
00175 dbus_bool_t passed_white_space;
00176 int num_prec;
00177
00178 str = find_string(pre, s);
00179 if( str==NULL || strlen(str)==0 )
00180 return 0xffff;
00181
00182
00183 left = 0;
00184 len = strlen(str);
00185 passed_white_space = FALSE;
00186 for(i=0; i<len && str[i]!='.'; i++)
00187 {
00188 if( isspace(str[i]) )
00189 {
00190 if( passed_white_space )
00191 break;
00192 else
00193 continue;
00194 }
00195 passed_white_space = TRUE;
00196 left *= 16;
00197 c = str[i];
00198 digit = (int) (c-'0');
00199 left += digit;
00200 }
00201 i++;
00202 right=0;
00203 num_prec=0;
00204 for( ; i<len; i++)
00205 {
00206 if( isspace(str[i]) )
00207 break;
00208 if( num_prec==2 )
00209 break;
00210 right *= 16;
00211 c = str[i];
00212 digit = (int) (c-'0');
00213 right += digit;
00214 num_prec++;
00215 }
00216
00217 for( ; num_prec<2; num_prec++)
00218 right*=16;
00219
00220 result = left*256 + (right&255);
00221 return result;
00222 }
00223
00234 char* find_string(char* pre, char* s)
00235 {
00236 char* where;
00237 static char buf[256];
00238 char* p;
00239
00240 where = strstr(s, pre);
00241 if( where==NULL )
00242 return NULL;
00243 where += strlen(pre);
00244
00245 p=buf;
00246 while( *where!='\n' && *where!='\r')
00247 {
00248 char c = *where;
00249
00250
00251 if( (isalnum(c) || isspace(c) || ispunct(c)) && c!=63 )
00252 {
00253 *p = c;
00254 ++p;
00255 }
00256
00257 ++where;
00258 }
00259 *p = '\0';
00260
00261
00262 --p;
00263 while( isspace(*p) )
00264 {
00265 *p='\0';
00266 --p;
00267 }
00268
00269 return buf;
00270 }
00271
00279 char* read_single_line(char* filename_format,...)
00280 {
00281 FILE* f;
00282 int i;
00283 int len;
00284 char filename[512];
00285 static char buf[512];
00286 va_list args;
00287
00288 va_start(args, filename_format);
00289 vsnprintf(filename, 512, filename_format, args);
00290 va_end(args);
00291
00292 f = fopen(filename, "rb");
00293 if( f==NULL )
00294 return NULL;
00295
00296 if( fgets(buf, 512, f)==NULL )
00297 {
00298 fclose(f);
00299 return NULL;
00300 }
00301
00302 len = strlen(buf);
00303 for(i=len-1; i>0; --i )
00304 {
00305 if( buf[i]=='\n' || buf[i]=='\r' )
00306 buf[i]='\0';
00307 else
00308 break;
00309 }
00310
00311 fclose(f);
00312 return buf;
00313 }
00314
00321 const char* get_last_element(const char* s)
00322 {
00323 int len;
00324 const char* p;
00325
00326 len = strlen(s);
00327 for(p=s+len-1; p>s; --p)
00328 {
00329 if( (*p)=='/' )
00330 return p+1;
00331 }
00332
00333 return s;
00334 }
00335
00336
00363 char* rename_and_merge(HalDevice* d,
00364 ComputeFDI naming_func,
00365 const char* namespace)
00366 {
00367 int append_num;
00368 char* computed_udi;
00369 HalDevice* computed_d;
00370
00371
00372
00373 append_num = -1;
00374 tryagain:
00375
00376 computed_udi = (*naming_func)(d, append_num);
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390 computed_d = ds_device_find(computed_udi);
00391 if( computed_d!=NULL )
00392 {
00393
00394 if( (!ds_property_exists(computed_d, "info.not_available"))
00395 && (!ds_property_get_bool(computed_d, "info.not_available")) )
00396 {
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414 if( ds_device_matches(computed_d, d, namespace) )
00415 {
00416 HAL_ERROR(("Found device already present as '%s'!\n",
00417 computed_d->udi));
00418 ds_print(d);
00419 ds_print(computed_d);
00420
00421 ds_device_destroy(d);
00422
00423 return NULL;
00424 }
00425
00428 append_num++;
00429 goto tryagain;
00430 }
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441 ds_device_merge(computed_d, d);
00442
00443
00444 ds_device_destroy(d);
00445
00446
00447 ds_property_set_bool(computed_d, "info.not_available", FALSE);
00448
00449 HAL_INFO(("Device %s is plugged in again", computed_d->udi));
00450
00451 }
00452 else
00453 {
00454
00455
00456
00457 ds_device_set_udi(d, computed_udi);
00458 ds_property_set_string(d, "info.udi", computed_udi);
00459
00460
00461 if( di_search_and_merge(d) )
00462 {
00463 HAL_INFO(("Found a .fdi file for %s", d->udi));
00464 }
00465
00466 }
00467
00468 return computed_udi;
00469 }
00470
00477 char* get_parent_sysfs_path(const char* path)
00478 {
00479 int i;
00480 int len;
00481 char* parent_path;
00482
00483
00484 parent_path = strndup(path, SYSFS_PATH_MAX);
00485 if( parent_path==NULL )
00486 DIE(("No memory"));
00487 len = strlen(parent_path);
00488 for(i=len-1; parent_path[i]!='/'; --i)
00489 {
00490 parent_path[i]='\0';
00491 }
00492 parent_path[i]='\0';
00493
00494 return parent_path;
00495 }
00496
00505 void find_and_set_physical_device(HalDevice* device)
00506 {
00507 HalDevice* d;
00508 HalDevice* parent;
00509 const char* parent_udi;
00510
00511 d = device;
00512 do
00513 {
00514 parent_udi = ds_property_get_string(d, "info.parent");
00515 if( parent_udi==NULL )
00516 {
00517 HAL_ERROR(("Error finding parent for %s\n", d->udi));
00518 return;
00519 }
00520
00521 parent = ds_device_find(parent_udi);
00522 if( parent==NULL )
00523 {
00524 HAL_ERROR(("Error resolving UDI %s\n", parent_udi));
00525 return;
00526 }
00527
00528 if( !ds_property_exists(parent, "info.physical_device") )
00529 {
00530 ds_property_set_string(device, "info.physical_device", parent_udi);
00531 return;
00532 }
00533
00534 d = parent;
00535 }
00536 while(TRUE);
00537 }
00538
00539
00540
00541 struct driver_entry_s
00542 {
00543 char driver_name[SYSFS_NAME_LEN];
00544 char device_path[SYSFS_PATH_MAX];
00545 struct driver_entry_s* next;
00547 };
00548
00550 static struct driver_entry_s* drivers_table_head = NULL;
00551
00557 static void drivers_add_entry(const char* driver_name, const char* device_path)
00558 {
00559 struct driver_entry_s* entry;
00560
00561 entry = malloc(sizeof(struct driver_entry_s));
00562 if( entry==NULL )
00563 DIE(("Out of memory"));
00564 strncpy(entry->driver_name, driver_name, SYSFS_NAME_LEN);
00565 strncpy(entry->device_path, device_path, SYSFS_PATH_MAX);
00566 entry->next = drivers_table_head;
00567 drivers_table_head = entry;
00568 }
00569
00577 const char* drivers_lookup(const char* device_path)
00578 {
00579 struct driver_entry_s* i;
00580
00581 for(i=drivers_table_head; i!=NULL; i=i->next)
00582 {
00583 if( strcmp(device_path, i->device_path)==0 )
00584 return i->driver_name;
00585 }
00586 return NULL;
00587 }
00588
00594 void drivers_collect(const char* bus_name)
00595 {
00596 char path[SYSFS_PATH_MAX];
00597 struct sysfs_directory* current;
00598 struct sysfs_link* current2;
00599 struct sysfs_directory* dir;
00600 struct sysfs_directory* dir2;
00601
00602
00603 snprintf(path, SYSFS_PATH_MAX, "%s/bus/%s/drivers", sysfs_mount_path, bus_name);
00604 dir = sysfs_open_directory(path);
00605 if( dir==NULL )
00606 {
00607 HAL_WARNING(("Error opening sysfs directory at %s\n", path));
00608 goto out;
00609 }
00610 if( sysfs_read_directory(dir)!=0 )
00611 {
00612 HAL_WARNING(("Error reading sysfs directory at %s\n", path));
00613 goto out;
00614 }
00615 if( dir->subdirs!=NULL )
00616 {
00617 dlist_for_each_data(dir->subdirs, current, struct sysfs_directory)
00618 {
00619
00620
00621 dir2 = sysfs_open_directory(current->path);
00622 if( dir2==NULL )
00623 DIE(("Error opening sysfs directory at %s\n", current->path));
00624 if( sysfs_read_directory(dir2)!=0 )
00625 DIE(("Error reading sysfs directory at %s\n", current->path));
00626
00627 if( dir2->links!=NULL )
00628 {
00629 dlist_for_each_data(dir2->links, current2,
00630 struct sysfs_link)
00631 {
00632
00633 drivers_add_entry(current->name, current2->target);
00634 }
00635 sysfs_close_directory(dir2);
00636 }
00637 }
00638 }
00639 out:
00640 if( dir!=NULL )
00641 sysfs_close_directory(dir);
00642 }
00643