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
standard_operations(int32 op,...)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
identify_partition(int fd,partition_data * partition,void ** cookie)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, sizeof(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
scan_partition(int fd,partition_data * partition,void * cookie)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
free_identify_partition_cookie(partition_data *,void * cookie)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