1 /* 2 * Copyright 2003 Tyler Akidau, haiku@akidau.net 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 /*! \file session.cpp 8 \brief Disk device manager partition module for CD/DVD sessions. 9 */ 10 11 12 #include <unistd.h> 13 14 #include <disk_device_manager/ddm_modules.h> 15 #include <disk_device_types.h> 16 #include <DiskDeviceTypes.h> 17 #include <KernelExport.h> 18 19 #include "Debug.h" 20 #include "Disc.h" 21 22 23 #define SESSION_PARTITION_MODULE_NAME "partitioning_systems/session/v1" 24 25 26 static status_t 27 standard_operations(int32 op, ...) 28 { 29 switch (op) { 30 case B_MODULE_INIT: 31 case B_MODULE_UNINIT: 32 return B_OK; 33 } 34 35 return B_ERROR; 36 } 37 38 39 static float 40 identify_partition(int fd, partition_data *partition, void **cookie) 41 { 42 DEBUG_INIT_ETC(NULL, ("fd: %d, id: %" B_PRId32 ", offset: %" B_PRIdOFF ", " 43 "size: %" B_PRIdOFF ", block_size: %" B_PRId32 ", flags: 0x%" B_PRIx32, 44 fd, partition->id, partition->offset, partition->size, 45 partition->block_size, partition->flags)); 46 47 device_geometry geometry; 48 float result = -1; 49 if ((partition->flags & B_PARTITION_IS_DEVICE) != 0 50 && partition->block_size == 2048 51 && ioctl(fd, B_GET_GEOMETRY, &geometry) == 0 52 && geometry.device_type == B_CD) { 53 Disc *disc = new(std::nothrow) Disc(fd); 54 if (disc != NULL && disc->InitCheck() == B_OK) { 55 // If we have only a single session then we can let the file system 56 // drivers play directly with the device. 57 if (disc->GetSession(1) != NULL) 58 result = 0.9f; 59 else 60 result = 0.1f; 61 *cookie = static_cast<void*>(disc); 62 } else 63 delete disc; 64 } 65 PRINT(("returning %g\n", result)); 66 return result; 67 } 68 69 70 static status_t 71 scan_partition(int fd, partition_data *partition, void *cookie) 72 { 73 DEBUG_INIT_ETC(NULL, ("fd: %d, id: %" B_PRId32 ", offset: %" B_PRId64 ", " 74 "size: %" B_PRIdOFF ", block_size: %" B_PRId32 ", cookie: %p", fd, 75 partition->id, partition->offset, partition->size, 76 partition->block_size, cookie)); 77 78 Disc *disc = static_cast<Disc*>(cookie); 79 partition->status = B_PARTITION_VALID; 80 partition->flags |= B_PARTITION_PARTITIONING_SYSTEM 81 | B_PARTITION_READ_ONLY; 82 partition->content_size = partition->size; 83 84 Session *session = NULL; 85 status_t error = B_OK; 86 for (int i = 0; (session = disc->GetSession(i)); i++) { 87 partition_data *child = create_child_partition(partition->id, 88 i, partition->offset + session->Offset(), session->Size(), -1); 89 if (!child) { 90 PRINT(("Unable to create child at index %d.\n", i)); 91 // something went wrong 92 error = B_ERROR; 93 break; 94 } 95 child->block_size = session->BlockSize(); 96 child->flags |= session->Flags(); 97 child->type = strdup(session->Type()); 98 if (!child->type) { 99 error = B_NO_MEMORY; 100 break; 101 } 102 child->parameters = NULL; 103 } 104 PRINT(("error: 0x%" B_PRIx32 ", `%s'\n", error, strerror(error))); 105 RETURN(error); 106 } 107 108 109 static void 110 free_identify_partition_cookie(partition_data */*partition*/, void *cookie) 111 { 112 DEBUG_INIT_ETC(NULL, ("cookie: %p", cookie)); 113 delete static_cast<Disc*>(cookie); 114 } 115 116 117 static partition_module_info sSessionModule = { 118 { 119 SESSION_PARTITION_MODULE_NAME, 120 0, 121 standard_operations 122 }, 123 "session", // short_name 124 MULTISESSION_PARTITION_NAME, // pretty_name 125 0, // flags 126 127 // scanning 128 identify_partition, // identify_partition 129 scan_partition, // scan_partition 130 free_identify_partition_cookie, // free_identify_partition_cookie 131 NULL, // free_partition_cookie 132 NULL, // free_partition_content_cookie 133 }; 134 135 partition_module_info *modules[] = { 136 &sSessionModule, 137 NULL 138 }; 139