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