diff options
author | arpi <arpi@b3059339-0415-0410-9bf9-f77b7e298cf2> | 2003-02-08 00:22:39 +0000 |
---|---|---|
committer | arpi <arpi@b3059339-0415-0410-9bf9-f77b7e298cf2> | 2003-02-08 00:22:39 +0000 |
commit | b606cb19527d294cfd05011de5dfd47b6c023296 (patch) | |
tree | 3ff67c8a11c35dceae1e87617329133dbd566dc8 | |
parent | 4e8a50437110dc3d70e406c8d3dbf2a522ff5594 (diff) |
sync with libdvdcss 1.2.5 (including u8->uint8_t and whitespace cosmetics...)
patch by Andreas Hess <jaska@gmx.net>
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@9334 b3059339-0415-0410-9bf9-f77b7e298cf2
-rw-r--r-- | libmpdvdkit2/README | 2 | ||||
-rw-r--r-- | libmpdvdkit2/bsdi_dvd.h | 35 | ||||
-rw-r--r-- | libmpdvdkit2/bsdi_ioctl.c | 100 | ||||
-rw-r--r-- | libmpdvdkit2/common.h | 11 | ||||
-rw-r--r-- | libmpdvdkit2/css.c | 273 | ||||
-rw-r--r-- | libmpdvdkit2/css.h | 4 | ||||
-rw-r--r-- | libmpdvdkit2/csstables.h | 22 | ||||
-rw-r--r-- | libmpdvdkit2/device.c | 179 | ||||
-rw-r--r-- | libmpdvdkit2/device.h | 7 | ||||
-rw-r--r-- | libmpdvdkit2/dvd_reader.c | 5 | ||||
-rw-r--r-- | libmpdvdkit2/dvdcss.h | 6 | ||||
-rw-r--r-- | libmpdvdkit2/error.c | 3 | ||||
-rw-r--r-- | libmpdvdkit2/ioctl.c | 442 | ||||
-rw-r--r-- | libmpdvdkit2/ioctl.h | 59 | ||||
-rw-r--r-- | libmpdvdkit2/libdvdcss.c | 258 | ||||
-rw-r--r-- | libmpdvdkit2/libdvdcss.h | 11 |
16 files changed, 932 insertions, 485 deletions
diff --git a/libmpdvdkit2/README b/libmpdvdkit2/README index 13cb826a44..3a84c1b195 100644 --- a/libmpdvdkit2/README +++ b/libmpdvdkit2/README @@ -6,7 +6,7 @@ What the hell is this? 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. diff --git a/libmpdvdkit2/bsdi_dvd.h b/libmpdvdkit2/bsdi_dvd.h index 43b2895320..ff61ebd252 100644 --- a/libmpdvdkit2/bsdi_dvd.h +++ b/libmpdvdkit2/bsdi_dvd.h @@ -224,6 +224,7 @@ typedef struct { #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 @@ typedef struct { #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,11 +258,22 @@ typedef struct { #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)) -struct cdrom_msf +struct cdrom_msf { __u8 cdmsf_min0; /* start minute */ __u8 cdmsf_sec0; /* start second */ @@ -268,26 +283,26 @@ struct cdrom_msf __u8 cdmsf_frame1; /* end frame */ }; -struct cdrom_tochdr +struct cdrom_tochdr { __u8 cdth_trk0; /* start track */ __u8 cdth_trk1; /* end track */ }; -struct cdrom_msf0 +struct cdrom_msf0 { __u8 minute; __u8 second; __u8 frame; }; -union cdrom_addr +union cdrom_addr { struct cdrom_msf0 msf; int lba; }; -struct cdrom_tocentry +struct cdrom_tocentry { __u8 cdte_track; __u8 cdte_adr :4; @@ -312,4 +327,14 @@ struct modesel_head __u8 block_length_med; __u8 block_length_lo; }; + +typedef struct +{ + int data; + int audio; + int cdi; + int xa; + int error; +} tracktype; + #endif /* _DVD_H_ */ diff --git a/libmpdvdkit2/bsdi_ioctl.c b/libmpdvdkit2/bsdi_ioctl.c index d12c57fc31..ce5a38adf2 100644 --- a/libmpdvdkit2/bsdi_ioctl.c +++ b/libmpdvdkit2/bsdi_ioctl.c @@ -49,8 +49,9 @@ typedef struct cgc 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 @@ int dvd_cdrom_ioctl(int fd, unsigned long cmd, void *arg) 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 u_char scsi_cdblen[8] = {6, 10, 10, 12, 12, 12, 10, 10}; 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 @@ static int scsi_cmd(int fd, cgc_t *cgc) 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 @@ static int dvd_ioctl(int fd, u_long cmd, void *arg) 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); @@ -580,9 +585,9 @@ cdrom_ioctl(int fd, u_long cmd, void *arg) tocentry->cdte_addr.msf.frame = buffer[11]; } else - tocentry->cdte_addr.lba = (((((buffer[8] << 8) + tocentry->cdte_addr.lba = (((((buffer[8] << 8) + buffer[9]) << 8) - + buffer[10]) << 8) + + buffer[10]) << 8) + buffer[11]; break; } @@ -593,14 +598,38 @@ cdrom_ioctl(int fd, u_long cmd, void *arg) ret = cdrom_tray_move(fd, 0); break; /* - * This sucks but emulates the expected behaviour. Instead of the return + * 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); @@ -659,6 +688,49 @@ static int cdrom_read_block(int fd, cgc_t *cgc, 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) { cgc_t cgc; diff --git a/libmpdvdkit2/common.h b/libmpdvdkit2/common.h index 87a4b77a8a..f99a67b2d8 100644 --- a/libmpdvdkit2/common.h +++ b/libmpdvdkit2/common.h @@ -13,7 +13,7 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -27,14 +27,7 @@ /***************************************************************************** * 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; +#include <inttypes.h> #if defined( WIN32 ) diff --git a/libmpdvdkit2/css.c b/libmpdvdkit2/css.c index c5ad40ab8d..59870b8099 100644 --- a/libmpdvdkit2/css.c +++ b/libmpdvdkit2/css.c @@ -14,7 +14,7 @@ * - DeCSSPlus by Ethan Hawke * - DecVOB * see http://www.lemuria.org/DeCSS/ by Tom Vogt for more information. - * + * * 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 * the Free Software Foundation; either version 2 of the License, or @@ -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 /***************************************************************************** @@ -117,17 +120,17 @@ int _dvdcss_test( dvdcss_t dvdcss ) * and stops when a session key (called bus key) has been established. * Always do the full auth sequence. Some drives seem to lie and always * respond with ASF=1. For instance the old DVD roms on Compaq Armada says - * that ASF=1 from the start and then later fail with a 'read of scrambled + * that ASF=1 from the start and then later fail with a 'read of scrambled * block without authentication' error. *****************************************************************************/ 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; @@ -135,7 +138,7 @@ static int GetBusKey( dvdcss_t dvdcss ) _dvdcss_debug( dvdcss, "requesting AGID" ); i_ret = ioctl_ReportAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); - /* We might have to reset hung authentication processes in the drive + /* We might have to reset hung authentication processes in the drive by invalidating the corresponding AGID'. As long as we haven't got an AGID, invalidate one (in sequence) and try again. */ for( i = 0; i_ret == -1 && i < 4 ; ++i ) @@ -218,7 +221,7 @@ static int GetBusKey( dvdcss_t dvdcss ) } /* Get challenge from LU */ - if( ioctl_ReportChallenge( dvdcss->i_fd, + if( ioctl_ReportChallenge( dvdcss->i_fd, &dvdcss->css.i_agid, p_buffer ) < 0 ) { _dvdcss_error( dvdcss, "ioctl ReportKeyChallenge failed" ); @@ -260,9 +263,9 @@ static int GetBusKey( dvdcss_t dvdcss ) } /***************************************************************************** - * PrintKey : debug function that dumps a key value + * 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 @@ int _dvdcss_title ( dvdcss_t dvdcss, int i_block ) 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 @@ int _dvdcss_title ( dvdcss_t dvdcss, int i_block ) 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; - _dvdcss_debug( dvdcss, "key found in cache" ); - } - close(fd); - } + /* 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( 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 ) { - _dvdcss_error( dvdcss, "fatal error in vts css key" ); - return i_ret; - } - else if( i_ret == 0 ) - { - _dvdcss_debug( dvdcss, "unencrypted title" ); - /* Still store this in the cache, so we don't need to check again. */ + 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; + } + + if( i_ret == 0 ) + { + _dvdcss_debug( dvdcss, "unencrypted title" ); + /* 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); - } - free(key_file); + /* 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 ); + } } /* Find our spot in the list */ @@ -385,7 +397,7 @@ int _dvdcss_title ( dvdcss_t dvdcss, int i_block ) * _dvdcss_disckey: get disc key. ***************************************************************************** * This function should only be called if DVD ioctls are present. - * It will set dvdcss->i_method = DVDCSS_METHOD_TITLE if it fails to find + * It will set dvdcss->i_method = DVDCSS_METHOD_TITLE if it fails to find * a valid disc key. * Two decryption methods are offered: * -disc key hash crack, @@ -412,7 +424,7 @@ int _dvdcss_disckey( dvdcss_t dvdcss ) /* This should have invaidated the AGID and got us ASF=1. */ if( GetASF( dvdcss ) != 1 ) { - /* Region mismatch (or region not set) is the most likely source. */ + /* Region mismatch (or region not set) is the most likely source. */ _dvdcss_error( dvdcss, "ASF not 1 after reading disc key (region mismatch?)" ); ioctl_InvalidateAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); @@ -478,11 +490,11 @@ int _dvdcss_disckey( dvdcss_t dvdcss ) *****************************************************************************/ 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 || + if( dvdcss->b_ioctls && ( dvdcss->i_method == DVDCSS_METHOD_KEY || dvdcss->i_method == DVDCSS_METHOD_DISC ) ) { /* We have a decrypted Disc key and the ioctls are available, @@ -517,7 +529,7 @@ int _dvdcss_titlekey( dvdcss_t dvdcss, int i_pos, dvd_key_t p_title_key ) break; case 0: - /* This might either be a title that has no key, + /* This might either be a title that has no key, * or we encountered a region error. */ _dvdcss_debug( dvdcss, "lost ASF reqesting title key" ); break; @@ -591,10 +603,10 @@ int _dvdcss_titlekey( dvdcss_t dvdcss, int i_pos, dvd_key_t p_title_key ) * 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 @@ static int GetASF( dvdcss_t dvdcss ) * 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,24 +701,24 @@ static void CryptKey( int i_key_type, int i_variant, 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 }; - - 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; - int i_term = 0; - int i_bit; - int i; + uint8_t p_secret[5] = { 0x55, 0xD6, 0xC4, 0xC5, 0x28 }; + + 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; for (i = 9; i >= 0; --i) p_scratch[i] = p_challenge[pp_perm_challenge[i_key_type][i]]; @@ -864,25 +876,25 @@ static void CryptKey( int i_key_type, int i_variant, /***************************************************************************** * DecryptKey: decrypt p_crypted with p_key. ***************************************************************************** - * Used to decrypt the disc key, with a player key, after requesting it - * in _dvdcss_disckey and to decrypt title keys, with a disc key, requested + * Used to decrypt the disc key, with a player key, after requesting it + * in _dvdcss_disckey and to decrypt title keys, with a disc key, requested * in _dvdcss_titlekey. - * The player keys and the resulting disc key are only used as KEKs + * The player keys and the resulting disc key are only used as KEKs * (key encryption keys). * Decryption is slightly dependant on the type of key: * -for disc key, invert is 0x00, - * -for title key, invert if 0xff. + * -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,12 +949,13 @@ static void DecryptKey( u8 invert, u8 const *p_key, * 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[] = + static const dvd_key_t player_keys[] = { { 0x01, 0xaf, 0xe3, 0x12, 0x80 }, { 0x12, 0x11, 0xca, 0x04, 0x3b }, @@ -986,8 +999,8 @@ static int DecryptDiscKey( u8 const *p_struct_disckey, dvd_key_t p_disc_key ) DecryptKey( 0, player_keys[n], p_struct_disckey + 5 * i, p_disc_key ); - /* The first part in the struct_disckey block is the - * 'disc key' encrypted with it self. Using this we + /* The first part in the struct_disckey block is the + * 'disc key' encrypted with it self. Using this we * can check if we decrypted the correct key. */ DecryptKey( 0, p_disc_key, p_struct_disckey, p_verify ); @@ -1000,7 +1013,7 @@ static int DecryptDiscKey( u8 const *p_struct_disckey, dvd_key_t p_disc_key ) n++; } - /* Have tried all combinations of positions and keys, + /* Have tried all combinations of positions and keys, * and we still didn't succeed. */ memset( p_disc_key, 0, KEY_SIZE ); return -1; @@ -1022,7 +1035,7 @@ static void DecryptTitleKey( dvd_key_t p_disc_key, dvd_key_t p_titlekey ) * CrackDiscKey: brute force disc key * CSS hash reversal function designed by Frank Stevenson ***************************************************************************** - * This function uses a big amount of memory to crack the disc key from the + * This function uses a big amount of memory to crack the disc key from the * disc key hash, if player keys are not available. *****************************************************************************/ #define K1TABLEWIDTH 10 @@ -1039,7 +1052,7 @@ static int investigate( unsigned char *hash, unsigned char *ckey ) 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 @@ -1057,7 +1070,7 @@ static int CrackDiscKey( dvdcss_t dvdcss, u8 *p_disc_key ) unsigned int nTry; /* iterator for K[1] possibilities */ unsigned int nPossibleK1; /* #of possible K[1] values */ unsigned char* K1table; /* Lookup table for possible K[1] */ - unsigned int* BigTable; /* LFSR2 startstate indexed by + unsigned int* BigTable; /* LFSR2 startstate indexed by * 1,2,5 output byte */ _dvdcss_debug( dvdcss, "cracking disc key" ); @@ -1236,11 +1249,11 @@ end: * 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; @@ -1367,7 +1380,7 @@ static int RecoverTitleKey( int i_start, u8 const *p_crypted, * The data of the PES packet begins at 0x15 (if there isn't any PTS/DTS) * or at 0x?? if there are both PTS and DTS's. * The seed value used with the unscrambling key is the 5 bytes at 0x54-0x58. - * The scrabled part of a sector begins at 0x80. + * The scrabled part of a sector begins at 0x80. *****************************************************************************/ /* Statistics */ @@ -1381,15 +1394,15 @@ static int i_tries = 0, i_success = 0; * The DVD should have been opened and be in an authenticated state. * i_pos is the starting sector, i_len is the maximum number of sectors to read *****************************************************************************/ -static int CrackTitleKey( dvdcss_t dvdcss, int i_pos, int i_len, +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 }; - int i_reads = 0; - int i_encrypted = 0; - int b_stop_scanning = 0; - int i_ret; + 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; + int i_ret; _dvdcss_debug( dvdcss, "cracking title key" ); @@ -1406,7 +1419,7 @@ static int CrackTitleKey( dvdcss_t dvdcss, int i_pos, int i_len, } i_ret = dvdcss_read( dvdcss, p_buf, 1, DVDCSS_NOFLAGS ); - + /* Either we are at the end of the physical device or the auth * have failed / were not done and we got a read error. */ if( i_ret <= 0 ) @@ -1418,7 +1431,7 @@ static int CrackTitleKey( dvdcss_t dvdcss, int i_pos, int i_len, break; } - /* Stop when we find a non MPEG stream block. + /* Stop when we find a non MPEG stream block. * (We must have reached the end of the stream). * For now, allow all blocks that begin with a start code. */ if( memcmp( p_buf, p_packstart, 3 ) ) @@ -1428,12 +1441,12 @@ static int CrackTitleKey( dvdcss_t dvdcss, int i_pos, int i_len, } if( p_buf[0x0d] & 0x07 ) - _dvdcss_debug( dvdcss, "stuffing in pack header" ); + _dvdcss_debug( dvdcss, "stuffing in pack header" ); /* PES_scrambling_control does not exist in a system_header, * a padding_stream or a private_stream2 (and others?). */ - if( p_buf[0x14] & 0x30 && ! ( p_buf[0x11] == 0xbb - || p_buf[0x11] == 0xbe + if( p_buf[0x14] & 0x30 && ! ( p_buf[0x11] == 0xbb + || p_buf[0x11] == 0xbe || p_buf[0x11] == 0xbf ) ) { i_encrypted++; @@ -1455,7 +1468,7 @@ static int CrackTitleKey( dvdcss_t dvdcss, int i_pos, int i_len, i_reads++; /* Emit a progress indication now and then. */ - if( !( i_reads & 0xfff ) ) + if( !( i_reads & 0xfff ) ) { _dvdcss_debug( dvdcss, "still cracking..." ); } @@ -1470,8 +1483,8 @@ static int CrackTitleKey( dvdcss_t dvdcss, int i_pos, int i_len, { /* Print some statistics. */ char psz_info[128]; - snprintf( psz_info, sizeof(psz_info), - "%d of %d attempts successful, %d of %d blocks scrambled", + snprintf( psz_info, sizeof(psz_info), + "%d of %d attempts successful, %d of %d blocks scrambled", i_success, i_tries, i_encrypted, i_reads ); _dvdcss_debug( dvdcss, psz_info ); } @@ -1482,7 +1495,7 @@ static int CrackTitleKey( dvdcss_t dvdcss, int i_pos, int i_len, 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" ); @@ -1495,13 +1508,14 @@ static int CrackTitleKey( dvdcss_t dvdcss, int i_pos, int i_len, /****************************************************************************** - * The original Ethan Hawke (DeCSSPlus) attack (modified). + * The original Ethan Hawke (DeCSSPlus) attack (modified). ****************************************************************************** * Tries to find a repeating pattern just before the encrypted part starts. * 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; @@ -1542,7 +1556,7 @@ static int AttackPattern( u8 const p_sec[0x800], int i_pos, u8 *p_key ) { fprintf( stderr, "key is %02x:%02x:%02x:%02x:%02x ", p_key[0], p_key[1], p_key[2], p_key[3], p_key[4] ); - fprintf( stderr, "at block %5d pattern len %3d period %3d %s\n", + fprintf( stderr, "at block %5d pattern len %3d period %3d %s\n", i_pos, i_best_plen, i_best_p, (res>=0?"y":"n") ); } #endif @@ -1560,13 +1574,14 @@ static int AttackPattern( u8 const p_sec[0x800], int i_pos, u8 *p_key ) * DVD specifies that there must only be one type of data in every sector. * Every sector is one pack and so must obviously be 2048 bytes long. * For the last pice of video data before a VOBU boundary there might not - * be exactly the right amount of data to fill a sector. They one has to + * be exactly the right amount of data to fill a sector. They one has to * pad the pack to 2048 bytes. For just a few bytes this is doen in the - * header but for any large amount you insert a PES packet from the + * header but for any large amount you insert a PES packet from the * 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;*/ @@ -1576,15 +1591,15 @@ static int AttackPadding( u8 const p_sec[0x800], int i_pos, u8 *p_key ) /* Coverd by the test below but usfull for debuging. */ if( i_pes_length == 0x800 - 0x14 ) return 0; - /* There must be room for at least 4? bytes of padding stream, + /* There must be room for at least 4? bytes of padding stream, * and it must be encrypted. * sector size - pack/pes header - padding startcode - padding length */ if( ( 0x800 - 0x14 - 4 - 2 - i_pes_length < 4 ) || ( p_sec[0x14 + i_pes_length + 0] == 0x00 && p_sec[0x14 + i_pes_length + 1] == 0x00 && p_sec[0x14 + i_pes_length + 2] == 0x01 ) ) - { - fprintf( stderr, "plain %d %02x:%02x:%02x:%02x (type %02x sub %02x)\n", + { + fprintf( stderr, "plain %d %02x:%02x:%02x:%02x (type %02x sub %02x)\n", 0x800 - 0x14 - 4 - 2 - i_pes_length, p_sec[0x14 + i_pes_length + 0], p_sec[0x14 + i_pes_length + 1], @@ -1595,16 +1610,16 @@ static int AttackPadding( u8 const p_sec[0x800], int i_pos, u8 *p_key ) } /* If we are here we know that there is a where in the pack a - encrypted PES header is (startcode + lenght). It's never more - than two packets in the pack, so we 'know' the length. The - plaintext at offset (0x14 + i_pes_length) will then be - 00 00 01 e0/bd/be xx xx, in the case of be the following bytes + encrypted PES header is (startcode + lenght). It's never more + than two packets in the pack, so we 'know' the length. The + plaintext at offset (0x14 + i_pes_length) will then be + 00 00 01 e0/bd/be xx xx, in the case of be the following bytes are also known. */ /* An encrypted SPU PES packet with another encrypted PES packet following. Normaly if the following was a padding stream that would be in plain text. So it will be another SPU PES packet. */ - if( p_sec[0x11] == 0xbd && + if( p_sec[0x11] == 0xbd && p_sec[0x17 + p_sec[0x16]] >= 0x20 && p_sec[0x17 + p_sec[0x16]] <= 0x3f ) { @@ -1615,16 +1630,16 @@ static int AttackPadding( u8 const p_sec[0x800], int i_pos, u8 *p_key ) * No reason execpt for time stamps to break the data into two packets. * So it's likely that the following PES packet is a padding stream. */ if( p_sec[0x11] == 0xe0 ) - { + { i_tries++; } - + if( 1 ) { /*fprintf( stderr, "key is %02x:%02x:%02x:%02x:%02x ", p_key[0], p_key[1], p_key[2], p_key[3], p_key[4] );*/ fprintf( stderr, "at block %5d padding len %4d " - "type %02x sub %02x\n", i_pos, i_pes_length, + "type %02x sub %02x\n", i_pos, i_pes_length, p_sec[0x11], p_sec[0x17 + p_sec[0x16]]); } diff --git a/libmpdvdkit2/css.h b/libmpdvdkit2/css.h index f48a14e581..82f64f8951 100644 --- a/libmpdvdkit2/css.h +++ b/libmpdvdkit2/css.h @@ -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_test ( dvdcss_t ); 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 * ); diff --git a/libmpdvdkit2/csstables.h b/libmpdvdkit2/csstables.h index 613ce61500..fb3cdfef47 100644 --- a/libmpdvdkit2/csstables.h +++ b/libmpdvdkit2/csstables.h @@ -13,7 +13,7 @@ * - DeCSSPlus by Ethan Hawke * - DecVOB * see http://www.lemuria.org/DeCSS/ by Tom Vogt for more information. - * + * * 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 * the Free Software Foundation; either version 2 of the License, or @@ -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 @@ static u8 p_css_tab1[ 256 ] = 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 @@ static u8 p_css_tab2[ 256 ] = 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 @@ static u8 p_css_tab3[ 512 ] = 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 @@ static u8 p_css_tab4[ 256 ] = 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 @@ static u8 p_css_tab5[ 256 ] = 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 @@ static u8 p_crypt_tab0[ 256 ] = 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 @@ static u8 p_crypt_tab1[ 256 ] = 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, @@ -347,10 +347,10 @@ static u8 p_crypt_tab2[ 256 ] = 0x4B, 0x3B, 0x03, 0xBB, 0x1C, 0x2A, 0xAC, 0x0C, 0x3F, 0x93, 0xC7, 0x72, 0x7A, 0x09, 0x22, 0x3D, 0x45, 0x78, 0xA9, 0xA8, 0xEA, 0xC9, 0x6A, 0xF7, - 0x29, 0x91, 0xF0, 0x02, 0x18, 0x3A, 0x4E, 0x7C + 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, diff --git a/libmpdvdkit2/device.c b/libmpdvdkit2/device.c index a75035c18e..d6fc672f31 100644 --- a/libmpdvdkit2/device.c +++ b/libmpdvdkit2/device.c @@ -12,7 +12,7 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -34,12 +34,10 @@ #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> +#include <unistd.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 */ @@ -84,11 +82,11 @@ int _dvdcss_use_ioctls( dvdcss_t dvdcss ) /* FIXME: implement this for Windows */ if( WIN2K ) { - return 1; + return 1; } else { - return 1; + return 1; } #else struct stat fileinfo; @@ -97,31 +95,31 @@ int _dvdcss_use_ioctls( dvdcss_t dvdcss ) ret = fstat( dvdcss->i_fd, &fileinfo ); if( ret < 0 ) { - return 1; /* What to do? Be conservative and try to use the ioctls */ + return 1; /* What to do? Be conservative and try to use the ioctls */ } - - /* Complete this list and check that we test for the right things + + /* Complete this list and check that we test for the right things * (I've assumed for all OSs that 'r', (raw) device, are char devices * and those that don't contain/use an 'r' in the name are block devices) * * Linux needs a block device * Solaris needs a char device - * Darwin needs a char device + * Darwin needs a char device * OpenBSD needs a char device * NetBSD needs a char device * FreeBSD can use either the block or the char device * BSD/OS can use either the block or the char device */ - + /* Check if this is a block/char device */ - if( S_ISBLK( fileinfo.st_mode ) || - S_ISCHR( fileinfo.st_mode ) ) + if( S_ISBLK( fileinfo.st_mode ) || + S_ISCHR( fileinfo.st_mode ) ) { - return 1; + return 1; } else { - return 0; + return 0; } #endif } @@ -250,6 +248,8 @@ static int libc_open ( dvdcss_t dvdcss, char const *psz_device ) return -1; } + dvdcss->i_pos = 0; + return 0; } @@ -285,6 +285,8 @@ static int win2k_open ( dvdcss_t dvdcss, char const *psz_device ) return -1; } + dvdcss->i_pos = 0; + return 0; } @@ -297,7 +299,7 @@ static int aspi_open( dvdcss_t dvdcss, char const * psz_device ) long (*lpGetSupport)( void ); long (*lpSendCommand)( void* ); char c_drive = psz_device[0]; - + /* load aspi and init w32_aspidev structure */ hASPI = LoadLibrary( "wnaspi32.dll" ); if( hASPI == NULL ) @@ -308,7 +310,7 @@ static int aspi_open( dvdcss_t dvdcss, char const * psz_device ) (FARPROC) lpGetSupport = GetProcAddress( hASPI, "GetASPI32SupportInfo" ); (FARPROC) lpSendCommand = GetProcAddress( hASPI, "SendASPI32Command" ); - + if(lpGetSupport == NULL || lpSendCommand == NULL ) { _dvdcss_error( dvdcss, "unable to get aspi function pointers" ); @@ -387,6 +389,7 @@ static int aspi_open( dvdcss_t dvdcss, char const * psz_device ) { fd->i_sid = MAKEWORD( i, j ); dvdcss->i_fd = (int) fd; + dvdcss->i_pos = 0; return 0; } else @@ -412,45 +415,59 @@ static int aspi_open( dvdcss_t dvdcss, char const * psz_device ) *****************************************************************************/ 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 ) @@ -458,19 +475,28 @@ static int aspi_seek( dvdcss_t dvdcss, int i_blocks ) int i_old_blocks; 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,17 +505,35 @@ static int aspi_seek( dvdcss_t dvdcss, int i_blocks ) *****************************************************************************/ 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" ); + 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 +546,26 @@ static int win2k_read ( dvdcss_t dvdcss, void *p_buffer, int i_blocks ) 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 +599,7 @@ static int libc_readv ( dvdcss_t dvdcss, struct iovec *p_iovec, int i_blocks ) * 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 +609,32 @@ static int libc_readv ( dvdcss_t dvdcss, struct iovec *p_iovec, int i_blocks ) { /* 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,13 +662,14 @@ static int win_readv ( dvdcss_t dvdcss, struct iovec *p_iovec, int i_blocks ) if( !dvdcss->p_readv_buffer ) { _dvdcss_error( dvdcss, " failed (readv)" ); + dvdcss->i_pos = -1; return -1; } } for( i_index = i_blocks; i_index; i_index-- ) { - i_blocks_total += p_iovec[i_index-1].iov_len; + i_blocks_total += p_iovec[i_index-1].iov_len; } if( i_blocks_total <= 0 ) return 0; @@ -610,6 +685,7 @@ static int win_readv ( dvdcss_t dvdcss, struct iovec *p_iovec, int i_blocks ) /* 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 +698,7 @@ static int win_readv ( dvdcss_t dvdcss, struct iovec *p_iovec, int i_blocks ) if( i_blocks_read < 0 ) { /* See above */ + dvdcss->i_pos = -1; return -1; } } @@ -639,8 +716,9 @@ static int win_readv ( dvdcss_t dvdcss, struct iovec *p_iovec, int i_blocks ) * garbage, this isn't an issue as we return the number of * blocks actually read */ i_blocks_total -= ( p_iovec[i_index].iov_len / DVDCSS_BLOCK_SIZE ); - } + } + dvdcss->i_pos += i_blocks_read; return i_blocks_read; } @@ -664,17 +742,17 @@ static int aspi_read_internal( int i_fd, void *p_data, int i_blocks ) ssc.SRB_HaId = LOBYTE( fd->i_sid ); ssc.SRB_Target = HIBYTE( fd->i_sid ); ssc.SRB_SenseLen = SENSE_LEN; - + ssc.SRB_PostProc = (LPVOID) hEvent; ssc.SRB_BufPointer = p_data; ssc.SRB_CDBLen = 12; - + ssc.CDBByte[0] = 0xA8; /* RAW */ ssc.CDBByte[2] = (UCHAR) (fd->i_blocks >> 24); ssc.CDBByte[3] = (UCHAR) (fd->i_blocks >> 16) & 0xff; ssc.CDBByte[4] = (UCHAR) (fd->i_blocks >> 8) & 0xff; ssc.CDBByte[5] = (UCHAR) (fd->i_blocks) & 0xff; - + /* We have to break down the reads into 64kb pieces (ASPI restriction) */ if( i_blocks > 32 ) { @@ -682,14 +760,15 @@ static int aspi_read_internal( int i_fd, void *p_data, int i_blocks ) ssc.CDBByte[9] = 32; fd->i_blocks += 32; - /* Initiate transfer */ + /* Initiate transfer */ ResetEvent( hEvent ); fd->lpSendCommand( (void*) &ssc ); /* 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, - i_blocks - 32) < 0 ) + if( aspi_read_internal( i_fd, + (uint8_t*) p_data + 32 * DVDCSS_BLOCK_SIZE, + i_blocks - 32) < 0 ) { return -1; } @@ -701,7 +780,7 @@ static int aspi_read_internal( int i_fd, void *p_data, int i_blocks ) ssc.CDBByte[9] = (UCHAR) i_blocks; fd->i_blocks += i_blocks; - /* Initiate transfer */ + /* Initiate transfer */ ResetEvent( hEvent ); fd->lpSendCommand( (void*) &ssc ); diff --git a/libmpdvdkit2/device.h b/libmpdvdkit2/device.h index c50e2c00eb..21da4ffba0 100644 --- a/libmpdvdkit2/device.h +++ b/libmpdvdkit2/device.h @@ -12,7 +12,7 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -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. */ diff --git a/libmpdvdkit2/dvd_reader.c b/libmpdvdkit2/dvd_reader.c index db9ec919ba..0a48c7fc21 100644 --- a/libmpdvdkit2/dvd_reader.c +++ b/libmpdvdkit2/dvd_reader.c @@ -154,7 +154,7 @@ static int initAllCSSKeys( dvd_reader_t *dvd ) 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 @@ static dvd_reader_t *DVDOpenImageFile( const char *location, int have_css ) 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 ); diff --git a/libmpdvdkit2/dvdcss.h b/libmpdvdkit2/dvdcss.h index 72e82e2b27..f90544e66d 100644 --- a/libmpdvdkit2/dvdcss.h +++ b/libmpdvdkit2/dvdcss.h @@ -16,7 +16,7 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -61,10 +61,6 @@ typedef struct dvdcss_s* dvdcss_t; */ extern char * dvdcss_interface_2; -/* - * Path to CSS key cache. Default == NULL (no cache). - */ -extern char * dvdcss_cache_dir; /* * Exported prototypes. diff --git a/libmpdvdkit2/error.c b/libmpdvdkit2/error.c index 4d7d19c0fc..c289fd98ee 100644 --- a/libmpdvdkit2/error.c +++ b/libmpdvdkit2/error.c @@ -10,7 +10,7 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -24,6 +24,7 @@ #include "config.h" #include <stdio.h> +#include <limits.h> #include "dvdcss.h" diff --git a/libmpdvdkit2/ioctl.c b/libmpdvdkit2/ioctl.c index 7dcc3d9c27..3a782d5d51 100644 --- a/libmpdvdkit2/ioctl.c +++ b/libmpdvdkit2/ioctl.c @@ -121,8 +121,9 @@ static int SolarisSendUSCSI( int fd, struct uscsi_cmd *p_sc ); * 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 /***************************************************************************** @@ -190,7 +191,7 @@ int ioctl_ReadCopyright( int i_fd, int i_layer, int *pi_copyright ) #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; @@ -199,7 +200,7 @@ int ioctl_ReadCopyright( int i_fd, int i_layer, int *pi_copyright ) if( i_ret < 0 || sc.uscsi_status ) { i_ret = -1; } - + *pi_copyright = p_buffer[ 4 ]; /* s->copyright.rmi = p_buffer[ 5 ]; */ @@ -216,41 +217,23 @@ int ioctl_ReadCopyright( int i_fd, int i_layer, int *pi_copyright ) #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 + /* 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; + sptd.Cdb[ 6 ] = i_layer; + sptd.Cdb[ 7 ] = DVD_STRUCT_COPYRIGHT; + + i_ret = SEND_SPTD( i_fd, &sptd, &tmp ); if( i_ret == 0 ) { - *pi_copyright = p_buffer[ 4 ]; - } + *pi_copyright = p_buffer[ 4 ]; + } } else { @@ -297,7 +280,7 @@ int ioctl_ReadCopyright( int i_fd, int i_layer, int *pi_copyright ) /***************************************************************************** * 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; @@ -340,7 +323,7 @@ int ioctl_ReadDiscKey( int i_fd, int *pi_agid, u8 *p_key ) rdc.command[ 7 ] = DVD_STRUCT_DISCKEY; rdc.command[ 10 ] = *pi_agid << 6; - + i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) ); if( i_ret < 0 ) @@ -355,7 +338,7 @@ int ioctl_ReadDiscKey( int i_fd, int *pi_agid, u8 *p_key ) 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 ) @@ -367,12 +350,12 @@ int ioctl_ReadDiscKey( int i_fd, int *pi_agid, u8 *p_key ) #elif defined( SOLARIS_USCSI ) INIT_USCSI( GPCMD_READ_DVD_STRUCTURE, DVD_DISCKEY_SIZE + 4 ); - + rs_cdb.cdb_opaque[ 7 ] = DVD_STRUCT_DISCKEY; rs_cdb.cdb_opaque[ 10 ] = *pi_agid << 6; - + i_ret = SolarisSendUSCSI( i_fd, &sc ); - + if( i_ret < 0 || sc.uscsi_status ) { i_ret = -1; @@ -384,7 +367,7 @@ int ioctl_ReadDiscKey( int i_fd, int *pi_agid, u8 *p_key ) #elif defined( DARWIN_DVD_IOCTL ) INIT_DVDIOCTL( dk_dvd_read_structure_t, DVDDiscKeyInfo, kDVDStructureFormatDiscKeyInfo ); - + dvd.grantID = *pi_agid; i_ret = ioctl( i_fd, DKIOCDVDREADSTRUCTURE, &dvd ); @@ -395,7 +378,7 @@ int ioctl_ReadDiscKey( int i_fd, int *pi_agid, u8 *p_key ) 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 ) ); @@ -405,11 +388,11 @@ int ioctl_ReadDiscKey( int i_fd, int *pi_agid, u8 *p_key ) key->KeyType = DvdDiskKey; key->KeyFlags = 0; - i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_READ_KEY, key, + i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_READ_KEY, key, key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1; if( i_ret < 0 ) - { + { return i_ret; } @@ -421,7 +404,7 @@ int ioctl_ReadDiscKey( int i_fd, int *pi_agid, u8 *p_key ) ssc.CDBByte[ 7 ] = DVD_STRUCT_DISCKEY; ssc.CDBByte[ 10 ] = *pi_agid << 6; - + i_ret = WinSendSSC( i_fd, &ssc ); if( i_ret < 0 ) @@ -448,7 +431,7 @@ int ioctl_ReadDiscKey( int i_fd, int *pi_agid, u8 *p_key ) sdc.command[ 7 ] = DVD_STRUCT_DISCKEY; sdc.command[ 10 ] = *pi_agid << 6; - + i_ret = DosDevIOCtl(i_fd, IOCTL_CDROMDISK, CDROMDISK_EXECMD, &sdc, sizeof(sdc), &ulParamLen, p_buffer, sizeof(p_buffer), &ulDataLen); @@ -470,7 +453,7 @@ int ioctl_ReadDiscKey( int i_fd, int *pi_agid, u8 *p_key ) /***************************************************************************** * 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; @@ -526,15 +509,15 @@ int ioctl_ReadTitleKey( int i_fd, int *pi_agid, int i_pos, u8 *p_key ) #elif defined( SOLARIS_USCSI ) INIT_USCSI( GPCMD_REPORT_KEY, 12 ); - + rs_cdb.cdb_opaque[ 2 ] = ( i_pos >> 24 ) & 0xff; rs_cdb.cdb_opaque[ 3 ] = ( i_pos >> 16 ) & 0xff; rs_cdb.cdb_opaque[ 4 ] = ( i_pos >> 8 ) & 0xff; rs_cdb.cdb_opaque[ 5 ] = ( i_pos ) & 0xff; rs_cdb.cdb_opaque[ 10 ] = DVD_REPORT_TITLE_KEY | (*pi_agid << 6); - + i_ret = SolarisSendUSCSI( i_fd, &sc ); - + if( i_ret < 0 || sc.uscsi_status ) { i_ret = -1; @@ -544,9 +527,9 @@ int ioctl_ReadTitleKey( int i_fd, int *pi_agid, int i_pos, u8 *p_key ) /* a->lstk.cpm = (buf[ 4 ] >> 7) & 1; */ /* a->lstk.cp_sec = (buf[ 4 ] >> 6) & 1; */ /* a->lstk.cgms = (buf[ 4 ] >> 4) & 3; */ - - memcpy( p_key, p_buffer + 5, DVD_KEY_SIZE ); - + + memcpy( p_key, p_buffer + 5, DVD_KEY_SIZE ); + #elif defined( DARWIN_DVD_IOCTL ) INIT_DVDIOCTL( dk_dvd_report_key_t, DVDTitleKeyInfo, kDVDKeyFormatTitleKey ); @@ -563,7 +546,7 @@ int ioctl_ReadTitleKey( int i_fd, int *pi_agid, int i_pos, u8 *p_key ) 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 ) ); @@ -575,7 +558,7 @@ int ioctl_ReadTitleKey( int i_fd, int *pi_agid, int i_pos, u8 *p_key ) key->Parameters.TitleOffset.QuadPart = (LONGLONG) i_pos * 2048 /*DVDCSS_BLOCK_SIZE*/; - i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_READ_KEY, key, + i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_READ_KEY, key, key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1; memcpy( p_key, key->KeyData, DVD_KEY_SIZE ); @@ -682,22 +665,22 @@ int ioctl_ReportAgid( int i_fd, int *pi_agid ) #elif defined( SOLARIS_USCSI ) INIT_USCSI( GPCMD_REPORT_KEY, 8 ); - + rs_cdb.cdb_opaque[ 10 ] = DVD_REPORT_AGID | (*pi_agid << 6); - + i_ret = SolarisSendUSCSI( i_fd, &sc ); - + if( i_ret < 0 || sc.uscsi_status ) { i_ret = -1; } *pi_agid = p_buffer[ 7 ] >> 6; - + #elif defined( DARWIN_DVD_IOCTL ) INIT_DVDIOCTL( dk_dvd_report_key_t, DVDAuthenticationGrantIDInfo, kDVDKeyFormatAGID_CSS ); - + dvd.grantID = *pi_agid; dvd.keyClass = kDVDKeyClassCSS_CPPM_CPRM; @@ -711,7 +694,7 @@ int ioctl_ReportAgid( int i_fd, int *pi_agid ) ULONG id; DWORD tmp; - i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_START_SESSION, + i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_START_SESSION, &tmp, 4, &id, sizeof( id ), &tmp, NULL ) ? 0 : -1; *pi_agid = id; @@ -758,7 +741,7 @@ int ioctl_ReportAgid( int i_fd, int *pi_agid ) /***************************************************************************** * 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; @@ -804,22 +787,22 @@ int ioctl_ReportChallenge( int i_fd, int *pi_agid, u8 *p_challenge ) #elif defined( SOLARIS_USCSI ) INIT_USCSI( GPCMD_REPORT_KEY, 16 ); - + rs_cdb.cdb_opaque[ 10 ] = DVD_REPORT_CHALLENGE | (*pi_agid << 6); - + i_ret = SolarisSendUSCSI( i_fd, &sc ); - + if( i_ret < 0 || sc.uscsi_status ) { i_ret = -1; } memcpy( p_challenge, p_buffer + 4, DVD_CHALLENGE_SIZE ); - + #elif defined( DARWIN_DVD_IOCTL ) INIT_DVDIOCTL( dk_dvd_report_key_t, DVDChallengeKeyInfo, kDVDKeyFormatChallengeKey ); - + dvd.grantID = *pi_agid; i_ret = ioctl( i_fd, DKIOCDVDREPORTKEY, &dvd ); @@ -830,7 +813,7 @@ int ioctl_ReportChallenge( int i_fd, int *pi_agid, u8 *p_challenge ) 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 ) ); @@ -840,7 +823,7 @@ int ioctl_ReportChallenge( int i_fd, int *pi_agid, u8 *p_challenge ) key->KeyType = DvdChallengeKey; key->KeyFlags = 0; - i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_READ_KEY, key, + i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_READ_KEY, key, key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1; if( i_ret < 0 ) @@ -938,22 +921,22 @@ int ioctl_ReportASF( int i_fd, int *pi_remove_me, int *pi_asf ) #elif defined( SOLARIS_USCSI ) INIT_USCSI( GPCMD_REPORT_KEY, 8 ); - + rs_cdb.cdb_opaque[ 10 ] = DVD_REPORT_ASF; - + i_ret = SolarisSendUSCSI( i_fd, &sc ); - + if( i_ret < 0 || sc.uscsi_status ) { i_ret = -1; } *pi_asf = p_buffer[ 7 ] & 1; - + #elif defined( DARWIN_DVD_IOCTL ) INIT_DVDIOCTL( dk_dvd_report_key_t, DVDAuthenticationSuccessFlagInfo, kDVDKeyFormatASF ); - + i_ret = ioctl( i_fd, DKIOCDVDREPORTKEY, &dvd ); *pi_asf = dvdbs.successFlag; @@ -962,7 +945,7 @@ int ioctl_ReportASF( int i_fd, int *pi_remove_me, int *pi_asf ) 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 ) ); @@ -973,7 +956,7 @@ int ioctl_ReportASF( int i_fd, int *pi_remove_me, int *pi_asf ) ((PDVD_ASF)key->KeyData)->SuccessFlag = *pi_asf; - i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_READ_KEY, key, + i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_READ_KEY, key, key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1; if( i_ret < 0 ) @@ -1025,7 +1008,7 @@ int ioctl_ReportASF( int i_fd, int *pi_remove_me, int *pi_asf ) /***************************************************************************** * 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; @@ -1071,24 +1054,24 @@ int ioctl_ReportKey1( int i_fd, int *pi_agid, u8 *p_key ) #elif defined( SOLARIS_USCSI ) INIT_USCSI( GPCMD_REPORT_KEY, 12 ); - + rs_cdb.cdb_opaque[ 10 ] = DVD_REPORT_KEY1 | (*pi_agid << 6); - + i_ret = SolarisSendUSCSI( i_fd, &sc ); - + if( i_ret < 0 || sc.uscsi_status ) { i_ret = -1; } memcpy( p_key, p_buffer + 4, DVD_KEY_SIZE ); - + #elif defined( DARWIN_DVD_IOCTL ) INIT_DVDIOCTL( dk_dvd_report_key_t, DVDKey1Info, kDVDKeyFormatKey1 ); - + dvd.grantID = *pi_agid; - + i_ret = ioctl( i_fd, DKIOCDVDREPORTKEY, &dvd ); memcpy( p_key, dvdbs.key1Value, DVD_KEY_SIZE ); @@ -1097,7 +1080,7 @@ int ioctl_ReportKey1( int i_fd, int *pi_agid, u8 *p_key ) 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 ) ); @@ -1107,7 +1090,7 @@ int ioctl_ReportKey1( int i_fd, int *pi_agid, u8 *p_key ) key->KeyType = DvdBusKey1; key->KeyFlags = 0; - i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_READ_KEY, key, + i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_READ_KEY, key, key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1; memcpy( p_key, key->KeyData, DVD_KEY_SIZE ); @@ -1192,11 +1175,11 @@ int ioctl_InvalidateAgid( int i_fd, int *pi_agid ) #elif defined( SOLARIS_USCSI ) INIT_USCSI( GPCMD_REPORT_KEY, 0 ); - + rs_cdb.cdb_opaque[ 10 ] = DVD_INVALIDATE_AGID | (*pi_agid << 6); - + i_ret = SolarisSendUSCSI( i_fd, &sc ); - + if( i_ret < 0 || sc.uscsi_status ) { i_ret = -1; @@ -1205,9 +1188,9 @@ int ioctl_InvalidateAgid( int i_fd, int *pi_agid ) #elif defined( DARWIN_DVD_IOCTL ) INIT_DVDIOCTL( dk_dvd_send_key_t, DVDAuthenticationGrantIDInfo, kDVDKeyFormatAGID_Invalidate ); - + dvd.grantID = *pi_agid; - + i_ret = ioctl( i_fd, DKIOCDVDSENDKEY, &dvd ); #elif defined( WIN32 ) @@ -1215,7 +1198,7 @@ int ioctl_InvalidateAgid( int i_fd, int *pi_agid ) { DWORD tmp; - i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_END_SESSION, + i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_END_SESSION, pi_agid, sizeof( *pi_agid ), NULL, 0, &tmp, NULL ) ? 0 : -1; } else @@ -1265,7 +1248,7 @@ int ioctl_InvalidateAgid( int i_fd, int *pi_agid ) /***************************************************************************** * 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 @@ int ioctl_SendChallenge( int i_fd, int *pi_agid, u8 *p_challenge ) 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 @@ int ioctl_SendChallenge( int i_fd, int *pi_agid, u8 *p_challenge ) 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 @@ int ioctl_SendChallenge( int i_fd, int *pi_agid, u8 *p_challenge ) 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,27 +1292,27 @@ int ioctl_SendChallenge( int i_fd, int *pi_agid, u8 *p_challenge ) 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 ); - + rs_cdb.cdb_opaque[ 10 ] = DVD_SEND_CHALLENGE | (*pi_agid << 6); - + p_buffer[ 1 ] = 0xe; memcpy( p_buffer + 4, p_challenge, DVD_CHALLENGE_SIZE ); - + if( SolarisSendUSCSI( i_fd, &sc ) < 0 || sc.uscsi_status ) { return -1; } - return 0; - + i_ret = 0; + #elif defined( DARWIN_DVD_IOCTL ) INIT_DVDIOCTL( dk_dvd_send_key_t, DVDChallengeKeyInfo, kDVDKeyFormatChallengeKey ); - + dvd.grantID = *pi_agid; dvd.keyClass = kDVDKeyClassCSS_CPPM_CPRM; @@ -1342,7 +1325,7 @@ int ioctl_SendChallenge( int i_fd, int *pi_agid, u8 *p_challenge ) 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,8 +1337,8 @@ int ioctl_SendChallenge( int i_fd, int *pi_agid, u8 *p_challenge ) memcpy( key->KeyData, p_challenge, DVD_CHALLENGE_SIZE ); - return DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_SEND_KEY, key, - key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1; + 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 @@ int ioctl_SendChallenge( int i_fd, int *pi_agid, u8 *p_challenge ) 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 @@ int ioctl_SendChallenge( int i_fd, int *pi_agid, u8 *p_challenge ) p_buffer[ 1 ] = 0xe; memcpy( p_buffer + 4, p_challenge, DVD_CHALLENGE_SIZE ); - return DosDevIOCtl(i_fd, IOCTL_CDROMDISK, CDROMDISK_EXECMD, - &sdc, sizeof(sdc), &ulParamLen, - p_buffer, sizeof(p_buffer), &ulDataLen); + 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" @@ -1402,7 +1385,7 @@ int ioctl_SendChallenge( int i_fd, int *pi_agid, u8 *p_challenge ) /***************************************************************************** * 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 @@ int ioctl_SendKey2( int i_fd, int *pi_agid, u8 *p_key ) 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 @@ int ioctl_SendKey2( int i_fd, int *pi_agid, u8 *p_key ) 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 @@ int ioctl_SendKey2( int i_fd, int *pi_agid, u8 *p_key ) 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,23 +1429,23 @@ int ioctl_SendKey2( int i_fd, int *pi_agid, u8 *p_key ) 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 ); - + rs_cdb.cdb_opaque[ 10 ] = DVD_SEND_KEY2 | (*pi_agid << 6); - + p_buffer[ 1 ] = 0xa; memcpy( p_buffer + 4, p_key, DVD_KEY_SIZE ); - + if( SolarisSendUSCSI( i_fd, &sc ) < 0 || sc.uscsi_status ) { return -1; } - return 0; - + i_ret = 0; + #elif defined( DARWIN_DVD_IOCTL ) INIT_DVDIOCTL( dk_dvd_send_key_t, DVDKey2Info, kDVDKeyFormatKey2 ); @@ -1479,7 +1462,7 @@ int ioctl_SendKey2( int i_fd, int *pi_agid, u8 *p_key ) 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,8 +1474,8 @@ int ioctl_SendKey2( int i_fd, int *pi_agid, u8 *p_key ) memcpy( key->KeyData, p_key, DVD_KEY_SIZE ); - return DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_SEND_KEY, key, - key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1; + 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 @@ int ioctl_SendKey2( int i_fd, int *pi_agid, u8 *p_key ) 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 @@ int ioctl_SendKey2( int i_fd, int *pi_agid, u8 *p_key ) p_buffer[ 1 ] = 0xa; memcpy( p_buffer + 4, p_key, DVD_KEY_SIZE ); - return DosDevIOCtl(i_fd, IOCTL_CDROMDISK, CDROMDISK_EXECMD, - &sdc, sizeof(sdc), &ulParamLen, - p_buffer, sizeof(p_buffer), &ulDataLen); + 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" @@ -1595,20 +1578,20 @@ int ioctl_ReportRPC( int i_fd, int *p_type, int *p_mask, int *p_scheme ) #elif defined( SOLARIS_USCSI ) INIT_USCSI( GPCMD_REPORT_KEY, 8 ); - + rs_cdb.cdb_opaque[ 10 ] = DVD_REPORT_RPC; - + i_ret = SolarisSendUSCSI( i_fd, &sc ); - + if( i_ret < 0 || sc.uscsi_status ) { i_ret = -1; } - + *p_type = p_buffer[ 4 ] >> 6; *p_mask = p_buffer[ 5 ]; *p_scheme = p_buffer[ 6 ]; - + #elif defined( DARWIN_DVD_IOCTL ) INIT_DVDIOCTL( dk_dvd_report_key_t, DVDRegionPlaybackControlInfo, kDVDKeyFormatRegionState ); @@ -1625,28 +1608,26 @@ int ioctl_ReportRPC( int i_fd, int *p_type, int *p_mask, int *p_scheme ) 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; + + i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_READ_KEY, key, + key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1; - /* 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 + 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 @@ int ioctl_ReportRPC( int i_fd, int *p_type, int *p_mask, int *p_scheme ) 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 ) @@ -1765,15 +1873,15 @@ static void HPUXInitSCTL( struct sctl_io *sctl_io, int i_type ) /***************************************************************************** * SolarisInitUSCSI: initialize a USCSICMD structure for the Solaris kernel ***************************************************************************** - * This function initializes a Solaris userspace scsi command structure for + * 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: @@ -1785,9 +1893,9 @@ static void SolarisInitUSCSI( struct uscsi_cmd *p_sc, int i_type ) 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; @@ -1848,6 +1956,36 @@ static int SolarisSendUSCSI( int i_fd, struct uscsi_cmd *p_sc ) { #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 @@ static void WinInitSSC( struct SRB_ExecSCSICmd *p_ssc, int i_type ) 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; @@ -1944,7 +2082,7 @@ static void QNXInitCPT( CAM_PASS_THRU * p_cpt, int i_type ) /***************************************************************************** * OS2InitSDC: initialize a SDC structure for the Execute SCSI-command ***************************************************************************** - * This function initializes a OS2 'execute SCSI command' structure for + * This function initializes a OS2 'execute SCSI command' structure for * future use, either a read command or a write command. *****************************************************************************/ static void OS2InitSDC( struct OS2_ExecSCSICmd *p_sdc, int i_type ) diff --git a/libmpdvdkit2/ioctl.h b/libmpdvdkit2/ioctl.h index 8288686152..13c095e60a 100644 --- a/libmpdvdkit2/ioctl.h +++ b/libmpdvdkit2/ioctl.h @@ -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 @@ int ioctl_SendKey2 ( int, int *, u8 * ); #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 @@ int ioctl_SendKey2 ( int, int *, u8 * ); #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 @@ int ioctl_SendKey2 ( int, int *, u8 * ); #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 @@ int ioctl_SendKey2 ( int, int *, u8 * ); #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 @@ int ioctl_SendKey2 ( int, int *, u8 * ); #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 @@ typedef union dvd_authinfo dvd_authinfo; #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 @@ typedef struct _DVD_ASF 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 { diff --git a/libmpdvdkit2/libdvdcss.c b/libmpdvdkit2/libdvdcss.c index b287da3f63..b30ec47414 100644 --- a/libmpdvdkit2/libdvdcss.c +++ b/libmpdvdkit2/libdvdcss.c @@ -11,7 +11,7 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -22,7 +22,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ -/** +/** * \mainpage libdvdcss developer documentation * * \section intro Introduction @@ -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,9 @@ #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> - -#ifdef HAVE_UNISTD_H -# include <unistd.h> -#endif +#include <errno.h> +#include <unistd.h> +#include <limits.h> #include "dvdcss.h" @@ -117,8 +125,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 +145,7 @@ extern dvdcss_t dvdcss_open ( char *psz_target ) 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 +171,9 @@ extern dvdcss_t dvdcss_open ( char *psz_target ) 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 +218,23 @@ extern dvdcss_t dvdcss_open ( char *psz_target ) } } - 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 @@ -223,26 +246,26 @@ extern dvdcss_t dvdcss_open ( char *psz_target ) free( dvdcss ); return NULL; } - + dvdcss->b_scrambled = 1; /* Assume the worst */ dvdcss->b_ioctls = _dvdcss_use_ioctls( dvdcss ); if( dvdcss->b_ioctls ) { i_ret = _dvdcss_test( dvdcss ); - if( i_ret < 0 ) - { - /* Disable the CSS ioctls and hope that it works? */ + if( i_ret < 0 ) + { + /* Disable the CSS ioctls and hope that it works? */ _dvdcss_debug( dvdcss, "could not check whether the disc was scrambled" ); - dvdcss->b_ioctls = 0; - } - else - { + dvdcss->b_ioctls = 0; + } + else + { _dvdcss_debug( dvdcss, i_ret ? "disc is scrambled" : "disc is unscrambled" ); - dvdcss->b_scrambled = i_ret; - } + dvdcss->b_scrambled = i_ret; + } } /* If disc is CSS protected and the ioctls work, authenticate the drive */ @@ -266,46 +289,127 @@ extern dvdcss_t dvdcss_open ( char *psz_target ) } #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=§or[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=§or[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] ); - break; - } - if(!disc_id) disc_id=strdup(title_name); - } - 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 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; + } + else if( psz_data[i] == '/' || psz_data[i] == '\\' ) + { + psz_data[i] = '-'; + } + } + + /* 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; } @@ -354,11 +458,11 @@ extern int dvdcss_seek ( dvdcss_t dvdcss, int i_blocks, int i_flags ) { /* title cracking method is too slow to be used at each seek */ if( ( ( i_flags & DVDCSS_SEEK_MPEG ) - && ( dvdcss->i_method != DVDCSS_METHOD_TITLE ) ) + && ( dvdcss->i_method != DVDCSS_METHOD_TITLE ) ) || ( i_flags & DVDCSS_SEEK_KEY ) ) { /* check the title key */ - if( _dvdcss_title( dvdcss, i_blocks ) ) + if( _dvdcss_title( dvdcss, i_blocks ) ) { return -1; } @@ -407,31 +511,31 @@ extern int dvdcss_read ( dvdcss_t dvdcss, void *p_buffer, if( ! memcmp( dvdcss->css.p_title_key, "\0\0\0\0\0", 5 ) ) { - /* For what we believe is an unencrypted title, - * check that there are no encrypted blocks */ + /* For what we believe is an unencrypted title, + * 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; + break; } - p_buffer = (void *) ((u8 *)p_buffer + DVDCSS_BLOCK_SIZE); + p_buffer = (void *) ((uint8_t *)p_buffer + DVDCSS_BLOCK_SIZE); } } - else + else { /* Decrypt the blocks we managed to read */ 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); - } + { + _dvdcss_unscramble( dvdcss->css.p_title_key, p_buffer ); + ((uint8_t*)p_buffer)[0x14] &= 0x8f; + p_buffer = (void *) ((uint8_t *)p_buffer + DVDCSS_BLOCK_SIZE); + } } - + return i_ret; } @@ -502,9 +606,9 @@ extern int dvdcss_readv ( dvdcss_t dvdcss, void *p_iovec, } _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; } diff --git a/libmpdvdkit2/libdvdcss.h b/libmpdvdkit2/libdvdcss.h index cb37bf498e..473644d5ef 100644 --- a/libmpdvdkit2/libdvdcss.h +++ b/libmpdvdkit2/libdvdcss.h @@ -1,5 +1,5 @@ /***************************************************************************** - * private.h: private DVD reading library data + * libdvdcss.h: private DVD reading library data ***************************************************************************** * Copyright (C) 1998-2001 VideoLAN * $Id$ @@ -11,7 +11,7 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -33,7 +33,7 @@ struct dvdcss_s 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 @@ struct dvdcss_s 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; |