Commit 8ccd224c authored by Sam Hocevar's avatar Sam Hocevar

 * fixes for the Qt plugin compilation under Debian

 * heavy butchering in the CSS and DVD ioctl code to put all architecture-
   dependent code in dvd_ioctl.c

 * added almost fully-functional /dev/dvd driver for MacOS X in
   extras/DVDioctl; to build it:

    % cd extras/DVDioctl
    % pbxbuild
    % kextload build/DVDioctl.kext # note: kextload has to be run as root

   be aware that the license for the DVDioctl kernel extension is
   not GPL but APSL, because I borrowed some code from the Darwin kernel.
parent a53dd0f3
......@@ -16,13 +16,14 @@ Here is a shortcut to copy-paste for a complete build:
make distclean 2>/dev/null ; ./configure --prefix=/usr --enable-gnome \
--enable-fb --with-glide --with-ggi --with-sdl --enable-esd \
--enable-alsa --enable-mga --enable-gtk --enable-qt && make
--enable-alsa --enable-mga --enable-gtk --enable-qt --enable-xvideo \
&& make
If you intend to debug stuff, you may want to disable optimizations:
make distclean 2>/dev/null ; ./configure --prefix=/usr --enable-gnome \
--enable-fb --with-glide --with-ggi --with-sdl --enable-esd \
--enable-alsa --enable-mga --enable-gtk --enable-qt \
--enable-alsa --enable-mga --enable-gtk --enable-qt --enable-xvideo \
--disable-optimizatons && make
......
......@@ -70,7 +70,7 @@ endif
# C headers directories
#
INCLUDE += @INCLUDE@
INCLUDE += -Iinclude -I/usr/local/include
INCLUDE += -Iinclude -Iextras -I/usr/local/include
#
# Libraries
......@@ -636,7 +636,7 @@ $(PLUGIN_GLIDE): %.o: %.c
$(PLUGIN_QT): %.o: Makefile.dep
$(PLUGIN_QT): %.o: .dep/%.dpp
$(PLUGIN_QT): %.o: %.moc
$(CC) $(CFLAGS) $(PCFLAGS) -I${QTDIR}/include -c -o $@ $(<:%.moc=%.cpp)
$(CC) $(CFLAGS) $(PCFLAGS) -I/usr/include/qt -I${QTDIR}/include -c -o $@ $(<:%.moc=%.cpp)
$(PLUGIN_QT:%.o=%.moc): %.moc: %.cpp
moc -i $< -o $@
......
/*****************************************************************************
* DVDioctl.cpp: Linux-like DVD driver for Darwin and MacOS X
*****************************************************************************
* Copyright (C) 1998-2000 Apple Computer, Inc. All rights reserved.
* Copyright (C) 2001 VideoLAN
* $Id: DVDioctl.cpp,v 1.1 2001/04/02 23:30:41 sam Exp $
*
* Authors: Samuel Hocevar <sam@zoy.org>
*
* The contents of this file constitute Original Code as defined in and
* are subject to the Apple Public Source License Version 1.1 (the
* "License"). You may not use this file except in compliance with the
* License. Please obtain a copy of the License at
* http://www.apple.com/publicsource and read it before using this file.
*
* This Original Code and all software distributed under the License are
* distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
* License for the specific language governing rights and limitations
* under the License.
*****************************************************************************/
/*****************************************************************************
* TODO:
* - add a timeout to waitForService() so that we don't wait forever
* - find a way to prevent user from ejecting DVD using the GUI while
* it is still in use
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
extern "C"
{
#include <sys/param.h>
#include <sys/conf.h>
#include <sys/syslog.h>
#include <sys/systm.h>
#include <sys/ioccom.h>
#include <sys/fcntl.h>
#include <sys/buf.h>
#include <sys/uio.h>
#include <miscfs/devfs/devfs.h>
#include <mach/mach_types.h>
}
#include <IOKit/IOLib.h>
#include <IOKit/IOService.h>
#include <IOKit/storage/IODVDMedia.h>
#include <IOKit/storage/IOMedia.h>
#include "DVDioctl.h"
/*****************************************************************************
* Driver class
*****************************************************************************/
class DVDioctl : public IOService
{
OSDeclareDefaultStructors( DVDioctl )
public:
virtual bool init ( OSDictionary *dictionary = 0 );
virtual IOService *probe ( IOService *provider, SInt32 *score );
virtual bool start ( IOService *provider );
virtual void stop ( IOService *provider );
virtual void free ( void );
};
#define super IOService
OSDefineMetaClassAndStructors( DVDioctl, IOService )
/*****************************************************************************
* Variable typedefs
*****************************************************************************/
typedef void * dkr_t;
typedef enum { DKRTYPE_BUF, DKRTYPE_DIO } dkrtype_t;
typedef struct dio { dev_t dev; struct uio * uio; } dio_t;
typedef struct buf buf_t;
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static int DVDClose ( dev_t, int, int, struct proc * );
static int DVDIoctl ( dev_t, u_long, caddr_t, int, struct proc * );
static int DVDOpen ( dev_t, int, int, struct proc * );
static int DVDSize ( dev_t );
static void DVDStrategy ( buf_t * );
static int DVDReadWrite( dkr_t, dkrtype_t );
static void DVDReadWriteCompletion( void *, void *, IOReturn, UInt64 );
static struct bdevsw device_functions =
{
DVDOpen, DVDClose, DVDStrategy, DVDIoctl, eno_dump, DVDSize, D_DISK
};
/*****************************************************************************
* Local variables
*****************************************************************************/
static DVDioctl * p_this = NULL;
static bool b_inuse;
static int i_major;
static void *p_node;
static IODVDMedia *p_dvd;
/*****************************************************************************
* DKR_GET_DEV: borrowed from IOMediaBSDClient.cpp
*****************************************************************************/
static inline dev_t DKR_GET_DEV(dkr_t dkr, dkrtype_t dkrtype)
{
return (dkrtype == DKRTYPE_BUF)
? ((buf_t *)dkr)->b_dev : ((dio_t *)dkr)->dev;
}
/*****************************************************************************
* DKR_GET_BYTE_COUNT: borrowed from IOMediaBSDClient.cpp
*****************************************************************************/
static inline UInt64 DKR_GET_BYTE_COUNT(dkr_t dkr, dkrtype_t dkrtype)
{
return (dkrtype == DKRTYPE_BUF)
? ((buf_t *)dkr)->b_bcount : ((dio_t *)dkr)->uio->uio_resid;
}
/*****************************************************************************
* DKR_GET_BYTE_START: borrowed from IOMediaBSDClient.cpp
*****************************************************************************/
static inline UInt64 DKR_GET_BYTE_START(dkr_t dkr, dkrtype_t dkrtype)
{
if (dkrtype == DKRTYPE_BUF)
{
buf_t * bp = (buf_t *)dkr;
return bp->b_blkno * p_dvd->getPreferredBlockSize();
}
return ((dio_t *)dkr)->uio->uio_offset;
}
/*****************************************************************************
* DKR_IS_READ: borrowed from IOMediaBSDClient.cpp
*****************************************************************************/
static inline bool DKR_IS_READ(dkr_t dkr, dkrtype_t dkrtype)
{
return (dkrtype == DKRTYPE_BUF)
? ((((buf_t *)dkr)->b_flags & B_READ) == B_READ)
: ((((dio_t *)dkr)->uio->uio_rw) == UIO_READ);
}
/*****************************************************************************
* DKR_IS_ASYNCHRONOUS: borrowed from IOMediaBSDClient.cpp
*****************************************************************************/
static inline bool DKR_IS_ASYNCHRONOUS(dkr_t dkr, dkrtype_t dkrtype)
{
return (dkrtype == DKRTYPE_BUF) ? true : false;
}
/*****************************************************************************
* DKR_IS_RAW: borrowed from IOMediaBSDClient.cpp
*****************************************************************************/
static inline bool DKR_IS_RAW(dkr_t dkr, dkrtype_t dkrtype)
{
return (dkrtype == DKRTYPE_BUF) ? false : true;
}
/*****************************************************************************
* DKR_SET_BYTE_COUNT: borrowed from IOMediaBSDClient.cpp
*****************************************************************************/
static inline void DKR_SET_BYTE_COUNT(dkr_t dkr, dkrtype_t dkrtype, UInt64 bcount)
{
if (dkrtype == DKRTYPE_BUF)
{
((buf_t *)dkr)->b_resid = ((buf_t *)dkr)->b_bcount - bcount;
}
else
{
((dio_t *)dkr)->uio->uio_resid -= bcount;
}
}
/*****************************************************************************
* DKR_RUN_COMPLETION: borrowed from IOMediaBSDClient.cpp
*****************************************************************************/
static inline void DKR_RUN_COMPLETION(dkr_t dkr, dkrtype_t dkrtype, IOReturn status)
{
if (dkrtype == DKRTYPE_BUF)
{
buf_t * bp = (buf_t *)dkr;
bp->b_error = p_this->errnoFromReturn(status);
bp->b_flags |= (status != kIOReturnSuccess) ? B_ERROR : 0;
biodone(bp);
}
}
/*****************************************************************************
* DKR_GET_BUFFER: borrowed from IOMediaBSDClient.cpp
*****************************************************************************/
static inline IOMemoryDescriptor * DKR_GET_BUFFER(dkr_t dkr, dkrtype_t dkrtype)
{
if (dkrtype == DKRTYPE_BUF)
{
buf_t * bp = (buf_t *)dkr;
if ( (bp->b_flags & B_VECTORLIST) )
{
assert(sizeof(IOPhysicalRange ) == sizeof(iovec ));
assert(sizeof(IOPhysicalRange::address) == sizeof(iovec::iov_base));
assert(sizeof(IOPhysicalRange::length ) == sizeof(iovec::iov_len ));
return IOMemoryDescriptor::withPhysicalRanges(
(IOPhysicalRange *) bp->b_vectorlist,
(UInt32) bp->b_vectorcount,
(bp->b_flags & B_READ) ? kIODirectionIn : kIODirectionOut,
true );
}
return IOMemoryDescriptor::withAddress(
(vm_address_t) bp->b_data,
(vm_size_t) bp->b_bcount,
(bp->b_flags & B_READ) ? kIODirectionIn : kIODirectionOut,
(bp->b_flags & B_PHYS) ? current_task() : kernel_task );
}
else
{
struct uio * uio = ((dio_t *)dkr)->uio;
assert(sizeof(IOVirtualRange ) == sizeof(iovec ));
assert(sizeof(IOVirtualRange::address) == sizeof(iovec::iov_base));
assert(sizeof(IOVirtualRange::length ) == sizeof(iovec::iov_len ));
return IOMemoryDescriptor::withRanges(
(IOVirtualRange *) uio->uio_iov,
(UInt32) uio->uio_iovcnt,
(uio->uio_rw == UIO_READ ) ? kIODirectionIn : kIODirectionOut,
(uio->uio_segflg != UIO_SYSSPACE) ? current_task() : kernel_task,
true );
}
}
/*****************************************************************************
* DVDioctl::init: initialize the driver structure
*****************************************************************************/
bool DVDioctl::init( OSDictionary *p_dict = 0 )
{
//IOLog( "DVD ioctl: initializing\n" );
p_this = this;
p_node = NULL;
p_dvd = NULL;
i_major = -1;
b_inuse = false;
bool res = super::init( p_dict );
return res;
}
/*****************************************************************************
* DVDioctl::probe: check whether the driver can be safely activated
*****************************************************************************/
IOService * DVDioctl::probe( IOService *provider, SInt32 *score )
{
//IOLog( "DVD ioctl: probing\n" );
IOService * res = super::probe( provider, score );
return res;
}
/*****************************************************************************
* DVDioctl::start: start the driver
*****************************************************************************/
bool DVDioctl::start( IOService *provider )
{
//IOLog( "DVD ioctl: starting\n" );
if( !super::start( provider ) )
{
return false;
}
//IOLog( "DVD ioctl: creating device\n" );
i_major = bdevsw_add( -1, &device_functions );
if( i_major == -1 )
{
//log(LOG_INFO, "DVD ioctl: failed to allocate a major number\n");
return false;
}
p_node = devfs_make_node ( makedev( i_major, 0 ), DEVFS_BLOCK,
UID_ROOT, GID_WHEEL, 0666, "dvd" );
if( p_node == NULL )
{
//log( LOG_INFO, "DVD ioctl: failed creating node\n" );
if( bdevsw_remove(i_major, &device_functions) == -1 )
{
//log( LOG_INFO, "DVD ioctl: bdevsw_remove failed\n" );
}
return false;
}
return true;
}
/*****************************************************************************
* DVDioctl::stop: stop the driver
*****************************************************************************/
void DVDioctl::stop( IOService *provider )
{
//IOLog( "DVD ioctl: removing device\n" );
if( p_node != NULL )
{
devfs_remove( p_node );
}
if( i_major != -1 )
{
if( bdevsw_remove(i_major, &device_functions) == -1 )
{
//log( LOG_INFO, "DVD ioctl: bdevsw_remove failed\n" );
}
}
//IOLog( "DVD ioctl: stopping\n" );
super::stop( provider );
}
/*****************************************************************************
* DVDioctl::free: free all resources allocated by the driver
*****************************************************************************/
void DVDioctl::free( void )
{
//IOLog( "DVD ioctl: freeing\n" );
super::free( );
}
#if 0
IOReturn DVDioctl::report( IODVDMedia *DVD, IOMemoryDescriptor *buffer, const DVDKeyClass keyClass, const UInt32 lba, const UInt8 agid, const DVDKeyFormat keyFormat )
{
IOLog( "DVD ioctl: reportkey\n" );
return DVD->getProvider()->reportKey( buffer, keyClass, lba, agid, keyFormat );
}
IOReturn DVDioctl::send( IODVDMedia *DVD, IOMemoryDescriptor *buffer, const DVDKeyClass keyClass, const UInt32 lba, const DVDKeyFormat keyFormat )
{
IOLog( "DVD ioctl: sendkey\n" );
return DVD->getProvider()->sendKey( buffer, keyClass, lba, keyFormat );
}
#endif
/* following functions are local */
/*****************************************************************************
* DVDOpen: look for an IODVDMedia object and open it
*****************************************************************************/
static int DVDOpen( dev_t dev, int flags, int devtype, struct proc * )
{
IOStorageAccess level;
int i_err;
/* Check that the device hasn't already been opened */
if( b_inuse )
{
//log( LOG_INFO, "DVD ioctl: already opened\n" );
return EBUSY;
}
else
{
b_inuse = true;
}
IOService * p_root = IOService::getServiceRoot();
if( p_root == NULL )
{
//log( LOG_INFO, "DVD ioctl: couldn't find root\n" );
b_inuse = false;
return ENXIO;
}
OSDictionary * p_dict = p_root->serviceMatching( kIODVDMediaClass );
if( p_dict == NULL )
{
//log( LOG_INFO, "DVD ioctl: couldn't find dictionary\n" );
b_inuse = false;
return ENXIO;
}
p_dvd = OSDynamicCast( IODVDMedia, p_root->waitForService( p_dict ) );
if( p_dvd == NULL )
{
//log( LOG_INFO, "DVD ioctl: couldn't find service\n" );
b_inuse = false;
return ENXIO;
}
//log( LOG_INFO, "DVD ioctl: found DVD\n" );
level = (flags & FWRITE) ? kIOStorageAccessReaderWriter
: kIOStorageAccessReader;
if( p_dvd->open( p_this, 0, level) )
{
log( LOG_INFO, "DVD ioctl: IODVDMedia->open()\n" );
i_err = 0;
}
else
{
log( LOG_INFO, "DVD ioctl: IODVDMedia object busy\n" );
b_inuse = false;
i_err = EBUSY;
}
return i_err;
}
/*****************************************************************************
* DVDClose: close the IODVDMedia object
*****************************************************************************/
static int DVDClose( dev_t dev, int flags, int devtype, struct proc * )
{
/* Release the device */
p_dvd->close( p_this );
b_inuse = false;
log( LOG_INFO, "DVD ioctl: IODVDMedia->close()\n" );
return 0;
}
/*****************************************************************************
* DVDSize: return the device size
*****************************************************************************/
static int DVDSize( dev_t dev )
{
return p_dvd->getPreferredBlockSize();
}
/*****************************************************************************
* DVDStrategy: perform read or write operations
*****************************************************************************/
static void DVDStrategy( buf_t * bp )
{
DVDReadWrite(bp, DKRTYPE_BUF);
return;
}
/*****************************************************************************
* DVDIoctl: issue an ioctl on the device
*****************************************************************************/
static int DVDIoctl( dev_t dev, u_long cmd, caddr_t addr, int flags,
struct proc *p )
{
switch( cmd )
{
case IODVD_READ_STRUCTURE:
//log( LOG_INFO, "DVD ioctl: IODVD_READ_STRUCTURE\n" );
return 0;
case IODVD_SEND_KEY:
//log( LOG_INFO, "DVD ioctl: IODVD_SEND_KEY\n" );
return 0;
case IODVD_REPORT_KEY:
//log( LOG_INFO, "DVD ioctl: IODVD_REPORT_KEY\n" );
return 0;
default:
//log( LOG_INFO, "DVD ioctl: unknown ioctl\n" );
return EINVAL;
}
}
/*****************************************************************************
* DVDReadWrite: borrowed from IOMediaBSDClient.cpp
*****************************************************************************/
static int DVDReadWrite(dkr_t dkr, dkrtype_t dkrtype)
{
IOMemoryDescriptor * buffer;
register UInt64 byteCount;
register UInt64 byteStart;
UInt64 mediaSize;
IOReturn status;
byteCount = DKR_GET_BYTE_COUNT(dkr, dkrtype);
byteStart = DKR_GET_BYTE_START(dkr, dkrtype);
mediaSize = p_dvd->getSize();
if ( byteStart >= mediaSize )
{
status = DKR_IS_READ(dkr,dkrtype) ? kIOReturnSuccess : kIOReturnIOError; goto dkreadwriteErr;
}
if ( DKR_IS_RAW(dkr, dkrtype) )
{
UInt64 mediaBlockSize = p_dvd->getPreferredBlockSize();
if ( (byteStart % mediaBlockSize) || (byteCount % mediaBlockSize) )
{
status = kIOReturnNotAligned;
goto dkreadwriteErr;
}
}
buffer = DKR_GET_BUFFER(dkr, dkrtype);
if ( buffer == 0 )
{
status = kIOReturnNoMemory;
goto dkreadwriteErr;
}
if ( byteCount > mediaSize - byteStart )
{
IOMemoryDescriptor * originalBuffer = buffer;
buffer = IOMemoryDescriptor::withSubRange( originalBuffer, 0,
mediaSize - byteStart, originalBuffer->getDirection() );
originalBuffer->release();
if ( buffer == 0 )
{
status = kIOReturnNoMemory;
goto dkreadwriteErr;
}
}
if ( DKR_IS_ASYNCHRONOUS(dkr, dkrtype) )
{
IOStorageCompletion completion;
completion.target = dkr;
completion.action = DVDReadWriteCompletion;
completion.parameter = (void *) dkrtype;
if ( DKR_IS_READ(dkr, dkrtype) )
{
p_dvd->read( p_this, byteStart, buffer, completion );
}
else
{
p_dvd->write( p_this, byteStart, buffer, completion );
}
status = kIOReturnSuccess;
}
else
{
if ( DKR_IS_READ(dkr, dkrtype) )
{
status = p_dvd->IOStorage::read( p_this, byteStart,
buffer, &byteCount );
}
else
{
status = p_dvd->IOStorage::write( p_this, byteStart,
buffer, &byteCount );
}
DVDReadWriteCompletion(dkr, (void *)dkrtype, status, byteCount);
}
buffer->release();
return p_this->errnoFromReturn(status);
dkreadwriteErr:
DVDReadWriteCompletion(dkr, (void *)dkrtype, status, 0);
return p_this->errnoFromReturn(status);
}
/*****************************************************************************
* DVDReadWriteCompletion: borrowed from IOMediaBSDClient.cpp