importing libdvdcss 1.2.2 files

git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@7028 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
arpi 2002-08-16 22:35:45 +00:00
parent 131935f8ad
commit 211d6637bc
14 changed files with 6866 additions and 0 deletions

315
libmpdvdkit2/bsdi_dvd.h Normal file
View File

@ -0,0 +1,315 @@
#ifndef _DVD_H_
#define _DVD_H_
#include <sys/cdefs.h>
#include <machine/endian.h>
#include <sys/ioctl.h>
__BEGIN_DECLS
int dvd_cdrom_ioctl(int, unsigned long, void *);
int cdrom_blocksize(int, int);
void dvd_cdrom_debug(int);
__END_DECLS
#define ioctl(a,b,c) dvd_cdrom_ioctl((a),(b),(c))
typedef unsigned char __u8;
typedef unsigned short __u16;
typedef unsigned int __u32;
#define DVD_READ_STRUCT 0x5390 /* Read structure */
#define DVD_WRITE_STRUCT 0x5391 /* Write structure */
#define DVD_AUTH 0x5392 /* Authentication */
#define DVD_STRUCT_PHYSICAL 0x00
#define DVD_STRUCT_COPYRIGHT 0x01
#define DVD_STRUCT_DISCKEY 0x02
#define DVD_STRUCT_BCA 0x03
#define DVD_STRUCT_MANUFACT 0x04
struct dvd_layer {
__u8 book_version : 4;
__u8 book_type : 4;
__u8 min_rate : 4;
__u8 disc_size : 4;
__u8 layer_type : 4;
__u8 track_path : 1;
__u8 nlayers : 2;
__u8 track_density : 4;
__u8 linear_density : 4;
__u8 bca : 1;
__u32 start_sector;
__u32 end_sector;
__u32 end_sector_l0;
};
struct dvd_physical {
__u8 type;
__u8 layer_num;
struct dvd_layer layer[4];
};
struct dvd_copyright {
__u8 type;
__u8 layer_num;
__u8 cpst;
__u8 rmi;
};
struct dvd_disckey {
__u8 type;
unsigned agid : 2;
__u8 value[2048];
};
struct dvd_bca {
__u8 type;
int len;
__u8 value[188];
};
struct dvd_manufact {
__u8 type;
__u8 layer_num;
int len;
__u8 value[2048];
};
typedef union {
__u8 type;
struct dvd_physical physical;
struct dvd_copyright copyright;
struct dvd_disckey disckey;
struct dvd_bca bca;
struct dvd_manufact manufact;
} dvd_struct;
/*
* DVD authentication ioctl
*/
/* Authentication states */
#define DVD_LU_SEND_AGID 0
#define DVD_HOST_SEND_CHALLENGE 1
#define DVD_LU_SEND_KEY1 2
#define DVD_LU_SEND_CHALLENGE 3
#define DVD_HOST_SEND_KEY2 4
/* Termination states */
#define DVD_AUTH_ESTABLISHED 5
#define DVD_AUTH_FAILURE 6
/* Other functions */
#define DVD_LU_SEND_TITLE_KEY 7
#define DVD_LU_SEND_ASF 8
#define DVD_INVALIDATE_AGID 9
#define DVD_LU_SEND_RPC_STATE 10
#define DVD_HOST_SEND_RPC_STATE 11
/* State data */
typedef __u8 dvd_key[5]; /* 40-bit value, MSB is first elem. */
typedef __u8 dvd_challenge[10]; /* 80-bit value, MSB is first elem. */
struct dvd_lu_send_agid {
__u8 type;
unsigned agid : 2;
};
struct dvd_host_send_challenge {
__u8 type;
unsigned agid : 2;
dvd_challenge chal;
};
struct dvd_send_key {
__u8 type;
unsigned agid : 2;
dvd_key key;
};
struct dvd_lu_send_challenge {
__u8 type;
unsigned agid : 2;
dvd_challenge chal;
};
#define DVD_CPM_NO_COPYRIGHT 0
#define DVD_CPM_COPYRIGHTED 1
#define DVD_CP_SEC_NONE 0
#define DVD_CP_SEC_EXIST 1
#define DVD_CGMS_UNRESTRICTED 0
#define DVD_CGMS_SINGLE 2
#define DVD_CGMS_RESTRICTED 3
struct dvd_lu_send_title_key {
__u8 type;
unsigned agid : 2;
dvd_key title_key;
int lba;
unsigned cpm : 1;
unsigned cp_sec : 1;
unsigned cgms : 2;
};
struct dvd_lu_send_asf {
__u8 type;
unsigned agid : 2;
unsigned asf : 1;
};
struct dvd_host_send_rpcstate {
__u8 type;
__u8 pdrc;
};
struct dvd_lu_send_rpcstate {
__u8 type : 2;
__u8 vra : 3;
__u8 ucca : 3;
__u8 region_mask;
__u8 rpc_scheme;
};
typedef union {
__u8 type;
struct dvd_lu_send_agid lsa;
struct dvd_host_send_challenge hsc;
struct dvd_send_key lsk;
struct dvd_lu_send_challenge lsc;
struct dvd_send_key hsk;
struct dvd_lu_send_title_key lstk;
struct dvd_lu_send_asf lsasf;
struct dvd_host_send_rpcstate hrpcs;
struct dvd_lu_send_rpcstate lrpcs;
} dvd_authinfo;
typedef struct {
__u16 report_key_length;
__u8 reserved1;
__u8 reserved2;
#if BYTE_ORDER == BIG_ENDIAN
__u8 type_code : 2;
__u8 vra : 3;
__u8 ucca : 3;
#elif BYTE_ORDER == LITTLE_ENDIAN
__u8 ucca : 3;
__u8 vra : 3;
__u8 type_code : 2;
#endif
__u8 region_mask;
__u8 rpc_scheme;
__u8 reserved3;
} rpc_state_t;
/*
* Stuff for the CDROM ioctls
*/
#define CDROMREADTOCHDR 0x5305 /* Read TOC header (cdrom_tochdr) */
#define CDROMREADTOCENTRY 0x5306 /* Read TOC entry (cdrom_tocentry) */
#define CDROMEJECT 0x5309 /* Ejects the cdrom media */
#define CDROMCLOSETRAY 0x5319 /* Reverse of CDROMEJECT */
#define CDROM_DRIVE_STATUS 0x5326 /* Get tray position, 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) */
#define CD_MINS 74 /* max. minutes per CD, not really a limit */
#define CD_SECS 60 /* seconds per minute */
#define CD_FRAMES 75 /* frames per second */
#define CD_MSF_OFFSET 150 /* MSF numbering offset of first frame */
#define CD_HEAD_SIZE 4 /* header (address) bytes per raw data frame */
#define CD_SYNC_SIZE 12 /* 12 sync bytes per raw data frame */
#define CD_FRAMESIZE 2048 /* bytes per frame, "cooked" mode */
#define CD_FRAMESIZE_RAW 2352 /* bytes per frame, "raw" mode */
#define CD_FRAMESIZE_RAW0 (CD_FRAMESIZE_RAW-CD_SYNC_SIZE-CD_HEAD_SIZE) /*2336*/
#define CD_FRAMESIZE_RAW1 (CD_FRAMESIZE_RAW-CD_SYNC_SIZE) /*2340*/
/* CD-ROM address types (cdrom_tocentry.cdte_format) */
#define CDROM_LBA 0x01 /* logical block: first frame is #0 */
#define CDROM_MSF 0x02 /* minute-second-frame: binary. not bcd here!*/
/* The leadout track is always 0xAA, regardless of # of tracks on disc */
#define CDROM_LEADOUT 0xAA
/* drive status returned by CDROM_DRIVE_STATUS ioctl */
#define CDS_NO_INFO 0 /* if not implemented */
#define CDS_NO_DISC 1
#define CDS_TRAY_OPEN 2
#define CDS_DRIVE_NOT_READY 3
#define CDS_DISC_OK 4
/* 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
{
__u8 cdmsf_min0; /* start minute */
__u8 cdmsf_sec0; /* start second */
__u8 cdmsf_frame0; /* start frame */
__u8 cdmsf_min1; /* end minute */
__u8 cdmsf_sec1; /* end second */
__u8 cdmsf_frame1; /* end frame */
};
struct cdrom_tochdr
{
__u8 cdth_trk0; /* start track */
__u8 cdth_trk1; /* end track */
};
struct cdrom_msf0
{
__u8 minute;
__u8 second;
__u8 frame;
};
union cdrom_addr
{
struct cdrom_msf0 msf;
int lba;
};
struct cdrom_tocentry
{
__u8 cdte_track;
__u8 cdte_adr :4;
__u8 cdte_ctrl :4;
__u8 cdte_format;
union cdrom_addr cdte_addr;
__u8 cdte_datamode;
};
struct modesel_head
{
__u8 reserved1;
__u8 medium;
__u8 reserved2;
__u8 block_desc_length;
__u8 density;
__u8 number_of_blocks_hi;
__u8 number_of_blocks_med;
__u8 number_of_blocks_lo;
__u8 reserved3;
__u8 block_length_hi;
__u8 block_length_med;
__u8 block_length_lo;
};
#endif /* _DVD_H_ */

698
libmpdvdkit2/bsdi_ioctl.c Normal file
View File

@ -0,0 +1,698 @@
#include "config.h"
/*
* Hacked version of the linux cdrom.c kernel module - everything except the
* DVD handling ripped out and the rest rewritten to use raw SCSI commands
* on BSD/OS 4.2 (but should work with earlier versions as well).
*/
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include </sys/dev/scsi/scsi.h>
#include </sys/dev/scsi/scsi_ioctl.h>
#include "bsdi_dvd.h"
/*
* Now get rid of the override/intercept macro so we can call the real ioctl()
* routine!
*/
#undef ioctl
#define CMD_READ_10 0x28
#define CMD_READ_TOC_PMA_ATIP 0x43
#define CMD_READ_CD 0xbe
#define CMD_START_STOP_UNIT 0x1b
#define CMD_SEND_KEY 0xa3
#define CMD_REPORT_KEY 0xa4
#define CMD_READ_DVD_STRUCTURE 0xad
#define copy_key(dest,src) memcpy((dest), (src), sizeof(dvd_key))
#define copy_chal(dest,src) memcpy((dest), (src), sizeof(dvd_challenge))
/* Define the Cdrom Generic Command structure */
typedef struct cgc
{
u_char cdb[12];
u_char *buf;
int buflen;
int rw;
int timeout;
scsi_user_sense_t *sus;
} cgc_t;
static int scsi_cmd(int, cgc_t *);
static int cdrom_ioctl(int, u_long, void *);
static int cdrom_tray_move(int, int);
static int dvd_ioctl(int, u_long, void *);
static int debug;
void dvd_cdrom_debug(int flag)
{
debug = flag;
}
/*
* This is the published entry point. Actually applications should simply
* include <dvd.h> and not refer to this at all.
*/
int dvd_cdrom_ioctl(int fd, unsigned long cmd, void *arg)
{
switch (cmd)
{
case DVD_AUTH:
case DVD_READ_STRUCT:
return(dvd_ioctl(fd, cmd, arg));
case CDROMREADTOCHDR:
case CDROMREADTOCENTRY:
case CDROMEJECT:
case CDROMREADRAW:
case CDROMREADMODE2:
case CDROMCLOSETRAY:
case CDROM_DRIVE_STATUS:
return(cdrom_ioctl(fd, cmd, arg));
default:
return(ioctl(fd, cmd, arg));
}
}
static void setup_report_key(cgc_t *cgc, u_int agid, u_int type)
{
cgc->cdb[0] = CMD_REPORT_KEY;
cgc->cdb[10] = type | (agid << 6);
switch (type)
{
case 0:
case 5:
case 8:
cgc->buflen = 8;
break;
case 1:
cgc->buflen = 16;
break;
case 2:
case 4:
cgc->buflen = 12;
break;
}
cgc->cdb[9] = cgc->buflen;
cgc->rw = SUC_READ;;
}
static void setup_send_key(cgc_t *cgc, u_int agid, u_int type)
{
cgc->cdb[0] = CMD_SEND_KEY;
cgc->cdb[10] = type | (agid << 6);
switch (type)
{
case 1:
cgc->buflen = 16;
break;
case 3:
cgc->buflen = 12;
break;
case 6:
cgc->buflen = 8;
break;
}
cgc->cdb[9] = cgc->buflen;
cgc->rw = SUC_WRITE;
}
static void cgc_init(cgc_t *cgc, void *buf, int len, int type)
{
memset(cgc, 0, sizeof (*cgc));
if (buf)
memset(buf, 0, len);
cgc->buf = (u_char *)buf;
cgc->buflen = len;
cgc->rw = type;
cgc->timeout = 5; /* 5 second timeout */
}
static int dvd_do_auth(int fd, dvd_authinfo *ai)
{
int ret;
u_char buf[20];
cgc_t cgc;
rpc_state_t rpc_state;
memset(buf, 0, sizeof(buf));
cgc_init(&cgc, buf, 0, SUC_READ);
switch (ai->type)
{
case DVD_LU_SEND_AGID: /* LU data send */
setup_report_key(&cgc, ai->lsa.agid, 0);
if (ret = scsi_cmd(fd, &cgc))
return ret;
ai->lsa.agid = buf[7] >> 6;
break;
case DVD_LU_SEND_KEY1:
setup_report_key(&cgc, ai->lsk.agid, 2);
if (ret = scsi_cmd(fd, &cgc))
return ret;
copy_key(ai->lsk.key, &buf[4]);
break;
case DVD_LU_SEND_CHALLENGE:
setup_report_key(&cgc, ai->lsc.agid, 1);
if (ret = scsi_cmd(fd, &cgc))
return ret;
copy_chal(ai->lsc.chal, &buf[4]);
break;
case DVD_LU_SEND_TITLE_KEY: /* Post-auth key */
setup_report_key(&cgc, ai->lstk.agid, 4);
cgc.cdb[5] = ai->lstk.lba;
cgc.cdb[4] = ai->lstk.lba >> 8;
cgc.cdb[3] = ai->lstk.lba >> 16;
cgc.cdb[2] = ai->lstk.lba >> 24;
if (ret = scsi_cmd(fd, &cgc))
return ret;
ai->lstk.cpm = (buf[4] >> 7) & 1;
ai->lstk.cp_sec = (buf[4] >> 6) & 1;
ai->lstk.cgms = (buf[4] >> 4) & 3;
copy_key(ai->lstk.title_key, &buf[5]);
break;
case DVD_LU_SEND_ASF:
setup_report_key(&cgc, ai->lsasf.agid, 5);
if (ret = scsi_cmd(fd, &cgc))
return ret;
ai->lsasf.asf = buf[7] & 1;
break;
case DVD_HOST_SEND_CHALLENGE: /* LU data receive (LU changes state) */
setup_send_key(&cgc, ai->hsc.agid, 1);
buf[1] = 0xe;
copy_chal(&buf[4], ai->hsc.chal);
if (ret = scsi_cmd(fd, &cgc))
return ret;
ai->type = DVD_LU_SEND_KEY1;
break;
case DVD_HOST_SEND_KEY2:
setup_send_key(&cgc, ai->hsk.agid, 3);
buf[1] = 0xa;
copy_key(&buf[4], ai->hsk.key);
if (ret = scsi_cmd(fd, &cgc))
{
ai->type = DVD_AUTH_FAILURE;
return ret;
}
ai->type = DVD_AUTH_ESTABLISHED;
break;
case DVD_INVALIDATE_AGID:
setup_report_key(&cgc, ai->lsa.agid, 0x3f);
if (ret = scsi_cmd(fd, &cgc))
return ret;
break;
case DVD_LU_SEND_RPC_STATE: /* Get region settings */
setup_report_key(&cgc, 0, 8);
memset(&rpc_state, 0, sizeof(rpc_state_t));
cgc.buf = (char *) &rpc_state;
if (ret = scsi_cmd(fd, &cgc))
{
ai->lrpcs.type = 0;
ai->lrpcs.rpc_scheme = 0;
}
else
{
ai->lrpcs.type = rpc_state.type_code;
ai->lrpcs.vra = rpc_state.vra;
ai->lrpcs.ucca = rpc_state.ucca;
ai->lrpcs.region_mask = rpc_state.region_mask;
ai->lrpcs.rpc_scheme = rpc_state.rpc_scheme;
}
break;
case DVD_HOST_SEND_RPC_STATE: /* Set region settings */
setup_send_key(&cgc, 0, 6);
buf[1] = 6;
buf[4] = ai->hrpcs.pdrc;
if (ret = scsi_cmd(fd, &cgc))
return ret;
break;
default:
return EINVAL;
}
return 0;
}
static int dvd_read_physical(int fd, dvd_struct *s)
{
int ret, i;
u_char buf[4 + 4 * 20], *base;
struct dvd_layer *layer;
cgc_t cgc;
cgc_init(&cgc, buf, sizeof(buf), SUC_READ);
cgc.cdb[0] = CMD_READ_DVD_STRUCTURE;
cgc.cdb[6] = s->physical.layer_num;
cgc.cdb[7] = s->type;
cgc.cdb[9] = cgc.buflen & 0xff;
if (ret = scsi_cmd(fd, &cgc))
return ret;
base = &buf[4];
layer = &s->physical.layer[0];
/* place the data... really ugly, but at least we won't have to
worry about endianess in userspace or here. */
for (i = 0; i < 4; ++i, base += 20, ++layer)
{
memset(layer, 0, sizeof(*layer));
layer->book_version = base[0] & 0xf;
layer->book_type = base[0] >> 4;
layer->min_rate = base[1] & 0xf;
layer->disc_size = base[1] >> 4;
layer->layer_type = base[2] & 0xf;
layer->track_path = (base[2] >> 4) & 1;
layer->nlayers = (base[2] >> 5) & 3;
layer->track_density = base[3] & 0xf;
layer->linear_density = base[3] >> 4;
layer->start_sector = base[5] << 16 | base[6] << 8 | base[7];
layer->end_sector = base[9] << 16 | base[10] << 8 | base[11];
layer->end_sector_l0 = base[13] << 16 | base[14] << 8 | base[15];
layer->bca = base[16] >> 7;
}
return 0;
}
static int dvd_read_copyright(int fd, dvd_struct *s)
{
int ret;
u_char buf[8];
cgc_t cgc;
cgc_init(&cgc, buf, sizeof(buf), SUC_READ);
cgc.cdb[0] = CMD_READ_DVD_STRUCTURE;
cgc.cdb[6] = s->copyright.layer_num;
cgc.cdb[7] = s->type;
cgc.cdb[8] = cgc.buflen >> 8;
cgc.cdb[9] = cgc.buflen & 0xff;
if (ret = scsi_cmd(fd, &cgc))
return ret;
s->copyright.cpst = buf[4];
s->copyright.rmi = buf[5];
return 0;
}
static int dvd_read_disckey(int fd, dvd_struct *s)
{
int ret, size;
u_char *buf;
cgc_t cgc;
size = sizeof(s->disckey.value) + 4;
if ((buf = (u_char *) malloc(size)) == NULL)
return ENOMEM;
cgc_init(&cgc, buf, size, SUC_READ);
cgc.cdb[0] = CMD_READ_DVD_STRUCTURE;
cgc.cdb[7] = s->type;
cgc.cdb[8] = size >> 8;
cgc.cdb[9] = size & 0xff;
cgc.cdb[10] = s->disckey.agid << 6;
if (!(ret = scsi_cmd(fd, &cgc)))
memcpy(s->disckey.value, &buf[4], sizeof(s->disckey.value));
free(buf);
return ret;
}
static int dvd_read_bca(int fd, dvd_struct *s)
{
int ret;
u_char buf[4 + 188];
cgc_t cgc;
cgc_init(&cgc, buf, sizeof(buf), SUC_READ);
cgc.cdb[0] = CMD_READ_DVD_STRUCTURE;
cgc.cdb[7] = s->type;
cgc.cdb[9] = cgc.buflen = 0xff;
if (ret = scsi_cmd(fd, &cgc))
return ret;
s->bca.len = buf[0] << 8 | buf[1];
if (s->bca.len < 12 || s->bca.len > 188)
return EIO;
memcpy(s->bca.value, &buf[4], s->bca.len);
return 0;
}
static int dvd_read_manufact(int fd, dvd_struct *s)
{
int ret = 0, size;
u_char *buf;
cgc_t cgc;
size = sizeof(s->manufact.value) + 4;
if ((buf = (u_char *) malloc(size)) == NULL)
return ENOMEM;
cgc_init(&cgc, buf, size, SUC_READ);
cgc.cdb[0] = CMD_READ_DVD_STRUCTURE;
cgc.cdb[7] = s->type;
cgc.cdb[8] = size >> 8;
cgc.cdb[9] = size & 0xff;
if (ret = scsi_cmd(fd, &cgc))
{
free(buf);
return ret;
}
s->manufact.len = buf[0] << 8 | buf[1];
if (s->manufact.len < 0 || s->manufact.len > 2048)
ret = -EIO;
else
memcpy(s->manufact.value, &buf[4], s->manufact.len);
free(buf);
return ret;
}
static int dvd_read_struct(int fd, dvd_struct *s)
{
switch (s->type)
{
case DVD_STRUCT_PHYSICAL:
return dvd_read_physical(fd, s);
case DVD_STRUCT_COPYRIGHT:
return dvd_read_copyright(fd, s);
case DVD_STRUCT_DISCKEY:
return dvd_read_disckey(fd, s);
case DVD_STRUCT_BCA:
return dvd_read_bca(fd, s);
case DVD_STRUCT_MANUFACT:
return dvd_read_manufact(fd, s);
default:
return EINVAL;
}
}
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;
unsigned char *cp;
struct scsi_user_cdb suc;
/* safety checks */
if (cgc->rw != SUC_READ && cgc->rw != SUC_WRITE)
return(EINVAL);
suc.suc_flags = cgc->rw;
cdblen = scsi_cdblen[(cgc->cdb[0] >> 5) & 7];
suc.suc_cdblen = cdblen;
bcopy(cgc->cdb, suc.suc_cdb, cdblen);
suc.suc_data = cgc->buf;
suc.suc_datalen = cgc->buflen;
suc.suc_timeout = cgc->timeout;
if (ioctl(fd, SCSIRAWCDB, &suc) == -1)
return(errno);
scsistatus = suc.suc_sus.sus_status;
/*
* If the device returns a scsi sense error and debugging is enabled print
* some hopefully useful information on stderr.
*/
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]);
}
if (cgc->sus)
bcopy(&suc.suc_sus, cgc->sus, sizeof (struct scsi_user_sense));
if (scsistatus)
return(EIO); /* generic i/o error for unsuccessful status */
return(0);
}
/*
* The entry point for the DVDioctls for BSD/OS.
*/
static int dvd_ioctl(int fd, u_long cmd, void *arg)
{
int ret;
switch (cmd)
{
case DVD_READ_STRUCT:
ret = dvd_read_struct(fd, (dvd_struct *)arg);
if (ret)
errno = ret;
return(ret ? -1 : 0);
case DVD_AUTH:
ret = dvd_do_auth (fd, (dvd_authinfo *)arg);
if (ret)
errno = ret;
return(ret ? -1 : 0);
default:
errno = EINVAL;
return(-1);
}
}
/*
* The entry point for the CDROMioctls for BSD/OS
*/
static int cdrom_read_block(int, cgc_t *, int, int, int, int);
static int cdrom_read_cd(int, cgc_t *, int, int, int );
int cdrom_blocksize(int, int );
static inline
int msf_to_lba(char m, char s, char f)
{
return (((m * CD_SECS) + s) * CD_FRAMES + f) - CD_MSF_OFFSET;
}
cdrom_ioctl(int fd, u_long cmd, void *arg)
{
int ret;
cgc_t cgc;
switch (cmd)
{
case CDROMREADRAW:
case CDROMREADMODE1:
case CDROMREADMODE2:
{
struct cdrom_msf *msf;
int blocksize = 0, format = 0, lba;
switch (cmd)
{
case CDROMREADRAW:
blocksize = CD_FRAMESIZE_RAW;
break;
case CDROMREADMODE1:
blocksize = CD_FRAMESIZE;
format = 2;
break;
case CDROMREADMODE2:
blocksize = CD_FRAMESIZE_RAW0;
break;
}
msf = (struct cdrom_msf *)arg;
lba = msf_to_lba(msf->cdmsf_min0,msf->cdmsf_sec0,
msf->cdmsf_frame0);
ret = EINVAL;
if (lba < 0)
break;
cgc_init(&cgc, arg, blocksize, SUC_READ);
ret = cdrom_read_block(fd, &cgc, lba, 1, format, blocksize);
if (ret)
{
/*
* SCSI-II devices are not required to support CMD_READ_CD (which specifies
* the blocksize to read) so try switching the block size with a mode select,
* doing the normal read sector command and then changing the sector size back
* to 2048.
*
* If the program dies before changing the blocksize back sdopen()
* in the kernel will fail opens with a message that looks something like:
*
* "sr1: blksize 2336 not multiple of 512: cannot use"
*
* At that point the drive has to be power cycled (or reset in some other way).
*/
if (ret = cdrom_blocksize(fd, blocksize))
break;
ret = cdrom_read_cd(fd, &cgc, lba, blocksize, 1);
ret |= cdrom_blocksize(fd, 2048);
}
break;
}
case CDROMREADTOCHDR:
{
struct cdrom_tochdr *tochdr = (struct cdrom_tochdr *) arg;
u_char buffer[12];
cgc_init(&cgc, buffer, sizeof (buffer), SUC_READ);
cgc.cdb[0] = CMD_READ_TOC_PMA_ATIP;
cgc.cdb[1] = 0x2; /* MSF */
cgc.cdb[8] = 12; /* LSB of length */
ret = scsi_cmd(fd, &cgc);
if (!ret)
{
tochdr->cdth_trk0 = buffer[2];
tochdr->cdth_trk1 = buffer[3];
}
break;
}
case CDROMREADTOCENTRY:
{
struct cdrom_tocentry *tocentry = (struct cdrom_tocentry *) arg;
u_char buffer[12];
cgc_init(&cgc, buffer, sizeof (buffer), SUC_READ);
cgc.cdb[0] = CMD_READ_TOC_PMA_ATIP;
cgc.cdb[1] = (tocentry->cdte_format == CDROM_MSF) ? 0x02 : 0;
cgc.cdb[6] = tocentry->cdte_track;
cgc.cdb[8] = 12; /* LSB of length */
ret = scsi_cmd(fd, &cgc);
if (ret)
break;
tocentry->cdte_ctrl = buffer[5] & 0xf;
tocentry->cdte_adr = buffer[5] >> 4;
tocentry->cdte_datamode = (tocentry->cdte_ctrl & 0x04) ? 1 : 0;
if (tocentry->cdte_format == CDROM_MSF)
{
tocentry->cdte_addr.msf.minute = buffer[9];
tocentry->cdte_addr.msf.second = buffer[10];
tocentry->cdte_addr.msf.frame = buffer[11];
}
else
tocentry->cdte_addr.lba = (((((buffer[8] << 8)
+ buffer[9]) << 8)
+ buffer[10]) << 8)
+ buffer[11];
break;
}
case CDROMEJECT: /* NO-OP for now */
ret = cdrom_tray_move(fd, 1);
break;
case CDROMCLOSETRAY:
ret = cdrom_tray_move(fd, 0);
break;
/*
* 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.
*/
case CDROM_DRIVE_STATUS:
return(CDS_NO_INFO);
break;
}
errno = ret;
return(ret ? -1 : 0);
}
static int cdrom_read_cd(int fd, cgc_t *cgc, int lba, int blocksize, int nblocks)
{
memset(&cgc->cdb, 0, sizeof(cgc->cdb));
cgc->cdb[0] = CMD_READ_10;
cgc->cdb[2] = (lba >> 24) & 0xff;
cgc->cdb[3] = (lba >> 16) & 0xff;
cgc->cdb[4] = (lba >> 8) & 0xff;
cgc->cdb[5] = lba & 0xff;
cgc->cdb[6] = (nblocks >> 16) & 0xff;
cgc->cdb[7] = (nblocks >> 8) & 0xff;
cgc->cdb[8] = nblocks & 0xff;
cgc->buflen = blocksize * nblocks;
return(scsi_cmd(fd, cgc));
}
static int cdrom_read_block(int fd, cgc_t *cgc,
int lba, int nblocks, int format, int blksize)
{
memset(&cgc->cdb, 0, sizeof(cgc->cdb));
cgc->cdb[0] = CMD_READ_CD;
/* expected sector size - cdda,mode1,etc. */
cgc->cdb[1] = format << 2;
/* starting address */
cgc->cdb[2] = (lba >> 24) & 0xff;
cgc->cdb[3] = (lba >> 16) & 0xff;
cgc->cdb[4] = (lba >> 8) & 0xff;
cgc->cdb[5] = lba & 0xff;
/* number of blocks */
cgc->cdb[6] = (nblocks >> 16) & 0xff;
cgc->cdb[7] = (nblocks >> 8) & 0xff;
cgc->cdb[8] = nblocks & 0xff;
cgc->buflen = blksize * nblocks;
/* set the header info returned */
switch (blksize)
{
case CD_FRAMESIZE_RAW0:
cgc->cdb[9] = 0x58;
break;
case CD_FRAMESIZE_RAW1:
cgc->cdb[9] = 0x78;
break;
case CD_FRAMESIZE_RAW:
cgc->cdb[9] = 0xf8;
break;
default:
cgc->cdb[9] = 0x10;
}
return(scsi_cmd(fd, cgc));
}
static int cdrom_tray_move(int fd, int flag)
{
cgc_t cgc;
cgc_init(&cgc, NULL, 0, SUC_READ);
cgc.cdb[0] = CMD_START_STOP_UNIT;
cgc.cdb[1] = 1; /* immediate */
cgc.cdb[4] = flag ? 0x2 : 0x3; /* eject : close */
return(scsi_cmd(fd, &cgc));
}
/*
* Required when we need to use READ_10 to issue other than 2048 block
* reads
*/
int cdrom_blocksize(int fd, int size)
{
cgc_t cgc;
struct modesel_head mh;
memset(&mh, 0, sizeof(mh));
mh.block_desc_length = 0x08;
mh.block_length_med = (size >> 8) & 0xff;
mh.block_length_lo = size & 0xff;
memset(&cgc, 0, sizeof(cgc));
cgc.cdb[0] = 0x15;
cgc.cdb[1] = 1 << 4;
cgc.cdb[4] = 12;
cgc.buflen = sizeof(mh);
cgc.buf = (u_char *) &mh;
cgc.rw = SUC_WRITE;
mh.block_desc_length = 0x08;
mh.block_length_med = (size >> 8) & 0xff;
mh.block_length_lo = size & 0xff;
return(scsi_cmd(fd, &cgc));
}

67
libmpdvdkit2/common.h Normal file
View File

@ -0,0 +1,67 @@
/*****************************************************************************
* common.h: common definitions
* Collection of useful common types and macros definitions
*****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN
* $Id$
*
* Authors: Samuel Hocevar <sam@via.ecp.fr>
* Vincent Seguin <seguin@via.ecp.fr>
* Gildas Bazin <gbazin@netcourrier.com>
*
* 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
* (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
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
/*****************************************************************************
* Basic types definitions
*****************************************************************************/
/* Basic types definitions */
typedef unsigned char u8;
typedef signed char s8;
typedef unsigned int u32;
typedef signed int s32;
typedef u8 byte_t;
#if defined( WIN32 )
/* several type definitions */
# if defined( __MINGW32__ )
# if !defined( _OFF_T_ )
typedef long long _off_t;
typedef _off_t off_t;
# define _OFF_T_
# else
# define off_t long long
# endif
# endif
# if defined( _MSC_VER )
# if !defined( _OFF_T_DEFINED )
typedef __int64 off_t;
# define _OFF_T_DEFINED
# else
# define off_t __int64
# endif
# define stat _stati64
# endif
# ifndef snprintf
# define snprintf _snprintf /* snprintf not defined in mingw32 (bug?) */
# endif
#endif

1588
libmpdvdkit2/css.c Normal file

File diff suppressed because it is too large Load Diff

56
libmpdvdkit2/css.h Normal file
View File

@ -0,0 +1,56 @@
/*****************************************************************************
* css.h: Structures for DVD authentication and unscrambling
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id$
*
* Author: Stéphane Borel <stef@via.ecp.fr>
*
* based on:
* - css-auth by Derek Fawcus <derek@spider.com>
* - DVD CSS ioctls example program by Andrew T. Veliath <andrewtv@usa.net>
* - DeCSSPlus by Ethan Hawke
* - The Divide and conquer attack by Frank A. Stevenson <frank@funcom.com>
*
* 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
* (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
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
#define KEY_SIZE 5
typedef u8 dvd_key_t[KEY_SIZE];
typedef struct dvd_title_s
{
int i_startlb;
dvd_key_t p_key;
struct dvd_title_s *p_next;
} dvd_title_t;
typedef struct css_s
{
int i_agid; /* Current Authenication Grant ID. */
dvd_key_t p_bus_key; /* Current session key. */
dvd_key_t p_disc_key; /* This DVD disc's key. */
dvd_key_t p_title_key; /* Current title key. */
} css_t;
/*****************************************************************************
* Prototypes in css.c
*****************************************************************************/
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 * );

392
libmpdvdkit2/csstables.h Normal file
View File

@ -0,0 +1,392 @@
/*****************************************************************************
* csstables.h: CSS Tables for DVD unscrambling
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id$
*
* Author: Stéphane Borel <stef@via.ecp.fr>
*
* based on:
* - css-auth by Derek Fawcus <derek@spider.com>
* - DVD CSS ioctls example program by Andrew T. Veliath <andrewtv@usa.net>
* - The Divide and conquer attack by Frank A. Stevenson <frank@funcom.com>
* - 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
* (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
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
static u8 p_css_tab1[ 256 ] =
{
0x33, 0x73, 0x3b, 0x26, 0x63, 0x23, 0x6b, 0x76,
0x3e, 0x7e, 0x36, 0x2b, 0x6e, 0x2e, 0x66, 0x7b,
0xd3, 0x93, 0xdb, 0x06, 0x43, 0x03, 0x4b, 0x96,
0xde, 0x9e, 0xd6, 0x0b, 0x4e, 0x0e, 0x46, 0x9b,
0x57, 0x17, 0x5f, 0x82, 0xc7, 0x87, 0xcf, 0x12,
0x5a, 0x1a, 0x52, 0x8f, 0xca, 0x8a, 0xc2, 0x1f,
0xd9, 0x99, 0xd1, 0x00, 0x49, 0x09, 0x41, 0x90,
0xd8, 0x98, 0xd0, 0x01, 0x48, 0x08, 0x40, 0x91,
0x3d, 0x7d, 0x35, 0x24, 0x6d, 0x2d, 0x65, 0x74,
0x3c, 0x7c, 0x34, 0x25, 0x6c, 0x2c, 0x64, 0x75,
0xdd, 0x9d, 0xd5, 0x04, 0x4d, 0x0d, 0x45, 0x94,
0xdc, 0x9c, 0xd4, 0x05, 0x4c, 0x0c, 0x44, 0x95,
0x59, 0x19, 0x51, 0x80, 0xc9, 0x89, 0xc1, 0x10,
0x58, 0x18, 0x50, 0x81, 0xc8, 0x88, 0xc0, 0x11,
0xd7, 0x97, 0xdf, 0x02, 0x47, 0x07, 0x4f, 0x92,
0xda, 0x9a, 0xd2, 0x0f, 0x4a, 0x0a, 0x42, 0x9f,
0x53, 0x13, 0x5b, 0x86, 0xc3, 0x83, 0xcb, 0x16,
0x5e, 0x1e, 0x56, 0x8b, 0xce, 0x8e, 0xc6, 0x1b,
0xb3, 0xf3, 0xbb, 0xa6, 0xe3, 0xa3, 0xeb, 0xf6,
0xbe, 0xfe, 0xb6, 0xab, 0xee, 0xae, 0xe6, 0xfb,
0x37, 0x77, 0x3f, 0x22, 0x67, 0x27, 0x6f, 0x72,
0x3a, 0x7a, 0x32, 0x2f, 0x6a, 0x2a, 0x62, 0x7f,
0xb9, 0xf9, 0xb1, 0xa0, 0xe9, 0xa9, 0xe1, 0xf0,
0xb8, 0xf8, 0xb0, 0xa1, 0xe8, 0xa8, 0xe0, 0xf1,
0x5d, 0x1d, 0x55, 0x84, 0xcd, 0x8d, 0xc5, 0x14,
0x5c, 0x1c, 0x54, 0x85, 0xcc, 0x8c, 0xc4, 0x15,
0xbd, 0xfd, 0xb5, 0xa4, 0xed, 0xad, 0xe5, 0xf4,
0xbc, 0xfc, 0xb4, 0xa5, 0xec, 0xac, 0xe4, 0xf5,
0x39, 0x79, 0x31, 0x20, 0x69, 0x29, 0x61, 0x70,
0x38, 0x78, 0x30, 0x21, 0x68, 0x28, 0x60, 0x71,
0xb7, 0xf7, 0xbf, 0xa2, 0xe7, 0xa7, 0xef, 0xf2,
0xba, 0xfa, 0xb2, 0xaf, 0xea, 0xaa, 0xe2, 0xff
};
static u8 p_css_tab2[ 256 ] =
{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x09, 0x08, 0x0b, 0x0a, 0x0d, 0x0c, 0x0f, 0x0e,
0x12, 0x13, 0x10, 0x11, 0x16, 0x17, 0x14, 0x15,
0x1b, 0x1a, 0x19, 0x18, 0x1f, 0x1e, 0x1d, 0x1c,
0x24, 0x25, 0x26, 0x27, 0x20, 0x21, 0x22, 0x23,
0x2d, 0x2c, 0x2f, 0x2e, 0x29, 0x28, 0x2b, 0x2a,
0x36, 0x37, 0x34, 0x35, 0x32, 0x33, 0x30, 0x31,
0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38,
0x49, 0x48, 0x4b, 0x4a, 0x4d, 0x4c, 0x4f, 0x4e,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0x5b, 0x5a, 0x59, 0x58, 0x5f, 0x5e, 0x5d, 0x5c,
0x52, 0x53, 0x50, 0x51, 0x56, 0x57, 0x54, 0x55,
0x6d, 0x6c, 0x6f, 0x6e, 0x69, 0x68, 0x6b, 0x6a,
0x64, 0x65, 0x66, 0x67, 0x60, 0x61, 0x62, 0x63,
0x7f, 0x7e, 0x7d, 0x7c, 0x7b, 0x7a, 0x79, 0x78,
0x76, 0x77, 0x74, 0x75, 0x72, 0x73, 0x70, 0x71,
0x92, 0x93, 0x90, 0x91, 0x96, 0x97, 0x94, 0x95,
0x9b, 0x9a, 0x99, 0x98, 0x9f, 0x9e, 0x9d, 0x9c,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x89, 0x88, 0x8b, 0x8a, 0x8d, 0x8c, 0x8f, 0x8e,
0xb6, 0xb7, 0xb4, 0xb5, 0xb2, 0xb3, 0xb0, 0xb1,
0xbf, 0xbe, 0xbd, 0xbc, 0xbb, 0xba, 0xb9, 0xb8,
0xa4, 0xa5, 0xa6, 0xa7, 0xa0, 0xa1, 0xa2, 0xa3,
0xad, 0xac, 0xaf, 0xae, 0xa9, 0xa8, 0xab, 0xaa,
0xdb, 0xda, 0xd9, 0xd8, 0xdf, 0xde, 0xdd, 0xdc,
0xd2, 0xd3, 0xd0, 0xd1, 0xd6, 0xd7, 0xd4, 0xd5,
0xc9, 0xc8, 0xcb, 0xca, 0xcd, 0xcc, 0xcf, 0xce,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8,
0xf6, 0xf7, 0xf4, 0xf5, 0xf2, 0xf3, 0xf0, 0xf1,
0xed, 0xec, 0xef, 0xee, 0xe9, 0xe8, 0xeb, 0xea,
0xe4, 0xe5, 0xe6, 0xe7, 0xe0, 0xe1, 0xe2, 0xe3
};
static u8 p_css_tab3[ 512 ] =
{
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff
};
static u8 p_css_tab4[ 256 ] =
{
0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
};
static u8 p_css_tab5[ 256 ] =
{
0xff, 0x7f, 0xbf, 0x3f, 0xdf, 0x5f, 0x9f, 0x1f,
0xef, 0x6f, 0xaf, 0x2f, 0xcf, 0x4f, 0x8f, 0x0f,
0xf7, 0x77, 0xb7, 0x37, 0xd7, 0x57, 0x97, 0x17,
0xe7, 0x67, 0xa7, 0x27, 0xc7, 0x47, 0x87, 0x07,
0xfb, 0x7b, 0xbb, 0x3b, 0xdb, 0x5b, 0x9b, 0x1b,
0xeb, 0x6b, 0xab, 0x2b, 0xcb, 0x4b, 0x8b, 0x0b,
0xf3, 0x73, 0xb3, 0x33, 0xd3, 0x53, 0x93, 0x13,
0xe3, 0x63, 0xa3, 0x23, 0xc3, 0x43, 0x83, 0x03,
0xfd, 0x7d, 0xbd, 0x3d, 0xdd, 0x5d, 0x9d, 0x1d,
0xed, 0x6d, 0xad, 0x2d, 0xcd, 0x4d, 0x8d, 0x0d,
0xf5, 0x75, 0xb5, 0x35, 0xd5, 0x55, 0x95, 0x15,
0xe5, 0x65, 0xa5, 0x25, 0xc5, 0x45, 0x85, 0x05,
0xf9, 0x79, 0xb9, 0x39, 0xd9, 0x59, 0x99, 0x19,
0xe9, 0x69, 0xa9, 0x29, 0xc9, 0x49, 0x89, 0x09,
0xf1, 0x71, 0xb1, 0x31, 0xd1, 0x51, 0x91, 0x11,
0xe1, 0x61, 0xa1, 0x21, 0xc1, 0x41, 0x81, 0x01,
0xfe, 0x7e, 0xbe, 0x3e, 0xde, 0x5e, 0x9e, 0x1e,
0xee, 0x6e, 0xae, 0x2e, 0xce, 0x4e, 0x8e, 0x0e,
0xf6, 0x76, 0xb6, 0x36, 0xd6, 0x56, 0x96, 0x16,
0xe6, 0x66, 0xa6, 0x26, 0xc6, 0x46, 0x86, 0x06,
0xfa, 0x7a, 0xba, 0x3a, 0xda, 0x5a, 0x9a, 0x1a,
0xea, 0x6a, 0xaa, 0x2a, 0xca, 0x4a, 0x8a, 0x0a,
0xf2, 0x72, 0xb2, 0x32, 0xd2, 0x52, 0x92, 0x12,
0xe2, 0x62, 0xa2, 0x22, 0xc2, 0x42, 0x82, 0x02,
0xfc, 0x7c, 0xbc, 0x3c, 0xdc, 0x5c, 0x9c, 0x1c,
0xec, 0x6c, 0xac, 0x2c, 0xcc, 0x4c, 0x8c, 0x0c,
0xf4, 0x74, 0xb4, 0x34, 0xd4, 0x54, 0x94, 0x14,
0xe4, 0x64, 0xa4, 0x24, 0xc4, 0x44, 0x84, 0x04,
0xf8, 0x78, 0xb8, 0x38, 0xd8, 0x58, 0x98, 0x18,
0xe8, 0x68, 0xa8, 0x28, 0xc8, 0x48, 0x88, 0x08,
0xf0, 0x70, 0xb0, 0x30, 0xd0, 0x50, 0x90, 0x10,
0xe0, 0x60, 0xa0, 0x20, 0xc0, 0x40, 0x80, 0x00
};
static u8 p_crypt_tab0[ 256 ] =
{
0xB7, 0xF4, 0x82, 0x57, 0xDA, 0x4D, 0xDB, 0xE2,
0x2F, 0x52, 0x1A, 0xA8, 0x68, 0x5A, 0x8A, 0xFF,
0xFB, 0x0E, 0x6D, 0x35, 0xF7, 0x5C, 0x76, 0x12,
0xCE, 0x25, 0x79, 0x29, 0x39, 0x62, 0x08, 0x24,
0xA5, 0x85, 0x7B, 0x56, 0x01, 0x23, 0x68, 0xCF,
0x0A, 0xE2, 0x5A, 0xED, 0x3D, 0x59, 0xB0, 0xA9,
0xB0, 0x2C, 0xF2, 0xB8, 0xEF, 0x32, 0xA9, 0x40,
0x80, 0x71, 0xAF, 0x1E, 0xDE, 0x8F, 0x58, 0x88,
0xB8, 0x3A, 0xD0, 0xFC, 0xC4, 0x1E, 0xB5, 0xA0,
0xBB, 0x3B, 0x0F, 0x01, 0x7E, 0x1F, 0x9F, 0xD9,
0xAA, 0xB8, 0x3D, 0x9D, 0x74, 0x1E, 0x25, 0xDB,
0x37, 0x56, 0x8F, 0x16, 0xBA, 0x49, 0x2B, 0xAC,
0xD0, 0xBD, 0x95, 0x20, 0xBE, 0x7A, 0x28, 0xD0,
0x51, 0x64, 0x63, 0x1C, 0x7F, 0x66, 0x10, 0xBB,
0xC4, 0x56, 0x1A, 0x04, 0x6E, 0x0A, 0xEC, 0x9C,
0xD6, 0xE8, 0x9A, 0x7A, 0xCF, 0x8C, 0xDB, 0xB1,
0xEF, 0x71, 0xDE, 0x31, 0xFF, 0x54, 0x3E, 0x5E,
0x07, 0x69, 0x96, 0xB0, 0xCF, 0xDD, 0x9E, 0x47,
0xC7, 0x96, 0x8F, 0xE4, 0x2B, 0x59, 0xC6, 0xEE,
0xB9, 0x86, 0x9A, 0x64, 0x84, 0x72, 0xE2, 0x5B,
0xA2, 0x96, 0x58, 0x99, 0x50, 0x03, 0xF5, 0x38,
0x4D, 0x02, 0x7D, 0xE7, 0x7D, 0x75, 0xA7, 0xB8,
0x67, 0x87, 0x84, 0x3F, 0x1D, 0x11, 0xE5, 0xFC,
0x1E, 0xD3, 0x83, 0x16, 0xA5, 0x29, 0xF6, 0xC7,
0x15, 0x61, 0x29, 0x1A, 0x43, 0x4F, 0x9B, 0xAF,
0xC5, 0x87, 0x34, 0x6C, 0x0F, 0x3B, 0xA8, 0x1D,
0x45, 0x58, 0x25, 0xDC, 0xA8, 0xA3, 0x3B, 0xD1,
0x79, 0x1B, 0x48, 0xF2, 0xE9, 0x93, 0x1F, 0xFC,
0xDB, 0x2A, 0x90, 0xA9, 0x8A, 0x3D, 0x39, 0x18,
0xA3, 0x8E, 0x58, 0x6C, 0xE0, 0x12, 0xBB, 0x25,
0xCD, 0x71, 0x22, 0xA2, 0x64, 0xC6, 0xE7, 0xFB,
0xAD, 0x94, 0x77, 0x04, 0x9A, 0x39, 0xCF, 0x7C
};
static u8 p_crypt_tab1[ 256 ] =
{
0x8C, 0x47, 0xB0, 0xE1, 0xEB, 0xFC, 0xEB, 0x56,
0x10, 0xE5, 0x2C, 0x1A, 0x5D, 0xEF, 0xBE, 0x4F,
0x08, 0x75, 0x97, 0x4B, 0x0E, 0x25, 0x8E, 0x6E,
0x39, 0x5A, 0x87, 0x53, 0xC4, 0x1F, 0xF4, 0x5C,
0x4E, 0xE6, 0x99, 0x30, 0xE0, 0x42, 0x88, 0xAB,
0xE5, 0x85, 0xBC, 0x8F, 0xD8, 0x3C, 0x54, 0xC9,
0x53, 0x47, 0x18, 0xD6, 0x06, 0x5B, 0x41, 0x2C,
0x67, 0x1E, 0x41, 0x74, 0x33, 0xE2, 0xB4, 0xE0,
0x23, 0x29, 0x42, 0xEA, 0x55, 0x0F, 0x25, 0xB4,
0x24, 0x2C, 0x99, 0x13, 0xEB, 0x0A, 0x0B, 0xC9,
0xF9, 0x63, 0x67, 0x43, 0x2D, 0xC7, 0x7D, 0x07,
0x60, 0x89, 0xD1, 0xCC, 0xE7, 0x94, 0x77, 0x74,
0x9B, 0x7E, 0xD7, 0xE6, 0xFF, 0xBB, 0x68, 0x14,
0x1E, 0xA3, 0x25, 0xDE, 0x3A, 0xA3, 0x54, 0x7B,
0x87, 0x9D, 0x50, 0xCA, 0x27, 0xC3, 0xA4, 0x50,
0x91, 0x27, 0xD4, 0xB0, 0x82, 0x41, 0x97, 0x79,
0x94, 0x82, 0xAC, 0xC7, 0x8E, 0xA5, 0x4E, 0xAA,
0x78, 0x9E, 0xE0, 0x42, 0xBA, 0x28, 0xEA, 0xB7,
0x74, 0xAD, 0x35, 0xDA, 0x92, 0x60, 0x7E, 0xD2,
0x0E, 0xB9, 0x24, 0x5E, 0x39, 0x4F, 0x5E, 0x63,
0x09, 0xB5, 0xFA, 0xBF, 0xF1, 0x22, 0x55, 0x1C,
0xE2, 0x25, 0xDB, 0xC5, 0xD8, 0x50, 0x03, 0x98,
0xC4, 0xAC, 0x2E, 0x11, 0xB4, 0x38, 0x4D, 0xD0,
0xB9, 0xFC, 0x2D, 0x3C, 0x08, 0x04, 0x5A, 0xEF,
0xCE, 0x32, 0xFB, 0x4C, 0x92, 0x1E, 0x4B, 0xFB,
0x1A, 0xD0, 0xE2, 0x3E, 0xDA, 0x6E, 0x7C, 0x4D,
0x56, 0xC3, 0x3F, 0x42, 0xB1, 0x3A, 0x23, 0x4D,
0x6E, 0x84, 0x56, 0x68, 0xF4, 0x0E, 0x03, 0x64,
0xD0, 0xA9, 0x92, 0x2F, 0x8B, 0xBC, 0x39, 0x9C,
0xAC, 0x09, 0x5E, 0xEE, 0xE5, 0x97, 0xBF, 0xA5,
0xCE, 0xFA, 0x28, 0x2C, 0x6D, 0x4F, 0xEF, 0x77,
0xAA, 0x1B, 0x79, 0x8E, 0x97, 0xB4, 0xC3, 0xF4
};
static u8 p_crypt_tab2[ 256 ] =
{
0xB7, 0x75, 0x81, 0xD5, 0xDC, 0xCA, 0xDE, 0x66,
0x23, 0xDF, 0x15, 0x26, 0x62, 0xD1, 0x83, 0x77,
0xE3, 0x97, 0x76, 0xAF, 0xE9, 0xC3, 0x6B, 0x8E,
0xDA, 0xB0, 0x6E, 0xBF, 0x2B, 0xF1, 0x19, 0xB4,
0x95, 0x34, 0x48, 0xE4, 0x37, 0x94, 0x5D, 0x7B,
0x36, 0x5F, 0x65, 0x53, 0x07, 0xE2, 0x89, 0x11,
0x98, 0x85, 0xD9, 0x12, 0xC1, 0x9D, 0x84, 0xEC,
0xA4, 0xD4, 0x88, 0xB8, 0xFC, 0x2C, 0x79, 0x28,
0xD8, 0xDB, 0xB3, 0x1E, 0xA2, 0xF9, 0xD0, 0x44,
0xD7, 0xD6, 0x60, 0xEF, 0x14, 0xF4, 0xF6, 0x31,
0xD2, 0x41, 0x46, 0x67, 0x0A, 0xE1, 0x58, 0x27,
0x43, 0xA3, 0xF8, 0xE0, 0xC8, 0xBA, 0x5A, 0x5C,
0x80, 0x6C, 0xC6, 0xF2, 0xE8, 0xAD, 0x7D, 0x04,
0x0D, 0xB9, 0x3C, 0xC2, 0x25, 0xBD, 0x49, 0x63,
0x8C, 0x9F, 0x51, 0xCE, 0x20, 0xC5, 0xA1, 0x50,
0x92, 0x2D, 0xDD, 0xBC, 0x8D, 0x4F, 0x9A, 0x71,
0x2F, 0x30, 0x1D, 0x73, 0x39, 0x13, 0xFB, 0x1A,
0xCB, 0x24, 0x59, 0xFE, 0x05, 0x96, 0x57, 0x0F,
0x1F, 0xCF, 0x54, 0xBE, 0xF5, 0x06, 0x1B, 0xB2,
0x6D, 0xD3, 0x4D, 0x32, 0x56, 0x21, 0x33, 0x0B,
0x52, 0xE7, 0xAB, 0xEB, 0xA6, 0x74, 0x00, 0x4C,
0xB1, 0x7F, 0x82, 0x99, 0x87, 0x0E, 0x5E, 0xC0,
0x8F, 0xEE, 0x6F, 0x55, 0xF3, 0x7E, 0x08, 0x90,
0xFA, 0xB6, 0x64, 0x70, 0x47, 0x4A, 0x17, 0xA7,
0xB5, 0x40, 0x8A, 0x38, 0xE5, 0x68, 0x3E, 0x8B,
0x69, 0xAA, 0x9B, 0x42, 0xA5, 0x10, 0x01, 0x35,
0xFD, 0x61, 0x9E, 0xE6, 0x16, 0x9C, 0x86, 0xED,
0xCD, 0x2E, 0xFF, 0xC4, 0x5B, 0xA0, 0xAE, 0xCC,
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
};
static u8 p_crypt_tab3[ 288 ] =
{
0x73, 0x51, 0x95, 0xE1, 0x12, 0xE4, 0xC0, 0x58,
0xEE, 0xF2, 0x08, 0x1B, 0xA9, 0xFA, 0x98, 0x4C,
0xA7, 0x33, 0xE2, 0x1B, 0xA7, 0x6D, 0xF5, 0x30,
0x97, 0x1D, 0xF3, 0x02, 0x60, 0x5A, 0x82, 0x0F,
0x91, 0xD0, 0x9C, 0x10, 0x39, 0x7A, 0x83, 0x85,
0x3B, 0xB2, 0xB8, 0xAE, 0x0C, 0x09, 0x52, 0xEA,
0x1C, 0xE1, 0x8D, 0x66, 0x4F, 0xF3, 0xDA, 0x92,
0x29, 0xB9, 0xD5, 0xC5, 0x77, 0x47, 0x22, 0x53,
0x14, 0xF7, 0xAF, 0x22, 0x64, 0xDF, 0xC6, 0x72,
0x12, 0xF3, 0x75, 0xDA, 0xD7, 0xD7, 0xE5, 0x02,
0x9E, 0xED, 0xDA, 0xDB, 0x4C, 0x47, 0xCE, 0x91,
0x06, 0x06, 0x6D, 0x55, 0x8B, 0x19, 0xC9, 0xEF,
0x8C, 0x80, 0x1A, 0x0E, 0xEE, 0x4B, 0xAB, 0xF2,
0x08, 0x5C, 0xE9, 0x37, 0x26, 0x5E, 0x9A, 0x90,
0x00, 0xF3, 0x0D, 0xB2, 0xA6, 0xA3, 0xF7, 0x26,
0x17, 0x48, 0x88, 0xC9, 0x0E, 0x2C, 0xC9, 0x02,
0xE7, 0x18, 0x05, 0x4B, 0xF3, 0x39, 0xE1, 0x20,
0x02, 0x0D, 0x40, 0xC7, 0xCA, 0xB9, 0x48, 0x30,
0x57, 0x67, 0xCC, 0x06, 0xBF, 0xAC, 0x81, 0x08,
0x24, 0x7A, 0xD4, 0x8B, 0x19, 0x8E, 0xAC, 0xB4,
0x5A, 0x0F, 0x73, 0x13, 0xAC, 0x9E, 0xDA, 0xB6,
0xB8, 0x96, 0x5B, 0x60, 0x88, 0xE1, 0x81, 0x3F,
0x07, 0x86, 0x37, 0x2D, 0x79, 0x14, 0x52, 0xEA,
0x73, 0xDF, 0x3D, 0x09, 0xC8, 0x25, 0x48, 0xD8,
0x75, 0x60, 0x9A, 0x08, 0x27, 0x4A, 0x2C, 0xB9,
0xA8, 0x8B, 0x8A, 0x73, 0x62, 0x37, 0x16, 0x02,
0xBD, 0xC1, 0x0E, 0x56, 0x54, 0x3E, 0x14, 0x5F,
0x8C, 0x8F, 0x6E, 0x75, 0x1C, 0x07, 0x39, 0x7B,
0x4B, 0xDB, 0xD3, 0x4B, 0x1E, 0xC8, 0x7E, 0xFE,
0x3E, 0x72, 0x16, 0x83, 0x7D, 0xEE, 0xF5, 0xCA,
0xC5, 0x18, 0xF9, 0xD8, 0x68, 0xAB, 0x38, 0x85,
0xA8, 0xF0, 0xA1, 0x73, 0x9F, 0x5D, 0x19, 0x0B,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x33, 0x72, 0x39, 0x25, 0x67, 0x26, 0x6D, 0x71,
0x36, 0x77, 0x3C, 0x20, 0x62, 0x23, 0x68, 0x74,
0xC3, 0x82, 0xC9, 0x15, 0x57, 0x16, 0x5D, 0x81
};

679
libmpdvdkit2/device.c Normal file
View File

@ -0,0 +1,679 @@
/*****************************************************************************
* device.h: DVD device access
*****************************************************************************
* Copyright (C) 1998-2002 VideoLAN
* $Id$
*
* Authors: Stéphane Borel <stef@via.ecp.fr>
* Samuel Hocevar <sam@zoy.org>
* Håkan Hjort <d95hjort@dtek.chalmers.se>
*
* 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
* (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
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#if defined( WIN32 )
# include <io.h> /* read() */
#else
# include <sys/uio.h> /* struct iovec */
#endif
#include "dvdcss/dvdcss.h"
#include "common.h"
#include "css.h"
#include "libdvdcss.h"
#include "ioctl.h"
#include "device.h"
/*****************************************************************************
* Device reading prototypes, win32 specific
*****************************************************************************/
#ifdef WIN32
int _win32_dvdcss_readv ( int, struct iovec *, int, char * );
int _win32_dvdcss_aopen ( dvdcss_t, char );
int _win32_dvdcss_aclose ( int );
int _win32_dvdcss_aseek ( int, int, int );
int _win32_dvdcss_aread ( int, void *, int );
#endif
/*****************************************************************************
* readv_*: readv() replacements for iovec-impaired C libraries
*****************************************************************************/
#if defined( WIN32 )
static inline int readv( int i_fd, struct iovec * p_iovec, int i_count )
{
int i_index, i_len, i_total = 0;
unsigned char *p_base;
int i_bytes;
for( i_index = i_count; i_index; i_index-- )
{
i_len = p_iovec->iov_len;
p_base = p_iovec->iov_base;
/* Loop is unrolled one time to spare the (i_bytes <= 0) test */
if( i_len > 0 )
{
i_bytes = read( i_fd, p_base, i_len );
if( i_bytes < 0 )
{
/* One of the reads failed, too bad.
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 */
return -1;
}
i_total += i_bytes;
if( i_bytes != i_len )
{
/* we reached the end of the file or a signal interrupted
the read */
return i_total;
}
}
p_iovec++;
}
return i_total;
}
#endif /* WIN32 */
int _dvdcss_use_ioctls( dvdcss_t dvdcss )
{
#if defined( WIN32 )
/* Some one need to implement this for Windows */
if( WIN2K )
{
return 1;
}
else
{
return 1;
}
#else
struct stat fileinfo;
int ret;
ret = fstat( dvdcss->i_fd, &fileinfo );
if( ret < 0 )
{
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
* (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
* 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 ) )
{
return 1;
}
else
{
return 0;
}
#endif
}
int _dvdcss_open ( dvdcss_t dvdcss )
{
char *psz_device = dvdcss->psz_device;
#if defined( WIN32 )
if( WIN2K )
{
char psz_dvd[7];
_snprintf( psz_dvd, 7, "\\\\.\\%c:", psz_device[0] );
/* To have access to ioctls, we need read and write access to the
* device. This is only allowed if you have administrator priviledges
* so we allow for a fallback method where ioctls are not available but
* we at least have read access to the device.
* (See Microsoft Q241374: Read and Write Access Required for SCSI
* Pass Through Requests) */
(HANDLE) dvdcss->i_fd =
CreateFile( psz_dvd, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING,
FILE_FLAG_RANDOM_ACCESS, NULL );
if( (HANDLE) dvdcss->i_fd == INVALID_HANDLE_VALUE )
(HANDLE) dvdcss->i_fd =
CreateFile( psz_dvd, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING,
FILE_FLAG_RANDOM_ACCESS, NULL );
if( (HANDLE) dvdcss->i_fd == INVALID_HANDLE_VALUE )
{
_dvdcss_error( dvdcss, "failed opening device" );
return -1;
}
}
else
{
dvdcss->i_fd = _win32_dvdcss_aopen( dvdcss, psz_device[0] );
if( dvdcss->i_fd == -1 )
{
_dvdcss_error( dvdcss, "failed opening device" );
return -1;
}
}
/* initialise readv temporary buffer */
dvdcss->p_readv_buffer = NULL;
dvdcss->i_readv_buf_size = 0;
#else
dvdcss->i_fd = dvdcss->i_read_fd = open( psz_device, 0 );
if( dvdcss->i_fd == -1 )
{
_dvdcss_error( dvdcss, "failed opening device" );
return -1;
}
#endif
return 0;
}
#ifndef WIN32
int _dvdcss_raw_open ( dvdcss_t dvdcss, char *psz_device )
{
dvdcss->i_raw_fd = open( psz_device, 0 );
if( dvdcss->i_raw_fd == -1 )
{
_dvdcss_error( dvdcss, "failed opening raw device, continuing" );
return -1;
}
else
{
dvdcss->i_read_fd = dvdcss->i_raw_fd;
}
return 0;
}
#endif
int _dvdcss_close ( dvdcss_t dvdcss )
{
#if defined( WIN32 )
if( WIN2K )
{
CloseHandle( (HANDLE) dvdcss->i_fd );
}
else
{
_win32_dvdcss_aclose( dvdcss->i_fd );
}
/* Free readv temporary buffer */
if( dvdcss->p_readv_buffer )
{
free( dvdcss->p_readv_buffer );
dvdcss->p_readv_buffer = NULL;
dvdcss->i_readv_buf_size = 0;
}
#else
close( dvdcss->i_fd );
if( dvdcss->i_raw_fd >= 0 )
{
close( dvdcss->i_raw_fd );
dvdcss->i_raw_fd = -1;
}
#endif
return 0;
}
int _dvdcss_seek ( dvdcss_t dvdcss, int i_blocks )
{
#if defined( WIN32 )
dvdcss->i_seekpos = i_blocks;
if( WIN2K )
{
LARGE_INTEGER li_read;
#ifndef INVALID_SET_FILE_POINTER
#define INVALID_SET_FILE_POINTER ((DWORD)-1)
#endif
li_read.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)
&& GetLastError() != NO_ERROR)
{
li_read.QuadPart = -DVDCSS_BLOCK_SIZE;
}
li_read.QuadPart /= DVDCSS_BLOCK_SIZE;
return (int)li_read.QuadPart;
}
else
{
return ( _win32_dvdcss_aseek( dvdcss->i_fd, i_blocks, SEEK_SET ) );
}
#else
off_t i_read;
dvdcss->i_seekpos = i_blocks;
i_read = lseek( dvdcss->i_read_fd,
(off_t)i_blocks * (off_t)DVDCSS_BLOCK_SIZE, SEEK_SET );
if( i_read < 0 )
{
_dvdcss_error( dvdcss, "seek error" );
}
return i_read / DVDCSS_BLOCK_SIZE;
#endif
}
int _dvdcss_read ( dvdcss_t dvdcss, void *p_buffer, int i_blocks )
{
#if defined( WIN32 )
if( WIN2K )
{
int i_bytes;
if( !ReadFile( (HANDLE) dvdcss->i_fd, p_buffer,
i_blocks * DVDCSS_BLOCK_SIZE,
(LPDWORD)&i_bytes, NULL ) )
{
return -1;
}
return i_bytes / DVDCSS_BLOCK_SIZE;
}
else
{
return _win32_dvdcss_aread( dvdcss->i_fd, p_buffer, i_blocks );
}
#else
int i_ret;
/* TODO: partial reads are wrong,i.e 2200/2048 = 1
* but the location has advanced 2200 bytes (lseek possition that is) */
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" );
return i_ret;
}
return i_ret / DVDCSS_BLOCK_SIZE;
#endif
}
int _dvdcss_readv ( dvdcss_t dvdcss, struct iovec *p_iovec, int i_blocks )
{
int i_read;
#if defined( WIN32 )
/* Check the size of the readv temp buffer, just in case we need to
* realloc something bigger */
if( dvdcss->i_readv_buf_size < i_blocks * DVDCSS_BLOCK_SIZE )
{
dvdcss->i_readv_buf_size = i_blocks * DVDCSS_BLOCK_SIZE;
if( dvdcss->p_readv_buffer ) free( dvdcss->p_readv_buffer );
/* Allocate a buffer which will be used as a temporary storage
* for readv */
dvdcss->p_readv_buffer = malloc( dvdcss->i_readv_buf_size );
if( !dvdcss->p_readv_buffer )
{
_dvdcss_error( dvdcss, " failed (readv)" );
return -1;
}
}
i_read = _win32_dvdcss_readv( dvdcss->i_fd, p_iovec, i_blocks,
dvdcss->p_readv_buffer );
return i_read;
#else
i_read = readv( dvdcss->i_read_fd, p_iovec, i_blocks );
return i_read / DVDCSS_BLOCK_SIZE;
#endif
}
#if defined( WIN32 )
/*****************************************************************************
* _win32_dvdcss_readv: vectored read using ReadFile for Win2K and
* _win32_dvdcss_aread for win9x
*****************************************************************************/
int _win32_dvdcss_readv( int i_fd, struct iovec *p_iovec,
int i_num_buffers, char *p_tmp_buffer )
{
int i_index;
int i_blocks, i_blocks_total = 0;
for( i_index = i_num_buffers; i_index; i_index-- )
{
i_blocks_total += p_iovec[i_index-1].iov_len;
}
if( i_blocks_total <= 0 ) return 0;
i_blocks_total /= DVDCSS_BLOCK_SIZE;
if( WIN2K )
{
unsigned long int i_bytes;
if( !ReadFile( (HANDLE)i_fd, p_tmp_buffer,
i_blocks_total * DVDCSS_BLOCK_SIZE, &i_bytes, NULL ) )
{
return -1;
/* The read failed... too bad.
As in the posix spec the file postition is left
unspecified after a failure */
}
i_blocks = i_bytes / DVDCSS_BLOCK_SIZE;
}
else /* Win9x */
{
i_blocks = _win32_dvdcss_aread( i_fd, p_tmp_buffer, i_blocks_total );
if( i_blocks < 0 )
{
return -1; /* idem */
}
}
/* We just have to copy the content of the temp buffer into the iovecs */
i_index = 0;
i_blocks_total = i_blocks;
while( i_blocks_total > 0 )
{
memcpy( p_iovec[i_index].iov_base,
&p_tmp_buffer[(i_blocks - i_blocks_total) * DVDCSS_BLOCK_SIZE],
p_iovec[i_index].iov_len );
/* if we read less blocks than asked, we'll just end up copying
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 );
i_index++;
}
return i_blocks;
}
/*****************************************************************************
* _win32_dvdcss_aopen: open dvd drive (load aspi and init w32_aspidev
* structure)
*****************************************************************************/
int _win32_dvdcss_aopen( dvdcss_t dvdcss, char c_drive )
{
HMODULE hASPI;
DWORD dwSupportInfo;
struct w32_aspidev *fd;
int i, j, i_hostadapters;
long (*lpGetSupport)( void );
long (*lpSendCommand)( void* );
hASPI = LoadLibrary( "wnaspi32.dll" );
if( hASPI == NULL )
{
_dvdcss_error( dvdcss, "unable to load wnaspi32.dll" );
return -1;
}
(FARPROC) lpGetSupport = GetProcAddress( hASPI, "GetASPI32SupportInfo" );
(FARPROC) lpSendCommand = GetProcAddress( hASPI, "SendASPI32Command" );
if(lpGetSupport == NULL || lpSendCommand == NULL )
{
_dvdcss_debug( dvdcss, "unable to get aspi function pointers" );
FreeLibrary( hASPI );
return -1;
}
dwSupportInfo = lpGetSupport();
if( HIBYTE( LOWORD ( dwSupportInfo ) ) == SS_NO_ADAPTERS )
{
_dvdcss_debug( dvdcss, "no host adapters found (aspi)" );
FreeLibrary( hASPI );
return -1;
}
if( HIBYTE( LOWORD ( dwSupportInfo ) ) != SS_COMP )
{
_dvdcss_error( dvdcss, "unable to initalize aspi layer" );
FreeLibrary( hASPI );
return -1;
}
i_hostadapters = LOBYTE( LOWORD( dwSupportInfo ) );
if( i_hostadapters == 0 )
{
FreeLibrary( hASPI );
return -1;
}
fd = malloc( sizeof( struct w32_aspidev ) );
if( fd == NULL )
{
FreeLibrary( hASPI );
return -1;
}
fd->i_blocks = 0;
fd->hASPI = (long) hASPI;
fd->lpSendCommand = lpSendCommand;
c_drive = c_drive > 'Z' ? c_drive - 'a' : c_drive - 'A';
for( i = 0; i < i_hostadapters; i++ )
{
for( j = 0; j < 15; j++ )
{
struct SRB_GetDiskInfo srbDiskInfo;
srbDiskInfo.SRB_Cmd = SC_GET_DISK_INFO;
srbDiskInfo.SRB_HaId = i;
srbDiskInfo.SRB_Flags = 0;
srbDiskInfo.SRB_Hdr_Rsvd = 0;
srbDiskInfo.SRB_Target = j;
srbDiskInfo.SRB_Lun = 0;
lpSendCommand( (void*) &srbDiskInfo );
if( (srbDiskInfo.SRB_Status == SS_COMP) &&
(srbDiskInfo.SRB_Int13HDriveInfo == c_drive) )
{
fd->i_sid = MAKEWORD( i, j );
return (int) fd;
}
}
}
free( (void*) fd );
FreeLibrary( hASPI );
_dvdcss_debug( dvdcss, "unable to get haid and target (aspi)" );
return( -1 );
}
/*****************************************************************************
* _win32_dvdcss_aclose: close dvd drive (unload aspi and free w32_aspidev
* structure)
*****************************************************************************/
int _win32_dvdcss_aclose( int i_fd )
{
struct w32_aspidev *fd = (struct w32_aspidev *) i_fd;
FreeLibrary( (HMODULE) fd->hASPI );
free( (void*) i_fd );
return 0;
}
/*****************************************************************************
* _win32_dvdcss_aseek: aspi version of _dvdcss_seek
*
* returns the number of blocks read.
*****************************************************************************/
int _win32_dvdcss_aseek( int i_fd, int i_blocks, int i_method )
{
int i_old_blocks;
char sz_buf[ DVDCSS_BLOCK_SIZE ];
struct w32_aspidev *fd = (struct w32_aspidev *) i_fd;
i_old_blocks = fd->i_blocks;
fd->i_blocks = i_blocks;
if( _win32_dvdcss_aread( i_fd, sz_buf, 1 ) == -1 )
{
fd->i_blocks = i_old_blocks;
return -1;
}
(fd->i_blocks)--;
return fd->i_blocks;
}
/*****************************************************************************
* _win32_dvdcss_aread: aspi version of _dvdcss_read
*
* returns the number of blocks read.
*****************************************************************************/
int _win32_dvdcss_aread( int i_fd, void *p_data, int i_blocks )
{
HANDLE hEvent;
struct SRB_ExecSCSICmd ssc;
struct w32_aspidev *fd = (struct w32_aspidev *) i_fd;
/* Create the transfer completion event */
hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
if( hEvent == NULL )
{
return -1;
}
memset( &ssc, 0, sizeof( ssc ) );
ssc.SRB_Cmd = SC_EXEC_SCSI_CMD;
ssc.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
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 )
{
ssc.SRB_BufLen = 32 * DVDCSS_BLOCK_SIZE;
ssc.CDBByte[9] = 32;
fd->i_blocks += 32;
/* Initiate transfer */
ResetEvent( hEvent );
fd->lpSendCommand( (void*) &ssc );
/* transfer the next 64kb (_win32_dvdcss_aread is called recursively)
* We need to check the status of the read on return */
if( _win32_dvdcss_aread( i_fd, (u8*) p_data + 32 * DVDCSS_BLOCK_SIZE,
i_blocks - 32) < 0 )
{
return -1;
}
}
else
{
/* This is the last transfer */
ssc.SRB_BufLen = i_blocks * DVDCSS_BLOCK_SIZE;
ssc.CDBByte[9] = (UCHAR) i_blocks;
fd->i_blocks += i_blocks;
/* Initiate transfer */
ResetEvent( hEvent );
fd->lpSendCommand( (void*) &ssc );
}
/* If the command has still not been processed, wait until it's finished */
if( ssc.SRB_Status == SS_PENDING )
{
WaitForSingleObject( hEvent, INFINITE );
}
CloseHandle( hEvent );
/* check that the transfer went as planned */
if( ssc.SRB_Status != SS_COMP )
{
return -1;
}
return i_blocks;
}
#endif

57
libmpdvdkit2/device.h Normal file
View File

@ -0,0 +1,57 @@
/*****************************************************************************
* device.h: DVD device access
*****************************************************************************
* Copyright (C) 1998-2002 VideoLAN
* $Id$
*
* Authors: Stéphane Borel <stef@via.ecp.fr>
* Samuel Hocevar <sam@zoy.org>
* Håkan Hjort <d95hjort@dtek.chalmers.se>
*
* 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
* (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
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
/*****************************************************************************
* iovec structure: vectored data entry
*****************************************************************************/
#if defined( WIN32 )
# include <io.h> /* read() */
#else
# include <sys/uio.h> /* struct iovec */
#endif
#if defined( WIN32 )
struct iovec
{
void *iov_base; /* Pointer to data. */
size_t iov_len; /* Length of data. */
};
#endif
/*****************************************************************************
* Device reading prototypes
*****************************************************************************/
int _dvdcss_use_ioctls ( dvdcss_t );
int _dvdcss_open ( dvdcss_t );
int _dvdcss_close ( dvdcss_t );
int _dvdcss_readv ( dvdcss_t, struct iovec *, int );
/*****************************************************************************
* Device reading prototypes, raw-device specific
*****************************************************************************/
#ifndef WIN32
int _dvdcss_raw_open ( dvdcss_t, char * );
#endif

97
libmpdvdkit2/dvdcss.h Normal file
View File

@ -0,0 +1,97 @@
/**
* \file dvdcss.h
* \author Stéphane Borel <stef@via.ecp.fr>
* \author Samuel Hocevar <sam@zoy.org>
* \brief The \e libdvdcss public header.
*
* This header contains the public types and functions that applications
* using \e libdvdcss may use.
*/
/*
* Copyright (C) 1998-2002 VideoLAN
* $Id$
*
* 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
* (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
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*/
#ifndef _DVDCSS_DVDCSS_H
#ifndef _DOXYGEN_SKIP_ME
#define _DVDCSS_DVDCSS_H 1
#endif
#ifdef __cplusplus
extern "C" {
#endif
/** Library instance handle, to be used for each library call. */
typedef struct dvdcss_s* dvdcss_t;
/** The block size of a DVD. */
#define DVDCSS_BLOCK_SIZE 2048
/** The default flag to be used by \e libdvdcss functions. */
#define DVDCSS_NOFLAGS 0
/** Flag to ask dvdcss_read() to decrypt the data it reads. */
#define DVDCSS_READ_DECRYPT (1 << 0)
/** Flag to tell dvdcss_seek() it is seeking in MPEG data. */
#define DVDCSS_SEEK_MPEG (1 << 0)
/** Flag to ask dvdcss_seek() to check the current title key. */
#define DVDCSS_SEEK_KEY (1 << 1)
/*
* Our version number. The variable name contains the interface version.
*/
extern char * dvdcss_interface_2;
/*
* Exported prototypes.
*/
extern dvdcss_t dvdcss_open ( char *psz_target );
extern int dvdcss_close ( dvdcss_t );
extern int dvdcss_seek ( dvdcss_t,
int i_blocks,
int i_flags );
extern int dvdcss_read ( dvdcss_t,
void *p_buffer,
int i_blocks,
int i_flags );
extern int dvdcss_readv ( dvdcss_t,
void *p_iovec,
int i_blocks,
int i_flags );
extern char * dvdcss_error ( dvdcss_t );
/*
* Deprecated stuff.
*/
#ifndef _DOXYGEN_SKIP_ME
#define dvdcss_title(a,b) dvdcss_seek(a,b,DVDCSS_SEEK_KEY)
#define dvdcss_handle dvdcss_t
#endif
#ifdef __cplusplus
}
#endif
#endif /* <dvdcss/dvdcss.h> */

57
libmpdvdkit2/error.c Normal file
View File

@ -0,0 +1,57 @@
/*****************************************************************************
* error.c: error management functions
*****************************************************************************
* Copyright (C) 1998-2002 VideoLAN
* $Id$
*
* Author: Samuel Hocevar <sam@zoy.org>
*
* 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
* (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
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
#include "config.h"
#include <stdio.h>
#include "dvdcss/dvdcss.h"
#include "common.h"
#include "css.h"
#include "libdvdcss.h"
/*****************************************************************************
* Error messages
*****************************************************************************/
void _dvdcss_error( dvdcss_t dvdcss, char *psz_string )
{
if( dvdcss->b_errors )
{
fprintf( stderr, "libdvdcss error: %s\n", psz_string );
}
dvdcss->psz_error = psz_string;
}
/*****************************************************************************
* Debug messages
*****************************************************************************/
void _dvdcss_debug( dvdcss_t dvdcss, char *psz_string )
{
if( dvdcss->b_debug )
{
fprintf( stderr, "libdvdcss debug: %s\n", psz_string );
}
}

1912
libmpdvdkit2/ioctl.c Normal file

File diff suppressed because it is too large Load Diff

362
libmpdvdkit2/ioctl.h Normal file
View File

@ -0,0 +1,362 @@
/*****************************************************************************
* ioctl.h: DVD ioctl replacement function
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id$
*
* Authors: Samuel Hocevar <sam@zoy.org>
*
* 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
* (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
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
int ioctl_ReadCopyright ( int, int, int * );
int ioctl_ReadDiscKey ( int, int *, u8 * );
int ioctl_ReadTitleKey ( int, int *, int, u8 * );
int ioctl_ReportAgid ( int, int * );
int ioctl_ReportChallenge ( int, int *, u8 * );
int ioctl_ReportKey1 ( int, int *, u8 * );
int ioctl_ReportASF ( int, int *, int * );
int ioctl_InvalidateAgid ( int, int * );
int ioctl_SendChallenge ( int, int *, u8 * );
int ioctl_SendKey2 ( int, int *, u8 * );
#define DVD_KEY_SIZE 5
#define DVD_CHALLENGE_SIZE 10
#define DVD_DISCKEY_SIZE 2048
/*****************************************************************************
* Common macro, BeOS specific
*****************************************************************************/
#if defined( SYS_BEOS )
#define INIT_RDC( TYPE, SIZE ) \
raw_device_command rdc; \
u8 p_buffer[ (SIZE) ]; \
memset( &rdc, 0, sizeof( raw_device_command ) ); \
rdc.data = (char *)p_buffer; \
rdc.data_length = (SIZE); \
BeInitRDC( &rdc, (TYPE) );
#endif
/*****************************************************************************
* Common macro, HP-UX specific
*****************************************************************************/
#if defined( HPUX_SCTL_IO )
#define INIT_SCTL_IO( TYPE, SIZE ) \
struct sctl_io sctl_io; \
u8 p_buffer[ (SIZE) ]; \
memset( &sctl_io, 0, sizeof( sctl_io ) ); \
sctl_io.data = (void *)p_buffer; \
sctl_io.data_length = (SIZE); \
HPUXInitSCTL( &sctl_io, (TYPE) );
#endif
/*****************************************************************************
* Common macro, Solaris specific
*****************************************************************************/
#if defined( SOLARIS_USCSI )
#define USCSI_TIMEOUT( SC, TO ) ( (SC)->uscsi_timeout = (TO) )
#define USCSI_RESID( SC ) ( (SC)->uscsi_resid )
#define INIT_USCSI( TYPE, SIZE ) \
struct uscsi_cmd sc; \
union scsi_cdb rs_cdb; \
u8 p_buffer[ (SIZE) ]; \
memset( &sc, 0, sizeof( struct uscsi_cmd ) ); \
sc.uscsi_cdb = (caddr_t)&rs_cdb; \
sc.uscsi_bufaddr = p_buffer; \
sc.uscsi_buflen = (SIZE); \
SolarisInitUSCSI( &sc, (TYPE) );
#endif
/*****************************************************************************
* Common macro, Darwin specific
*****************************************************************************/
#if defined( DARWIN_DVD_IOCTL )
#define INIT_DVDIOCTL( DKDVD_TYPE, BUFFER_TYPE, FORMAT ) \
DKDVD_TYPE dvd; \
BUFFER_TYPE dvdbs; \
memset( &dvd, 0, sizeof(dvd) ); \
memset( &dvdbs, 0, sizeof(dvdbs) ); \
dvd.format = FORMAT; \
dvd.buffer = &dvdbs; \
dvd.bufferLength = sizeof(dvdbs);
#endif
/*****************************************************************************
* Common macro, win32 (ASPI) specific
*****************************************************************************/
#if defined( WIN32 )
#define INIT_SSC( TYPE, SIZE ) \
struct SRB_ExecSCSICmd ssc; \
u8 p_buffer[ (SIZE) ]; \
memset( &ssc, 0, sizeof( struct SRB_ExecSCSICmd ) ); \
ssc.SRB_BufPointer = (char *)p_buffer; \
ssc.SRB_BufLen = (SIZE); \
WinInitSSC( &ssc, (TYPE) );
#endif
/*****************************************************************************
* Common macro, QNX specific
*****************************************************************************/
#if defined( __QNXNTO__ )
#define INIT_CPT( TYPE, SIZE ) \
CAM_PASS_THRU * p_cpt; \
uint8_t * p_buffer; \
int structSize = sizeof( CAM_PASS_THRU ) + (SIZE); \
p_cpt = (CAM_PASS_THRU *) malloc ( structSize ); \
p_buffer = (uint8_t *) p_cpt + sizeof( CAM_PASS_THRU ); \
memset( p_cpt, 0, structSize ); \
p_cpt->cam_data_ptr = sizeof( CAM_PASS_THRU ); \
p_cpt->cam_dxfer_len = (SIZE); \
QNXInitCPT( p_cpt, (TYPE) );
#endif
/*****************************************************************************
* Common macro, OS2 specific
*****************************************************************************/
#if defined( SYS_OS2 )
#define INIT_SSC( TYPE, SIZE ) \
struct OS2_ExecSCSICmd sdc; \
u8 p_buffer[ (SIZE) ]; \
unsigned long ulParamLen; \
unsigned long ulDataLen; \
memset( &sdc, 0, sizeof( OS2_ExecSCSICmd ) ); \
memset( &p_buffer, 0, SIZE ); \
sdc.data_length = (SIZE); \
ulParamLen = sizeof(sdc); \
OS2InitSDC( &sdc, (TYPE) )
#endif
/*****************************************************************************
* Additional types, OpenBSD specific
*****************************************************************************/
#if defined( HAVE_OPENBSD_DVD_STRUCT )
typedef union dvd_struct dvd_struct;
typedef union dvd_authinfo dvd_authinfo;
#endif
/*****************************************************************************
* Various DVD I/O tables
*****************************************************************************/
#if defined( SYS_BEOS ) || defined( WIN32 ) || defined ( SOLARIS_USCSI ) || defined ( HPUX_SCTL_IO ) || defined ( __QNXNTO__ ) || defined ( SYS_OS2 )
/* The generic packet command opcodes for CD/DVD Logical Units,
* From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */
# define GPCMD_READ_DVD_STRUCTURE 0xad
# define GPCMD_REPORT_KEY 0xa4
# define GPCMD_SEND_KEY 0xa3
/* DVD struct types */
# define DVD_STRUCT_PHYSICAL 0x00
# define DVD_STRUCT_COPYRIGHT 0x01
# define DVD_STRUCT_DISCKEY 0x02
# define DVD_STRUCT_BCA 0x03
# define DVD_STRUCT_MANUFACT 0x04
/* Key formats */
# define DVD_REPORT_AGID 0x00
# define DVD_REPORT_CHALLENGE 0x01
# define DVD_SEND_CHALLENGE 0x01
# define DVD_REPORT_KEY1 0x02
# define DVD_SEND_KEY2 0x03
# define DVD_REPORT_TITLE_KEY 0x04
# define DVD_REPORT_ASF 0x05
# define DVD_SEND_RPC 0x06
# define DVD_REPORT_RPC 0x08
# define DVD_INVALIDATE_AGID 0x3f
#endif
/*****************************************************************************
* win32 ioctl specific
*****************************************************************************/
#if defined( WIN32 )
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define IOCTL_DVD_START_SESSION CTL_CODE(FILE_DEVICE_DVD, 0x0400, METHOD_BUFFERED, FILE_READ_ACCESS)
#define IOCTL_DVD_READ_KEY CTL_CODE(FILE_DEVICE_DVD, 0x0401, METHOD_BUFFERED, FILE_READ_ACCESS)
#define IOCTL_DVD_SEND_KEY CTL_CODE(FILE_DEVICE_DVD, 0x0402, METHOD_BUFFERED, FILE_READ_ACCESS)
#define IOCTL_DVD_END_SESSION CTL_CODE(FILE_DEVICE_DVD, 0x0403, METHOD_BUFFERED, FILE_READ_ACCESS)
#define IOCTL_DVD_GET_REGION CTL_CODE(FILE_DEVICE_DVD, 0x0405, METHOD_BUFFERED, FILE_READ_ACCESS)
#define IOCTL_DVD_SEND_KEY2 CTL_CODE(FILE_DEVICE_DVD, 0x0406, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_SCSI_PASS_THROUGH_DIRECT CTL_CODE(FILE_DEVICE_CONTROLLER, 0x0405, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define DVD_CHALLENGE_KEY_LENGTH (12 + sizeof(DVD_COPY_PROTECT_KEY))
#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_ASF_LENGTH (sizeof(DVD_ASF) + sizeof(DVD_COPY_PROTECT_KEY))
#define DVD_REGION_LENGTH (sizeof(DVD_REGION))
#define SCSI_IOCTL_DATA_OUT 0
#define SCSI_IOCTL_DATA_IN 1
typedef ULONG DVD_SESSION_ID, *PDVD_SESSION_ID;
typedef enum
{
DvdChallengeKey = 0x01,
DvdBusKey1,
DvdBusKey2,
DvdTitleKey,
DvdAsf,
DvdSetRpcKey = 0x6,
DvdGetRpcKey = 0x8,
DvdDiskKey = 0x80,
DvdInvalidateAGID = 0x3f
} DVD_KEY_TYPE;
typedef struct _DVD_COPY_PROTECT_KEY
{
ULONG KeyLength;
DVD_SESSION_ID SessionId;
DVD_KEY_TYPE KeyType;
ULONG KeyFlags;
union
{
struct
{
ULONG FileHandle;
ULONG Reserved; // used for NT alignment
};
LARGE_INTEGER TitleOffset;
} Parameters;
UCHAR KeyData[0];
} DVD_COPY_PROTECT_KEY, *PDVD_COPY_PROTECT_KEY;
typedef struct _DVD_ASF
{
UCHAR Reserved0[3];
UCHAR SuccessFlag:1;
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 _SCSI_PASS_THROUGH_DIRECT
{
USHORT Length;
UCHAR ScsiStatus;
UCHAR PathId;
UCHAR TargetId;
UCHAR Lun;
UCHAR CdbLength;
UCHAR SenseInfoLength;
UCHAR DataIn;
ULONG DataTransferLength;
ULONG TimeOutValue;
PVOID DataBuffer;
ULONG SenseInfoOffset;
UCHAR Cdb[16];
} SCSI_PASS_THROUGH_DIRECT, *PSCSI_PASS_THROUGH_DIRECT;
/*****************************************************************************
* win32 aspi specific
*****************************************************************************/
#define WIN2K ( GetVersion() < 0x80000000 )
#define ASPI_HAID 0
#define ASPI_TARGET 0
#define SENSE_LEN 0x0E
#define SC_EXEC_SCSI_CMD 0x02
#define SC_GET_DISK_INFO 0x06
#define SS_COMP 0x01
#define SS_PENDING 0x00
#define SS_NO_ADAPTERS 0xE8
#define SRB_DIR_IN 0x08
#define SRB_DIR_OUT 0x10
#define SRB_EVENT_NOTIFY 0x40
struct w32_aspidev
{
long hASPI;
short i_sid;
int i_blocks;
long (*lpSendCommand)( void* );
};
#pragma pack(1)
struct SRB_GetDiskInfo
{
unsigned char SRB_Cmd;
unsigned char SRB_Status;
unsigned char SRB_HaId;
unsigned char SRB_Flags;
unsigned long SRB_Hdr_Rsvd;
unsigned char SRB_Target;
unsigned char SRB_Lun;
unsigned char SRB_DriveFlags;
unsigned char SRB_Int13HDriveInfo;
unsigned char SRB_Heads;
unsigned char SRB_Sectors;
unsigned char SRB_Rsvd1[22];
};
struct SRB_ExecSCSICmd
{
unsigned char SRB_Cmd;
unsigned char SRB_Status;
unsigned char SRB_HaId;
unsigned char SRB_Flags;
unsigned long SRB_Hdr_Rsvd;
unsigned char SRB_Target;
unsigned char SRB_Lun;
unsigned short SRB_Rsvd1;
unsigned long SRB_BufLen;
unsigned char *SRB_BufPointer;
unsigned char SRB_SenseLen;
unsigned char SRB_CDBLen;
unsigned char SRB_HaStat;
unsigned char SRB_TargStat;
unsigned long *SRB_PostProc;
unsigned char SRB_Rsvd2[20];
unsigned char CDBByte[16];
unsigned char SenseArea[SENSE_LEN+2];
};
#pragma pack()
#endif
/*****************************************************************************
* OS2 ioctl specific
*****************************************************************************/
#if defined( SYS_OS2 )
#define CDROMDISK_EXECMD 0x7A
#define EX_DIRECTION_IN 0x01
#define EX_PLAYING_CHK 0x02
#pragma pack(1)
struct OS2_ExecSCSICmd
{
unsigned long id_code; // 'CD01'
unsigned short data_length; // length of the Data Packet
unsigned short cmd_length; // length of the Command Buffer
unsigned short flags; // flags
unsigned char command[16]; // Command Buffer for SCSI command
} OS2_ExecSCSICmd;
#pragma pack()
#endif

513
libmpdvdkit2/libdvdcss.c Normal file
View File

@ -0,0 +1,513 @@
/* libdvdcss.c: DVD reading library.
*
* Authors: Stéphane Borel <stef@via.ecp.fr>
* Samuel Hocevar <sam@zoy.org>
* Håkan Hjort <d95hjort@dtek.chalmers.se>
*
* Copyright (C) 1998-2002 VideoLAN
* $Id$
*
* 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
* (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
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*/
/**
* \mainpage libdvdcss developer documentation
*
* \section intro Introduction
*
* \e libdvdcss is a simple library designed for accessing DVDs like a block
* device without having to bother about the decryption. The important features
* are:
* \li portability: currently supported platforms are GNU/Linux, FreeBSD,
* NetBSD, OpenBSD, BSD/OS, BeOS, Windows 95/98, Windows NT/2000, MacOS X,
* Solaris, HP-UX and OS/2.
* \li adaptability: unlike most similar projects, libdvdcss doesn't require
* the region of your drive to be set and will try its best to read from
* the disc even in the case of a region mismatch.
* \li simplicity: a DVD player can be built around the \e libdvdcss API using
* no more than 4 or 5 library calls.
*
* \e libdvdcss is free software, released under the General Public License.
* This ensures that \e libdvdcss remains free and used only with free
* software.
*
* \section api The libdvdcss API
*
* The complete \e libdvdcss programming interface is documented in the
* dvdcss.h file.
*
* \section env Environment variables
*
* Some environment variables can be used to change the behaviour of
* \e libdvdcss without having to modify the program which uses it. These
* variables are:
*
* \li \b DVDCSS_VERBOSE: sets the verbosity level.
* - \c 0 outputs no messages at all.
* - \c 1 outputs error messages to stderr.
* - \c 2 outputs error messages and debug messages to stderr.
*
* \li \b DVDCSS_METHOD: sets the authentication and decryption method
* that \e libdvdcss will use to read scrambled discs. Can be one
* of \c title, \c key or \c disc.
* - \c key is the default method. \e libdvdcss will use a set of
* calculated player keys to try and get the disc key. This can fail
* if the drive does not recognize any of the player keys.
* - \c disc is a fallback method when \c key has failed. Instead of
* using player keys, \e libdvdcss will crack the disc key using
* a brute force algorithm. This process is CPU intensive and requires
* 64 MB of memory to store temporary data.
* - \c title is the fallback when all other methods have failed. It does
* not rely on a key exchange with the DVD drive, but rather uses a
* crypto attack to guess the title key. On rare cases this may fail
* because there is not enough encrypted data on the disc to perform
* a statistical attack, but in the other hand it is the only way to
* 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.
*
*/
/*
* Preamble
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include "dvdcss/dvdcss.h"
#include "common.h"
#include "css.h"
#include "libdvdcss.h"
#include "ioctl.h"
#include "device.h"
/**
* \brief Symbol for version checks.
*
* The name of this symbol contains the library major number, which makes it
* easy to check which \e libdvdcss development headers are installed on the
* system with tools such as autoconf.
*
* The variable itself contains the exact version number of the library,
* which can be useful for specific feature needs.
*/
char * dvdcss_interface_2 = VERSION;
/**
* \brief Open a DVD device or directory and return a dvdcss instance.
*
* \param psz_target a string containing the target name, for instance
* "/dev/hdc" or "E:".
* \return a handle to a dvdcss instance or NULL on error.
*
* Initialize the \e libdvdcss library and open the requested DVD device or
* directory. \e libdvdcss checks whether ioctls can be performed on the disc,
* and when possible, the disc key is retrieved.
*
* dvdcss_open() returns a handle to be used for all subsequent \e libdvdcss
* calls. If an error occured, NULL is returned.
*/
extern dvdcss_t dvdcss_open ( char *psz_target )
{
int i_ret;
char *psz_method = getenv( "DVDCSS_METHOD" );
char *psz_verbose = getenv( "DVDCSS_VERBOSE" );
#ifndef WIN32
char *psz_raw_device = getenv( "DVDCSS_RAW_DEVICE" );
#endif
dvdcss_t dvdcss;
/*
* Allocate the library structure
*/
dvdcss = malloc( sizeof( struct dvdcss_s ) );
if( dvdcss == NULL )
{
return NULL;
}
/*
* Initialize structure with default values
*/
#ifndef WIN32
dvdcss->i_raw_fd = -1;
#endif
dvdcss->p_titles = NULL;
dvdcss->psz_device = (char *)strdup( psz_target );
dvdcss->psz_error = "no error";
dvdcss->i_method = DVDCSS_METHOD_KEY;
dvdcss->b_debug = 0;
dvdcss->b_errors = 0;
/*
* Find verbosity from DVDCSS_VERBOSE environment variable
*/
if( psz_verbose != NULL )
{
switch( atoi( psz_verbose ) )
{
case 2:
dvdcss->b_debug = 1;
case 1:
dvdcss->b_errors = 1;
case 0:
break;
}
}
/*
* Find method from DVDCSS_METHOD environment variable
*/
if( psz_method != NULL )
{
if( !strncmp( psz_method, "key", 4 ) )
{
dvdcss->i_method = DVDCSS_METHOD_KEY;
}
else if( !strncmp( psz_method, "disc", 5 ) )
{
dvdcss->i_method = DVDCSS_METHOD_DISC;
}
else if( !strncmp( psz_method, "title", 5 ) )
{
dvdcss->i_method = DVDCSS_METHOD_TITLE;
}
else
{
_dvdcss_error( dvdcss, "unknown decrypt method, please choose "
"from 'title', 'key' or 'disc'" );
free( dvdcss->psz_device );
free( dvdcss );
return NULL;
}
}
/*
* Open device
*/
i_ret = _dvdcss_open( dvdcss );
if( i_ret < 0 )
{
free( dvdcss->psz_device );
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? */
_dvdcss_debug( dvdcss,
"could not check whether the disc was scrambled" );
dvdcss->b_ioctls = 0;
}
else
{
_dvdcss_debug( dvdcss, i_ret ? "disc is scrambled"
: "disc is unscrambled" );
dvdcss->b_scrambled = i_ret;
}
}
/* If disc is CSS protected and the ioctls work, authenticate the drive */
if( dvdcss->b_scrambled && dvdcss->b_ioctls )
{
i_ret = _dvdcss_disckey( dvdcss );
if( i_ret < 0 )
{
_dvdcss_close( dvdcss );
free( dvdcss->psz_device );
free( dvdcss );
return NULL;
}
}
#ifndef WIN32
if( psz_raw_device != NULL )
{
_dvdcss_raw_open( dvdcss, psz_raw_device );
}
#endif
return dvdcss;
}
/**
* \brief Return a string containing the latest error that occured in the
* given \e libdvdcss instance.
*
* \param dvdcss a \e libdvdcss instance.
* \return a null-terminated string containing the latest error message.
*
* This function returns a constant string containing the latest error that
* occured in \e libdvdcss. It can be used to format error messages at your
* convenience in your application.
*/
extern char * dvdcss_error ( dvdcss_t dvdcss )
{
return dvdcss->psz_error;
}
/**
* \brief Seek in the disc and change the current key if requested.
*
* \param dvdcss a \e libdvdcss instance.
* \param i_blocks an absolute block offset to seek to.
* \param i_flags #DVDCSS_NOFLAGS, optionally ored with one of #DVDCSS_SEEK_KEY
* or #DVDCSS_SEEK_MPEG.
* \return the new position in blocks, or a negative value in case an error
* happened.
*
* This function seeks to the requested position, in logical blocks.
*
* You typically set \p i_flags to #DVDCSS_NOFLAGS when seeking in a .IFO.
*
* If #DVDCSS_SEEK_MPEG is specified in \p i_flags and if \e libdvdcss finds it
* reasonable to do so (ie, if the dvdcss method is not "title"), the current
* title key will be checked and a new one will be calculated if necessary.
* This flag is typically used when reading data from a VOB.
*
* If #DVDCSS_SEEK_KEY is specified, the title key will be always checked,
* even with the "title" method. This is equivalent to using the now
* deprecated dvdcss_title() call. This flag is typically used when seeking
* in a new title.
*/
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 ) )
|| ( i_flags & DVDCSS_SEEK_KEY ) )
{
/* check the title key */
if( _dvdcss_title( dvdcss, i_blocks ) )
{
return -1;
}
}
return _dvdcss_seek( dvdcss, i_blocks );
}
/**
* \brief Read from the disc and decrypt data if requested.
*
* \param dvdcss a \e libdvdcss instance.
* \param p_buffer a buffer that will contain the data read from the disc.
* \param i_blocks the amount of blocks to read.
* \param i_flags #DVDCSS_NOFLAGS, optionally ored with #DVDCSS_READ_DECRYPT.
* \return the amount of blocks read, or a negative value in case an
* error happened.
*
* This function reads \p i_blocks logical blocks from the DVD.
*
* You typically set \p i_flags to #DVDCSS_NOFLAGS when reading data from a
* .IFO file on the DVD.
*
* If #DVDCSS_READ_DECRYPT is specified in \p i_flags, dvdcss_read() will
* automatically decrypt scrambled sectors. This flag is typically used when
* reading data from a .VOB file on the DVD. It has no effect on unscrambled
* discs or unscrambled sectors, and can be safely used on those.
*
* \warning dvdcss_read() expects to be able to write \p i_blocks *
* #DVDCSS_BLOCK_SIZE bytes in \p p_buffer.
*/
extern int dvdcss_read ( dvdcss_t dvdcss, void *p_buffer,
int i_blocks,
int i_flags )
{
int i_ret, i_index;
i_ret = _dvdcss_read( dvdcss, p_buffer, i_blocks );
if( i_ret <= 0
|| !dvdcss->b_scrambled
|| !(i_flags & DVDCSS_READ_DECRYPT) )
{
return i_ret;
}
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( i_index = i_ret; i_index; i_index-- )
{
if( ((u8*)p_buffer)[0x14] & 0x30 )
{
_dvdcss_error( dvdcss, "no key but found encrypted block" );
/* Only return the initial range of unscrambled blocks? */
/* or fail completely? return 0; */
break;
}
p_buffer = (void *) ((u8 *)p_buffer + DVDCSS_BLOCK_SIZE);
}
}
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);
}
}
return i_ret;
}
/**
* \brief Read from the disc into multiple buffers and decrypt data if
* requested.
*
* \param dvdcss a \e libdvdcss instance.
* \param p_iovec a pointer to an array of iovec structures that will contain
* the data read from the disc.
* \param i_blocks the amount of blocks to read.
* \param i_flags #DVDCSS_NOFLAGS, optionally ored with #DVDCSS_READ_DECRYPT.
* \return the amount of blocks read, or a negative value in case an
* error happened.
*
* This function reads \p i_blocks logical blocks from the DVD and writes them
* to an array of iovec structures.
*
* You typically set \p i_flags to #DVDCSS_NOFLAGS when reading data from a
* .IFO file on the DVD.
*
* If #DVDCSS_READ_DECRYPT is specified in \p i_flags, dvdcss_readv() will
* automatically decrypt scrambled sectors. This flag is typically used when
* reading data from a .VOB file on the DVD. It has no effect on unscrambled
* discs or unscrambled sectors, and can be safely used on those.
*
* \warning dvdcss_readv() expects to be able to write \p i_blocks *
* #DVDCSS_BLOCK_SIZE bytes in the buffers pointed by \p p_iovec.
* Moreover, all iov_len members of the iovec structures should be
* multiples of #DVDCSS_BLOCK_SIZE.
*/
extern int dvdcss_readv ( dvdcss_t dvdcss, void *p_iovec,
int i_blocks,
int i_flags )
{
struct iovec *_p_iovec = (struct iovec *)p_iovec;
int i_ret, i_index;
void *iov_base;
size_t iov_len;
i_ret = _dvdcss_readv( dvdcss, _p_iovec, i_blocks );
if( i_ret <= 0
|| !dvdcss->b_scrambled
|| !(i_flags & DVDCSS_READ_DECRYPT) )
{
return i_ret;
}
/* Initialize loop for decryption */
iov_base = _p_iovec->iov_base;
iov_len = _p_iovec->iov_len;
/* Decrypt the blocks we managed to read */
for( i_index = i_ret; i_index; i_index-- )
{
/* Check that iov_len is a multiple of 2048 */
if( iov_len & 0x7ff )
{
return -1;
}
while( iov_len == 0 )
{
_p_iovec++;
iov_base = _p_iovec->iov_base;
iov_len = _p_iovec->iov_len;
}
_dvdcss_unscramble( dvdcss->css.p_title_key, iov_base );
((u8*)iov_base)[0x14] &= 0x8f;
iov_base = (void *) ((u8*)iov_base + DVDCSS_BLOCK_SIZE);
iov_len -= DVDCSS_BLOCK_SIZE;
}
return i_ret;
}
/**
* \brief Close the DVD and clean up the library.
*
* \param dvdcss a \e libdvdcss instance.
* \return zero in case of success, a negative value otherwise.
*
* This function closes the DVD device and frees all the memory allocated
* by \e libdvdcss. On return, the #dvdcss_t is invalidated and may not be
* used again.
*/
extern int dvdcss_close ( dvdcss_t dvdcss )
{
dvd_title_t *p_title;
int i_ret;
/* Free our list of keys */
p_title = dvdcss->p_titles;
while( p_title )
{
dvd_title_t *p_tmptitle = p_title->p_next;
free( p_title );
p_title = p_tmptitle;
}
i_ret = _dvdcss_close( dvdcss );
if( i_ret < 0 )
{
return i_ret;
}
free( dvdcss->psz_device );
free( dvdcss );
return 0;
}
/*
* Deprecated. See dvdcss_seek().
*/
#undef dvdcss_title
extern int dvdcss_title ( dvdcss_t dvdcss, int i_block )
{
return _dvdcss_title( dvdcss, i_block );
}

73
libmpdvdkit2/libdvdcss.h Normal file
View File

@ -0,0 +1,73 @@
/*****************************************************************************
* private.h: private DVD reading library data
*****************************************************************************
* Copyright (C) 1998-2001 VideoLAN
* $Id$
*
* Authors: Stéphane Borel <stef@via.ecp.fr>
* Samuel Hocevar <sam@zoy.org>
*
* 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
* (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
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
/*****************************************************************************
* The libdvdcss structure
*****************************************************************************/
struct dvdcss_s
{
/* File descriptor */
char * psz_device;
int i_fd;
int i_seekpos;
/* Decryption stuff */
int i_method;
css_t css;
int b_ioctls;
int b_scrambled;
dvd_title_t *p_titles;
/* Error management */
char * psz_error;
int b_errors;
int b_debug;
#ifdef WIN32
char * p_readv_buffer;
int i_readv_buf_size;
#endif
#ifndef WIN32
int i_raw_fd;
int i_read_fd;
#endif
};
/*****************************************************************************
* libdvdcss method: used like init flags
*****************************************************************************/
#define DVDCSS_METHOD_KEY 0
#define DVDCSS_METHOD_DISC 1
#define DVDCSS_METHOD_TITLE 2
/*****************************************************************************
* Functions used across the library
*****************************************************************************/
int _dvdcss_seek ( dvdcss_t, int );
int _dvdcss_read ( dvdcss_t, void *, int );
void _dvdcss_error ( dvdcss_t, char * );
void _dvdcss_debug ( dvdcss_t, char * );