110919Slancea/*
210919Slancea * Copyright 2003 Tyler Akidau, haiku@akidau.net
310919Slancea * Distributed under the terms of the MIT License.
410919Slancea */
510919Slancea
610919Slancea
710919Slancea/*!	\file session.cpp
810919Slancea	\brief Disk device manager partition module for CD/DVD sessions.
910919Slancea*/
1010919Slancea
1110919Slancea
1210919Slancea#include <unistd.h>
1310919Slancea
1410919Slancea#include <disk_device_manager/ddm_modules.h>
1510919Slancea#include <disk_device_types.h>
1610919Slancea#include <DiskDeviceTypes.h>
1710919Slancea#include <KernelExport.h>
1810919Slancea
1910919Slancea#include "Debug.h"
2010919Slancea#include "Disc.h"
2110919Slancea
2210919Slancea
2310919Slancea#define SESSION_PARTITION_MODULE_NAME "partitioning_systems/session/v1"
2410919Slancea
2510919Slancea
2610919Slanceastatic status_t
2710919Slanceastandard_operations(int32 op, ...)
2810919Slancea{
2910919Slancea	switch (op) {
3010919Slancea		case B_MODULE_INIT:
3110919Slancea		case B_MODULE_UNINIT:
3210919Slancea			return B_OK;
3310919Slancea	}
3410919Slancea
3510919Slancea	return B_ERROR;
3610919Slancea}
3710919Slancea
3810919Slancea
3910919Slanceastatic float
4010919Slanceaidentify_partition(int fd, partition_data *partition, void **cookie)
4110919Slancea{
4210919Slancea	DEBUG_INIT_ETC(NULL, ("fd: %d, id: %ld, offset: %Ld, "
4310919Slancea		"size: %Ld, block_size: %ld, flags: 0x%lx", fd,
4410919Slancea		partition->id, partition->offset, partition->size,
4510919Slancea		partition->block_size, partition->flags));
4610919Slancea
4710919Slancea	device_geometry geometry;
4810919Slancea	float result = -1;
4910919Slancea	if ((partition->flags & B_PARTITION_IS_DEVICE) != 0
5010919Slancea		&& partition->block_size == 2048
5110919Slancea		&& ioctl(fd, B_GET_GEOMETRY, &geometry) == 0
5210919Slancea		&& geometry.device_type == B_CD) {
5310919Slancea		Disc *disc = new(std::nothrow) Disc(fd);
5410919Slancea		if (disc != NULL && disc->InitCheck() == B_OK) {
5510919Slancea			// If we have only a single session then we can let the file system
5610919Slancea			// drivers play directly with the device.
5710919Slancea			Session *session = disc->GetSession(1);
5810919Slancea			if (session != NULL) {
5910919Slancea				result = 0.9f;
6010919Slancea				delete session;
6110919Slancea			} else
6210919Slancea				result = 0.1f;
6310919Slancea
6410919Slancea			*cookie = static_cast<void*>(disc);
6510919Slancea		} else
6610919Slancea			delete disc;
6710919Slancea	}
6810919Slancea	PRINT(("returning %g\n", result));
6910919Slancea	return result;
7010919Slancea}
7110919Slancea
7210919Slancea
7310919Slanceastatic status_t
7410919Slanceascan_partition(int fd, partition_data *partition, void *cookie)
7510919Slancea{
7610919Slancea	DEBUG_INIT_ETC(NULL, ("fd: %d, id: %ld, offset: %Ld, size: %Ld, "
7710919Slancea		"block_size: %ld, cookie: %p", fd, partition->id, partition->offset,
7810919Slancea		partition->size, partition->block_size, cookie));
7910919Slancea
8010919Slancea	Disc *disc = static_cast<Disc*>(cookie);
8110919Slancea	partition->status = B_PARTITION_VALID;
8210919Slancea	partition->flags |= B_PARTITION_PARTITIONING_SYSTEM
8310919Slancea		| B_PARTITION_READ_ONLY;
8410919Slancea	partition->content_size = partition->size;
8510919Slancea
8610919Slancea	Session *session = NULL;
8710919Slancea	status_t error = B_OK;
8810919Slancea	for (int i = 0; (session = disc->GetSession(i)); i++) {
8910919Slancea		partition_data *child = create_child_partition(partition->id,
9010919Slancea			i, partition->offset + session->Offset(), session->Size(), -1);
9110919Slancea		if (!child) {
9210919Slancea			PRINT(("Unable to create child at index %d.\n", i));
9310919Slancea			// something went wrong
9410919Slancea			error = B_ERROR;
9510919Slancea			break;
9610919Slancea		}
9710919Slancea		child->block_size = session->BlockSize();
9810919Slancea		child->flags |= session->Flags();
9910919Slancea		child->type = strdup(session->Type());
10010919Slancea		delete session;
10110919Slancea		if (!child->type) {
10210919Slancea			error = B_NO_MEMORY;
10310919Slancea			break;
10410919Slancea		}
10510919Slancea		child->parameters = NULL;
10610919Slancea	}
10710919Slancea	PRINT(("error: 0x%lx, `%s'\n", error, strerror(error)));
10810919Slancea	RETURN(error);
10910919Slancea}
11010919Slancea
11110919Slancea
11210919Slanceastatic void
11310919Slanceafree_identify_partition_cookie(partition_data */*partition*/, void *cookie)
114{
115	DEBUG_INIT_ETC(NULL, ("cookie: %p", cookie));
116	delete static_cast<Disc*>(cookie);
117}
118
119
120static partition_module_info sSessionModule = {
121	{
122		SESSION_PARTITION_MODULE_NAME,
123		0,
124		standard_operations
125	},
126	"session",							// short_name
127	MULTISESSION_PARTITION_NAME,		// pretty_name
128	0,									// flags
129
130	// scanning
131	identify_partition,					// identify_partition
132	scan_partition,						// scan_partition
133	free_identify_partition_cookie,		// free_identify_partition_cookie
134	NULL,								// free_partition_cookie
135	NULL,								// free_partition_content_cookie
136};
137
138partition_module_info *modules[] = {
139	&sSessionModule,
140	NULL
141};
142