[MPlayer-dev-eng]

Andreas Hess jaska at gmx.net
Sat Feb 8 00:21:39 CET 2003


On Sat, Feb 08, 2003 at 12:13:31AM +0100, Alex Beregszaszi wrote:
> please remake it with cvs diff -bB to avoid annoying cosmetics

I've kept these cosmetics for maximum libdvdcss compatibility, but
your wish is my command.
-------------- next part --------------
Index: AUTHORS
===================================================================
RCS file: /cvsroot/mplayer/main/AUTHORS,v
retrieving revision 1.25
diff -b -B -u -r1.25 AUTHORS
--- AUTHORS	5 Feb 2003 00:19:54 -0000	1.25
+++ AUTHORS	7 Feb 2003 23:25:32 -0000
@@ -458,7 +458,7 @@
     * various small bugfixes
 
 Andreas Hess <jaska at gmx.net>
-    * upgrading libdvdcss to 1.2.4 in libmpdvdkit2
+    * upgrading libdvdcss in libmpdvdkit2
     * various small bugfixes
 
 Salvador Eduardo Tropea <salvador at inti.gov.ar>
Index: libmpdvdkit2/README
===================================================================
RCS file: /cvsroot/mplayer/main/libmpdvdkit2/README,v
retrieving revision 1.3
diff -b -B -u -r1.3 README
--- libmpdvdkit2/README	17 Aug 2002 10:25:18 -0000	1.3
+++ libmpdvdkit2/README	7 Feb 2003 23:25:38 -0000
@@ -6,7 +6,7 @@
 Nothing special, just a collection of sources and patches and fixes:
 
 - dvdread 0.9.3 + static libdvdcss (removed dlopen code)
-- libdvdcss 1.2.2 + per-disc css key cache patch
+- libdvdcss 1.2.5
 - optimizations enabled, asserts disabled
 everything packed together with _static_ linking to maximize performance.
 
Index: libmpdvdkit2/bsdi_dvd.h
===================================================================
RCS file: /cvsroot/mplayer/main/libmpdvdkit2/bsdi_dvd.h,v
retrieving revision 1.1
diff -b -B -u -r1.1 bsdi_dvd.h
--- libmpdvdkit2/bsdi_dvd.h	16 Aug 2002 22:35:45 -0000	1.1
+++ libmpdvdkit2/bsdi_dvd.h	7 Feb 2003 23:25:39 -0000
@@ -224,6 +224,7 @@
 #define CDROMEJECT		0x5309 /* Ejects the cdrom media */
 #define CDROMCLOSETRAY          0x5319 /* Reverse of CDROMEJECT */
 #define CDROM_DRIVE_STATUS      0x5326 /* Get tray position, etc. */
+#define CDROM_DISC_STATUS	0x5327 /* Get disc type, etc. */
 #define CDROMREADMODE2		0x530c /* Read CDROM mode 2 data (2336 Bytes) */
 #define CDROMREADMODE1		0x530d /* Read CDROM mode 1 data (2048 Bytes) */
 #define CDROMREADRAW            0x5314 /* read data in raw mode (2352 bytes) */
@@ -244,6 +245,9 @@
 #define CDROM_LBA 0x01 		/* logical block: first frame is #0 */
 #define CDROM_MSF 0x02 		/* minute-second-frame: binary. not bcd here!*/
 
+/* bit to tell whether track is data or audio (cdrom_tocentry.cdte_ctrl) */
+#define CDROM_DATA_TRACK        0x04
+
 /* The leadout track is always 0xAA, regardless of # of tracks on disc */
 #define CDROM_LEADOUT           0xAA
 
@@ -254,6 +258,17 @@
 #define CDS_DRIVE_NOT_READY     3
 #define CDS_DISC_OK             4
 
+/*
+ * Return values for CDROM_DISC_STATUS ioctl.
+ * Can also return CDS_NO_INFO and CDS_NO_DISC from above
+*/
+#define	CDS_AUDIO		100
+#define	CDS_DATA_1		101
+#define	CDS_DATA_2		102
+#define	CDS_XA_2_1		103
+#define	CDS_XA_2_2		104
+#define	CDS_MIXED		105
+
 /* For compile compatibility only - we don't support changers */
 #define CDSL_NONE               ((int) (~0U>>1)-1)
 #define CDSL_CURRENT            ((int) (~0U>>1))
@@ -312,4 +327,14 @@
 	__u8	block_length_med;
 	__u8	block_length_lo;
 };
+
+typedef	struct
+{
+	int	data;
+	int	audio;
+	int	cdi;
+	int	xa;
+	int	error;
+} tracktype;
+
 #endif /* _DVD_H_ */
Index: libmpdvdkit2/bsdi_ioctl.c
===================================================================
RCS file: /cvsroot/mplayer/main/libmpdvdkit2/bsdi_ioctl.c,v
retrieving revision 1.1
diff -b -B -u -r1.1 bsdi_ioctl.c
--- libmpdvdkit2/bsdi_ioctl.c	16 Aug 2002 22:35:45 -0000	1.1
+++ libmpdvdkit2/bsdi_ioctl.c	7 Feb 2003 23:25:39 -0000
@@ -49,8 +49,9 @@
 static int scsi_cmd(int, cgc_t *);
 static int cdrom_ioctl(int, u_long, void *);
 static int cdrom_tray_move(int, int);
+static void cdrom_count_tracks(int, tracktype *);
 static int dvd_ioctl(int, u_long, void *);
-static	int	debug;
+static	int	debug = 0;
 
 void dvd_cdrom_debug(int flag)
 	{
@@ -72,9 +73,11 @@
 		case	CDROMREADTOCENTRY:
 		case	CDROMEJECT:
 		case	CDROMREADRAW:
+		case	CDROMREADMODE1:
 		case	CDROMREADMODE2:
 		case	CDROMCLOSETRAY:
 		case	CDROM_DRIVE_STATUS:
+		case	CDROM_DISC_STATUS:
 			return(cdrom_ioctl(fd, cmd, arg));
 		default:
 			return(ioctl(fd, cmd, arg));
@@ -401,7 +404,7 @@
 
 static int scsi_cmd(int fd, cgc_t *cgc)
 	{
-	int	scsistatus, cdblen;
+	int	i, scsistatus, cdblen;
 	unsigned char	*cp;
 	struct	scsi_user_cdb suc;
 
@@ -427,12 +430,14 @@
 	if	(scsistatus && debug)
 		{
 		cp = suc.suc_sus.sus_sense;
-		fprintf(stderr,"scsistatus = %x cmd = %x\n",
-			scsistatus, cgc->cdb[0]);
-		fprintf(stderr, "sense %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x\n", 
-			cp[0], cp[1], cp[2], cp[3], cp[4], cp[5],
-			cp[6], cp[7], cp[8], cp[9], cp[10], cp[11],
-			cp[12], cp[13], cp[14], cp[15]);
+		fprintf(stderr,"scsistatus = %x cdb =",
+			scsistatus);
+		for	(i = 0; i < cdblen; i++)
+			fprintf(stderr, " %x", cgc->cdb[i]);
+		fprintf(stderr, "\nsense =");
+		for	(i = 0; i < 16; i++)
+			fprintf(stderr, " %x", cp[i]);
+		fprintf(stderr, "\n");
 		}
 	if	(cgc->sus)
 		bcopy(&suc.suc_sus, cgc->sus, sizeof (struct scsi_user_sense));
@@ -456,7 +461,7 @@
 				errno = ret;
 			return(ret ? -1 : 0);
 		case	DVD_AUTH:
-			ret = dvd_do_auth (fd, (dvd_authinfo *)arg);
+			ret = dvd_do_auth(fd, (dvd_authinfo *)arg);
 			if	(ret)
 				errno = ret;
 			return(ret ? -1 : 0);
@@ -596,11 +601,35 @@
  * This sucks but emulates the expected behaviour.  Instead of the return 
  * value being the actual status a success/fail indicator should have been
  * returned and the 3rd arg to the ioctl should have been an 'int *' to update
- * with the actual status.
+ * with the actual status.   Both the drive and disc status ioctl calls are
+ * similarily braindamaged.
 */
 		case	CDROM_DRIVE_STATUS:
+			return(CDS_NO_INFO);	/* XXX */
+		case	CDROM_DISC_STATUS:
+			{
+			tracktype tracks;
+			int	cnt;
+
+			cdrom_count_tracks(fd, &tracks);
+			if	(tracks.error)
+				return(tracks.error);
+			if	(tracks.audio > 0)
+				{
+				cnt = tracks.data + tracks.cdi + tracks.xa;
+				if	(cnt == 0)
+					return(CDS_AUDIO);
+				else
+					return(CDS_MIXED);
+				}
+			if	(tracks.cdi)
+				return(CDS_XA_2_2);
+			if	(tracks.xa)
+				return(CDS_XA_2_1);
+			if	(tracks.data)
+				return(CDS_DATA_1);
 			return(CDS_NO_INFO);
-			break;
+			}
 		}
 	errno = ret;
 	return(ret ? -1 : 0);
@@ -657,6 +686,49 @@
 			cgc->cdb[9] = 0x10;
 		}
 	return(scsi_cmd(fd, cgc));
+	}
+
+static void cdrom_count_tracks(int fd, tracktype *tracks)
+	{
+	struct	cdrom_tochdr header;
+	struct	cdrom_tocentry entry;
+	int	ret, i;
+
+	bzero(tracks, sizeof (*tracks));
+	ret = cdrom_ioctl(fd, CDROMREADTOCHDR, &header);
+/*
+ * This whole business is a crock anyhow so we don't bother distinguishing
+ * between no media, drive not ready, etc and on any error just say we have
+ * no info.
+*/
+	if	(ret)
+		{
+		tracks->error = CDS_NO_INFO;
+		return;
+		}
+
+	entry.cdte_format = CDROM_MSF;
+	for	(i = header.cdth_trk0; i <= header.cdth_trk1; i++)
+		{
+		entry.cdte_track = i;
+		if	(cdrom_ioctl(fd, CDROMREADTOCENTRY, &entry))
+			{
+			tracks->error = CDS_NO_INFO;
+			return;
+			}
+		if	(entry.cdte_ctrl & CDROM_DATA_TRACK)
+			{
+			if	(entry.cdte_format == 0x10)
+				tracks->cdi++;
+			else if	(entry.cdte_format == 0x20)
+				tracks->xa++;
+			else
+				tracks->data++;
+			}
+		else
+			tracks->audio++;
+		}
+	return;
 	}
 
 static int cdrom_tray_move(int fd, int flag)
Index: libmpdvdkit2/common.h
===================================================================
RCS file: /cvsroot/mplayer/main/libmpdvdkit2/common.h,v
retrieving revision 1.1
diff -b -B -u -r1.1 common.h
--- libmpdvdkit2/common.h	16 Aug 2002 22:35:45 -0000	1.1
+++ libmpdvdkit2/common.h	7 Feb 2003 23:25:39 -0000
@@ -27,14 +27,22 @@
 /*****************************************************************************
  * Basic types definitions
  *****************************************************************************/
-
-/* Basic types definitions */
-typedef unsigned char           u8;
-typedef signed char             s8;
-typedef unsigned int            u32;
-typedef signed int              s32;
-
-typedef u8                  byte_t;
+#if defined( HAVE_STDINT_H )
+#   include <stdint.h>
+#elif defined( HAVE_INTTYPES_H )
+#   include <inttypes.h>
+#elif defined( SYS_CYGWIN )
+#   include <sys/types.h>
+    /* Cygwin only defines half of these... */
+    typedef u_int8_t            uint8_t;
+    typedef u_int32_t           uint32_t;
+#else
+    /* Fallback types (very x86-centric, sorry) */
+    typedef unsigned char       uint8_t;
+    typedef signed char         int8_t;
+    typedef unsigned int        uint32_t;
+    typedef signed int          int32_t;
+#endif
 
 #if defined( WIN32 )
 
Index: libmpdvdkit2/css.c
===================================================================
RCS file: /cvsroot/mplayer/main/libmpdvdkit2/css.c,v
retrieving revision 1.5
diff -b -B -u -r1.5 css.c
--- libmpdvdkit2/css.c	29 Dec 2002 15:32:56 -0000	1.5
+++ libmpdvdkit2/css.c	7 Feb 2003 23:25:41 -0000
@@ -42,6 +42,7 @@
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <unistd.h>
+#include <limits.h>
 
 #include "dvdcss.h"
 
@@ -58,19 +59,21 @@
 static int  GetBusKey       ( dvdcss_t );
 static int  GetASF          ( dvdcss_t );
 
-static void CryptKey        ( int, int, u8 const *, u8 * );
-static void DecryptKey      ( u8, u8 const *, u8 const *, u8 * );
+static void CryptKey        ( int, int, uint8_t const *, uint8_t * );
+static void DecryptKey      ( uint8_t,
+                              uint8_t const *, uint8_t const *, uint8_t * );
 
-static int  DecryptDiscKey  ( u8 const *, dvd_key_t );
-static int  CrackDiscKey    ( dvdcss_t, u8 * );
+static int  DecryptDiscKey  ( uint8_t const *, dvd_key_t );
+static int  CrackDiscKey    ( dvdcss_t, uint8_t * );
 
 static void DecryptTitleKey ( dvd_key_t, dvd_key_t );
-static int  RecoverTitleKey ( int, u8 const *, u8 const *, u8 const *, u8 * );
+static int  RecoverTitleKey ( int, uint8_t const *,
+                              uint8_t const *, uint8_t const *, uint8_t * );
 static int  CrackTitleKey   ( dvdcss_t, int, int, dvd_key_t );
 
-static int  AttackPattern   ( u8 const[], int, u8 * );
+static int  AttackPattern   ( uint8_t const[], int, uint8_t * );
 #if 0
-static int  AttackPadding   ( u8 const[], int, u8 * );
+static int  AttackPadding   ( uint8_t const[], int, uint8_t * );
 #endif
 
 /*****************************************************************************
@@ -122,12 +125,12 @@
  *****************************************************************************/
 static int GetBusKey( dvdcss_t dvdcss )
 {
-    u8        p_buffer[10];
-    u8        p_challenge[2*KEY_SIZE];
+    uint8_t   p_buffer[10];
+    uint8_t   p_challenge[2*KEY_SIZE];
     dvd_key_t p_key1;
     dvd_key_t p_key2;
     dvd_key_t p_key_check;
-    u8        i_variant = 0;
+    uint8_t   i_variant = 0;
     char      psz_warning[80];
     int       i_ret = -1;
     int       i;
@@ -262,7 +265,7 @@
 /*****************************************************************************
  * PrintKey : debug function that dumps a key value 
  *****************************************************************************/
-static void PrintKey( dvdcss_t dvdcss, char *prefix, u8 const *data )
+static void PrintKey( dvdcss_t dvdcss, char *prefix, uint8_t const *data )
 {
     char psz_output[80];
 
@@ -282,8 +285,7 @@
     dvd_title_t *p_title;
     dvd_title_t *p_newtitle;
     dvd_key_t    p_title_key;
-    int          i_ret=-1;
-    char* key_file=NULL;
+    int          i_fd, i_ret = -1, b_cache = 0;
 
     if( ! dvdcss->b_scrambled )
     {
@@ -307,44 +309,54 @@
         return 0;
     }
 
-    /* check teh CSS Key cache, if available: */
-    if(dvdcss->psz_cache){
-	int fd;
-	key_file=malloc(strlen(dvdcss->psz_cache)+12+4);
-	sprintf(key_file,"%s/%.10x",dvdcss->psz_cache,i_block);
-	if ( (fd=open( key_file,O_RDONLY ) ) > 0 ){
-	    if(read(fd, p_title_key, 5)==5){
-		// success!
-		free(key_file); key_file=NULL;
-		i_ret=1;
+    /* Check whether the key is in our disk cache */
+    if( dvdcss->psz_cachefile[0] )
+    {
+        /* XXX: be careful, we use sprintf and not snprintf */
+        sprintf( dvdcss->psz_block, "%.10x", i_block );
+        i_fd = open( dvdcss->psz_cachefile, O_RDONLY );
+        b_cache = 1;
+
+        if( i_fd >= 0 )
+        {
+            if( read( i_fd, p_title_key, 5 ) == 5 )
+            {
 		_dvdcss_debug( dvdcss, "key found in cache" );
+                /* Don't try to save it again */
+                b_cache = 0;
+                i_ret = 1;
 	    }
-	    close(fd);
+            close( i_fd );
 	}
     }
 
     /* Crack or decrypt CSS title key for current VTS */
-    if(i_ret<0) i_ret = _dvdcss_titlekey( dvdcss, i_block, p_title_key );
+    if( i_ret < 0 )
+    {
+        i_ret = _dvdcss_titlekey( dvdcss, i_block, p_title_key );
 
     if( i_ret < 0 )
     {
         _dvdcss_error( dvdcss, "fatal error in vts css key" );
         return i_ret;
     }
-    else if( i_ret == 0 )
+
+        if( i_ret == 0 )
     {
         _dvdcss_debug( dvdcss, "unencrypted title" );
-        /* Still store this in the cache, so we don't need to check again. */
+            /* We cache this anyway, so we don't need to check again. */
+        }
     }
 
-    /* store in key-cache */
-    if(key_file){
-	int fd;
-	if ( (fd=open( key_file,O_RDWR|O_CREAT|O_EXCL,0644 ) ) > 0 ){
-	    write(fd, p_title_key, 5);
-	    close(fd);
+    /* Key is valid, we store it on disk. */
+    if( b_cache )
+    {
+        i_fd = open( dvdcss->psz_cachefile, O_RDWR|O_CREAT|O_EXCL, 0644 );
+        if( i_fd >= 0 )
+        {
+            write( i_fd, p_title_key, 5 );
+            close( i_fd );
 	}
-	free(key_file);
     }
 
     /* Find our spot in the list */
@@ -478,8 +490,8 @@
  *****************************************************************************/
 int _dvdcss_titlekey( dvdcss_t dvdcss, int i_pos, dvd_key_t p_title_key )
 {
-    static u8 p_garbage[ 2048 ];          /* static because we never read it */
-    u8  p_key[KEY_SIZE];
+    static uint8_t p_garbage[ 2048 ];     /* static because we never read it */
+    uint8_t p_key[ KEY_SIZE ];
     int i, i_ret = 0;
 
     if( dvdcss->b_ioctls && ( dvdcss->i_method == DVDCSS_METHOD_KEY || 
@@ -591,10 +603,10 @@
  * sec : sector to unscramble
  * key : title key for this sector
  *****************************************************************************/
-int _dvdcss_unscramble( dvd_key_t p_key, u8 *p_sec )
+int _dvdcss_unscramble( dvd_key_t p_key, uint8_t *p_sec )
 {
     unsigned int    i_t1, i_t2, i_t3, i_t4, i_t5, i_t6;
-    u8             *p_end = p_sec + 0x800;
+    uint8_t        *p_end = p_sec + 0x800;
 
     /* PES_scrambling_control */
     if( p_sec[0x14] & 0x30)
@@ -670,16 +682,16 @@
  * i_variant : between 0 and 31.
  *****************************************************************************/
 static void CryptKey( int i_key_type, int i_variant,
-                      u8 const *p_challenge, u8 *p_key )
+                      uint8_t const *p_challenge, uint8_t *p_key )
 {
     /* Permutation table for challenge */
-    u8      pp_perm_challenge[3][10] =
+    uint8_t pp_perm_challenge[3][10] =
             { { 1, 3, 0, 7, 5, 2, 9, 6, 4, 8 },
               { 6, 1, 9, 3, 8, 5, 7, 4, 0, 2 },
               { 4, 0, 3, 5, 7, 2, 8, 6, 1, 9 } };
 
     /* Permutation table for variant table for key2 and buskey */
-    u8      pp_perm_variant[2][32] =
+    uint8_t pp_perm_variant[2][32] =
             { { 0x0a, 0x08, 0x0e, 0x0c, 0x0b, 0x09, 0x0f, 0x0d,
                 0x1a, 0x18, 0x1e, 0x1c, 0x1b, 0x19, 0x1f, 0x1d,
                 0x02, 0x00, 0x06, 0x04, 0x03, 0x01, 0x07, 0x05,
@@ -689,21 +701,21 @@
                 0x13, 0x1b, 0x17, 0x1f, 0x03, 0x0b, 0x07, 0x0f,
                 0x11, 0x19, 0x15, 0x1d, 0x01, 0x09, 0x05, 0x0d } };
 
-    u8      p_variants[32] =
+    uint8_t p_variants[32] =
             {   0xB7, 0x74, 0x85, 0xD0, 0xCC, 0xDB, 0xCA, 0x73,
                 0x03, 0xFE, 0x31, 0x03, 0x52, 0xE0, 0xB7, 0x42,
                 0x63, 0x16, 0xF2, 0x2A, 0x79, 0x52, 0xFF, 0x1B,
                 0x7A, 0x11, 0xCA, 0x1A, 0x9B, 0x40, 0xAD, 0x01 };
 
     /* The "secret" key */
-    u8      p_secret[5] = { 0x55, 0xD6, 0xC4, 0xC5, 0x28 };
+    uint8_t p_secret[5] = { 0x55, 0xD6, 0xC4, 0xC5, 0x28 };
 
-    u8      p_bits[30], p_scratch[10], p_tmp1[5], p_tmp2[5];
-    u8      i_lfsr0_o;  /* 1 bit used */
-    u8      i_lfsr1_o;  /* 1 bit used */
-    u32     i_lfsr0, i_lfsr1;
-    u8      i_css_variant, i_cse, i_index, i_combined, i_carry;
-    u8      i_val = 0;
+    uint8_t p_bits[30], p_scratch[10], p_tmp1[5], p_tmp2[5];
+    uint8_t i_lfsr0_o;  /* 1 bit used */
+    uint8_t i_lfsr1_o;  /* 1 bit used */
+    uint8_t i_css_variant, i_cse, i_index, i_combined, i_carry;
+    uint8_t i_val = 0;
+    uint32_t i_lfsr0, i_lfsr1;
     int     i_term = 0;
     int     i_bit;
     int     i;
@@ -873,16 +885,16 @@
  *  -for disc key, invert is 0x00,
  *  -for title key, invert if 0xff. 
  *****************************************************************************/
-static void DecryptKey( u8 invert, u8 const *p_key, 
-                        u8 const *p_crypted, u8 *p_result )
+static void DecryptKey( uint8_t invert, uint8_t const *p_key,
+                        uint8_t const *p_crypted, uint8_t *p_result )
 {
     unsigned int    i_lfsr1_lo;
     unsigned int    i_lfsr1_hi;
     unsigned int    i_lfsr0;
     unsigned int    i_combined;
-    u8              o_lfsr0;
-    u8              o_lfsr1;
-    u8              k[5];
+    uint8_t         o_lfsr0;
+    uint8_t         o_lfsr1;
+    uint8_t         k[5];
     int             i;
 
     i_lfsr1_lo = p_key[0] | 0x100;
@@ -937,10 +949,11 @@
  * p_struct_disckey: the 2048 byte DVD_STRUCT_DISCKEY data
  * p_disc_key: result, the 5 byte disc key
  *****************************************************************************/
-static int DecryptDiscKey( u8 const *p_struct_disckey, dvd_key_t p_disc_key )
+static int DecryptDiscKey( uint8_t const *p_struct_disckey,
+                           dvd_key_t p_disc_key )
 {
-    u8 p_verify[KEY_SIZE];
-    int i, n = 0;
+    uint8_t p_verify[KEY_SIZE];
+    unsigned int i, n = 0;
 
     static const dvd_key_t player_keys[] = 
     {
@@ -1039,7 +1052,7 @@
     return memcmp( key, ckey, KEY_SIZE );
 }
 
-static int CrackDiscKey( dvdcss_t dvdcss, u8 *p_disc_key )
+static int CrackDiscKey( dvdcss_t dvdcss, uint8_t *p_disc_key )
 {
     unsigned char B[5] = { 0,0,0,0,0 }; /* Second Stage of mangle cipher */
     unsigned char C[5] = { 0,0,0,0,0 }; /* Output Stage of mangle cipher
@@ -1236,11 +1249,11 @@
  * Called from Attack* which are in turn called by CrackTitleKey.  Given
  * a guessed(?) plain text and the chiper text.  Returns -1 on failure.
  *****************************************************************************/
-static int RecoverTitleKey( int i_start, u8 const *p_crypted,
-                            u8 const *p_decrypted,
-                            u8 const *p_sector_seed, u8 *p_key )
+static int RecoverTitleKey( int i_start, uint8_t const *p_crypted,
+                            uint8_t const *p_decrypted,
+                            uint8_t const *p_sector_seed, uint8_t *p_key )
 {
-    u8 p_buffer[10];
+    uint8_t p_buffer[10];
     unsigned int i_t1, i_t2, i_t3, i_t4, i_t5, i_t6;
     unsigned int i_try;
     unsigned int i_candidate;
@@ -1384,8 +1397,8 @@
 static int CrackTitleKey( dvdcss_t dvdcss, int i_pos, int i_len, 
                           dvd_key_t p_titlekey )
 {
-    u8       p_buf[0x800];
-    const u8 p_packstart[4] = { 0x00, 0x00, 0x01, 0xba };
+    uint8_t       p_buf[0x800];
+    const uint8_t p_packstart[4] = { 0x00, 0x00, 0x01, 0xba };
     int      i_reads = 0;
     int      i_encrypted = 0;
     int      b_stop_scanning = 0;
@@ -1482,7 +1495,7 @@
         return 1;
     }
 
-    if( i_encrypted == 0 && i_reads>0 )
+    if( i_encrypted == 0 && i_reads > 0 )
     {
         memset( p_titlekey, 0, KEY_SIZE );
         _dvdcss_debug( dvdcss, "file was unscrambled" );
@@ -1501,7 +1514,8 @@
  * Then it guesses that the plain text for first encrypted bytes are
  * a contiuation of that pattern.
  *****************************************************************************/
-static int AttackPattern( u8 const p_sec[0x800], int i_pos, u8 *p_key )
+static int AttackPattern( uint8_t const p_sec[0x800],
+                          int i_pos, uint8_t *p_key )
 {
     unsigned int i_best_plen = 0;
     unsigned int i_best_p = 0;
@@ -1566,7 +1580,8 @@
  * Padding stream. This looks like 0x00 00 01 be xx xx ff ff ...
  * where xx xx is the length of the padding stream.
  *****************************************************************************/
-static int AttackPadding( u8 const p_sec[0x800], int i_pos, u8 *p_key )
+static int AttackPadding( uint8_t const p_sec[0x800],
+                          int i_pos, uint8_t *p_key )
 {
     unsigned int i_pes_length;
     /*static int i_tries = 0, i_success = 0;*/
Index: libmpdvdkit2/css.h
===================================================================
RCS file: /cvsroot/mplayer/main/libmpdvdkit2/css.h,v
retrieving revision 1.1
diff -b -B -u -r1.1 css.h
--- libmpdvdkit2/css.h	16 Aug 2002 22:35:45 -0000	1.1
+++ libmpdvdkit2/css.h	7 Feb 2003 23:25:41 -0000
@@ -28,7 +28,7 @@
  *****************************************************************************/
 #define KEY_SIZE 5
 
-typedef u8 dvd_key_t[KEY_SIZE];
+typedef uint8_t dvd_key_t[KEY_SIZE];
 
 typedef struct dvd_title_s
 {
@@ -52,5 +52,5 @@
 int   _dvdcss_title       ( dvdcss_t, int );
 int   _dvdcss_disckey     ( dvdcss_t );
 int   _dvdcss_titlekey    ( dvdcss_t, int , dvd_key_t );
-int   _dvdcss_unscramble  ( u8 *, u8 * );
+int   _dvdcss_unscramble  ( uint8_t *, uint8_t * );
 
Index: libmpdvdkit2/csstables.h
===================================================================
RCS file: /cvsroot/mplayer/main/libmpdvdkit2/csstables.h,v
retrieving revision 1.1
diff -b -B -u -r1.1 csstables.h
--- libmpdvdkit2/csstables.h	16 Aug 2002 22:35:45 -0000	1.1
+++ libmpdvdkit2/csstables.h	7 Feb 2003 23:25:42 -0000
@@ -30,7 +30,7 @@
  *****************************************************************************/
 
 
-static u8 p_css_tab1[ 256 ] =
+static uint8_t p_css_tab1[ 256 ] =
 {
     0x33, 0x73, 0x3b, 0x26, 0x63, 0x23, 0x6b, 0x76,
     0x3e, 0x7e, 0x36, 0x2b, 0x6e, 0x2e, 0x66, 0x7b,
@@ -66,7 +66,7 @@
     0xba, 0xfa, 0xb2, 0xaf, 0xea, 0xaa, 0xe2, 0xff
 };
 
-static u8 p_css_tab2[ 256 ] =
+static uint8_t p_css_tab2[ 256 ] =
 {
     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
     0x09, 0x08, 0x0b, 0x0a, 0x0d, 0x0c, 0x0f, 0x0e,
@@ -102,7 +102,7 @@
     0xe4, 0xe5, 0xe6, 0xe7, 0xe0, 0xe1, 0xe2, 0xe3
 };
 
-static u8 p_css_tab3[ 512 ] =
+static uint8_t p_css_tab3[ 512 ] =
 {
     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
@@ -170,7 +170,7 @@
     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff
 };
 
-static u8 p_css_tab4[ 256 ] =
+static uint8_t p_css_tab4[ 256 ] =
 {
     0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
     0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
@@ -206,7 +206,7 @@
     0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
 };
 
-static u8 p_css_tab5[ 256 ] =
+static uint8_t p_css_tab5[ 256 ] =
 {
     0xff, 0x7f, 0xbf, 0x3f, 0xdf, 0x5f, 0x9f, 0x1f,
     0xef, 0x6f, 0xaf, 0x2f, 0xcf, 0x4f, 0x8f, 0x0f,
@@ -242,7 +242,7 @@
     0xe0, 0x60, 0xa0, 0x20, 0xc0, 0x40, 0x80, 0x00
 };
 
-static u8 p_crypt_tab0[ 256 ] =
+static uint8_t p_crypt_tab0[ 256 ] =
 {
     0xB7, 0xF4, 0x82, 0x57, 0xDA, 0x4D, 0xDB, 0xE2,
     0x2F, 0x52, 0x1A, 0xA8, 0x68, 0x5A, 0x8A, 0xFF,
@@ -278,7 +278,7 @@
     0xAD, 0x94, 0x77, 0x04, 0x9A, 0x39, 0xCF, 0x7C
 };
 
-static u8 p_crypt_tab1[ 256 ] =
+static uint8_t p_crypt_tab1[ 256 ] =
 {
     0x8C, 0x47, 0xB0, 0xE1, 0xEB, 0xFC, 0xEB, 0x56,
     0x10, 0xE5, 0x2C, 0x1A, 0x5D, 0xEF, 0xBE, 0x4F,
@@ -314,7 +314,7 @@
     0xAA, 0x1B, 0x79, 0x8E, 0x97, 0xB4, 0xC3, 0xF4
 };
 
-static u8 p_crypt_tab2[ 256 ] =
+static uint8_t p_crypt_tab2[ 256 ] =
 {
     0xB7, 0x75, 0x81, 0xD5, 0xDC, 0xCA, 0xDE, 0x66,
     0x23, 0xDF, 0x15, 0x26, 0x62, 0xD1, 0x83, 0x77,
@@ -350,7 +350,7 @@
     0x29, 0x91, 0xF0, 0x02, 0x18, 0x3A, 0x4E, 0x7C 
 };
 
-static u8 p_crypt_tab3[ 288 ] =
+static uint8_t p_crypt_tab3[ 288 ] =
 {
     0x73, 0x51, 0x95, 0xE1, 0x12, 0xE4, 0xC0, 0x58,
     0xEE, 0xF2, 0x08, 0x1B, 0xA9, 0xFA, 0x98, 0x4C,
Index: libmpdvdkit2/device.c
===================================================================
RCS file: /cvsroot/mplayer/main/libmpdvdkit2/device.c,v
retrieving revision 1.3
diff -b -B -u -r1.3 device.c
--- libmpdvdkit2/device.c	29 Dec 2002 15:32:56 -0000	1.3
+++ libmpdvdkit2/device.c	7 Feb 2003 23:25:43 -0000
@@ -34,12 +34,9 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
+#include <limits.h>
 
-#ifdef HAVE_UNISTD_H
-#   include <unistd.h>
-#endif
-
-#if defined( WIN32 )
+#if defined( WIN32 ) && !defined( SYS_CYGWIN )
 #   include <io.h>                                                 /* read() */
 #else
 #   include <sys/uio.h>                                      /* struct iovec */
@@ -250,6 +247,8 @@
         return -1;
     }
 
+    dvdcss->i_pos = 0;
+
     return 0;
 }
 
@@ -285,6 +284,8 @@
         return -1;
     }
 
+    dvdcss->i_pos = 0;
+
     return 0;
 }
 
@@ -387,6 +388,7 @@
                 {
                     fd->i_sid = MAKEWORD( i, j );
                     dvdcss->i_fd = (int) fd;
+                    dvdcss->i_pos = 0;
                     return 0;
                 }
                 else
@@ -412,45 +414,59 @@
  *****************************************************************************/
 static int libc_seek( dvdcss_t dvdcss, int i_blocks )
 {
-    off_t   i_read;
+    off_t   i_seek;
 
-    dvdcss->i_seekpos = i_blocks;
+    if( dvdcss->i_pos == i_blocks )
+    {
+        /* We are already in position */
+        return i_blocks;
+    }
 
-    i_read = lseek( dvdcss->i_read_fd,
+    i_seek = lseek( dvdcss->i_read_fd,
                     (off_t)i_blocks * (off_t)DVDCSS_BLOCK_SIZE, SEEK_SET );
 
-    if( i_read < 0 )
+    if( i_seek < 0 )
     {
         _dvdcss_error( dvdcss, "seek error" );
+        dvdcss->i_pos = -1;
+        return i_seek;
     }
 
-    return i_read / DVDCSS_BLOCK_SIZE;
+    dvdcss->i_pos = i_seek / DVDCSS_BLOCK_SIZE;
+
+    return dvdcss->i_pos;
 }
 
 #if defined( WIN32 )
 static int win2k_seek( dvdcss_t dvdcss, int i_blocks )
 {
-    LARGE_INTEGER li_read;
-
-    dvdcss->i_seekpos = i_blocks;
+    LARGE_INTEGER li_seek;
 
 #ifndef INVALID_SET_FILE_POINTER
 #   define INVALID_SET_FILE_POINTER ((DWORD)-1)
 #endif
 
-    li_read.QuadPart = (LONGLONG)i_blocks * DVDCSS_BLOCK_SIZE;
+    if( dvdcss->i_pos == i_blocks )
+    {
+        /* We are already in position */
+        return i_blocks;
+    }
+
+    li_seek.QuadPart = (LONGLONG)i_blocks * DVDCSS_BLOCK_SIZE;
 
-    li_read.LowPart = SetFilePointer( (HANDLE) dvdcss->i_fd,
-                                      li_read.LowPart,
-                                      &li_read.HighPart, FILE_BEGIN );
-    if( (li_read.LowPart == INVALID_SET_FILE_POINTER)
+    li_seek.LowPart = SetFilePointer( (HANDLE) dvdcss->i_fd,
+                                      li_seek.LowPart,
+                                      &li_seek.HighPart, FILE_BEGIN );
+    if( (li_seek.LowPart == INVALID_SET_FILE_POINTER)
         && GetLastError() != NO_ERROR)
     {
-        li_read.QuadPart = -DVDCSS_BLOCK_SIZE;
+        dvdcss->i_pos = -1;
+        return -1;
     }
 
-    li_read.QuadPart /= DVDCSS_BLOCK_SIZE;
-    return (int)li_read.QuadPart;
+    dvdcss->i_pos = li_seek.QuadPart / DVDCSS_BLOCK_SIZE;
+
+    return dvdcss->i_pos;
 }
 
 static int aspi_seek( dvdcss_t dvdcss, int i_blocks )
@@ -459,18 +475,27 @@
     char sz_buf[ DVDCSS_BLOCK_SIZE ];
     struct w32_aspidev *fd = (struct w32_aspidev *) dvdcss->i_fd;
     
+    if( dvdcss->i_pos == i_blocks )
+    {
+        /* We are already in position */
+        return i_blocks;
+    }
+
     i_old_blocks = fd->i_blocks;
     fd->i_blocks = i_blocks;
 
     if( aspi_read_internal( dvdcss->i_fd, sz_buf, 1 ) == -1 )
     {
         fd->i_blocks = i_old_blocks;
+        dvdcss->i_pos = -1;
         return -1;
     }
 
     (fd->i_blocks)--;
 
-    return fd->i_blocks;
+    dvdcss->i_pos = fd->i_blocks;
+
+    return dvdcss->i_pos;
 }
 #endif
 
@@ -479,11 +504,11 @@
  *****************************************************************************/
 static int libc_read ( dvdcss_t dvdcss, void *p_buffer, int i_blocks )
 {
-    int i_ret;
-    /* TODO: partial reads are wrong,i.e 2200/2048 = 1 
-     * but the location has advanced 2200 bytes (lseek possition that is) */
+    off_t i_ret;
+
     i_ret = read( dvdcss->i_read_fd, p_buffer,
                   (off_t)i_blocks * DVDCSS_BLOCK_SIZE );
+
     if( i_ret < 0 )
     {
         _dvdcss_error( dvdcss, "read error" );
@@ -487,9 +512,27 @@
     if( i_ret < 0 )
     {
         _dvdcss_error( dvdcss, "read error" );
+        dvdcss->i_pos = -1;
         return i_ret;
     }
 
+    /* Handle partial reads */
+    if( i_ret != (off_t)i_blocks * DVDCSS_BLOCK_SIZE )
+    {
+        int i_seek;
+
+        dvdcss->i_pos = -1;
+        i_seek = libc_seek( dvdcss, i_ret / DVDCSS_BLOCK_SIZE );
+        if( i_seek < 0 )
+        {
+            return i_seek;
+        }
+
+        /* We have to return now so that i_pos isn't clobbered */
+        return i_ret / DVDCSS_BLOCK_SIZE;
+    }
+
+    dvdcss->i_pos += i_ret / DVDCSS_BLOCK_SIZE;
     return i_ret / DVDCSS_BLOCK_SIZE;
 }
 
@@ -502,15 +545,26 @@
               i_blocks * DVDCSS_BLOCK_SIZE,
               (LPDWORD)&i_bytes, NULL ) )
     {
+        dvdcss->i_pos = -1;
         return -1;
     }
 
+    dvdcss->i_pos += i_bytes / DVDCSS_BLOCK_SIZE;
     return i_bytes / DVDCSS_BLOCK_SIZE;
 }
 
 static int aspi_read ( dvdcss_t dvdcss, void *p_buffer, int i_blocks )
 {
-    return aspi_read_internal( dvdcss->i_fd, p_buffer, i_blocks );
+    int i_read = aspi_read_internal( dvdcss->i_fd, p_buffer, i_blocks );
+
+    if( i_read < 0 )
+    {
+        dvdcss->i_pos = -1;
+        return i_read;
+    }
+
+    dvdcss->i_pos += i_read;
+    return i_read;
 }
 #endif
 
@@ -544,6 +598,7 @@
              * We won't even bother returning the reads that went ok,
              * and as in the posix spec the file postition is left
              * unspecified after a failure */
+            dvdcss->i_pos = -1;
             return -1;
         }
 
@@ -553,14 +608,32 @@
         {
             /* We reached the end of the file or a signal interrupted
              * the read. Return a partial read. */
+            int i_seek;
+
+            dvdcss->i_pos = -1;
+            i_seek = libc_seek( dvdcss, i_total / DVDCSS_BLOCK_SIZE );
+            if( i_seek < 0 )
+            {
+                return i_seek;
+            }
+
+            /* We have to return now so that i_pos isn't clobbered */
             return i_total / DVDCSS_BLOCK_SIZE;
         }
     }
 
+    dvdcss->i_pos += i_total / DVDCSS_BLOCK_SIZE;
     return i_total / DVDCSS_BLOCK_SIZE;
 #else
     int i_read = readv( dvdcss->i_read_fd, p_iovec, i_blocks );
 
+    if( i_read < 0 )
+    {
+        dvdcss->i_pos = -1;
+        return i_read;
+    }
+
+    dvdcss->i_pos += i_read / DVDCSS_BLOCK_SIZE;
     return i_read / DVDCSS_BLOCK_SIZE;
 #endif
 }
@@ -588,6 +661,7 @@
         if( !dvdcss->p_readv_buffer )
         {
             _dvdcss_error( dvdcss, " failed (readv)" );
+            dvdcss->i_pos = -1;
             return -1;
         }
     }
@@ -610,6 +684,7 @@
             /* The read failed... too bad.
              * As in the posix spec the file postition is left
              * unspecified after a failure */
+            dvdcss->i_pos = -1;
             return -1;
         }
         i_blocks_read = i_bytes / DVDCSS_BLOCK_SIZE;
@@ -622,6 +697,7 @@
         if( i_blocks_read < 0 )
         {
             /* See above */
+            dvdcss->i_pos = -1;
             return -1;
         }
     }
@@ -641,6 +717,7 @@
         i_blocks_total -= ( p_iovec[i_index].iov_len / DVDCSS_BLOCK_SIZE );
     } 
 
+    dvdcss->i_pos += i_blocks_read;
     return i_blocks_read;
 }
 
@@ -688,7 +765,8 @@
 
         /* transfer the next 64kb (aspi_read_internal is called recursively)
          * We need to check the status of the read on return */
-        if( aspi_read_internal( i_fd, (u8*) p_data + 32 * DVDCSS_BLOCK_SIZE,
+        if( aspi_read_internal( i_fd,
+                                (uint8_t*) p_data + 32 * DVDCSS_BLOCK_SIZE,
                                  i_blocks - 32) < 0 )
         {
             return -1;
Index: libmpdvdkit2/device.h
===================================================================
RCS file: /cvsroot/mplayer/main/libmpdvdkit2/device.h,v
retrieving revision 1.2
diff -b -B -u -r1.2 device.h
--- libmpdvdkit2/device.h	29 Dec 2002 15:32:56 -0000	1.2
+++ libmpdvdkit2/device.h	7 Feb 2003 23:25:43 -0000
@@ -26,13 +26,14 @@
 /*****************************************************************************
  * iovec structure: vectored data entry
  *****************************************************************************/
-#if defined( WIN32 )
+#if defined( WIN32 ) && !defined( SYS_CYGWIN )
 #   include <io.h>                                                 /* read() */
 #else
+#   include <sys/types.h>
 #   include <sys/uio.h>                                      /* struct iovec */
 #endif
 
-#if defined( WIN32 )
+#if defined( WIN32 ) && !defined( SYS_CYGWIN )
 struct iovec
 {
     void *iov_base;     /* Pointer to data. */
Index: libmpdvdkit2/dvd_reader.c
===================================================================
RCS file: /cvsroot/mplayer/main/libmpdvdkit2/dvd_reader.c,v
retrieving revision 1.5
diff -b -B -u -r1.5 dvd_reader.c
--- libmpdvdkit2/dvd_reader.c	10 Jan 2003 22:48:49 -0000	1.5
+++ libmpdvdkit2/dvd_reader.c	7 Feb 2003 23:25:44 -0000
@@ -154,7 +154,7 @@
  extern char * get_path( char * filename );
 #endif
 
-extern char * dvdcss_cache_dir;
+//extern char * dvdcss_cache_dir;
 
 /**
  * Open a DVD image or block device file.
@@ -164,13 +164,14 @@
     dvd_reader_t *dvd;
     dvd_input_t dev;
 
-    /* setup cache dir */
+    /* setup cache dir is no longer needed, it's now implemented in libdvdcss.c
     if(!dvdcss_cache_dir){
 	dvdcss_cache_dir=get_path( "" );
 	if ( dvdcss_cache_dir ) { mkdir( dvdcss_cache_dir,493 ); free( dvdcss_cache_dir ); }
 	dvdcss_cache_dir=get_path( "DVDKeys" );
 	if(dvdcss_cache_dir) mkdir( dvdcss_cache_dir,493 );
     }
+    */
     
     /* open it */
     dev = DVDinput_open( location );
Index: libmpdvdkit2/dvdcss.h
===================================================================
RCS file: /cvsroot/mplayer/main/libmpdvdkit2/dvdcss.h,v
retrieving revision 1.2
diff -b -B -u -r1.2 dvdcss.h
--- libmpdvdkit2/dvdcss.h	16 Aug 2002 22:50:21 -0000	1.2
+++ libmpdvdkit2/dvdcss.h	7 Feb 2003 23:25:44 -0000
@@ -61,10 +61,6 @@
  */
 extern char *        dvdcss_interface_2;
 
-/*
- * Path to CSS key cache. Default == NULL (no cache).
- */
-extern char * dvdcss_cache_dir;
 
 /*
  * Exported prototypes.
Index: libmpdvdkit2/error.c
===================================================================
RCS file: /cvsroot/mplayer/main/libmpdvdkit2/error.c,v
retrieving revision 1.2
diff -b -B -u -r1.2 error.c
--- libmpdvdkit2/error.c	16 Aug 2002 22:50:21 -0000	1.2
+++ libmpdvdkit2/error.c	7 Feb 2003 23:25:44 -0000
@@ -24,6 +24,7 @@
 #include "config.h"
 
 #include <stdio.h>
+#include <limits.h>
 
 #include "dvdcss.h"
 
Index: libmpdvdkit2/ioctl.c
===================================================================
RCS file: /cvsroot/mplayer/main/libmpdvdkit2/ioctl.c,v
retrieving revision 1.5
diff -b -B -u -r1.5 ioctl.c
--- libmpdvdkit2/ioctl.c	8 Jan 2003 14:11:33 -0000	1.5
+++ libmpdvdkit2/ioctl.c	7 Feb 2003 23:25:46 -0000
@@ -121,6 +121,7 @@
  * Local prototypes, win32 (aspi) specific
  *****************************************************************************/
 #if defined( WIN32 )
+static void WinInitSPTD ( SCSI_PASS_THROUGH_DIRECT *, int );
 static void WinInitSSC ( struct SRB_ExecSCSICmd *, int );
 static int  WinSendSSC ( int, struct SRB_ExecSCSICmd * );
 #endif
@@ -216,36 +217,18 @@
 #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.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 = 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;
+        i_ret = SEND_SPTD( i_fd, &sptd, &tmp );
 
         if( i_ret == 0 )
         {
@@ -297,7 +280,7 @@
 /*****************************************************************************
  * ioctl_ReadDiscKey: get the disc key
  *****************************************************************************/
-int ioctl_ReadDiscKey( int i_fd, int *pi_agid, u8 *p_key )
+int ioctl_ReadDiscKey( int i_fd, int *pi_agid, uint8_t *p_key )
 {
     int i_ret;
 
@@ -395,7 +378,7 @@
     if( WIN2K ) /* NT/2k/XP */
     {
         DWORD tmp;
-        u8 buffer[DVD_DISK_KEY_LENGTH];
+        uint8_t buffer[DVD_DISK_KEY_LENGTH];
         PDVD_COPY_PROTECT_KEY key = (PDVD_COPY_PROTECT_KEY) &buffer;
 
         memset( &buffer, 0, sizeof( buffer ) );
@@ -470,7 +453,7 @@
 /*****************************************************************************
  * ioctl_ReadTitleKey: get the title key
  *****************************************************************************/
-int ioctl_ReadTitleKey( int i_fd, int *pi_agid, int i_pos, u8 *p_key )
+int ioctl_ReadTitleKey( int i_fd, int *pi_agid, int i_pos, uint8_t *p_key )
 {
     int i_ret;
 
@@ -563,7 +546,7 @@
     if( WIN2K ) /* NT/2k/XP */
     {
         DWORD tmp;
-        u8 buffer[DVD_BUS_KEY_LENGTH];
+        uint8_t buffer[DVD_TITLE_KEY_LENGTH];
         PDVD_COPY_PROTECT_KEY key = (PDVD_COPY_PROTECT_KEY) &buffer;
 
         memset( &buffer, 0, sizeof( buffer ) );
@@ -758,7 +741,7 @@
 /*****************************************************************************
  * ioctl_ReportChallenge: get challenge from the drive
  *****************************************************************************/
-int ioctl_ReportChallenge( int i_fd, int *pi_agid, u8 *p_challenge )
+int ioctl_ReportChallenge( int i_fd, int *pi_agid, uint8_t *p_challenge )
 {
     int i_ret;
 
@@ -830,7 +813,7 @@
     if( WIN2K ) /* NT/2k/XP */
     {
         DWORD tmp;
-        u8 buffer[DVD_CHALLENGE_KEY_LENGTH];
+        uint8_t buffer[DVD_CHALLENGE_KEY_LENGTH];
         PDVD_COPY_PROTECT_KEY key = (PDVD_COPY_PROTECT_KEY) &buffer;
 
         memset( &buffer, 0, sizeof( buffer ) );
@@ -962,7 +945,7 @@
     if( WIN2K ) /* NT/2k/XP */
     {
         DWORD tmp;
-        u8 buffer[DVD_ASF_LENGTH];
+        uint8_t buffer[DVD_ASF_LENGTH];
         PDVD_COPY_PROTECT_KEY key = (PDVD_COPY_PROTECT_KEY) &buffer;
 
         memset( &buffer, 0, sizeof( buffer ) );
@@ -1025,7 +1008,7 @@
 /*****************************************************************************
  * ioctl_ReportKey1: get the first key from the drive
  *****************************************************************************/
-int ioctl_ReportKey1( int i_fd, int *pi_agid, u8 *p_key )
+int ioctl_ReportKey1( int i_fd, int *pi_agid, uint8_t *p_key )
 {
     int i_ret;
 
@@ -1097,7 +1080,7 @@
     if( WIN2K ) /* NT/2k/XP */
     {
         DWORD tmp;
-        u8 buffer[DVD_BUS_KEY_LENGTH];
+        uint8_t buffer[DVD_BUS_KEY_LENGTH];
         PDVD_COPY_PROTECT_KEY key = (PDVD_COPY_PROTECT_KEY) &buffer;
 
         memset( &buffer, 0, sizeof( buffer ) );
@@ -1265,7 +1248,7 @@
 /*****************************************************************************
  * ioctl_SendChallenge: send challenge to the drive
  *****************************************************************************/
-int ioctl_SendChallenge( int i_fd, int *pi_agid, u8 *p_challenge )
+int ioctl_SendChallenge( int i_fd, int *pi_agid, uint8_t *p_challenge )
 {
     int i_ret;
 
@@ -1278,7 +1261,7 @@
 
     memcpy( auth_info.hsc.chal, p_challenge, DVD_CHALLENGE_SIZE );
 
-    return ioctl( i_fd, DVD_AUTH, &auth_info );
+    i_ret = ioctl( i_fd, DVD_AUTH, &auth_info );
 
 #elif defined( HAVE_BSD_DVD_STRUCT )
     struct dvd_authinfo auth_info;
@@ -1289,7 +1272,7 @@
 
     memcpy( auth_info.keychal, p_challenge, DVD_CHALLENGE_SIZE );
 
-    return ioctl( i_fd, DVDIOCSENDKEY, &auth_info );
+    i_ret = ioctl( i_fd, DVDIOCSENDKEY, &auth_info );
 
 #elif defined( SYS_BEOS )
     INIT_RDC( GPCMD_SEND_KEY, 16 );
@@ -1299,7 +1282,7 @@
     p_buffer[ 1 ] = 0xe;
     memcpy( p_buffer + 4, p_challenge, DVD_CHALLENGE_SIZE );
 
-    return ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
+    i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
 
 #elif defined( HPUX_SCTL_IO )
     INIT_SCTL_IO( GPCMD_SEND_KEY, 16 );
@@ -1309,7 +1292,7 @@
     p_buffer[ 1 ] = 0xe;
     memcpy( p_buffer + 4, p_challenge, DVD_CHALLENGE_SIZE );
 
-    return ioctl( i_fd, SIOC_IO, &sctl_io );
+    i_ret = ioctl( i_fd, SIOC_IO, &sctl_io );
 
 #elif defined( SOLARIS_USCSI )
     INIT_USCSI( GPCMD_SEND_KEY, 16 );
@@ -1324,7 +1307,7 @@
         return -1;
     }
 
-    return 0;
+    i_ret = 0;
     
 #elif defined( DARWIN_DVD_IOCTL )
     INIT_DVDIOCTL( dk_dvd_send_key_t, DVDChallengeKeyInfo,
@@ -1342,7 +1325,7 @@
     if( WIN2K ) /* NT/2k/XP */
     {
         DWORD tmp;
-        u8 buffer[DVD_CHALLENGE_KEY_LENGTH];
+        uint8_t buffer[DVD_CHALLENGE_KEY_LENGTH];
         PDVD_COPY_PROTECT_KEY key = (PDVD_COPY_PROTECT_KEY) &buffer;
 
         memset( &buffer, 0, sizeof( buffer ) );
@@ -1354,7 +1337,7 @@
 
         memcpy( key->KeyData, p_challenge, DVD_CHALLENGE_SIZE );
 
-        return DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_SEND_KEY, key, 
+        i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_SEND_KEY, key,
                 key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1;
     }
     else
@@ -1366,7 +1349,7 @@
         p_buffer[ 1 ] = 0xe;
         memcpy( p_buffer + 4, p_challenge, DVD_CHALLENGE_SIZE );
 
-        return WinSendSSC( i_fd, &ssc );
+        i_ret = WinSendSSC( i_fd, &ssc );
     }
 
 #elif defined( __QNXNTO__ )
@@ -1388,9 +1371,9 @@
     p_buffer[ 1 ] = 0xe;
     memcpy( p_buffer + 4, p_challenge, DVD_CHALLENGE_SIZE );
 
-    return DosDevIOCtl(i_fd, IOCTL_CDROMDISK, CDROMDISK_EXECMD,
+    i_ret = DosDevIOCtl( i_fd, IOCTL_CDROMDISK, CDROMDISK_EXECMD,
                        &sdc, sizeof(sdc), &ulParamLen,
-                       p_buffer, sizeof(p_buffer), &ulDataLen);
+                         p_buffer, sizeof(p_buffer), &ulDataLen );
 
 #else
 #   error "DVD ioctls are unavailable on this system"
@@ -1402,7 +1385,7 @@
 /*****************************************************************************
  * ioctl_SendKey2: send the second key to the drive
  *****************************************************************************/
-int ioctl_SendKey2( int i_fd, int *pi_agid, u8 *p_key )
+int ioctl_SendKey2( int i_fd, int *pi_agid, uint8_t *p_key )
 {
     int i_ret;
 
@@ -1415,7 +1398,7 @@
 
     memcpy( auth_info.hsk.key, p_key, DVD_KEY_SIZE );
 
-    return ioctl( i_fd, DVD_AUTH, &auth_info );
+    i_ret = ioctl( i_fd, DVD_AUTH, &auth_info );
 
 #elif defined( HAVE_BSD_DVD_STRUCT )
     struct dvd_authinfo auth_info;
@@ -1426,7 +1409,7 @@
 
     memcpy( auth_info.keychal, p_key, DVD_KEY_SIZE );
 
-    return ioctl( i_fd, DVDIOCSENDKEY, &auth_info );
+    i_ret = ioctl( i_fd, DVDIOCSENDKEY, &auth_info );
 
 #elif defined( SYS_BEOS )
     INIT_RDC( GPCMD_SEND_KEY, 12 );
@@ -1436,7 +1419,7 @@
     p_buffer[ 1 ] = 0xa;
     memcpy( p_buffer + 4, p_key, DVD_KEY_SIZE );
 
-    return ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
+    i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
 
 #elif defined( HPUX_SCTL_IO )
     INIT_SCTL_IO( GPCMD_SEND_KEY, 12 );
@@ -1446,7 +1429,7 @@
     p_buffer[ 1 ] = 0xa;
     memcpy( p_buffer + 4, p_key, DVD_KEY_SIZE );
 
-    return ioctl( i_fd, SIOC_IO, &sctl_io );
+    i_ret = ioctl( i_fd, SIOC_IO, &sctl_io );
 
 #elif defined( SOLARIS_USCSI )
     INIT_USCSI( GPCMD_SEND_KEY, 12 );
@@ -1461,7 +1444,7 @@
         return -1;
     }
 
-    return 0;
+    i_ret = 0;
     
 #elif defined( DARWIN_DVD_IOCTL )
     INIT_DVDIOCTL( dk_dvd_send_key_t, DVDKey2Info,
@@ -1479,7 +1462,7 @@
     if( WIN2K ) /* NT/2k/XP */
     {
         DWORD tmp;
-        u8 buffer[DVD_BUS_KEY_LENGTH];
+        uint8_t buffer[DVD_BUS_KEY_LENGTH];
         PDVD_COPY_PROTECT_KEY key = (PDVD_COPY_PROTECT_KEY) &buffer;
 
         memset( &buffer, 0, sizeof( buffer ) );
@@ -1491,7 +1474,7 @@
 
         memcpy( key->KeyData, p_key, DVD_KEY_SIZE );
 
-        return DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_SEND_KEY, key, 
+        i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_SEND_KEY, key,
                 key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1;
     }
     else
@@ -1503,7 +1486,7 @@
         p_buffer[ 1 ] = 0xa;
         memcpy( p_buffer + 4, p_key, DVD_KEY_SIZE );
 
-        return WinSendSSC( i_fd, &ssc );
+        i_ret = WinSendSSC( i_fd, &ssc );
     }
 
 #elif defined( __QNXNTO__ )
@@ -1525,9 +1508,9 @@
     p_buffer[ 1 ] = 0xa;
     memcpy( p_buffer + 4, p_key, DVD_KEY_SIZE );
 
-    return DosDevIOCtl(i_fd, IOCTL_CDROMDISK, CDROMDISK_EXECMD,
+    i_ret = DosDevIOCtl( i_fd, IOCTL_CDROMDISK, CDROMDISK_EXECMD,
                        &sdc, sizeof(sdc), &ulParamLen,
-                       p_buffer, sizeof(p_buffer), &ulDataLen);
+                         p_buffer, sizeof(p_buffer), &ulDataLen );
 
 #else
 #   error "DVD ioctls are unavailable on this system"
@@ -1625,28 +1608,26 @@
     if( WIN2K ) /* NT/2k/XP */
     {
         DWORD tmp;
-        u8 buffer[ DVD_REGION_LENGTH ];
-        PDVD_REGION region = (PDVD_REGION) &buffer;
+        uint8_t buffer[DVD_RPC_KEY_LENGTH];
+        PDVD_COPY_PROTECT_KEY key = (PDVD_COPY_PROTECT_KEY) &buffer;
 
         memset( &buffer, 0, sizeof( buffer ) );
 
-        i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_GET_REGION, NULL, 0,
-                region, DVD_REGION_LENGTH, &tmp, NULL ) ? 0 : -1;
+        key->KeyLength  = DVD_RPC_KEY_LENGTH;
+        key->KeyType    = DvdGetRpcKey;
+        key->KeyFlags   = 0;
 
-        /* Someone who has the headers should correct all this. */
-        /* Use the IOCTL_SCSI_PASS_THROUGH_DIRECT so we get the real
-         * values of theses entities?  */
-        if(region->SystemRegion != 0) {
-            *p_type = region->ResetCount > 1 ? 1 : 3 - region->ResetCount;
-            *p_mask =  0xff ^ (1 << (region->SystemRegion - 1));
-            *p_scheme = 1;
-        }
-        else
+        i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_READ_KEY, key,
+                key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1;
+
+        if( i_ret < 0 )
         {
-            *p_type = 0;  /* ?? */
-            *p_mask = 0xff;
-            *p_scheme = 1; /* ?? */
+            return i_ret;
         }
+
+        *p_type = ((PDVD_RPC_KEY)key->KeyData)->TypeCode;
+        *p_mask = ((PDVD_RPC_KEY)key->KeyData)->RegionMask;
+        *p_scheme = ((PDVD_RPC_KEY)key->KeyData)->RpcScheme;
     }
     else
     {
@@ -1693,6 +1674,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;
+
+    i_ret = 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;
+
+    i_ret = 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;
+
+    i_ret = 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;
+
+    i_ret = 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 = SolarisSendUSCSI( i_fd, &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;
+
+    i_ret = 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;
+
+        i_ret = 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;
+
+        i_ret = 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;
+
+    i_ret = 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;
+
+    i_ret = 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 )
@@ -1848,6 +1956,36 @@
 
 #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 ] = (uint8_t)(p_sptd->DataTransferLength >> 8) & 0xff;
+    p_sptd->Cdb[ 9 ] = (uint8_t) p_sptd->DataTransferLength       & 0xff;
+    p_sptd->CdbLength = 12;
+
+    p_sptd->TimeOutValue = 2;
+}
+
+/*****************************************************************************
  * WinInitSSC: initialize a ssc structure for the win32 aspi layer
  *****************************************************************************
  * This function initializes a ssc raw device command structure for future
@@ -1874,8 +2012,8 @@
 
     p_ssc->CDBByte[ 0 ] = i_type;
 
-    p_ssc->CDBByte[ 8 ] = (u8)(p_ssc->SRB_BufLen >> 8) & 0xff;
-    p_ssc->CDBByte[ 9 ] = (u8) p_ssc->SRB_BufLen       & 0xff;
+    p_ssc->CDBByte[ 8 ] = (uint8_t)(p_ssc->SRB_BufLen >> 8) & 0xff;
+    p_ssc->CDBByte[ 9 ] = (uint8_t) p_ssc->SRB_BufLen       & 0xff;
     p_ssc->SRB_CDBLen   = 12;
 
     p_ssc->SRB_SenseLen = SENSE_LEN;
Index: libmpdvdkit2/ioctl.h
===================================================================
RCS file: /cvsroot/mplayer/main/libmpdvdkit2/ioctl.h,v
retrieving revision 1.2
diff -b -B -u -r1.2 ioctl.h
--- libmpdvdkit2/ioctl.h	29 Dec 2002 15:32:56 -0000	1.2
+++ libmpdvdkit2/ioctl.h	7 Feb 2003 23:25:47 -0000
@@ -22,15 +22,17 @@
  *****************************************************************************/
 
 int ioctl_ReadCopyright     ( int, int, int * );
-int ioctl_ReadDiscKey       ( int, int *, u8 * );
-int ioctl_ReadTitleKey      ( int, int *, int, u8 * );
+int ioctl_ReadDiscKey       ( int, int *, uint8_t * );
+int ioctl_ReadTitleKey      ( int, int *, int, uint8_t * );
 int ioctl_ReportAgid        ( int, int * );
-int ioctl_ReportChallenge   ( int, int *, u8 * );
-int ioctl_ReportKey1        ( int, int *, u8 * );
+int ioctl_ReportChallenge   ( int, int *, uint8_t * );
+int ioctl_ReportKey1        ( int, int *, uint8_t * );
 int ioctl_ReportASF         ( int, int *, int * );
 int ioctl_InvalidateAgid    ( int, int * );
-int ioctl_SendChallenge     ( int, int *, u8 * );
-int ioctl_SendKey2          ( int, int *, u8 * );
+int ioctl_SendChallenge     ( int, int *, uint8_t * );
+int ioctl_SendKey2          ( int, int *, uint8_t * );
+int ioctl_ReportRPC         ( int, int *, int *, int * );
+int ioctl_SendRPC           ( int, int );
 
 #define DVD_KEY_SIZE 5
 #define DVD_CHALLENGE_SIZE 10
@@ -42,7 +44,7 @@
 #if defined( SYS_BEOS )
 #define INIT_RDC( TYPE, SIZE ) \
     raw_device_command rdc; \
-    u8 p_buffer[ (SIZE) ]; \
+    uint8_t p_buffer[ (SIZE)+1 ]; \
     memset( &rdc, 0, sizeof( raw_device_command ) ); \
     rdc.data = (char *)p_buffer; \
     rdc.data_length = (SIZE); \
@@ -55,7 +57,7 @@
 #if defined( HPUX_SCTL_IO )
 #define INIT_SCTL_IO( TYPE, SIZE ) \
     struct sctl_io sctl_io; \
-    u8 p_buffer[ (SIZE) ]; \
+    uint8_t p_buffer[ (SIZE)+1 ]; \
     memset( &sctl_io, 0, sizeof( sctl_io ) ); \
     sctl_io.data = (void *)p_buffer; \
     sctl_io.data_length = (SIZE); \
@@ -71,10 +73,10 @@
 #define INIT_USCSI( TYPE, SIZE ) \
     struct uscsi_cmd sc; \
     union scsi_cdb rs_cdb; \
-    u8 p_buffer[ (SIZE) ]; \
+    uint8_t p_buffer[ (SIZE)+1 ]; \
     memset( &sc, 0, sizeof( struct uscsi_cmd ) ); \
     sc.uscsi_cdb = (caddr_t)&rs_cdb; \
-    sc.uscsi_bufaddr = p_buffer; \
+    sc.uscsi_bufaddr = (caddr_t)p_buffer; \
     sc.uscsi_buflen = (SIZE); \
     SolarisInitUSCSI( &sc, (TYPE) );
 #endif
@@ -94,12 +96,26 @@
 #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; \
+    uint8_t 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) ]; \
+    uint8_t p_buffer[ (SIZE)+1 ]; \
     memset( &ssc, 0, sizeof( struct SRB_ExecSCSICmd ) ); \
     ssc.SRB_BufPointer = (char *)p_buffer; \
     ssc.SRB_BufLen = (SIZE); \
@@ -128,7 +144,7 @@
 #if defined( SYS_OS2 )
 #define INIT_SSC( TYPE, SIZE ) \
     struct OS2_ExecSCSICmd sdc; \
-    u8 p_buffer[ (SIZE) ]; \
+    uint8_t p_buffer[ (SIZE)+1 ]; \
     unsigned long ulParamLen; \
     unsigned long ulDataLen; \
     memset( &sdc, 0, sizeof( OS2_ExecSCSICmd ) ); \
@@ -195,8 +211,8 @@
 #define DVD_BUS_KEY_LENGTH              (8 + sizeof(DVD_COPY_PROTECT_KEY))
 #define DVD_TITLE_KEY_LENGTH            (8 + sizeof(DVD_COPY_PROTECT_KEY))
 #define DVD_DISK_KEY_LENGTH             (2048 + sizeof(DVD_COPY_PROTECT_KEY))
+#define DVD_RPC_KEY_LENGTH              (sizeof(DVD_RPC_KEY) + sizeof(DVD_COPY_PROTECT_KEY))
 #define DVD_ASF_LENGTH                  (sizeof(DVD_ASF) + sizeof(DVD_COPY_PROTECT_KEY))
-#define DVD_REGION_LENGTH               (sizeof(DVD_REGION))
 
 #define DVD_COPYRIGHT_MASK              0x00000040
 #define DVD_NOT_COPYRIGHTED             0x00000000
@@ -271,12 +287,15 @@
     UCHAR Reserved1:7;
 } DVD_ASF, * PDVD_ASF;
 
-typedef struct _DVD_REGION {
-  UCHAR  CopySystem;
-  UCHAR  RegionData;
-  UCHAR  SystemRegion;
-  UCHAR  ResetCount;
-} DVD_REGION, *PDVD_REGION;
+typedef struct _DVD_RPC_KEY
+{
+    UCHAR UserResetsAvailable:3;
+    UCHAR ManufacturerResetsAvailable:3;
+    UCHAR TypeCode:2;
+    UCHAR RegionMask;
+    UCHAR RpcScheme;
+    UCHAR Reserved2[1];
+} DVD_RPC_KEY, * PDVD_RPC_KEY;
 
 typedef struct _SCSI_PASS_THROUGH_DIRECT
 {
Index: libmpdvdkit2/libdvdcss.c
===================================================================
RCS file: /cvsroot/mplayer/main/libmpdvdkit2/libdvdcss.c,v
retrieving revision 1.7
diff -b -B -u -r1.7 libdvdcss.c
--- libmpdvdkit2/libdvdcss.c	8 Jan 2003 16:10:39 -0000	1.7
+++ libmpdvdkit2/libdvdcss.c	7 Feb 2003 23:25:47 -0000
@@ -77,8 +77,17 @@
  *       decrypt a DVD stored on a hard disc, or a DVD with the wrong region
  *       on an RPC2 drive.
  *
- * \li \b DVDCSS_RAW_DEVICE: specify the raw device to use.
- * 
+ * \li \b DVDCSS_RAW_DEVICE: specify the raw device to use. Exact usage will
+ *     depend on your operating system, the Linux utility to set up raw devices
+ *     is \c raw(8) for instance. Please note that on most operating systems,
+ *     using a raw device requires highly aligned buffers: Linux requires a
+ *     2048 bytes alignment (which is the size of a DVD sector).
+ *
+ * \li \b DVDCSS_CACHE: specify a directory in which to store title key
+ *     values. This will speed up descrambling of DVDs which are in the
+ *     cache. The DVDCSS_CACHE directory is created if it does not exist,
+ *     and a subdirectory is created named after the DVD's title or
+ *     manufacturing date.
  */
 
 /*
@@ -92,10 +101,8 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
-
-#ifdef HAVE_UNISTD_H
-#   include <unistd.h>
-#endif
+#include <errno.h>
+#include <limits.h>
 
 #include "dvdcss.h"
 
@@ -117,8 +124,6 @@
  */
 char * dvdcss_interface_2 = VERSION;
 
-char * dvdcss_cache_dir = NULL;
-
 /**
  * \brief Open a DVD device or directory and return a dvdcss instance.
  *
@@ -139,6 +144,7 @@
 
     char *psz_method = getenv( "DVDCSS_METHOD" );
     char *psz_verbose = getenv( "DVDCSS_VERBOSE" );
+    char *psz_cache = getenv( "DVDCSS_CACHE" );
 #ifndef WIN32
     char *psz_raw_device = getenv( "DVDCSS_RAW_DEVICE" );
 #endif
@@ -164,9 +170,9 @@
     dvdcss->psz_device = (char *)strdup( psz_target );
     dvdcss->psz_error = "no error";
     dvdcss->i_method = DVDCSS_METHOD_KEY;
+    dvdcss->psz_cachefile[0] = '\0';
     dvdcss->b_debug = 0;
     dvdcss->b_errors = 0;
-    dvdcss->psz_cache = NULL;
 
     /*
      *  Find verbosity from DVDCSS_VERBOSE environment variable
@@ -211,7 +217,23 @@
         }
     }
 
-    if(!dvdcss_cache_dir) dvdcss_cache_dir = getenv( "DVDCSS_CACHE" );
+    /*
+     *  Find cache dir from the DVDCSS_CACHE environment variable
+     */
+    if( psz_cache != NULL )
+    {
+        if( psz_cache[0] == '\0' )
+        {
+            psz_cache = NULL;
+        }
+        /* Check that we can add the ID directory and the block filename */
+        else if( strlen( psz_cache ) + 1 + 32 + 1 + 10 + 1 > PATH_MAX )
+        {
+            _dvdcss_error( dvdcss, "cache directory name is too long" );
+            psz_cache = NULL;
+        }
+    }
+    else psz_cache = get_path( "DVDKeys" );
 
     /*
      *  Open device
@@ -266,46 +288,127 @@
     }
 #endif
 
-    /* if the CACHE is enabled, extract some unique disc ID */
-    if(dvdcss_cache_dir){
-	char* disc_id=NULL;
-	/*char title_name[64];*/
-	char sector[DVDCSS_BLOCK_SIZE];
-	// 32768+40  -> disc title (32 uppercase chars)
-	// 32768+813 -> disc manufacturing date + serial no (16 digit number)
-	int ret=dvdcss->pf_seek( dvdcss, 32768/DVDCSS_BLOCK_SIZE);
-	//printf("disc_id seek: %d -> %d,  i_fd=%d  i_read_fd=%d\n",32768/DVDCSS_BLOCK_SIZE,ret,dvdcss->i_fd,dvdcss->i_read_fd);
-	if(dvdcss->pf_read( dvdcss, sector, 1) == 1){
-	    // check disc title first:
-	    char* title_name=&sector[40];
-	    int i=0;
-	    while(i<32 && title_name[i]>='0' && title_name[i]<='z') i++;
-	    title_name[i]=0;
-	    if(i>5){
-		disc_id=strdup(title_name);
-	    } else {
-		// use disc date+serial:
-		title_name=&sector[813];
-		title_name[16]=0;
-	        for ( i=0;i<16;i++ )
-		    if ( ( title_name[i] < '0' )||( title_name[i] > '9' ) ){
-		        disc_id=malloc(16+4);
-	                snprintf( disc_id,17,"%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X",title_name[0],title_name[1],title_name[2],title_name[3],title_name[4],title_name[5],title_name[6],title_name[7] );
+    /* If the cache is enabled, extract a unique disc ID */
+    if( psz_cache )
+    {
+        uint8_t p_sector[DVDCSS_BLOCK_SIZE];
+        unsigned char   psz_debug[PATH_MAX+30];
+        unsigned char * psz_data;
+        int i;
+
+        /* We read sector 0. If it starts with 0x000001ba (BE), we are
+         * reading a VOB file, and we should not cache anything. */
+
+        i_ret = dvdcss->pf_seek( dvdcss, 0 );
+        if( i_ret != 0 )
+        {
+            goto nocache;
+        }
+
+        i_ret = dvdcss->pf_read( dvdcss, p_sector, 1 );
+        if( i_ret != 1 )
+        {
+            goto nocache;
+        }
+
+        if( p_sector[0] == 0x00 && p_sector[1] == 0x00
+             && p_sector[2] == 0x01 && p_sector[3] == 0xba )
+        {
+            goto nocache;
+        }
+
+        /* The data we are looking for is at sector 16 (32768 bytes):
+         *  - offset 40: disc title (32 uppercase chars)
+         *  - offset 813: manufacturing date + serial no (16 digits) */
+
+        i_ret = dvdcss->pf_seek( dvdcss, 16 );
+        if( i_ret != 16 )
+        {
+            goto nocache;
+        }
+
+        i_ret = dvdcss->pf_read( dvdcss, p_sector, 1 );
+        if( i_ret != 1 )
+        {
+            goto nocache;
+        }
+
+        /* Get the disc title */
+        psz_data = p_sector + 40;
+        psz_data[32] = '\0';
+
+        for( i = 0 ; i < 32 ; i++ )
+        {
+            if( psz_data[i] <= ' ' )
+            {
+                psz_data[i] = '\0';
 			break;
 		    }
-		if(!disc_id) disc_id=strdup(title_name);
+            else if( psz_data[i] == '/' || psz_data[i] == '\\' )
+            {
+                psz_data[i] = '-';
 	    }
-	    if(disc_id){
-		// yeah, we have a disc name/id, let's set up cache path:
-		/*char* dir;*/
-		dvdcss->psz_cache = malloc(strlen(dvdcss_cache_dir)+strlen(disc_id)+4);
-		sprintf(dvdcss->psz_cache,"%s/%s",dvdcss_cache_dir,disc_id);
-		mkdir( dvdcss->psz_cache,493 );
-		free(disc_id);
-		fprintf(stderr,"Using CSS Key-cache dir: %s\n",dvdcss->psz_cache);
 	    }
+
+        /* If it's not long enough, try the date + serial */
+        if( strlen( psz_data ) < 6 )
+        {
+            psz_data = p_sector + 813;
+            psz_data[16] = '\0';
+
+            /* Check that all characters are digits, otherwise convert. */
+            for( i = 0 ; i < 16 ; i++ )
+            {
+                if( psz_data[i] < '0' || psz_data[i] > '9' )
+                {
+                    sprintf( psz_data,
+                             "%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X",
+                             psz_data[0], psz_data[1], psz_data[2],
+                             psz_data[3], psz_data[4], psz_data[5],
+                             psz_data[6], psz_data[7] );
+                    break;
 	}
     }
+        }
+
+        /* We have a disc name or ID, we can create the cache dir */
+        i = sprintf( dvdcss->psz_cachefile, "%s", psz_cache );
+#if !defined( WIN32 ) || defined( SYS_CYGWIN )
+        i_ret = mkdir( dvdcss->psz_cachefile, 0755 );
+#else
+        i_ret = mkdir( dvdcss->psz_cachefile );
+#endif
+        if( i_ret < 0 && errno != EEXIST )
+        {
+            _dvdcss_error( dvdcss, "failed creating cache directory" );
+            dvdcss->psz_cachefile[0] = '\0';
+            goto nocache;
+        }
+
+        i += sprintf( dvdcss->psz_cachefile + i, "/%s/", psz_data );
+#if !defined( WIN32 ) || defined( SYS_CYGWIN )
+        i_ret = mkdir( dvdcss->psz_cachefile, 0755 );
+#else
+        i_ret = mkdir( dvdcss->psz_cachefile );
+#endif
+        if( i_ret < 0 && errno != EEXIST )
+        {
+            _dvdcss_error( dvdcss, "failed creating cache subdirectory" );
+            dvdcss->psz_cachefile[0] = '\0';
+            goto nocache;
+        }
+
+        /* Pointer to the filename we will use. */
+        dvdcss->psz_block = dvdcss->psz_cachefile + i;
+
+        sprintf( psz_debug, "using CSS key cache dir: %s",
+                            dvdcss->psz_cachefile );
+        _dvdcss_debug( dvdcss, psz_debug );
+    }
+    nocache:
+
+    /* Seek at the beginning, just for safety. */
+    dvdcss->pf_seek( dvdcss, 0 );
 
     return dvdcss;
 }
@@ -411,14 +514,14 @@
 	 * check that there are no encrypted blocks */
         for( i_index = i_ret; i_index; i_index-- )
         {
-            if( ((u8*)p_buffer)[0x14] & 0x30 )
+            if( ((uint8_t*)p_buffer)[0x14] & 0x30 )
             {
                 _dvdcss_error( dvdcss, "no key but found encrypted block" );
                 /* Only return the initial range of unscrambled blocks? */
                 /* or fail completely? return 0; */
 		break;
             }
-            p_buffer = (void *) ((u8 *)p_buffer + DVDCSS_BLOCK_SIZE);
+            p_buffer = (void *) ((uint8_t *)p_buffer + DVDCSS_BLOCK_SIZE);
         }
     }
     else 
@@ -427,8 +530,8 @@
         for( i_index = i_ret; i_index; i_index-- )
 	{
 	    _dvdcss_unscramble( dvdcss->css.p_title_key, p_buffer );
-	    ((u8*)p_buffer)[0x14] &= 0x8f;
-            p_buffer = (void *) ((u8 *)p_buffer + DVDCSS_BLOCK_SIZE);
+            ((uint8_t*)p_buffer)[0x14] &= 0x8f;
+            p_buffer = (void *) ((uint8_t *)p_buffer + DVDCSS_BLOCK_SIZE);
 	}
     }
     
@@ -502,9 +605,9 @@
         }
 
         _dvdcss_unscramble( dvdcss->css.p_title_key, iov_base );
-        ((u8*)iov_base)[0x14] &= 0x8f;
+        ((uint8_t*)iov_base)[0x14] &= 0x8f;
 
-        iov_base = (void *) ((u8*)iov_base + DVDCSS_BLOCK_SIZE);
+        iov_base = (void *) ((uint8_t*)iov_base + DVDCSS_BLOCK_SIZE);
         iov_len -= DVDCSS_BLOCK_SIZE;
     }
 
Index: libmpdvdkit2/libdvdcss.h
===================================================================
RCS file: /cvsroot/mplayer/main/libmpdvdkit2/libdvdcss.h,v
retrieving revision 1.3
diff -b -B -u -r1.3 libdvdcss.h
--- libmpdvdkit2/libdvdcss.h	29 Dec 2002 15:32:56 -0000	1.3
+++ libmpdvdkit2/libdvdcss.h	7 Feb 2003 23:25:48 -0000
@@ -1,5 +1,5 @@
 /*****************************************************************************
- * private.h: private DVD reading library data
+ * libdvdcss.h: private DVD reading library data
  *****************************************************************************
  * Copyright (C) 1998-2001 VideoLAN
  * $Id: libdvdcss.h,v 1.3 2002/12/29 15:32:56 arpi Exp $
@@ -33,7 +33,7 @@
     char * psz_device;
     int    i_fd;
     int    i_read_fd;
-    int    i_seekpos;
+    int    i_pos;
 
     /* File handling */
     int ( * pf_seek )  ( dvdcss_t, int );
@@ -46,7 +46,10 @@
     int          b_ioctls;
     int          b_scrambled;
     dvd_title_t *p_titles;
-    char *	 psz_cache;
+
+    /* Key cache directory and pointer to the filename */
+    char   psz_cachefile[PATH_MAX];
+    char * psz_block;
 
     /* Error management */
     char * psz_error;


More information about the MPlayer-dev-eng mailing list