| @@ -29,26 +29,30 @@ | | | @@ -29,26 +29,30 @@ |
29 | #include <sys/statvfs.h> | | 29 | #include <sys/statvfs.h> |
30 | #include <sys/dkio.h> | | 30 | #include <sys/dkio.h> |
31 | #include <dev/scsipi/scsi_spc.h> | | 31 | #include <dev/scsipi/scsi_spc.h> |
32 | #include <dev/scsipi/scsipi_all.h> | | 32 | #include <dev/scsipi/scsipi_all.h> |
33 | #include <dev/scsipi/scsipi_cd.h> | | 33 | #include <dev/scsipi/scsipi_cd.h> |
34 | #include <sys/scsiio.h> | | 34 | #include <sys/scsiio.h> |
35 | | | 35 | |
36 | #include <libhal.h> | | 36 | #include <libhal.h> |
37 | | | 37 | |
38 | #include <logger.h> | | 38 | #include <logger.h> |
39 | | | 39 | |
40 | #define SLEEP_PERIOD 5 | | 40 | #define SLEEP_PERIOD 5 |
41 | | | 41 | |
| | | 42 | #define _EXPOSE_MMC |
| | | 43 | #include <sys/cdio.h> |
| | | 44 | |
| | | 45 | |
42 | enum discstate { | | 46 | enum discstate { |
43 | DISC_INSERTED, | | 47 | DISC_INSERTED, |
44 | DISC_EJECTED, | | 48 | DISC_EJECTED, |
45 | DISC_NONE, | | 49 | DISC_NONE, |
46 | DISC_UNKNOWN | | 50 | DISC_UNKNOWN |
47 | }; | | 51 | }; |
48 | | | 52 | |
49 | static enum discstate | | 53 | static enum discstate |
50 | scsi_test_unit_ready (int fd) | | 54 | scsi_test_unit_ready (int fd) |
51 | { | | 55 | { |
52 | struct scsi_test_unit_ready tur; | | 56 | struct scsi_test_unit_ready tur; |
53 | scsireq_t req; | | 57 | scsireq_t req; |
54 | | | 58 | |
| @@ -197,26 +201,200 @@ is_mounted (const char *device_file) | | | @@ -197,26 +201,200 @@ is_mounted (const char *device_file) |
197 | | | 201 | |
198 | return FALSE; | | 202 | return FALSE; |
199 | } | | 203 | } |
200 | | | 204 | |
201 | static void | | 205 | static void |
202 | close_device (int *fd) | | 206 | close_device (int *fd) |
203 | { | | 207 | { |
204 | if (*fd > 0) { | | 208 | if (*fd > 0) { |
205 | close (*fd); | | 209 | close (*fd); |
206 | *fd = -1; | | 210 | *fd = -1; |
207 | } | | 211 | } |
208 | } | | 212 | } |
209 | | | 213 | |
| | | 214 | |
| | | 215 | /* XXX why not share this further */ |
| | | 216 | static char const * |
| | | 217 | get_profile_typestring(int profile) |
| | | 218 | { |
| | | 219 | switch (profile) { |
| | | 220 | case 0x00 : return "unknown"; // "Unknown[0] profile"; |
| | | 221 | case 0x01 : return "unknown"; // "Non removeable disc"; |
| | | 222 | case 0x02 : return "unknown"; // "Removable disc"; |
| | | 223 | case 0x03 : return "mo"; // Magneto Optical with sector erase"; |
| | | 224 | case 0x04 : return "mo"; // "Magneto Optical write once"; |
| | | 225 | case 0x05 : return "mo"; // "Advance Storage Magneto Optical"; |
| | | 226 | case 0x08 : return "cd_rom"; // "CD-ROM"; no writing |
| | | 227 | case 0x09 : return "cd_r"; // "CD-R recordable"; |
| | | 228 | case 0x0a : return "cd_rw"; // "CD-RW rewritable"; |
| | | 229 | case 0x10 : return "dvd_rom"; // "DVD-ROM"; no writing |
| | | 230 | case 0x11 : return "dvd_r"; // "DVD-R sequential"; |
| | | 231 | case 0x12 : return "dvd_ram"; // "DVD-RAM rewritable"; |
| | | 232 | case 0x13 : return "dvd_rw"; // "DVD-RW restricted overwrite"; |
| | | 233 | case 0x14 : return "dvd_rw"; // "DVD-RW sequential"; |
| | | 234 | case 0x15 : return "dvd_r"; // "DVD-R dual layer sequential"; |
| | | 235 | case 0x16 : return "dvd_r"; // "DVD-R dual layer jump"; |
| | | 236 | case 0x17 : return "dvd_rw"; // "DVD-RW dual layer"; |
| | | 237 | case 0x18 : return "unknown"; // "DVD-Download disc"; UNKNOWN |
| | | 238 | case 0x1a : return "dvd_plus_rw"; // "DVD+RW rewritable"; |
| | | 239 | case 0x1b : return "dvd_plus_r"; // "DVD+R recordable"; |
| | | 240 | case 0x20 : return "ddcd_rom"; // "DDCD readonly (retracted)"; no writing |
| | | 241 | case 0x21 : return "ddcd_r"; // "DDCD-R recordable (retracted)"; OK? |
| | | 242 | case 0x22 : return "ddcd_rw"; // "DDCD-RW rewritable (retracted)"; OK? |
| | | 243 | case 0x2a : return "dvd_plus_rw_dl";//"DVD+RW double layer"; |
| | | 244 | case 0x2b : return "dvd_plus_r_dl";// "DVD+R double layer"; |
| | | 245 | case 0x40 : return "bd_rom"; // "BD-ROM"; |
| | | 246 | case 0x41 : return "bd_r"; // "BD-R Sequential Recording (SRM)"; |
| | | 247 | case 0x42 : return "bd_r"; // "BD-R Random Recording (RRM)"; |
| | | 248 | case 0x43 : return "bd_re"; // "BD-RE rewritable"; |
| | | 249 | case 0x50 : return "hddvd_rom"; // "HD DVD-ROM (retracted)"; |
| | | 250 | case 0x51 : return "hddvd_r"; // "HD DVD-R (retracted)"; |
| | | 251 | case 0x52 : return "hddvd_ram"; // "HD DVD-RAM (retracted)"; |
| | | 252 | case 0x53 : return "hddvd_rw"; // "HD DVD-RW (retracted)"; |
| | | 253 | case 0x58 : return "hddvd_r_dl"; // "HD DVD-R dual layer (retracted)"; |
| | | 254 | case 0x5a : return "hddvd_rw_dl"; // "HD DVD-RW dual layer (retracted)"; |
| | | 255 | } |
| | | 256 | /* reserved */ |
| | | 257 | return "unknown"; |
| | | 258 | } |
| | | 259 | |
| | | 260 | |
| | | 261 | static void |
| | | 262 | set_volume_properties(int fd, LibHalContext *ctx, char *udi, int state) |
| | | 263 | { |
| | | 264 | struct mmc_discinfo di; |
| | | 265 | struct mmc_trackinfo ti; |
| | | 266 | struct volume_id *vid; |
| | | 267 | DBusError error; |
| | | 268 | uint64_t capacity; |
| | | 269 | char const *disc_type; |
| | | 270 | char *disc_fstype, *disc_label; |
| | | 271 | int has_audio, has_data, is_vcd, is_svcd, is_videodvd, is_appendable, is_blank, is_rewritable; |
| | | 272 | int tracknr, err; |
| | | 273 | |
| | | 274 | disc_fstype = ""; |
| | | 275 | disc_label = ""; |
| | | 276 | disc_type = "unknown"; |
| | | 277 | has_audio = has_data = is_vcd = is_svcd = is_videodvd = is_appendable = is_blank = is_rewritable = 0; |
| | | 278 | capacity = 0; |
| | | 279 | |
| | | 280 | dbus_error_init (&error); |
| | | 281 | if (state == DISC_INSERTED) { |
| | | 282 | /* fetch new values */ |
| | | 283 | memset(&di, 0, sizeof(struct mmc_discinfo)); |
| | | 284 | err = ioctl(fd, MMCGETDISCINFO, &di); |
| | | 285 | if (!err) { |
| | | 286 | disc_type = get_profile_typestring(di.mmc_profile); |
| | | 287 | is_rewritable = di.mmc_cur & MMC_CAP_REWRITABLE; |
| | | 288 | is_blank = (di.disc_state == MMC_STATE_EMPTY); |
| | | 289 | is_appendable = (di.disc_state != MMC_STATE_FULL); |
| | | 290 | |
| | | 291 | /* can't check is_videodvd, is_svcd, is_vcd (yet); use volume lib */ |
| | | 292 | disc_fstype = "cd9660"; |
| | | 293 | disc_label = "label"; |
| | | 294 | vid = NULL; |
| | | 295 | #if 0 |
| | | 296 | vid = volume_id_open_fd (fd); |
| | | 297 | if (vid) { |
| | | 298 | if (volume_id_probe_all (vid, 0, psize) == 0) { |
| | | 299 | hal_device_property_set_string (d, "volume.label", vid->label); |
| | | 300 | hal_device_property_set_string (d, "volume.partition.label", vid->label); |
| | | 301 | hal_device_property_set_string (d, "volume.uuid", vid->uuid); |
| | | 302 | hal_device_property_set_string (d, "volume.partition.uuid", vid->uuid); |
| | | 303 | } |
| | | 304 | volume_id_close (vid); |
| | | 305 | } |
| | | 306 | #endif |
| | | 307 | for (tracknr = di.first_track; tracknr <= di.last_track_last_session; tracknr++) { |
| | | 308 | memset(&ti, 0, sizeof(struct mmc_trackinfo)); |
| | | 309 | ti.tracknr = tracknr; |
| | | 310 | err = ioctl(fd, MMCGETTRACKINFO, &ti); |
| | | 311 | if (err) |
| | | 312 | break; |
| | | 313 | if (!(ti.flags & MMC_TRACKINFO_BLANK)) { |
| | | 314 | if (ti.flags & MMC_TRACKINFO_DATA) |
| | | 315 | has_data = TRUE; |
| | | 316 | if (ti.flags & MMC_TRACKINFO_AUDIO) |
| | | 317 | has_audio = TRUE; |
| | | 318 | } |
| | | 319 | capacity += (ti.track_size + ti.free_blocks) * di.sector_size; |
| | | 320 | } |
| | | 321 | } |
| | | 322 | } |
| | | 323 | |
| | | 324 | /* add volume properties (ignoring dbus errors) */ |
| | | 325 | libhal_device_set_property_bool (ctx, udi, "volume.ignore", FALSE, &error); /* make visible */ |
| | | 326 | libhal_device_set_property_bool (ctx, udi, "volume.ismounted", FALSE, &error); /* XXX fixme XXX */ |
| | | 327 | libhal_device_set_property_bool (ctx, udi, "volume.ismounted_readonly", FALSE, &error); /* XXX fixme XXX */ |
| | | 328 | libhal_device_set_property_string (ctx, udi, "volume.fsusage", "filesystem", &error); |
| | | 329 | libhal_device_set_property_string (ctx, udi, "volume.fstype", disc_fstype, &error); |
| | | 330 | libhal_device_set_property_string (ctx, udi, "volume.label", disc_label, &error); |
| | | 331 | libhal_device_set_property_string (ctx, udi, "volume.uuid", "", &error); |
| | | 332 | libhal_device_set_property_uint64 (ctx, udi, "volume.size", capacity, &error); |
| | | 333 | |
| | | 334 | /* add volume.disc properties (ignoring dbus errors) */ |
| | | 335 | libhal_device_set_property_bool (ctx, udi, "volume.disc.has_audio", has_audio, &error); |
| | | 336 | libhal_device_set_property_bool (ctx, udi, "volume.disc.has_data", has_data, &error); |
| | | 337 | libhal_device_set_property_bool (ctx, udi, "volume.disc.is_vcd", is_vcd, &error); |
| | | 338 | libhal_device_set_property_bool (ctx, udi, "volume.disc.is_svcd", is_svcd, &error); |
| | | 339 | libhal_device_set_property_bool (ctx, udi, "volume.disc.is_videodvd", is_videodvd, &error); |
| | | 340 | libhal_device_set_property_bool (ctx, udi, "volume.disc.is_appendable", is_appendable, &error); |
| | | 341 | libhal_device_set_property_bool (ctx, udi, "volume.disc.is_blank", is_blank, &error); |
| | | 342 | libhal_device_set_property_bool (ctx, udi, "volume.disc.is_rewritable", is_rewritable, &error); |
| | | 343 | |
| | | 344 | libhal_device_set_property_string (ctx, udi, "volume.disc.type", disc_type, &error); |
| | | 345 | libhal_device_set_property_uint64 (ctx, udi, "volume.disc.capacity", capacity, &error); |
| | | 346 | |
| | | 347 | my_dbus_error_free (&error); |
| | | 348 | } |
| | | 349 | |
| | | 350 | |
| | | 351 | static void |
| | | 352 | update_disc_volume_properties(int fd, LibHalContext *ctx, const char *udi, int state) |
| | | 353 | { |
| | | 354 | DBusError error; |
| | | 355 | char **volumes; |
| | | 356 | char *vol_udi; |
| | | 357 | int num_volumes, i; |
| | | 358 | |
| | | 359 | dbus_error_init (&error); |
| | | 360 | |
| | | 361 | /* update volume children */ |
| | | 362 | if ((volumes = libhal_manager_find_device_string_match ( |
| | | 363 | ctx, "info.parent", udi, &num_volumes, &error)) != NULL) { |
| | | 364 | dbus_error_free (&error); |
| | | 365 | |
| | | 366 | for (i = 0; i < num_volumes; i++) { |
| | | 367 | vol_udi = volumes[i]; |
| | | 368 | if (libhal_device_get_property_bool (ctx, vol_udi, "block.is_volume", &error)) { |
| | | 369 | dbus_error_free (&error); |
| | | 370 | HAL_DEBUG(("Updating child %s of %s\n", udi, vol_udi)); |
| | | 371 | set_volume_properties(fd, ctx, vol_udi, state); |
| | | 372 | |
| | | 373 | #if 0 |
| | | 374 | if (libhal_device_get_property_bool (ctx, vol_udi, "volume.is_mounted", &error)) { |
| | | 375 | dbus_error_free (&error); |
| | | 376 | HAL_DEBUG (("Forcing unmount of child '%s'", vol_udi)); |
| | | 377 | force_unmount (ctx, vol_udi); |
| | | 378 | } |
| | | 379 | #endif |
| | | 380 | } |
| | | 381 | } |
| | | 382 | libhal_free_string_array (volumes); |
| | | 383 | } |
| | | 384 | my_dbus_error_free (&error); |
| | | 385 | } |
| | | 386 | |
| | | 387 | |
210 | int | | 388 | int |
211 | main (int argc, char *argv[]) | | 389 | main (int argc, char *argv[]) |
212 | { | | 390 | { |
213 | char *udi; | | 391 | char *udi; |
214 | char *device_file, *raw_device_file; | | 392 | char *device_file, *raw_device_file; |
215 | LibHalContext *ctx = NULL; | | 393 | LibHalContext *ctx = NULL; |
216 | DBusError error; | | 394 | DBusError error; |
217 | char *bus; | | 395 | char *bus; |
218 | char *drive_type; | | 396 | char *drive_type; |
219 | int state, last_state; | | 397 | int state, last_state; |
220 | char *support_media_changed_str; | | 398 | char *support_media_changed_str; |
221 | int support_media_changed; | | 399 | int support_media_changed; |
222 | int fd = -1; | | 400 | int fd = -1; |
| @@ -265,54 +443,60 @@ main (int argc, char *argv[]) | | | @@ -265,54 +443,60 @@ main (int argc, char *argv[]) |
265 | */ | | 443 | */ |
266 | for (;;) { | | 444 | for (;;) { |
267 | sleep (SLEEP_PERIOD); | | 445 | sleep (SLEEP_PERIOD); |
268 | if (is_mounted (device_file)) { | | 446 | if (is_mounted (device_file)) { |
269 | close_device (&fd); | | 447 | close_device (&fd); |
270 | } else if ((fd < 0) && ((fd = open (raw_device_file, O_RDONLY | O_NONBLOCK)) < 0)) { | | 448 | } else if ((fd < 0) && ((fd = open (raw_device_file, O_RDONLY | O_NONBLOCK)) < 0)) { |
271 | HAL_DEBUG (("open failed for %s: %s", raw_device_file, strerror (errno))); | | 449 | HAL_DEBUG (("open failed for %s: %s", raw_device_file, strerror (errno))); |
272 | } else { | | 450 | } else { |
273 | /* Check if a disc is in the drive */ | | 451 | /* Check if a disc is in the drive */ |
274 | state = scsi_test_unit_ready (fd); | | 452 | state = scsi_test_unit_ready (fd); |
275 | | | 453 | |
276 | if (state == last_state) { | | 454 | if (state == last_state) { |
277 | HAL_DEBUG (("state has not changed %d %s", state, device_file)); | | 455 | HAL_DEBUG (("state has not changed %d %s", state, device_file)); |
| | | 456 | /* TODO check if eject button was pressed */ |
| | | 457 | /* see linux addons/addon-storage.c */ |
278 | continue; | | 458 | continue; |
279 | } else { | | 459 | } else { |
280 | HAL_DEBUG (("new state %d %s", state, device_file)); | | 460 | HAL_DEBUG (("new state %d %s", state, device_file)); |
281 | } | | 461 | } |
282 | | | 462 | |
283 | switch (state) { | | 463 | switch (state) { |
284 | case DISC_EJECTED: | | 464 | case DISC_EJECTED: |
285 | HAL_DEBUG (("Media removal detected on %s", device_file)); | | 465 | HAL_DEBUG (("Media removal detected on %s", device_file)); |
286 | last_state = state; | | 466 | last_state = state; |
287 | | | 467 | |
288 | libhal_device_set_property_bool (ctx, udi, "storage.removable.media_available", FALSE, &error); | | 468 | libhal_device_set_property_bool (ctx, udi, "storage.removable.media_available", FALSE, &error); |
289 | my_dbus_error_free (&error); | | 469 | my_dbus_error_free (&error); |
290 | | | 470 | |
291 | /* attempt to unmount all childs */ | | 471 | /* attempt to unmount all childs */ |
292 | unmount_childs (ctx, udi); | | 472 | unmount_childs (ctx, udi); |
293 | | | 473 | |
| | | 474 | update_disc_volume_properties(fd, ctx, udi, state); |
| | | 475 | |
294 | /* could have a fs on the main block device; do a rescan to remove it */ | | 476 | /* could have a fs on the main block device; do a rescan to remove it */ |
295 | libhal_device_rescan (ctx, udi, &error); | | 477 | libhal_device_rescan (ctx, udi, &error); |
296 | my_dbus_error_free (&error); | | 478 | my_dbus_error_free (&error); |
297 | break; | | 479 | break; |
298 | | | 480 | |
299 | case DISC_INSERTED: | | 481 | case DISC_INSERTED: |
300 | HAL_DEBUG (("Media insertion detected on %s", device_file)); | | 482 | HAL_DEBUG (("Media insertion detected on %s", device_file)); |
301 | last_state = state; | | 483 | last_state = state; |
302 | | | 484 | |
303 | libhal_device_set_property_bool (ctx, udi, "storage.removable.media_available", TRUE, &error); | | 485 | libhal_device_set_property_bool (ctx, udi, "storage.removable.media_available", TRUE, &error); |
304 | my_dbus_error_free (&error); | | 486 | my_dbus_error_free (&error); |
305 | | | 487 | |
| | | 488 | update_disc_volume_properties(fd, ctx, udi, state); |
| | | 489 | |
306 | /* could have a fs on the main block device; do a rescan to add it */ | | 490 | /* could have a fs on the main block device; do a rescan to add it */ |
307 | libhal_device_rescan (ctx, udi, &error); | | 491 | libhal_device_rescan (ctx, udi, &error); |
308 | my_dbus_error_free (&error); | | 492 | my_dbus_error_free (&error); |
309 | break; | | 493 | break; |
310 | | | 494 | |
311 | case DISC_UNKNOWN: | | 495 | case DISC_UNKNOWN: |
312 | default: | | 496 | default: |
313 | HAL_DEBUG (("Device gone detected on %s", device_file)); | | 497 | HAL_DEBUG (("Device gone detected on %s", device_file)); |
314 | last_state = state; | | 498 | last_state = state; |
315 | | | 499 | |
316 | unmount_childs (ctx, udi); | | 500 | unmount_childs (ctx, udi); |
317 | close_device (&fd); | | 501 | close_device (&fd); |
318 | goto out; | | 502 | goto out; |