ref: 74a14cf8b238c1efb540e3cc83d9ee4b71a4a70d
parent: ec1bd09bf4768c9641363c13af2248edd0e24c91
author: Jon Lech Johansen <[email protected]>
date: Mon Nov 25 13:44:31 EST 2002
* ./src/ioctl.[ch]: Implemented ioctl_SendRPC. * ./test/dvd_region.c: enabled set_region.
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,10 @@
# ChangeLog for libdvdcss #
#=========================#
+HEAD
+
+ * ./src/ioctl.[ch]: Implemented ioctl_SendRPC.
+
1.2.4
Thu, 14 Nov 2002 16:15:00 +0200
--- a/src/ioctl.c
+++ b/src/ioctl.c
@@ -2,7 +2,7 @@
* ioctl.c: DVD ioctl replacement function
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
- * $Id: ioctl.c,v 1.20 2002/11/15 18:39:08 jlj Exp $
+ * $Id: ioctl.c,v 1.21 2002/11/25 18:44:31 jlj Exp $
*
* Authors: Markus Kuespert <[email protected]>
* Samuel Hocevar <[email protected]>
@@ -118,8 +118,9 @@
* Local prototypes, win32 (aspi) specific
*****************************************************************************/
#if defined( WIN32 )
-static void WinInitSSC ( struct SRB_ExecSCSICmd *, int );
-static int WinSendSSC ( int, struct SRB_ExecSCSICmd * );
+static void WinInitSPTD ( SCSI_PASS_THROUGH_DIRECT *, int );
+static void WinInitSSC ( struct SRB_ExecSCSICmd *, int );
+static int WinSendSSC ( int, struct SRB_ExecSCSICmd * );
#endif
/*****************************************************************************
@@ -213,37 +214,19 @@
#elif defined( WIN32 )
if( WIN2K ) /* NT/2k/XP */
{
- DWORD tmp;
- u8 p_buffer[ 8 ];
- SCSI_PASS_THROUGH_DIRECT sptd;
+ INIT_SPTD( GPCMD_READ_DVD_STRUCTURE, 8 );
/* When using IOCTL_DVD_READ_STRUCTURE and
DVD_COPYRIGHT_DESCRIPTOR, CopyrightProtectionType
seems to be always 6 ???
- To work around this M$ bug we try to send a raw scsi command
+ To work around this MS bug we try to send a raw scsi command
instead (if we've got enough privileges to do so). */
- memset( &sptd, 0, sizeof( sptd ) );
- memset( &p_buffer, 0, sizeof( p_buffer ) );
+ sptd.Cdb[ 6 ] = i_layer;
+ sptd.Cdb[ 7 ] = DVD_STRUCT_COPYRIGHT;
- sptd.Length = sizeof( SCSI_PASS_THROUGH_DIRECT );
- sptd.CdbLength = 12;
- sptd.DataIn = SCSI_IOCTL_DATA_IN;
- sptd.DataTransferLength = 8;
- sptd.TimeOutValue = 2;
- sptd.DataBuffer = p_buffer;
- sptd.Cdb[ 0 ] = GPCMD_READ_DVD_STRUCTURE;
- sptd.Cdb[ 6 ] = i_layer;
- sptd.Cdb[ 7 ] = DVD_STRUCT_COPYRIGHT;
- sptd.Cdb[ 8 ] = (8 >> 8) & 0xff;
- sptd.Cdb[ 9 ] = 8 & 0xff;
+ i_ret = SEND_SPTD( i_fd, &sptd, &tmp );
- i_ret = DeviceIoControl( (HANDLE) i_fd,
- IOCTL_SCSI_PASS_THROUGH_DIRECT,
- &sptd, sizeof( SCSI_PASS_THROUGH_DIRECT ),
- &sptd, sizeof( SCSI_PASS_THROUGH_DIRECT ),
- &tmp, NULL ) ? 0 : -1;
-
if( i_ret == 0 )
{
*pi_copyright = p_buffer[ 4 ];
@@ -560,7 +543,7 @@
if( WIN2K ) /* NT/2k/XP */
{
DWORD tmp;
- u8 buffer[DVD_BUS_KEY_LENGTH];
+ u8 buffer[DVD_TITLE_KEY_LENGTH];
PDVD_COPY_PROTECT_KEY key = (PDVD_COPY_PROTECT_KEY) &buffer;
memset( &buffer, 0, sizeof( buffer ) );
@@ -1688,6 +1671,133 @@
return i_ret;
}
+/*****************************************************************************
+ * ioctl_SendRPC: set RPC status for the drive
+ *****************************************************************************/
+int ioctl_SendRPC( int i_fd, int i_pdrc )
+{
+ int i_ret;
+
+#if defined( HAVE_LINUX_DVD_STRUCT ) && defined( DVD_HOST_SEND_RPC_STATE )
+ dvd_authinfo auth_info;
+
+ memset( &auth_info, 0, sizeof( auth_info ) );
+ auth_info.type = DVD_HOST_SEND_RPC_STATE;
+ auth_info.hrpcs.pdrc = i_pdrc;
+
+ return ioctl( i_fd, DVD_AUTH, &auth_info );
+
+#elif defined( HAVE_LINUX_DVD_STRUCT )
+ /* FIXME: OpenBSD doesn't know this */
+ i_ret = -1;
+
+#elif defined( HAVE_BSD_DVD_STRUCT )
+ struct dvd_authinfo auth_info;
+
+ memset( &auth_info, 0, sizeof( auth_info ) );
+ auth_info.format = DVD_SEND_RPC;
+ auth_info.region = i_pdrc;
+
+ return ioctl( i_fd, DVDIOCSENDKEY, &auth_info );
+
+#elif defined( SYS_BEOS )
+ INIT_RDC( GPCMD_SEND_KEY, 8 );
+
+ rdc.command[ 10 ] = DVD_SEND_RPC;
+
+ p_buffer[ 1 ] = 6;
+ p_buffer[ 4 ] = i_pdrc;
+
+ return ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
+
+#elif defined( HPUX_SCTL_IO )
+ INIT_SCTL_IO( GPCMD_SEND_KEY, 8 );
+
+ sctl_io.cdb[ 10 ] = DVD_SEND_RPC;
+
+ p_buffer[ 1 ] = 6;
+ p_buffer[ 4 ] = i_pdrc;
+
+ return ioctl( i_fd, SIOC_IO, &sctl_io );
+
+#elif defined( SOLARIS_USCSI )
+ INIT_USCSI( GPCMD_SEND_KEY, 8 );
+
+ rs_cdb.cdb_opaque[ 10 ] = DVD_SEND_RPC;
+
+ p_buffer[ 1 ] = 6;
+ p_buffer[ 4 ] = i_pdrc;
+
+ i_ret = ioctl( i_fd, USCSICMD, &sc );
+
+ if( i_ret < 0 || sc.uscsi_status )
+ {
+ i_ret = -1;
+ }
+
+#elif defined( DARWIN_DVD_IOCTL )
+ INIT_DVDIOCTL( dk_dvd_send_key_t, DVDRegionPlaybackControlInfo,
+ kDVDKeyFormatSetRegion );
+
+ dvd.keyClass = kDVDKeyClassCSS_CPPM_CPRM;
+ dvdbs.driveRegion = i_pdrc;
+
+ return ioctl( i_fd, DKIOCDVDSENDKEY, &dvd );
+
+#elif defined( WIN32 )
+ if( WIN2K ) /* NT/2k/XP */
+ {
+ INIT_SPTD( GPCMD_SEND_KEY, 8 );
+
+ sptd.Cdb[ 10 ] = DVD_SEND_RPC;
+
+ p_buffer[ 1 ] = 6;
+ p_buffer[ 4 ] = i_pdrc;
+
+ return SEND_SPTD( i_fd, &sptd, &tmp );
+ }
+ else
+ {
+ INIT_SSC( GPCMD_SEND_KEY, 8 );
+
+ ssc.CDBByte[ 10 ] = DVD_SEND_RPC;
+
+ p_buffer[ 1 ] = 6;
+ p_buffer[ 4 ] = i_pdrc;
+
+ return WinSendSSC( i_fd, &ssc );
+ }
+
+#elif defined( __QNXNTO__ )
+
+ INIT_CPT( GPCMD_SEND_KEY, 8 );
+
+ p_cpt->cam_cdb[ 10 ] = DVD_SEND_RPC;
+
+ p_buffer[ 1 ] = 6;
+ p_buffer[ 4 ] = i_pdrc;
+
+ return devctl(i_fd, DCMD_CAM_PASS_THRU, p_cpt, structSize, NULL);
+
+#elif defined( SYS_OS2 )
+ INIT_SSC( GPCMD_SEND_KEY, 8 );
+
+ sdc.command[ 10 ] = DVD_SEND_RPC;
+
+ p_buffer[ 1 ] = 6;
+ p_buffer[ 4 ] = i_pdrc;
+
+ return DosDevIOCtl(i_fd, IOCTL_CDROMDISK, CDROMDISK_EXECMD,
+ &sdc, sizeof(sdc), &ulParamLen,
+ p_buffer, sizeof(p_buffer), &ulDataLen);
+
+#else
+# error "DVD ioctls are unavailable on this system"
+
+#endif
+ return i_ret;
+}
+
/* Local prototypes */
#if defined( SYS_BEOS )
@@ -1794,6 +1904,36 @@
#endif
#if defined( WIN32 )
+/*****************************************************************************
+ * WinInitSPTD: initialize a sptd structure
+ *****************************************************************************
+ * This function initializes a SCSI pass through command structure for future
+ * use, either a read command or a write command.
+ *****************************************************************************/
+static void WinInitSPTD( SCSI_PASS_THROUGH_DIRECT *p_sptd, int i_type )
+{
+ memset( p_sptd->DataBuffer, 0, p_sptd->DataTransferLength );
+
+ switch( i_type )
+ {
+ case GPCMD_SEND_KEY:
+ p_sptd->DataIn = SCSI_IOCTL_DATA_OUT;
+ break;
+
+ case GPCMD_READ_DVD_STRUCTURE:
+ case GPCMD_REPORT_KEY:
+ p_sptd->DataIn = SCSI_IOCTL_DATA_IN;
+ break;
+ }
+
+ p_sptd->Cdb[ 0 ] = i_type;
+ p_sptd->Cdb[ 8 ] = (u8)(p_sptd->DataTransferLength >> 8) & 0xff;
+ p_sptd->Cdb[ 9 ] = (u8) p_sptd->DataTransferLength & 0xff;
+ p_sptd->CdbLength = 12;
+
+ p_sptd->TimeOutValue = 2;
+}
+
/*****************************************************************************
* WinInitSSC: initialize a ssc structure for the win32 aspi layer
*****************************************************************************
--- a/src/ioctl.h
+++ b/src/ioctl.h
@@ -2,7 +2,7 @@
* ioctl.h: DVD ioctl replacement function
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
- * $Id: ioctl.h,v 1.11 2002/11/15 18:39:08 jlj Exp $
+ * $Id: ioctl.h,v 1.12 2002/11/25 18:44:31 jlj Exp $
*
* Authors: Samuel Hocevar <[email protected]>
*
@@ -31,6 +31,8 @@
int ioctl_InvalidateAgid ( int, int * );
int ioctl_SendChallenge ( int, int *, u8 * );
int ioctl_SendKey2 ( int, int *, u8 * );
+int ioctl_ReportRPC ( int, int *, int *, int * );
+int ioctl_SendRPC ( int, int );
#define DVD_KEY_SIZE 5
#define DVD_CHALLENGE_SIZE 10
@@ -94,9 +96,23 @@
#endif
/*****************************************************************************
- * Common macro, win32 (ASPI) specific
+ * Common macro, win32 specific
*****************************************************************************/
#if defined( WIN32 )
+#define INIT_SPTD( TYPE, SIZE ) \
+ DWORD tmp; \
+ SCSI_PASS_THROUGH_DIRECT sptd; \
+ u8 p_buffer[ (SIZE) ]; \
+ memset( &sptd, 0, sizeof( SCSI_PASS_THROUGH_DIRECT ) ); \
+ sptd.Length = sizeof( SCSI_PASS_THROUGH_DIRECT ); \
+ sptd.DataBuffer = p_buffer; \
+ sptd.DataTransferLength = (SIZE); \
+ WinInitSPTD( &sptd, (TYPE) );
+#define SEND_SPTD( DEV, SPTD, TMP ) \
+ (DeviceIoControl( (HANDLE)(DEV), IOCTL_SCSI_PASS_THROUGH_DIRECT, \
+ (SPTD), sizeof( SCSI_PASS_THROUGH_DIRECT ), \
+ (SPTD), sizeof( SCSI_PASS_THROUGH_DIRECT ), \
+ (TMP), NULL ) ? 0 : -1)
#define INIT_SSC( TYPE, SIZE ) \
struct SRB_ExecSCSICmd ssc; \
u8 p_buffer[ (SIZE) ]; \
--- a/test/dvd_region.c
+++ b/test/dvd_region.c
@@ -14,8 +14,9 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
+#include <getopt.h>
-#include "dvdcss/dvdcss.h"
+#include <dvdcss/dvdcss.h>
#include "config.h"
#include "common.h"
@@ -25,7 +26,6 @@
int set_region(int fd, int region)
{
-#if 0
int ret, region_mask;
if(region > 8 || region <= 0) {
@@ -42,7 +42,7 @@
perror("dvd_region");
return ret;
}
-#endif
+
return 0;
}
@@ -155,6 +155,7 @@
/* Print version number */
printf( "found libdvdcss version %s\n", dvdcss_interface_2 );
+ /* TODO: use dvdcss_open instead of open */
if( (fd = open(device_name, O_RDONLY | O_NONBLOCK)) < 0 ) {
perror("open");
@@ -176,9 +177,6 @@
fprintf( stderr, "you must specify the region!\n" );
exit(0);
}
-
- fprintf( stderr, "setting the region is not supported yet!\n");
- exit( 1 );
if( (ret = set_region(fd, region)) < 0 )
return ret;