]> git.sesse.net Git - vlc/blobdiff - extras/MacOSX_dvdioctl/DVDioctl.cpp
* ./configure.in: fixed linking of the ipv4 plugin.
[vlc] / extras / MacOSX_dvdioctl / DVDioctl.cpp
index 9eb0aed236357aa675fc27914100f57b7e6423e4..c72769cb02c3644ad47f31b719f132403d51308d 100644 (file)
@@ -3,9 +3,10 @@
  *****************************************************************************
  * 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 $
+ * $Id: DVDioctl.cpp,v 1.7 2001/06/25 11:34:08 sam Exp $
  *
  * Authors: Samuel Hocevar <sam@zoy.org>
+ *          Eugenio Jarosiewicz <ej0@cise.ufl.edu>
  *
  * The contents of this file constitute Original Code as defined in and
  * are subject to the Apple Public Source License Version 1.1 (the
@@ -49,8 +50,13 @@ extern "C"
 
 #include <IOKit/IOLib.h>
 #include <IOKit/IOService.h>
-#include <IOKit/storage/IODVDMedia.h>
 #include <IOKit/storage/IOMedia.h>
+#include <IOKit/storage/IODVDMedia.h>
+#include <IOKit/storage/IODVDBlockStorageDriver.h>
+
+#undef CONTROL //some include above #defines this and breaks the next include...grr.
+#include <IOKit/scsi-commands/IOSCSIMultimediaCommandsDevice.h>
+#include <IOKit/scsi-commands/IODVDServices.h>
 
 #include "DVDioctl.h"
 
@@ -76,25 +82,25 @@ 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;
+typedef enum       { DKRTYPE_BUF, DKRTYPE_DIO }      dkrtype_t;
+typedef struct dio { dev_t dev; struct uio * uio; }  dio_t;
+typedef struct buf                                   buf_t;
+typedef void *                                       dkr_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 int  DVDClose        ( dev_t, int, int, struct proc * );
+static int  DVDBlockIoctl   ( 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
+    DVDOpen, DVDClose, DVDStrategy, DVDBlockIoctl, eno_dump, DVDSize, D_DISK
 };
 
 /*****************************************************************************
@@ -106,6 +112,9 @@ static bool b_inuse;
 static int i_major;
 static void *p_node;
 static IODVDMedia *p_dvd;
+static IODVDBlockStorageDriver *p_drive;
+static IODVDServices *p_services;
+static IOSCSIMultimediaCommandsDevice *p_scsi_mcd;
 
 /*****************************************************************************
  * DKR_GET_DEV: borrowed from IOMediaBSDClient.cpp
@@ -249,6 +258,9 @@ bool DVDioctl::init( OSDictionary *p_dict = 0 )
 
     p_node  = NULL;
     p_dvd   = NULL;
+    p_drive = NULL;
+    p_services = NULL;
+    p_scsi_mcd = NULL;
     i_major = -1;
     b_inuse = false;
 
@@ -341,20 +353,6 @@ void DVDioctl::free( void )
     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 */
 
 /*****************************************************************************
@@ -363,7 +361,6 @@ IOReturn DVDioctl::send( IODVDMedia *DVD, IOMemoryDescriptor *buffer, const DVDK
 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 )
@@ -408,19 +405,22 @@ static int DVDOpen( dev_t dev, int flags, int devtype, struct proc * )
     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
+    if( ! p_dvd->open( p_this, 0, level) )
     {
         log( LOG_INFO, "DVD ioctl: IODVDMedia object busy\n" );
         b_inuse = false;
-        i_err = EBUSY;
+        return EBUSY;
     }
 
-    return i_err;
+    p_drive = p_dvd->getProvider();
+
+    p_services = OSDynamicCast( IODVDServices, p_drive->getProvider() );
+
+    p_scsi_mcd = OSDynamicCast( IOSCSIMultimediaCommandsDevice, p_services->getProvider() );
+
+    log( LOG_INFO, "DVD ioctl: IODVDMedia->open()\n" );
+
+    return 0;
 }
 
 /*****************************************************************************
@@ -430,6 +430,11 @@ static int DVDClose( dev_t dev, int flags, int devtype, struct proc * )
 {
     /* Release the device */
     p_dvd->close( p_this );
+
+    p_dvd   = NULL;
+    p_drive = NULL;
+    p_services = NULL;
+    p_scsi_mcd = NULL;
     b_inuse = false;
 
     log( LOG_INFO, "DVD ioctl: IODVDMedia->close()\n" );
@@ -455,29 +460,113 @@ static void DVDStrategy( buf_t * bp )
 }
 
 /*****************************************************************************
- * DVDIoctl: issue an ioctl on the device
+ * DVDBlockIoctl: issue an ioctl on the block device
  *****************************************************************************/
-static int DVDIoctl( dev_t dev, u_long cmd, caddr_t addr, int flags,
-                     struct proc *p )
+static int DVDBlockIoctl( dev_t dev, u_long cmd, caddr_t addr, int flags,
+                          struct proc *p )
 {
+#define p_data (((dvdioctl_data_t *)addr))
+    IOReturn            i_ret = EINVAL;
+
+    /* Only needed for IODVD_READ_STRUCTURE */
+    SCSITask           *p_request;
+    SCSIServiceResponse response;
+    
+    IOMemoryDescriptor *p_mem;
+
+    p_mem = IOMemoryDescriptor::withAddress( p_data->p_buffer,
+                                             p_data->i_size,
+                                             kIODirectionOutIn );
+
     switch( cmd )
     {
         case IODVD_READ_STRUCTURE:
-            //log( LOG_INFO, "DVD ioctl: IODVD_READ_STRUCTURE\n" );
-            return 0;
+
+            log( LOG_INFO, "DVD ioctl: IODVD_READ_STRUCTURE\n" );
+
+            i_ret = kIOReturnUnsupported;
+            response = kSCSIServiceResponse_SERVICE_DELIVERY_OR_TARGET_FAILURE;
+
+/* HACK! - Make GetSCSITask and friends in /System/Library/Frameworks/Kernel.framework/Versions/A/Headers/IOKit/scsi-commands/IOSCSIPrimaryCommandsDevice.h public by moving public: from line 96 to line 79 (as root).  It's only a compile time check - not a link time thing, so it should be ok. */
+            p_request = p_scsi_mcd->GetSCSITask( );
+
+            if ( p_scsi_mcd->READ_DVD_STRUCTURE ( p_request,
+                                                  p_mem,
+                                                  p_data->i_lba,
+                                                  0,//?LAYER_NUMBER
+                                                  p_data->i_keyformat,
+                                                  p_mem->getLength(),//p_data->i_size ?
+                                                  p_data->i_agid,
+                                                  0x00 //?CONTROL
+                                                   ) == true )
+                {
+                    /* The command was successfully built, now send it */
+                    response = p_scsi_mcd->SendCommand( p_request );
+                }
+                else
+                {
+#if 0
+                    exit -1;
+                    PANIC_NOW(( "IOSCSIMultimediaCommandsDevice:: "
+                                "readDVDstruct malformed command" ));
+#endif
+                }
+
+                if( ( response == kSCSIServiceResponse_TASK_COMPLETE ) &&
+                    ( p_request->GetTaskStatus ( ) == kSCSITaskStatus_GOOD ) )
+                {
+                    i_ret = kIOReturnSuccess;
+                }
+                else
+                {
+                    i_ret = kIOReturnError;
+                }
+
+                p_scsi_mcd->ReleaseSCSITask( p_request );
+                        
+            }
+
+            break;
 
         case IODVD_SEND_KEY:
-            //log( LOG_INFO, "DVD ioctl: IODVD_SEND_KEY\n" );
-            return 0;
+
+            log( LOG_INFO, "DVD ioctl: send key to `%s', "
+                 "buf %d, class %d, lba N/A, agid %d, format %d\n",
+                 p_drive->getDeviceTypeName(),
+                 (int)p_data->p_buffer, p_data->i_keyclass,
+                 p_data->i_agid, p_data->i_keyformat );
+
+            i_ret = p_drive->sendKey( p_mem, (DVDKeyClass)p_data->i_keyclass,
+                                      p_data->i_agid,
+                                      (DVDKeyFormat)p_data->i_keyformat );
+
+            break;
 
         case IODVD_REPORT_KEY:
-            //log( LOG_INFO, "DVD ioctl: IODVD_REPORT_KEY\n" );
-            return 0;
+
+            log( LOG_INFO, "DVD ioctl: report key from `%s', "
+                 "buf %d, class %d, lba %d, agid %d, format %d\n",
+                 p_drive->getDeviceTypeName(),
+                 (int)p_data->p_buffer, p_data->i_keyclass, p_data->i_lba,
+                 p_data->i_agid, p_data->i_keyformat );
+
+            i_ret = p_drive->reportKey( p_mem, (DVDKeyClass)p_data->i_keyclass,
+                                        p_data->i_lba, p_data->i_agid,
+                                        (DVDKeyFormat)p_data->i_keyformat );
+
+            break;
 
         default:
-            //log( LOG_INFO, "DVD ioctl: unknown ioctl\n" );
-            return EINVAL;
+
+            log( LOG_INFO, "DVD ioctl: unknown ioctl\n" );
+
+            i_ret = EINVAL;
+
+            break;
     }
+
+    return i_ret;
+#undef p_data
 }
 
 /*****************************************************************************
@@ -591,7 +680,7 @@ static void DVDReadWriteCompletion( void *   target,
 
     if ( status != kIOReturnSuccess )
     {
-        IOLog( "%s: %s.\n", /*p_this->name*/ "DVD ioctl",
+        IOLog( "DVD ioctl: %s (is the disc authenticated ?)\n",
                p_this->stringFromReturn(status) );
     }