]> git.sesse.net Git - vlc/blobdiff - extras/libdvdcss/ioctl.c
* Added vlc-arts to the debian package generation.
[vlc] / extras / libdvdcss / ioctl.c
index 70370cd297b91f03fd6cb679d9f792a5246a3c53..7b18d172bf19225dd178d3c5fa8dddb096f3843f 100644 (file)
@@ -2,11 +2,14 @@
  * ioctl.c: DVD ioctl replacement function
  *****************************************************************************
  * Copyright (C) 1999-2001 VideoLAN
- * $Id: ioctl.c,v 1.6 2001/08/06 13:28:00 sam Exp $
+ * $Id: ioctl.c,v 1.16 2001/12/11 14:43:38 sam Exp $
  *
  * Authors: Markus Kuespert <ltlBeBoy@beosmail.com>
  *          Samuel Hocevar <sam@zoy.org>
  *          Jon Lech Johansen <jon-vl@nanocrew.net>
+ *          Håkan Hjort <d95hjort@dtek.chalmers.se>
+ *          Eugenio Jarosiewicz <ej0@cise.ufl.edu>
+ *          David Siebörger <drs-videolan@rucus.ru.ac.za>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -28,6 +31,8 @@
  *****************************************************************************/
 #include "defs.h"
 
+#include <stdio.h>
+
 #include <string.h>                                    /* memcpy(), memset() */
 #include <sys/types.h>
 
 #ifdef DVD_STRUCT_IN_LINUX_CDROM_H
 #   include <linux/cdrom.h>
 #endif
+#ifdef DVD_STRUCT_IN_DVD_H
+#   include <dvd.h>
+#endif
+#ifdef DVD_STRUCT_IN_BSDI_DVDIOCTL_DVD_H
+#   include <BSDI_dvdioctl/dvd.h>
+#endif
 #ifdef SYS_BEOS
 #   include <malloc.h>
 #   include <scsi.h>
 #endif
+#ifdef HPUX_SCTL_IO
+#   include <sys/scsi.h>
+#endif
+#ifdef SOLARIS_USCSI
+#   include <unistd.h>
+#   include <stropts.h>
+#   include <sys/scsi/scsi_types.h>
+#   include <sys/scsi/impl/uscsi.h>
+#endif
 
-#include "config.h"
 #include "common.h"
 
 #ifdef SYS_DARWIN
-#   include "DVDioctl/DVDioctl.h"
+#   include <IOKit/storage/IODVDMediaBSDClient.h>
+/* #   include "DVDioctl/DVDioctl.h" */
 #endif
 
 #include "ioctl.h"
 
+
 /*****************************************************************************
  * Local prototypes, BeOS specific
  *****************************************************************************/
 static void BeInitRDC ( raw_device_command *, int );
 #endif
 
+/*****************************************************************************
+ * Local prototypes, HP-UX specific
+ *****************************************************************************/
+#if defined( HPUX_SCTL_IO )
+static void HPUXInitSCTL ( struct sctl_io *sctl_io, int i_type );
+#endif
+
+/*****************************************************************************
+ * Local prototypes, Solaris specific
+ *****************************************************************************/
+#if defined( SOLARIS_USCSI )
+static void SolarisInitUSCSI( struct uscsi_cmd *p_sc, int i_type );
+#endif
+
 /*****************************************************************************
  * Local prototypes, win32 (aspi) specific
  *****************************************************************************/
@@ -84,7 +119,7 @@ int ioctl_ReadCopyright( int i_fd, int i_layer, int *pi_copyright )
 {
     int i_ret;
 
-#if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
+#if defined( HAVE_LINUX_DVD_STRUCT )
     dvd_struct dvd;
 
     dvd.type = DVD_STRUCT_COPYRIGHT;
@@ -114,10 +149,49 @@ int ioctl_ReadCopyright( int i_fd, int i_layer, int *pi_copyright )
 
     *pi_copyright = p_buffer[ 4 ];
 
+#elif defined( HPUX_SCTL_IO )
+    INIT_SCTL_IO( GPCMD_READ_DVD_STRUCTURE, 8 );
+
+    sctl_io.cdb[ 6 ] = i_layer;
+    sctl_io.cdb[ 7 ] = DVD_STRUCT_COPYRIGHT;
+
+    i_ret = ioctl( i_fd, SIOC_IO, &sctl_io );
+
+    *pi_copyright = p_buffer[ 4 ];
+
+#elif defined( SOLARIS_USCSI )
+    INIT_USCSI( GPCMD_READ_DVD_STRUCTURE, 8 );
+    
+    rs_cdb.cdb_opaque[ 6 ] = i_layer;
+    rs_cdb.cdb_opaque[ 7 ] = DVD_STRUCT_COPYRIGHT;
+
+    i_ret = ioctl(i_fd, USCSICMD, &sc);
+
+    if( i_ret < 0 || sc.uscsi_status ) {
+        i_ret = -1;
+    }
+    
+    *pi_copyright = p_buffer[ 4 ];
+    /* s->copyright.rmi = p_buffer[ 5 ]; */
+
 #elif defined( SYS_DARWIN )
-    *pi_copyright = 1;
+    dk_dvd_read_structure_t dvd;
+    DVDCopyrightInfo dvdcpi;
+    
+    memset(&dvd, 0, sizeof(dvd));
+    memset(&dvdcpi, 0, sizeof(dvdcpi));
 
-    i_ret = 0;
+    dvd.buffer = &dvdcpi;
+    dvd.bufferLength = sizeof(dvdcpi);
+    dvd.format = kDVDStructureFormatCopyrightInfo;
+    dvd.layer = i_layer;
+
+    /* dvdcpi.dataLength[0] = 0x00; */ /* dataLength[0] is already memset to 0 */
+    /* dvdcpi.dataLength[1] = 0x06; */
+    
+    i_ret = ioctl( i_fd, DKIOCDVDREADSTRUCTURE, &dvd );
+
+    *pi_copyright = dvdcpi.copyrightProtectionSystemType;
 
 #elif defined( WIN32 )
     if( WIN2K ) /* NT/Win2000/Whistler */
@@ -184,13 +258,13 @@ int ioctl_ReadCopyright( int i_fd, int i_layer, int *pi_copyright )
 }
 
 /*****************************************************************************
- * ioctl_ReadKey: get the disc key
+ * ioctl_ReadDiscKey: get the disc key
  *****************************************************************************/
-int ioctl_ReadKey( int i_fd, int *pi_agid, u8 *p_key )
+int ioctl_ReadDiscKey( int i_fd, int *pi_agid, u8 *p_key )
 {
     int i_ret;
 
-#if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
+#if defined( HAVE_LINUX_DVD_STRUCT )
     dvd_struct dvd;
 
     dvd.type = DVD_STRUCT_DISCKEY;
@@ -237,10 +311,56 @@ int ioctl_ReadKey( int i_fd, int *pi_agid, u8 *p_key )
 
     memcpy( p_key, p_buffer + 4, 2048 );
 
+#elif defined( HPUX_SCTL_IO )
+    INIT_SCTL_IO( GPCMD_READ_DVD_STRUCTURE, 2048 + 4 );
+
+    sctl_io.cdb[ 7 ]  = DVD_STRUCT_DISCKEY;
+    sctl_io.cdb[ 10 ] = *pi_agid << 6;
+    
+    i_ret = ioctl( i_fd, SIOC_IO, &sctl_io );
+
+    if( i_ret < 0 )
+    {
+        return i_ret;
+    }
+
+    memcpy( p_key, p_buffer + 4, 2048 );
+
+#elif defined( SOLARIS_USCSI )
+    INIT_USCSI( GPCMD_READ_DVD_STRUCTURE, 2048 + 4 );
+    
+    rs_cdb.cdb_opaque[ 7 ] = DVD_STRUCT_DISCKEY;
+    rs_cdb.cdb_opaque[ 10 ] = *pi_agid << 6;
+    
+    i_ret = ioctl( i_fd, USCSICMD, &sc );
+    
+    if( i_ret < 0 || sc.uscsi_status )
+    {
+        i_ret = -1;
+        return i_ret;
+    }
+
+    memcpy( p_key, p_buffer + 4, 2048 );
+
 #elif defined( SYS_DARWIN )
-    i_ret = 0;
+    dk_dvd_read_structure_t dvd;
+    DVDDiscKeyInfo dvddki;
+    
+    memset(&dvd, 0, sizeof(dvd));
+    memset(&dvddki, 0, sizeof(dvddki));
+
+    dvd.buffer = &dvddki;
+    dvd.bufferLength = sizeof(dvddki);
+    dvd.format = kDVDStructureFormatDiscKeyInfo;
+    dvd.grantID = *pi_agid;
+
+    /* 2048+2 ; maybe we should do bit shifts to value of (sizeof(dvddki)-2) */
+    dvddki.dataLength[0] = 0x04;
+    dvddki.dataLength[1] = 0x02;
 
-    memset( p_key, 0x00, 2048 );
+    i_ret = ioctl( i_fd, DKIOCDVDREADSTRUCTURE, &dvd );
+
+    memcpy( p_key, dvddki.discKeyStructures, sizeof(dvddki.discKeyStructures) );
 
 #elif defined( WIN32 )
     if( WIN2K ) /* NT/Win2000/Whistler */
@@ -291,6 +411,77 @@ int ioctl_ReadKey( int i_fd, int *pi_agid, u8 *p_key )
     return i_ret;
 }
 
+/*****************************************************************************
+ * ioctl_ReadTitleKey: get the title key
+ *****************************************************************************/
+int ioctl_ReadTitleKey( int i_fd, int *pi_agid, int i_pos, u8 *p_key )
+{
+    int i_ret;
+
+#if defined( HAVE_LINUX_DVD_STRUCT )
+    dvd_authinfo dvd_ai;
+
+    memset( &dvd_ai, 0, sizeof(dvd_ai) );
+    dvd_ai.type = DVD_LU_SEND_TITLE_KEY;
+    dvd_ai.lstk.agid = *pi_agid;
+    dvd_ai.lstk.lba = i_pos;
+
+    i_ret = ioctl( i_fd, DVD_AUTH, &dvd_ai );
+
+    if( i_ret < 0 )
+    {
+        return i_ret;
+    }
+
+    memcpy( p_key, dvd_ai.lstk.title_key, 5 );
+
+#elif defined( HAVE_BSD_DVD_STRUCT )
+    i_ret = -1;
+
+#elif defined( SYS_BEOS )
+    i_ret = -1;
+
+#elif defined( HPUX_SCTL_IO )
+    i_ret = -1;
+
+#elif defined( SOLARIS_USCSI )
+    i_ret = -1;
+
+#elif defined( SYS_DARWIN )
+    dk_dvd_report_key_t dvd;
+    DVDTitleKeyInfo dvdtki;
+    
+    memset(&dvd, 0, sizeof(dvd));
+    memset(&dvdtki, 0, sizeof(dvdtki));
+
+    dvd.buffer = &dvdtki;
+    dvd.bufferLength = sizeof(dvdtki);
+    dvd.format = kDVDKeyFormatTitleKey;
+    dvd.grantID = *pi_agid;
+    dvd.keyClass = kDVDKeyClassCSS_CPPM_CPRM; /* or this - this is memset 0x00 anyways */
+
+    /* dvdtki.dataLength[0] = 0x00; */ /* dataLength[0] is already memset to 0 */
+    dvdtki.dataLength[1] = 0x0a;
+    
+    /* What are DVDTitleKeyInfo.{CP_MOD,CGMS,CP_SEC,CPM} and do they need to be set? */
+
+    i_ret = ioctl( i_fd, DKIOCDVDREPORTKEY, &dvd );
+
+    memcpy( p_key, dvdtki.titleKeyValue, sizeof(dvdtki.titleKeyValue) );
+
+#elif defined( WIN32 )
+    i_ret = -1;
+
+#else
+
+    i_ret = -1;
+
+#endif
+
+    return i_ret;
+}
+
+
 /*****************************************************************************
  * ioctl_ReportAgid: get AGID from the drive
  *****************************************************************************/
@@ -298,7 +489,7 @@ int ioctl_ReportAgid( int i_fd, int *pi_agid )
 {
     int i_ret;
 
-#if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
+#if defined( HAVE_LINUX_DVD_STRUCT )
     dvd_authinfo auth_info;
 
     auth_info.type = DVD_LU_SEND_AGID;
@@ -327,17 +518,50 @@ int ioctl_ReportAgid( int i_fd, int *pi_agid )
 
     *pi_agid = p_buffer[ 7 ] >> 6;
 
-#elif defined( SYS_DARWIN )
-    INIT_DVDIOCTL( 8 );
+#elif defined( HPUX_SCTL_IO )
+    INIT_SCTL_IO( GPCMD_REPORT_KEY, 8 );
 
-    dvdioctl.i_keyformat = kCSSAGID;
-    dvdioctl.i_agid = *pi_agid;
-    dvdioctl.i_lba = 0;
+    sctl_io.cdb[ 10 ] = DVD_REPORT_AGID | (*pi_agid << 6);
 
-    i_ret = ioctl( i_fd, IODVD_REPORT_KEY, &dvdioctl );
+    i_ret = ioctl( i_fd, SIOC_IO, &sctl_io );
 
     *pi_agid = p_buffer[ 7 ] >> 6;
 
+#elif defined( SOLARIS_USCSI )
+    INIT_USCSI( GPCMD_REPORT_KEY, 8 );
+    
+    rs_cdb.cdb_opaque[ 10 ] = DVD_REPORT_AGID | (*pi_agid << 6);
+    
+    i_ret = ioctl( i_fd, USCSICMD, &sc );
+    
+    if( i_ret < 0 || sc.uscsi_status )
+    {
+        i_ret = -1;
+    }
+
+    *pi_agid = p_buffer[ 7 ] >> 6;
+    
+#elif defined( SYS_DARWIN )
+    dk_dvd_report_key_t dvd;
+    DVDAuthenticationGrantIDInfo dvdagid;
+    
+    memset(&dvd, 0, sizeof(dvd));
+    memset(&dvdagid, 0, sizeof(dvdagid));
+
+    dvd.buffer = &dvdagid;
+    dvd.bufferLength = sizeof(dvdagid);
+    dvd.format = kDVDKeyFormatAGID_CSS;
+    dvd.grantID = *pi_agid;
+    dvdagid.grantID = *pi_agid; /* do we need this? */
+    dvd.keyClass = kDVDKeyClassCSS_CPPM_CPRM; /* or this - this is memset 0x00 anyways */
+
+    /* dvdagid.dataLength[0] = 0x00; */ /* dataLength[0] is already memset to 0 */
+    /* dvdagid.dataLength[1] = 0x06; */
+
+    i_ret = ioctl( i_fd, DKIOCDVDREPORTKEY, &dvd );
+
+    *pi_agid = dvdagid.grantID;
+
 #elif defined( WIN32 )
     if( WIN2K ) /* NT/Win2000/Whistler */
     {
@@ -375,7 +599,7 @@ int ioctl_ReportChallenge( int i_fd, int *pi_agid, u8 *p_challenge )
 {
     int i_ret;
 
-#if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
+#if defined( HAVE_LINUX_DVD_STRUCT )
     dvd_authinfo auth_info;
 
     auth_info.type = DVD_LU_SEND_CHALLENGE;
@@ -404,17 +628,48 @@ int ioctl_ReportChallenge( int i_fd, int *pi_agid, u8 *p_challenge )
 
     memcpy( p_challenge, p_buffer + 4, 12 );
 
-#elif defined( SYS_DARWIN )
-    INIT_DVDIOCTL( 16 );
+#elif defined( HPUX_SCTL_IO )
+    INIT_SCTL_IO( GPCMD_REPORT_KEY, 16 );
 
-    dvdioctl.i_keyformat = kChallengeKey;
-    dvdioctl.i_agid = *pi_agid;
-    dvdioctl.i_lba = 0;
+    sctl_io.cdb[ 10 ] = DVD_REPORT_CHALLENGE | (*pi_agid << 6);
 
-    i_ret = ioctl( i_fd, IODVD_REPORT_KEY, &dvdioctl );
+    i_ret = ioctl( i_fd, SIOC_IO, &sctl_io );
 
     memcpy( p_challenge, p_buffer + 4, 12 );
 
+#elif defined( SOLARIS_USCSI )
+    INIT_USCSI( GPCMD_REPORT_KEY, 16 );
+    
+    rs_cdb.cdb_opaque[ 10 ] = DVD_REPORT_CHALLENGE | (*pi_agid << 6);
+    
+    i_ret = ioctl( i_fd, USCSICMD, &sc );
+    
+    if( i_ret < 0 || sc.uscsi_status )
+    {
+        i_ret = -1;
+    }
+
+    memcpy( p_challenge, p_buffer + 4, 12 );
+    
+#elif defined( SYS_DARWIN )
+    dk_dvd_report_key_t dvd;
+    DVDChallengeKeyInfo dvdcki;
+    
+    memset(&dvd, 0, sizeof(dvd));
+    memset(&dvdcki, 0, sizeof(dvdcki));
+
+    dvd.buffer = &dvdcki;
+    dvd.bufferLength = sizeof(dvdcki);
+    dvd.format = kDVDKeyFormatChallengeKey;
+    dvd.grantID = *pi_agid;
+
+    /* dvdcki.dataLength[0] = 0x00; */ /* dataLength[0] is already memset to 0 */
+    dvdcki.dataLength[1] = 0x0e;
+
+    i_ret = ioctl( i_fd, DKIOCDVDREPORTKEY, &dvd );
+
+    memcpy( p_challenge, dvdcki.challengeKeyValue, sizeof(dvdcki.challengeKeyValue) );
+
 #elif defined( WIN32 )
     if( WIN2K ) /* NT/Win2000/Whistler */
     {
@@ -465,7 +720,7 @@ int ioctl_ReportASF( int i_fd, int *pi_agid, int *pi_asf )
 {
     int i_ret;
 
-#if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
+#if defined( HAVE_LINUX_DVD_STRUCT )
     dvd_authinfo auth_info;
 
     auth_info.type = DVD_LU_SEND_ASF;
@@ -496,16 +751,48 @@ int ioctl_ReportASF( int i_fd, int *pi_agid, int *pi_asf )
 
     *pi_asf = p_buffer[ 7 ] & 1;
 
-#elif defined( SYS_DARWIN )
-    INIT_DVDIOCTL( 8 );
+#elif defined( HPUX_SCTL_IO )
+    INIT_SCTL_IO( GPCMD_REPORT_KEY, 8 );
+
+    sctl_io.cdb[ 10 ] = DVD_REPORT_ASF | (*pi_agid << 6);
+
+    i_ret = ioctl( i_fd, SIOC_IO, &sctl_io );
 
-    dvdioctl.i_keyformat = kASF;
-    dvdioctl.i_agid = *pi_agid;
-    dvdioctl.i_lba = 0;
+    *pi_asf = p_buffer[ 7 ] & 1;
 
-    i_ret = ioctl( i_fd, IODVD_REPORT_KEY, &dvdioctl );
+#elif defined( SOLARIS_USCSI )
+    INIT_USCSI( GPCMD_REPORT_KEY, 8 );
+    
+    rs_cdb.cdb_opaque[ 10 ] = DVD_REPORT_ASF | (*pi_agid << 6);
+    
+    i_ret = ioctl( i_fd, USCSICMD, &sc );
+    
+    if( i_ret < 0 || sc.uscsi_status )
+    {
+        i_ret = -1;
+    }
 
     *pi_asf = p_buffer[ 7 ] & 1;
+    
+#elif defined( SYS_DARWIN )
+    dk_dvd_report_key_t dvd;
+    DVDAuthenticationSuccessFlagInfo dvdasfi;
+    
+    memset(&dvd, 0, sizeof(dvd));
+    memset(&dvdasfi, 0, sizeof(dvdasfi));
+
+    dvd.buffer = &dvdasfi;
+    dvd.bufferLength = sizeof(dvdasfi);
+    dvd.format = kDVDKeyFormatASF;
+    dvd.grantID = *pi_agid;
+    dvdasfi.successFlag = *pi_asf;
+
+    /* dvdasfi.dataLength[0] = 0x00; */ /* dataLength[0] is already memset to 0 */
+    dvdasfi.dataLength[1] = 0x06;
+    
+    i_ret = ioctl( i_fd, DKIOCDVDREPORTKEY, &dvd );
+
+    *pi_asf = dvdasfi.successFlag;
 
 #elif defined( WIN32 )
     if( WIN2K ) /* NT/Win2000/Whistler */
@@ -559,7 +846,7 @@ int ioctl_ReportKey1( int i_fd, int *pi_agid, u8 *p_key )
 {
     int i_ret;
 
-#if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
+#if defined( HAVE_LINUX_DVD_STRUCT )
     dvd_authinfo auth_info;
 
     auth_info.type = DVD_LU_SEND_KEY1;
@@ -588,16 +875,48 @@ int ioctl_ReportKey1( int i_fd, int *pi_agid, u8 *p_key )
 
     memcpy( p_key, p_buffer + 4, 8 );
 
-#elif defined( SYS_DARWIN )
-    INIT_DVDIOCTL( 12 );
+#elif defined( HPUX_SCTL_IO )
+    INIT_SCTL_IO( GPCMD_REPORT_KEY, 12 );
 
-    dvdioctl.i_keyformat = kKey1;
-    dvdioctl.i_agid = *pi_agid;
+    sctl_io.cdb[ 10 ] = DVD_REPORT_KEY1 | (*pi_agid << 6);
 
-    i_ret = ioctl( i_fd, IODVD_SEND_KEY, &dvdioctl );
+    i_ret = ioctl( i_fd, SIOC_IO, &sctl_io );
 
     memcpy( p_key, p_buffer + 4, 8 );
 
+#elif defined( SOLARIS_USCSI )
+    INIT_USCSI( GPCMD_REPORT_KEY, 12 );
+    
+    rs_cdb.cdb_opaque[ 10 ] = DVD_REPORT_KEY1 | (*pi_agid << 6);
+    
+    i_ret = ioctl( i_fd, USCSICMD, &sc );
+    
+    if( i_ret < 0 || sc.uscsi_status )
+    {
+        i_ret = -1;
+    }
+
+    memcpy( p_key, p_buffer + 4, 8 );;
+    
+#elif defined( SYS_DARWIN )
+    dk_dvd_report_key_t dvd;
+    DVDKey1Info dvdk1i;
+    
+    memset(&dvd, 0, sizeof(dvd));
+    memset(&dvdk1i, 0, sizeof(dvdk1i));
+
+    dvd.buffer = &dvdk1i;
+    dvd.bufferLength = sizeof(dvdk1i);
+    dvd.format = kDVDKeyFormatKey1;
+    dvd.grantID = *pi_agid;
+    
+    /* dvdk1i.dataLength[0] = 0x00; */ /* dataLength[0] is already memset to 0 */
+    dvdk1i.dataLength[1] = 0x0a;
+
+    i_ret = ioctl( i_fd, DKIOCDVDREPORTKEY, &dvd );
+
+    memcpy( p_key, dvdk1i.key1Value, sizeof(dvdk1i.key1Value) );
+
 #elif defined( WIN32 )
     if( WIN2K ) /* NT/Win2000/Whistler */
     {
@@ -643,7 +962,7 @@ int ioctl_InvalidateAgid( int i_fd, int *pi_agid )
 {
     int i_ret;
 
-#if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
+#if defined( HAVE_LINUX_DVD_STRUCT )
     dvd_authinfo auth_info;
 
     auth_info.type = DVD_INVALIDATE_AGID;
@@ -670,13 +989,44 @@ int ioctl_InvalidateAgid( int i_fd, int *pi_agid )
 
     i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
 
+#elif defined( HPUX_SCTL_IO )
+    INIT_SCTL_IO( GPCMD_REPORT_KEY, 0 );
+
+    sctl_io.cdb[ 10 ] = DVD_INVALIDATE_AGID | (*pi_agid << 6);
+
+    i_ret = ioctl( i_fd, SIOC_IO, &sctl_io );
+
+#elif defined( SOLARIS_USCSI )
+    INIT_USCSI( GPCMD_REPORT_KEY, 0 );
+    
+    rs_cdb.cdb_opaque[ 10 ] = DVD_INVALIDATE_AGID | (*pi_agid << 6);
+    
+    i_ret = ioctl( i_fd, USCSICMD, &sc );
+    
+    if( i_ret < 0 || sc.uscsi_status )
+    {
+        i_ret = -1;
+    }
+
 #elif defined( SYS_DARWIN )
-    INIT_DVDIOCTL( 0 );
+    dk_dvd_send_key_t dvd;
+    DVDAuthenticationGrantIDInfo dvdagid;
+    
+    memset(&dvd, 0, sizeof(dvd));
+    memset(&dvdagid, 0, sizeof(dvdagid));
+
+    dvd.buffer = &dvdagid;
+    dvd.bufferLength = sizeof(dvdagid);
+    dvd.format = kDVDKeyFormatAGID_Invalidate;
+    dvd.grantID = *pi_agid;
+    dvdagid.grantID = *pi_agid; /* we need this? */
+    
+    /* dvdagid.dataLength[0] = 0x00; */ /* dataLength[0] is already memset to 0 */
+    /* dvdagid.dataLength[1] = 0x06; */
 
-    dvdioctl.i_keyformat = kInvalidateAGID;
-    dvdioctl.i_agid = *pi_agid;
+    i_ret = ioctl( i_fd, DKIOCDVDSENDKEY, &dvd );
 
-    i_ret = ioctl( i_fd, IODVD_SEND_KEY, &dvdioctl );
+    *pi_agid = dvdagid.grantID;
 
 #elif defined( WIN32 )
     if( WIN2K ) /* NT/Win2000/Whistler */
@@ -716,7 +1066,9 @@ int ioctl_InvalidateAgid( int i_fd, int *pi_agid )
  *****************************************************************************/
 int ioctl_SendChallenge( int i_fd, int *pi_agid, u8 *p_challenge )
 {
-#if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
+    int i_ret;
+
+#if defined( HAVE_LINUX_DVD_STRUCT )
     dvd_authinfo auth_info;
 
     auth_info.type = DVD_HOST_SEND_CHALLENGE;
@@ -746,16 +1098,49 @@ int ioctl_SendChallenge( int i_fd, int *pi_agid, u8 *p_challenge )
 
     return ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
 
-#elif defined( SYS_DARWIN )
-    INIT_DVDIOCTL( 16 );
+#elif defined( HPUX_SCTL_IO )
+    INIT_SCTL_IO( GPCMD_SEND_KEY, 16 );
 
-    dvdioctl.i_keyformat = kChallengeKey;
-    dvdioctl.i_agid = *pi_agid;
+    sctl_io.cdb[ 10 ] = DVD_SEND_CHALLENGE | (*pi_agid << 6);
 
     p_buffer[ 1 ] = 0xe;
     memcpy( p_buffer + 4, p_challenge, 12 );
 
-    return ioctl( i_fd, IODVD_SEND_KEY, &dvdioctl );
+    return ioctl( i_fd, SIOC_IO, &sctl_io );
+
+#elif defined( SOLARIS_USCSI )
+    INIT_USCSI( GPCMD_SEND_KEY, 16 );
+    
+    rs_cdb.cdb_opaque[ 10 ] = DVD_SEND_CHALLENGE | (*pi_agid << 6);
+    
+    p_buffer[ 1 ] = 0xe;
+    memcpy( p_buffer + 4, p_challenge, 12 );
+    
+    if( ioctl( i_fd, USCSICMD, &sc ) < 0 || sc.uscsi_status )
+    {
+        return -1;
+    }
+
+    return 0;
+    
+#elif defined( SYS_DARWIN )
+    dk_dvd_send_key_t dvd;
+    DVDChallengeKeyInfo dvdcki;
+    
+    memset(&dvd, 0, sizeof(dvd));
+    memset(&dvdcki, 0, sizeof(dvdcki));
+
+    dvd.buffer = &dvdcki;
+    dvd.bufferLength = sizeof(dvdcki);
+    dvd.format = kDVDKeyFormatChallengeKey;
+    dvd.grantID = *pi_agid;
+
+    /* dvdcki.dataLength[0] = 0x00; */ /* dataLength[0] is already memset to 0 */
+    dvdcki.dataLength[1] = 0x0e;
+
+    memcpy( dvdcki.challengeKeyValue, p_challenge,  sizeof(dvdcki.challengeKeyValue) );
+
+    i_ret = ioctl( i_fd, DKIOCDVDSENDKEY, &dvd );
 
 #elif defined( WIN32 )
     if( WIN2K ) /* NT/Win2000/Whistler */
@@ -793,6 +1178,7 @@ int ioctl_SendChallenge( int i_fd, int *pi_agid, u8 *p_challenge )
     return -1;
 
 #endif
+    return i_ret;
 }
 
 /*****************************************************************************
@@ -800,7 +1186,9 @@ int ioctl_SendChallenge( int i_fd, int *pi_agid, u8 *p_challenge )
  *****************************************************************************/
 int ioctl_SendKey2( int i_fd, int *pi_agid, u8 *p_key )
 {
-#if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
+    int i_ret;
+
+#if defined( HAVE_LINUX_DVD_STRUCT )
     dvd_authinfo auth_info;
 
     auth_info.type = DVD_HOST_SEND_KEY2;
@@ -830,6 +1218,50 @@ int ioctl_SendKey2( int i_fd, int *pi_agid, u8 *p_key )
 
     return ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
 
+#elif defined( HPUX_SCTL_IO )
+    INIT_SCTL_IO( GPCMD_SEND_KEY, 12 );
+
+    sctl_io.cdb[ 10 ] = DVD_SEND_KEY2 | (*pi_agid << 6);
+
+    p_buffer[ 1 ] = 0xa;
+    memcpy( p_buffer + 4, p_key, 8 );
+
+    return ioctl( i_fd, SIOC_IO, &sctl_io );
+
+#elif defined( SOLARIS_USCSI )
+    INIT_USCSI( GPCMD_SEND_KEY, 12 );
+    
+    rs_cdb.cdb_opaque[ 10 ] = DVD_SEND_KEY2 | (*pi_agid << 6);
+    
+    p_buffer[ 1 ] = 0xa;
+    memcpy( p_buffer + 4, p_key, 8 );
+    
+    if( ioctl( i_fd, USCSICMD, &sc ) < 0 || sc.uscsi_status )
+    {
+        return -1;
+    }
+
+    return 0;
+    
+#elif defined( SYS_DARWIN )
+    dk_dvd_send_key_t dvd;
+    DVDKey2Info dvdk2i;
+    
+    memset(&dvd, 0, sizeof(dvd));
+    memset(&dvdk2i, 0, sizeof(dvdk2i));
+
+    dvd.buffer = &dvdk2i;
+    dvd.bufferLength = sizeof(dvdk2i);
+    dvd.format = kDVDKeyFormatKey2;
+    dvd.grantID = *pi_agid;
+
+    /* dvdk2i.dataLength[0] = 0x00; */ /*dataLength[0] is already memset to 0 */
+    dvdk2i.dataLength[1] = 0x0a;
+    
+    memcpy( dvdk2i.key2Value, p_key, sizeof(dvdk2i.key2Value) );
+
+    i_ret = ioctl( i_fd, DKIOCDVDSENDKEY, &dvd );
+
 #elif defined( WIN32 )
     if( WIN2K ) /* NT/Win2000/Whistler */
     {
@@ -861,22 +1293,12 @@ int ioctl_SendKey2( int i_fd, int *pi_agid, u8 *p_key )
         return WinSendSSC( i_fd, &ssc );
     }
 
-#elif defined( SYS_DARWIN )
-    INIT_DVDIOCTL( 12 );
-
-    dvdioctl.i_keyformat = kKey2;
-    dvdioctl.i_agid = *pi_agid;
-
-    p_buffer[ 1 ] = 0xa;
-    memcpy( p_buffer + 4, p_key, 8 );
-
-    return ioctl( i_fd, IODVD_SEND_KEY, &dvdioctl );
-
 #else
     /* DVD ioctls unavailable - do as if the ioctl failed */
     return -1;
 
 #endif
+    return i_ret;
 }
 
 /* Local prototypes */
@@ -917,6 +1339,76 @@ static void BeInitRDC( raw_device_command *p_rdc, int i_type )
 }
 #endif
 
+#if defined( HPUX_SCTL_IO )
+/*****************************************************************************
+ * HPUXInitSCTL: initialize a sctl_io structure for the HP-UX kernel
+ *****************************************************************************
+ * This function initializes a HP-UX command structure for future
+ * use, either a read command or a write command.
+ *****************************************************************************/
+static void HPUXInitSCTL( struct sctl_io *sctl_io, int i_type )
+{
+    memset( sctl_io->data, 0, sctl_io->data_length );
+
+    switch( i_type )
+    {
+        case GPCMD_SEND_KEY:
+            /* leave the flags to 0 */
+            break;
+
+        case GPCMD_READ_DVD_STRUCTURE:
+        case GPCMD_REPORT_KEY:
+            sctl_io->flags = SCTL_READ;
+            break;
+    }
+
+    sctl_io->cdb[ 0 ]        = i_type;
+
+    sctl_io->cdb[ 8 ]        = (sctl_io->data_length >> 8) & 0xff;
+    sctl_io->cdb[ 9 ]        =  sctl_io->data_length       & 0xff;
+    sctl_io->cdb_length      = 12;
+
+    sctl_io->max_msecs       = 1000000;
+}
+#endif
+
+#if defined( SOLARIS_USCSI )
+/*****************************************************************************
+ * SolarisInitUSCSI: initialize a USCSICMD structure for the Solaris kernel
+ *****************************************************************************
+ * This function initializes a Solaris userspace scsi command structure for 
+ * future use, either a read command or a write command.
+ *****************************************************************************/
+static void SolarisInitUSCSI( struct uscsi_cmd *p_sc, int i_type )
+{   
+    union scsi_cdb *rs_cdb;
+    memset( p_sc->uscsi_cdb, 0, sizeof( union scsi_cdb ) );
+    memset( p_sc->uscsi_bufaddr, 0, p_sc->uscsi_buflen );
+    
+    switch( i_type )
+    {
+        case GPCMD_SEND_KEY:
+           p_sc->uscsi_flags = USCSI_ISOLATE | USCSI_WRITE;
+            break;
+
+        case GPCMD_READ_DVD_STRUCTURE:
+        case GPCMD_REPORT_KEY:
+           p_sc->uscsi_flags = USCSI_ISOLATE | USCSI_READ;
+            break;
+    }
+    
+    rs_cdb = (union scsi_cdb *)p_sc->uscsi_cdb;
+    
+    rs_cdb->scc_cmd = i_type;
+
+    rs_cdb->cdb_opaque[ 8 ] = (p_sc->uscsi_buflen >> 8) & 0xff;
+    rs_cdb->cdb_opaque[ 9 ] =  p_sc->uscsi_buflen       & 0xff;
+    p_sc->uscsi_cdblen = 12;
+
+    USCSI_TIMEOUT( p_sc, 15 );
+}
+#endif
+
 #if defined( WIN32 )
 /*****************************************************************************
  * WinInitSSC: initialize a ssc structure for the win32 aspi layer