xref: /haiku/src/add-ons/kernel/partitioning_systems/session/session.cpp (revision 21258e2674226d6aa732321b6f8494841895af5f)
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, 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
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