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 #include <ctype.h>
00031 #include <stdio.h>
00032 #include <stdlib.h>
00033 #include <string.h>
00034 #include <getopt.h>
00035 #include <assert.h>
00036 #include <unistd.h>
00037 #include <stdarg.h>
00038 #include <limits.h>
00039
00040 #include "../logger.h"
00041 #include "../device_store.h"
00042 #include "../hald.h"
00043
00044 #include "common.h"
00045 #include "class_device.h"
00046
00054 typedef struct {
00055 HalDevice *device;
00056 ClassDeviceHandler *handler;
00057 } AsyncInfo;
00058
00059 static void
00060 class_device_got_device_file (HalDevice *d, gpointer user_data,
00061 gboolean prop_exists);
00062
00063 static void
00064 class_device_final (ClassDeviceHandler* self, HalDevice *d);
00065
00066
00075 dbus_bool_t
00076 class_device_accept (ClassDeviceHandler *self,
00077 const char *path,
00078 struct sysfs_class_device *class_device,
00079 dbus_bool_t is_probing)
00080 {
00081
00082
00083
00084
00085
00086 if (strcmp (class_device->classname, self->sysfs_class_name) == 0) {
00087 return TRUE;
00088 }
00089
00090 return FALSE;
00091 }
00092
00103 void
00104 class_device_visit (ClassDeviceHandler *self,
00105 const char *path,
00106 struct sysfs_class_device *class_device,
00107 dbus_bool_t is_probing)
00108 {
00109 HalDevice *d;
00110 char dev_file[SYSFS_PATH_MAX];
00111 char dev_file_prop_name[SYSFS_PATH_MAX];
00112
00113
00114 if (class_device->sysdevice == NULL) {
00115 return;
00116 }
00117
00118
00119 d = hal_device_new ();
00120 hal_device_store_add (hald_get_tdl (), d);
00121
00122
00123 if (!self->merge_or_add) {
00124 hal_device_property_set_string (d, "info.bus",
00125 self->hal_class_name);
00126 hal_device_property_set_string (d, "linux.sysfs_path", path);
00127 hal_device_property_set_string (d, "linux.sysfs_path_device",
00128 class_device->sysdevice->path);
00129 }
00130
00131
00132 hal_device_property_set_string (d, ".udev.sysfs_path", path);
00133 hal_device_property_set_string (d, ".udev.class_name",
00134 self->sysfs_class_name);
00135
00136
00137 if (self->require_device_file) {
00138
00139
00140 self->get_device_file_target (self, d, path, class_device,
00141 dev_file_prop_name,
00142 SYSFS_PATH_MAX);
00143 hal_device_property_set_string (d, ".target_dev",
00144 dev_file_prop_name);
00145
00146
00147 if (is_probing) {
00148 if (!class_device_get_device_file (path, dev_file,
00149 SYSFS_PATH_MAX)) {
00150 HAL_WARNING (("Couldn't get device file for "
00151 "sysfs path %s", path));
00152 return;
00153 }
00154
00155
00156
00157 self->udev_event (self, d, dev_file);
00158 }
00159 }
00160
00161
00162
00163 if (self->merge_or_add) {
00164 AsyncInfo *ai = g_new0 (AsyncInfo, 1);
00165 ai->device = d;
00166 ai->handler = self;
00167
00168
00169 hal_device_store_match_key_value_string_async (
00170 hald_get_gdl (),
00171 "linux.sysfs_path_device",
00172 class_device->sysdevice->path,
00173 class_device_got_sysdevice, ai,
00174 is_probing ? 0 : HAL_LINUX_HOTPLUG_TIMEOUT);
00175 } else {
00176 char *parent_sysfs_path;
00177 AsyncInfo *ai = g_new0 (AsyncInfo, 1);
00178
00179 parent_sysfs_path =
00180 get_parent_sysfs_path (class_device->sysdevice->path);
00181
00182 ai->device = d;
00183 ai->handler = self;
00184
00185
00186 hal_device_store_match_key_value_string_async (
00187 hald_get_gdl (),
00188 "linux.sysfs_path_device",
00189 parent_sysfs_path,
00190 class_device_got_parent_device, ai,
00191 is_probing ? 0 : HAL_LINUX_HOTPLUG_TIMEOUT);
00192 }
00193 }
00194
00203 void
00204 class_device_removed (ClassDeviceHandler* self, const char *sysfs_path,
00205 HalDevice *d)
00206 {
00207 HAL_INFO (("sysfs_path = '%s'", sysfs_path));
00208 }
00209
00217 void
00218 class_device_udev_event (ClassDeviceHandler *self, HalDevice *d,
00219 char *dev_file)
00220 {
00221 const char *target_dev;
00222 char *target_dev_copy;
00223
00224
00225 target_dev = hal_device_property_get_string (d, ".target_dev");
00226 assert (target_dev != NULL);
00227
00228
00229
00230 target_dev_copy = strdup (target_dev);
00231 assert (target_dev_copy != NULL);
00232
00233
00234 hal_device_property_set_string (d, target_dev_copy, dev_file);
00235
00236 free (target_dev_copy);
00237 }
00238
00239
00248 void
00249 class_device_got_parent_device (HalDeviceStore *store, HalDevice *parent,
00250 gpointer user_data)
00251 {
00252 AsyncInfo *ai = user_data;
00253 HalDevice *d = (HalDevice *) ai->device;
00254 ClassDeviceHandler *self = ai->handler;
00255
00256 g_free (ai);
00257
00258 if (parent == NULL) {
00259 HAL_WARNING (("No parent for class device at sysfs path %s",
00260 d->udi));
00261
00262 hal_device_store_remove (hald_get_tdl (), d);
00263 g_object_unref (d);
00264 return;
00265 }
00266
00267
00268 hal_device_property_set_string (d, "info.parent", parent->udi);
00269
00270
00271 if (self->require_device_file) {
00272 const char *target_dev;
00273 target_dev = hal_device_property_get_string (d, ".target_dev");
00274 assert (target_dev != NULL);
00275
00276 hal_device_async_wait_property (
00277 d, target_dev,
00278 class_device_got_device_file,
00279 (gpointer) self,
00280 is_probing ? 0 : HAL_LINUX_HOTPLUG_TIMEOUT);
00281 } else {
00282 class_device_final (self, d);
00283 }
00284 }
00285
00286
00295 void
00296 class_device_got_sysdevice (HalDeviceStore *store,
00297 HalDevice *sysdevice,
00298 gpointer user_data)
00299 {
00300 AsyncInfo *ai = user_data;
00301 HalDevice *d = (HalDevice *) ai->device;
00302 ClassDeviceHandler *self = ai->handler;
00303
00304 HAL_INFO (("Entering d=0x%0x, sysdevice=0x%0x!", d, sysdevice));
00305
00306 if (sysdevice == NULL) {
00307 HAL_WARNING (("Sysdevice for a class device never appeared!"));
00308
00309 hal_device_store_remove (hald_get_tdl (), d);
00310 g_object_unref (d);
00311 return;
00312 }
00313
00314
00315 if (hal_device_has_property (sysdevice, "info.bus") &&
00316 hal_device_has_property (sysdevice, "info.parent") &&
00317 (strcmp (hal_device_property_get_string (sysdevice, "info.bus"),
00318 "usbif") == 0)) {
00319 const char *parent_udi;
00320 HalDevice *parent_device;
00321
00322 parent_udi = hal_device_property_get_string (sysdevice,
00323 "info.parent");
00324 parent_device = hal_device_store_find (hald_get_gdl (),
00325 parent_udi);
00326 if (parent_device != NULL) {
00327 sysdevice = parent_device;
00328 }
00329 }
00330
00331
00332 hal_device_property_set_string (d, ".sysdevice", sysdevice->udi);
00333
00334
00335 if (self->require_device_file) {
00336 const char *target_dev;
00337 target_dev = hal_device_property_get_string (d, ".target_dev");
00338 assert (target_dev != NULL);
00339
00340 hal_device_async_wait_property (
00341 d, target_dev,
00342 class_device_got_device_file,
00343 (gpointer) self,
00344 is_probing ? 0 : HAL_LINUX_HOTPLUG_TIMEOUT);
00345 } else {
00346 class_device_final (self, d);
00347 }
00348 }
00349
00350 static void
00351 class_device_got_device_file (HalDevice *d, gpointer user_data,
00352 gboolean prop_exists)
00353 {
00354 ClassDeviceHandler *self = (ClassDeviceHandler *) user_data;
00355
00356
00357
00358 if (!prop_exists) {
00359 HAL_WARNING (("Never got device file for class device at %s",
00360 hal_device_property_get_string (d, ".udev.sysfs_path")));
00361 hal_device_store_remove (hald_get_tdl (), d);
00362 g_object_unref (d);
00363 return;
00364 }
00365
00366 class_device_final (self, d);
00367 }
00368
00369 static void
00370 class_device_final (ClassDeviceHandler* self, HalDevice *d)
00371 {
00372 const char *sysfs_path = NULL;
00373 struct sysfs_class_device *class_device;
00374
00375
00376
00377 sysfs_path = hal_device_property_get_string (d, ".udev.sysfs_path");
00378 assert (sysfs_path != NULL);
00379 class_device = sysfs_open_class_device (sysfs_path);
00380 if (class_device == NULL)
00381 DIE (("Coulnd't get sysfs class device object for path %s",
00382 sysfs_path));
00383 self->pre_process (self, d, sysfs_path, class_device);
00384 sysfs_close_class_device (class_device);
00385
00386 if (self->merge_or_add) {
00387 const char *sysdevice_udi;
00388 HalDevice *sysdevice;
00389
00390
00391 sysdevice_udi = hal_device_property_get_string (d, ".sysdevice");
00392 assert (sysdevice_udi != NULL);
00393 sysdevice = hal_device_store_find (hald_get_gdl (),
00394 sysdevice_udi);
00395 assert (sysdevice != NULL);
00396
00397
00398 hal_device_property_remove (d, ".udev.sysfs_path");
00399 hal_device_property_remove (d, ".udev.class_name");
00400 hal_device_property_remove (d, ".sysdevice");
00401 hal_device_property_remove (d, ".target_dev");
00402
00403
00404
00405 hal_device_merge (sysdevice, d);
00406
00407 HAL_INFO (("Merged udi=%s onto %s",
00408 hal_device_get_udi (d),
00409 hal_device_get_udi (sysdevice)));
00410
00411
00412 hal_device_store_remove (hald_get_tdl (), d);
00413 g_object_unref (d);
00414
00415 self->post_merge (self, sysdevice);
00416 } else {
00417 char *new_udi;
00418 HalDevice *new_d;
00419
00420
00421 hal_device_property_remove (d, ".udev.sysfs_path");
00422 hal_device_property_remove (d, ".udev.class_name");
00423 hal_device_property_remove (d, ".sysdevice");
00424 hal_device_property_remove (d, ".target_dev");
00425
00426
00427
00428
00429 new_udi = rename_and_merge (d, self->compute_udi, self->hal_class_name);
00430 if (new_udi != NULL) {
00431 new_d = hal_device_store_find (hald_get_gdl (),
00432 new_udi);
00433
00434 self->got_udi (self, new_d!=NULL ? new_d : d, new_udi);
00435
00436 hal_device_store_add (hald_get_gdl (),
00437 new_d != NULL ? new_d : d);
00438 }
00439 hal_device_store_remove (hald_get_tdl (), d);
00440 g_object_unref (d);
00441 }
00442 }
00443
00444
00448 void
00449 class_device_init (ClassDeviceHandler *self)
00450 {
00451 }
00452
00457 void
00458 class_device_detection_done (ClassDeviceHandler *self)
00459 {
00460 }
00461
00465 void
00466 class_device_shutdown (ClassDeviceHandler *self)
00467 {
00468 }
00469
00470
00485 void
00486 class_device_pre_process (ClassDeviceHandler *self,
00487 HalDevice *d,
00488 const char *sysfs_path,
00489 struct sysfs_class_device *class_device)
00490 {
00491
00492 }
00493
00502 void
00503 class_device_post_merge (ClassDeviceHandler *self,
00504 HalDevice *d)
00505 {
00506
00507 }
00508
00514 void
00515 class_device_tick (ClassDeviceHandler *self)
00516 {
00517 }
00518
00533 void
00534 class_device_get_device_file_target (ClassDeviceHandler *self,
00535 HalDevice *d,
00536 const char *sysfs_path,
00537 struct sysfs_class_device *class_device,
00538 char* dev_file_prop,
00539 int dev_file_prop_len)
00540 {
00541 snprintf (dev_file_prop, dev_file_prop_len,
00542 "%s.device", self->hal_class_name);
00543 }
00544
00545 void
00546 class_device_got_udi (ClassDeviceHandler *self,
00547 HalDevice *d,
00548 const char *udi)
00549 {
00550 }
00551