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
26static status_t
27standard_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
39static float
40identify_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
70static status_t
71scan_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
109static void
110free_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
117static 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
135partition_module_info *modules[] = {
136	&sSessionModule,
137	NULL
138};
139