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
00027 #ifdef HAVE_CONFIG_H
00028 # include <config.h>
00029 #endif
00030
00031 #include <stdio.h>
00032 #include <stdlib.h>
00033 #include <string.h>
00034 #include <sys/types.h>
00035 #include <sys/stat.h>
00036 #include <unistd.h>
00037 #include <mntent.h>
00038 #include <syslog.h>
00039 #include <linux/limits.h>
00040
00041 #include <dbus/dbus.h>
00042
00058 static char sysfs_mnt_path[PATH_MAX];
00059
00065 static int
00066 get_sysfs_mnt_path ()
00067 {
00068 FILE *mnt;
00069 struct mntent *mntent;
00070 int ret = 0;
00071 size_t dirlen = 0;
00072
00073 if ((mnt = setmntent ("/proc/mounts", "r")) == NULL) {
00074 return -1;
00075 }
00076
00077 while (ret == 0 && dirlen == 0
00078 && (mntent = getmntent (mnt)) != NULL) {
00079 if (strcmp (mntent->mnt_type, "sysfs") == 0) {
00080 dirlen = strlen (mntent->mnt_dir);
00081 if (dirlen <= (PATH_MAX - 1)) {
00082 strcpy (sysfs_mnt_path, mntent->mnt_dir);
00083 } else {
00084 ret = -1;
00085 }
00086 }
00087 }
00088 endmntent (mnt);
00089
00090 if (dirlen == 0 && ret == 0) {
00091 ret = -1;
00092 }
00093 return ret;
00094 }
00095
00096 static const char *file_list_usb[] = {
00097 "idProduct",
00098 "idVendor",
00099 "bcdDevice",
00100 "bMaxPower",
00101
00102 "bmAttributes",
00103 "manufacturer",
00104 "product",
00105 "bDeviceClass",
00106 "bDeviceSubClass",
00107 "bDeviceProtocol",
00108 "bNumConfigurations",
00109 "bConfigurationValue",
00110 "bNumInterfaces",
00111 NULL
00112 };
00113
00114 static const char *file_list_usbif[] = {
00115 "bInterfaceClass",
00116 "bInterfaceSubClass",
00117 "bInterfaceProtocol",
00118 "bInterfaceNumber",
00119 NULL
00120 };
00121
00122 static const char *file_list_scsi_device[] = { NULL };
00123
00124 static const char *file_list_scsi_generic[] = { NULL };
00125
00126 static const char *file_list_scsi_host[] = { NULL };
00127
00128 static const char *file_list_block[] = {
00129 "dev",
00130 "size",
00131 NULL
00132 };
00133
00134 static const char *file_list_pci[] = {
00135 "device",
00136 "vendor",
00137 "subsystem_device",
00138 "subsystem_vendor",
00139 "class",
00140 NULL
00141 };
00142
00143
00144 #define strcat_len(dst, src) do { \
00145 dst[sizeof (dst) - 1] = '\0'; \
00146 strncat (dst, src, sizeof (dst) - strlen (dst) - 1); \
00147 } while(0)
00148
00149 static int
00150 wait_for_sysfs_info (char *devpath, char *hotplug_type)
00151 {
00152 size_t devpath_len;
00153 const char **file_list;
00154 int num_tries;
00155 int rc;
00156 struct stat stat_buf;
00157 int i;
00158 char path[PATH_MAX];
00159
00160 syslog (LOG_NOTICE, "waiting for %s info at %s",
00161 hotplug_type, devpath);
00162
00163 devpath_len = strlen (devpath);
00164
00165 file_list = NULL;
00166
00167 if (strcmp (hotplug_type, "pci") == 0) {
00168 file_list = file_list_pci;
00169 } else if (strcmp (hotplug_type, "usb") == 0) {
00170 int is_interface = 0;
00171
00172 for (i = devpath_len - 1; devpath[i] != '/' && i > 0; --i) {
00173 if (devpath[i] == ':') {
00174 is_interface = TRUE;
00175 break;
00176 }
00177 }
00178
00179 if (is_interface) {
00180 syslog (LOG_NOTICE, "%s is an USB interface",
00181 devpath);
00182 file_list = file_list_usbif;
00183 } else
00184 file_list = file_list_usb;
00185 } else if (strcmp (hotplug_type, "scsi_device") == 0) {
00186 file_list = file_list_scsi_device;
00187 } else if (strcmp (hotplug_type, "scsi_generic") == 0) {
00188 file_list = file_list_scsi_generic;
00189 } else if (strcmp (hotplug_type, "scsi_host") == 0) {
00190 file_list = file_list_scsi_host;
00191 } else if (strcmp (hotplug_type, "block") == 0) {
00192 file_list = file_list_block;
00193 }
00194
00195 if (file_list == NULL) {
00196 syslog (LOG_WARNING, "Dont know how to wait for %s at %s; "
00197 "sleeping 1000 ms", hotplug_type, devpath);
00198 usleep (1000 * 1000);
00199 return -1;
00200 }
00201
00202 num_tries = 0;
00203
00204 try_again:
00205 if (num_tries > 0) {
00206 usleep (100 * 1000);
00207 }
00208
00209 if (num_tries == 20 * 10) {
00210 syslog (LOG_NOTICE, "timed out for %s (waited %d ms)",
00211 devpath, num_tries * 100);
00212 return -1;
00213 }
00214
00215 num_tries++;
00216
00217
00218 strncpy (path, sysfs_mnt_path, PATH_MAX);
00219 strcat_len (path, devpath);
00220
00221
00222
00223 rc = stat (path, &stat_buf);
00224
00225 if (rc != 0)
00226 goto try_again;
00227
00228
00229 for (i = 0; file_list[i] != NULL; i++) {
00230 const char *file;
00231
00232 file = file_list[i];
00233 strncpy (path, sysfs_mnt_path, PATH_MAX);
00234 strcat_len (path, devpath);
00235 strcat_len (path, "/");
00236 strcat_len (path, file);
00237
00238
00239 rc = stat (path, &stat_buf);
00240
00241
00242
00243 if (rc != 0)
00244 goto try_again;
00245 }
00246
00247 syslog (LOG_NOTICE, "got info for %s (waited %d ms)",
00248 devpath, (num_tries - 1) * 100);
00249
00250 return 0;
00251 }
00252
00253
00261 int
00262 main (int argc, char *argv[], char *envp[])
00263 {
00264 int i, j, len;
00265 char *str;
00266 char *hotplug_type;
00267 char *devpath;
00268 int is_add;
00269 DBusError error;
00270 DBusConnection *sysbus_connection;
00271 DBusMessage *message;
00272 DBusMessageIter iter;
00273 DBusMessageIter iter_dict;
00274
00275 if (argc != 2)
00276 return 1;
00277
00278 if (get_sysfs_mnt_path () != 0)
00279 return 1;
00280
00281 openlog ("hal.hotplug", LOG_PID, LOG_USER);
00282
00283
00284 dbus_error_init (&error);
00285 sysbus_connection = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
00286 if (sysbus_connection == NULL)
00287 return 1;
00288
00289
00290 message = dbus_message_new_method_call (
00291 "org.freedesktop.Hal",
00292 "/org/freedesktop/Hal/Linux/Hotplug",
00293 "org.freedesktop.Hal.Linux.Hotplug",
00294 "HotplugEvent");
00295
00296
00297 dbus_message_set_no_reply (message, TRUE);
00298
00299 hotplug_type = argv[1];
00300 devpath = NULL;
00301
00302 is_add = FALSE;
00303
00304 dbus_message_iter_init (message, &iter);
00305 dbus_message_iter_append_string (&iter, hotplug_type);
00306 dbus_message_iter_append_dict (&iter, &iter_dict);
00307 for (i = 0; envp[i] != NULL; i++) {
00308 str = envp[i];
00309 len = strlen (str);
00310 for (j = 0; j < len && str[j] != '='; j++);
00311 str[j] = '\0';
00312
00313 dbus_message_iter_append_dict_key (&iter_dict, str);
00314 dbus_message_iter_append_string (&iter_dict, str + j + 1);
00315
00316 if (strcmp (str, "DEVPATH") == 0) {
00317 devpath = str + j + 1;
00318 } else if (strcmp (str, "ACTION") == 0) {
00319 if (strcmp (str + j + 1, "add") == 0) {
00320 is_add = TRUE;
00321 }
00322 }
00323 }
00324
00325 if (devpath != NULL && is_add) {
00326 int rc;
00327
00328
00329 rc = wait_for_sysfs_info (devpath, hotplug_type);
00330 if (rc != 0) {
00332 }
00333 } else {
00334
00335
00336
00337
00338 }
00339
00340 usleep (1000 * 1000);
00341
00342 if (!dbus_connection_send (sysbus_connection, message, NULL))
00343 return 1;
00344
00345 dbus_message_unref (message);
00346 dbus_connection_flush (sysbus_connection);
00347
00348
00349 usleep (500 * 1000);
00350
00351 dbus_connection_disconnect (sysbus_connection);
00352
00353 return 0;
00354 }
00355