IOBDMediaBSDClient.cpp [plain text]
#include <sys/errno.h>
#include <sys/proc.h>
#include <IOKit/storage/IOBDMediaBSDClient.h>
#define super IOMediaBSDClient
OSDefineMetaClassAndStructors(IOBDMediaBSDClient, IOMediaBSDClient)
typedef struct
{
uint8_t format;
uint8_t reserved0008[3];
uint32_t address;
uint8_t grantID;
uint8_t layer;
uint8_t reserved0080[4];
uint16_t bufferLength;
user32_addr_t buffer;
} dk_bd_read_structure_32_t;
typedef struct
{
uint8_t format;
uint8_t reserved0008[3];
uint32_t address;
uint8_t grantID;
uint8_t layer;
uint8_t reserved0080[4];
uint16_t bufferLength;
user64_addr_t buffer;
} dk_bd_read_structure_64_t;
typedef struct
{
uint8_t format;
uint8_t keyClass;
uint8_t reserved0016[2];
uint32_t address;
uint8_t grantID;
uint8_t reserved0072[5];
uint16_t bufferLength;
user32_addr_t buffer;
} dk_bd_report_key_32_t;
typedef struct
{
uint8_t format;
uint8_t keyClass;
uint8_t reserved0016[2];
uint32_t address;
uint8_t grantID;
uint8_t reserved0072[5];
uint16_t bufferLength;
user64_addr_t buffer;
} dk_bd_report_key_64_t;
typedef struct
{
uint8_t format;
uint8_t keyClass;
uint8_t reserved0016[6];
uint8_t grantID;
uint8_t reserved0072[5];
uint16_t bufferLength;
user32_addr_t buffer;
} dk_bd_send_key_32_t;
typedef struct
{
uint8_t format;
uint8_t keyClass;
uint8_t reserved0016[6];
uint8_t grantID;
uint8_t reserved0072[5];
uint16_t bufferLength;
user64_addr_t buffer;
} dk_bd_send_key_64_t;
typedef struct
{
uint8_t reserved0000[14];
uint16_t bufferLength;
user32_addr_t buffer;
} dk_bd_read_disc_info_32_t;
typedef struct
{
uint8_t reserved0000[14];
uint16_t bufferLength;
user64_addr_t buffer;
} dk_bd_read_disc_info_64_t;
typedef struct
{
uint8_t reserved0000[4];
uint32_t address;
uint8_t addressType;
uint8_t reserved0072[5];
uint16_t bufferLength;
user32_addr_t buffer;
} dk_bd_read_track_info_32_t;
typedef struct
{
uint8_t reserved0000[4];
uint32_t address;
uint8_t addressType;
uint8_t reserved0072[5];
uint16_t bufferLength;
user64_addr_t buffer;
} dk_bd_read_track_info_64_t;
#define DKIOCBDREADSTRUCTURE32 _IOW('d', 160, dk_bd_read_structure_32_t)
#define DKIOCBDREADSTRUCTURE64 _IOW('d', 160, dk_bd_read_structure_64_t)
#define DKIOCBDREPORTKEY32 _IOW('d', 161, dk_bd_report_key_32_t)
#define DKIOCBDREPORTKEY64 _IOW('d', 161, dk_bd_report_key_64_t)
#define DKIOCBDSENDKEY32 _IOW('d', 162, dk_bd_send_key_32_t)
#define DKIOCBDSENDKEY64 _IOW('d', 162, dk_bd_send_key_64_t)
#define DKIOCBDREADDISCINFO32 _IOWR('d', 164, dk_bd_read_disc_info_32_t)
#define DKIOCBDREADDISCINFO64 _IOWR('d', 164, dk_bd_read_disc_info_64_t)
#define DKIOCBDREADTRACKINFO32 _IOWR('d', 165, dk_bd_read_track_info_32_t)
#define DKIOCBDREADTRACKINFO64 _IOWR('d', 165, dk_bd_read_track_info_64_t)
static bool DKIOC_IS_RESERVED(caddr_t data, uint32_t reserved)
{
UInt32 index;
for ( index = 0; index < sizeof(reserved) * 8; index++, reserved >>= 1 )
{
if ( (reserved & 1) )
{
if ( data[index] ) return true;
}
}
return false;
}
static IOMemoryDescriptor * DKIOC_PREPARE_BUFFER( user_addr_t address,
UInt32 length,
IODirection direction,
proc_t proc )
{
IOMemoryDescriptor * buffer = 0;
if ( address && length )
{
buffer = IOMemoryDescriptor::withAddressRange( address,
length,
direction,
(proc == kernproc) ? kernel_task : current_task() );
}
if ( buffer )
{
if ( buffer->prepare() != kIOReturnSuccess ) {
buffer->release();
buffer = 0;
}
}
return buffer;
}
static void DKIOC_COMPLETE_BUFFER(IOMemoryDescriptor * buffer)
{
if ( buffer )
{
buffer->complete(); buffer->release(); }
}
IOBDMedia * IOBDMediaBSDClient::getProvider() const
{
return (IOBDMedia *) IOService::getProvider();
}
int IOBDMediaBSDClient::ioctl( dev_t dev,
u_long cmd,
caddr_t data,
int flags,
proc_t proc )
{
IOMemoryDescriptor * buffer = 0;
int error = 0;
IOReturn status = kIOReturnSuccess;
switch ( cmd )
{
case DKIOCBDREADSTRUCTURE32: {
dk_bd_read_structure_32_t * request;
request = (dk_bd_read_structure_32_t *) data;
if ( proc_is64bit(proc) ) { error = ENOTTY; break; }
if ( DKIOC_IS_RESERVED(data, 0x3C0E) ) { error = EINVAL; break; }
buffer = DKIOC_PREPARE_BUFFER(
CAST_USER_ADDR_T(request->buffer),
request->bufferLength,
kIODirectionIn,
proc );
status = getProvider()->readStructure(
buffer,
request->format,
request->address,
request->layer,
request->grantID );
status = (status == kIOReturnUnderrun) ? kIOReturnSuccess : status;
DKIOC_COMPLETE_BUFFER(buffer);
} break;
case DKIOCBDREADSTRUCTURE64: {
dk_bd_read_structure_64_t * request;
request = (dk_bd_read_structure_64_t *) data;
if ( proc_is64bit(proc) == 0 ) { error = ENOTTY; break; }
if ( DKIOC_IS_RESERVED(data, 0x3C0E) ) { error = EINVAL; break; }
buffer = DKIOC_PREPARE_BUFFER(
request->buffer,
request->bufferLength,
kIODirectionIn,
proc );
status = getProvider()->readStructure(
buffer,
request->format,
request->address,
request->layer,
request->grantID );
status = (status == kIOReturnUnderrun) ? kIOReturnSuccess : status;
DKIOC_COMPLETE_BUFFER(buffer);
} break;
case DKIOCBDREPORTKEY32: {
dk_bd_report_key_32_t * request = (dk_bd_report_key_32_t *) data;
if ( proc_is64bit(proc) ) { error = ENOTTY; break; }
if ( DKIOC_IS_RESERVED(data, 0x3E0C) ) { error = EINVAL; break; }
buffer = DKIOC_PREPARE_BUFFER(
CAST_USER_ADDR_T(request->buffer),
request->bufferLength,
kIODirectionIn,
proc );
status = getProvider()->reportKey(
buffer,
request->keyClass,
request->address,
request->grantID,
request->format );
status = (status == kIOReturnUnderrun) ? kIOReturnSuccess : status;
DKIOC_COMPLETE_BUFFER(buffer);
} break;
case DKIOCBDREPORTKEY64: {
dk_bd_report_key_64_t * request = (dk_bd_report_key_64_t *) data;
if ( proc_is64bit(proc) == 0 ) { error = ENOTTY; break; }
if ( DKIOC_IS_RESERVED(data, 0x3E0C) ) { error = EINVAL; break; }
buffer = DKIOC_PREPARE_BUFFER(
request->buffer,
request->bufferLength,
kIODirectionIn,
proc );
status = getProvider()->reportKey(
buffer,
request->keyClass,
request->address,
request->grantID,
request->format );
status = (status == kIOReturnUnderrun) ? kIOReturnSuccess : status;
DKIOC_COMPLETE_BUFFER(buffer);
} break;
case DKIOCBDSENDKEY32: {
dk_bd_send_key_32_t * request = (dk_bd_send_key_32_t *) data;
if ( proc_is64bit(proc) ) { error = ENOTTY; break; }
if ( DKIOC_IS_RESERVED(data, 0x3EFC) ) { error = EINVAL; break; }
buffer = DKIOC_PREPARE_BUFFER(
CAST_USER_ADDR_T(request->buffer),
request->bufferLength,
kIODirectionOut,
proc );
status = getProvider()->sendKey(
buffer,
request->keyClass,
request->grantID,
request->format );
status = (status == kIOReturnUnderrun) ? kIOReturnSuccess : status;
DKIOC_COMPLETE_BUFFER(buffer);
} break;
case DKIOCBDSENDKEY64: {
dk_bd_send_key_64_t * request = (dk_bd_send_key_64_t *) data;
if ( proc_is64bit(proc) == 0 ) { error = ENOTTY; break; }
if ( DKIOC_IS_RESERVED(data, 0x3EFC) ) { error = EINVAL; break; }
buffer = DKIOC_PREPARE_BUFFER(
request->buffer,
request->bufferLength,
kIODirectionOut,
proc );
status = getProvider()->sendKey(
buffer,
request->keyClass,
request->grantID,
request->format );
status = (status == kIOReturnUnderrun) ? kIOReturnSuccess : status;
DKIOC_COMPLETE_BUFFER(buffer);
} break;
case DKIOCBDGETSPEED: {
status = getProvider()->getSpeed((uint16_t *)data);
} break;
case DKIOCBDSETSPEED: {
status = getProvider()->setSpeed(*(uint16_t *)data);
} break;
case DKIOCBDREADDISCINFO32: {
dk_bd_read_disc_info_32_t * request;
request = (dk_bd_read_disc_info_32_t *) data;
if ( proc_is64bit(proc) ) { error = ENOTTY; break; }
if ( DKIOC_IS_RESERVED(data, 0x3FFF) ) { error = EINVAL; break; }
buffer = DKIOC_PREPARE_BUFFER(
CAST_USER_ADDR_T(request->buffer),
request->bufferLength,
kIODirectionIn,
proc );
status = getProvider()->readDiscInfo(
buffer,
0,
&request->bufferLength );
status = (status == kIOReturnUnderrun) ? kIOReturnSuccess : status;
DKIOC_COMPLETE_BUFFER(buffer);
} break;
case DKIOCBDREADDISCINFO64: {
dk_bd_read_disc_info_64_t * request;
request = (dk_bd_read_disc_info_64_t *) data;
if ( proc_is64bit(proc) == 0 ) { error = ENOTTY; break; }
if ( DKIOC_IS_RESERVED(data, 0x3FFF) ) { error = EINVAL; break; }
buffer = DKIOC_PREPARE_BUFFER(
request->buffer,
request->bufferLength,
kIODirectionIn,
proc );
status = getProvider()->readDiscInfo(
buffer,
0,
&request->bufferLength );
status = (status == kIOReturnUnderrun) ? kIOReturnSuccess : status;
DKIOC_COMPLETE_BUFFER(buffer);
} break;
case DKIOCBDREADTRACKINFO32: {
dk_bd_read_track_info_32_t * request;
request = (dk_bd_read_track_info_32_t *) data;
if ( proc_is64bit(proc) ) { error = ENOTTY; break; }
if ( DKIOC_IS_RESERVED(data, 0x3E0F) ) { error = EINVAL; break; }
buffer = DKIOC_PREPARE_BUFFER(
CAST_USER_ADDR_T(request->buffer),
request->bufferLength,
kIODirectionIn,
proc );
status = getProvider()->readTrackInfo(
buffer,
request->address,
request->addressType,
0,
&request->bufferLength );
status = (status == kIOReturnUnderrun) ? kIOReturnSuccess : status;
DKIOC_COMPLETE_BUFFER(buffer);
} break;
case DKIOCBDREADTRACKINFO64: {
dk_bd_read_track_info_64_t * request;
request = (dk_bd_read_track_info_64_t *) data;
if ( proc_is64bit(proc) == 0 ) { error = ENOTTY; break; }
if ( DKIOC_IS_RESERVED(data, 0x3E0F) ) { error = EINVAL; break; }
buffer = DKIOC_PREPARE_BUFFER(
request->buffer,
request->bufferLength,
kIODirectionIn,
proc );
status = getProvider()->readTrackInfo(
buffer,
request->address,
request->addressType,
0,
&request->bufferLength );
status = (status == kIOReturnUnderrun) ? kIOReturnSuccess : status;
DKIOC_COMPLETE_BUFFER(buffer);
} break;
case DKIOCBDSPLITTRACK: {
status = getProvider()->splitTrack(*(uint32_t *)data);
} break;
default:
{
error = super::ioctl(dev, cmd, data, flags, proc);
} break;
}
return error ? error : getProvider()->errnoFromReturn(status);
}
OSMetaClassDefineReservedUnused(IOBDMediaBSDClient, 0);
OSMetaClassDefineReservedUnused(IOBDMediaBSDClient, 1);
OSMetaClassDefineReservedUnused(IOBDMediaBSDClient, 2);
OSMetaClassDefineReservedUnused(IOBDMediaBSDClient, 3);
OSMetaClassDefineReservedUnused(IOBDMediaBSDClient, 4);
OSMetaClassDefineReservedUnused(IOBDMediaBSDClient, 5);
OSMetaClassDefineReservedUnused(IOBDMediaBSDClient, 6);
OSMetaClassDefineReservedUnused(IOBDMediaBSDClient, 7);