[Mplayer-cvslog] CVS: main/libmpdvdkit Makefile,NONE,1.1 README,NONE,1.1 bswap.h,NONE,1.1 common.h,NONE,1.1 config.h,NONE,1.1 css.c,NONE,1.1 css.h,NONE,1.1 csstables.h,NONE,1.1 dvd_reader.c,NONE,1.1 dvd_reader.h,NONE,1.1 dvd_udf.c,NONE,1.1 dvd_udf.h,NONE,1.1 dvdcss.h,NONE,1.1 get_path.c,NONE,1.1 ifo_print.c,NONE,1.1 ifo_print.h,NONE,1.1 ifo_read.c,NONE,1.1 ifo_read.h,NONE,1.1 ifo_types.h,NONE,1.1 int_types.h,NONE,1.1 ioctl.c,NONE,1.1 ioctl.h,NONE,1.1 libdvdcss.c,NONE,1.1 libdvdcss.h,NONE,1.1 nav_print.c,NONE,1.1 nav_print.h,NONE,1.1 nav_read.c,NONE,1.1 nav_read.h,NONE,1.1 nav_types.h,NONE,1.1
Arpi of Ize
arpi at mplayerhq.hu
Wed Apr 24 21:28:07 CEST 2002
Update of /cvsroot/mplayer/main/libmpdvdkit
In directory mail:/var/tmp.root/cvs-serv3761
Added Files:
Makefile README bswap.h common.h config.h css.c css.h
csstables.h dvd_reader.c dvd_reader.h dvd_udf.c dvd_udf.h
dvdcss.h get_path.c ifo_print.c ifo_print.h ifo_read.c
ifo_read.h ifo_types.h int_types.h ioctl.c ioctl.h libdvdcss.c
libdvdcss.h nav_print.c nav_print.h nav_read.c nav_read.h
nav_types.h
Log Message:
mplayer-dvdkit v1.0-pre2 by .so
--- NEW FILE ---
ifneq ($(wildcard ../config.mak),)
include ../config.mak
endif
SRCS = dvd_reader.c dvd_udf.c ifo_read.c ifo_print.c nav_read.c nav_print.c \
css.c ioctl.c libdvdcss.c
OBJS = $(SRCS:.c=.o)
LIB=libmpdvdkit
.SUFFIXES: .c .o
ifeq ($(OPTFLAGS),)
OPTFLAGS = -mcpu=pentium -march=pentium -O4 -I.
else
OPTFLAGS += -DHAVE_MPLAYER
endif
CFLAGS= $(OPTFLAGS) \
-D_LARGEFILE64_SOURCE \
-DSYS_LINUX -D_FILE_OFFSET_BITS=64 -D__USE_UNIX98 -D_REENTRANT -D_GNU_SOURCE \
-ffast-math -funroll-loops -fomit-frame-pointer
.c.o:
$(CC) $(CFLAGS) -c -o $@ $<
all: $(LIB).a
default: $(LIB).a
$(LIB).a: $(OBJS)
ar rc $(LIB).a $(OBJS)
$(LIB).so: $(OBJS)
$(CC) -o $(LIB).so -shared -rdynamic $(OBJS)
clean:
rm -f $(OBJS) $(LIB).a .depend
distclean: clean
dep: depend
depend: .depend
.depend: Makefile config.h
$(CC) -MM $(CFLAGS) $(SRCS) 1>.depend
#
# include dependency files if they exist
#
ifneq ($(wildcard .depend),)
include .depend
endif
--- NEW FILE ---
MPlayer DVD-kit v1.0-pre2 :)
made by Pontscho for the MPlayer project
What the hell is this?
======================
nothing special, just collection of sources and patches and fixes:
- dvdread 0.9.2 + assert() bug workaround
- libdvdcss 0.0.3 + css key cache patch + per-disc caching
- optimizations enabled, asserts disabled
everything packed together with static linking to maximize performance
Why?
====
users keep complaining about the still not fixed assert() bug, the
buggy libdvdcss 1.0 or the slow key-cracking process...
so Pontscho decided to pack these together, fix bugs and make it
available for the MPlayer users.
Installation? How? What?
========================
Just unpack this archive inside the mplayer source dir,
and MPlayer's ./configure will detects and use this!
How to create mpdvdkit shared object?
=====================================
make libmpdvdkit.so
--- NEW FILE ---
/**
* Copyright (C) 2000, 2001 Billy Biggs <vektor at dumbterm.net>,
* Håkan Hjort <d95hjort at 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-1307 USA
*/
#ifndef BSWAP_H_INCLUDED
#define BSWAP_H_INCLUDED
//#include <config.h>
#if defined(WORDS_BIGENDIAN)
/* All bigendian systems are fine, just ignore the swaps. */
#define B2N_16(x) (void)(x)
#define B2N_32(x) (void)(x)
#define B2N_64(x) (void)(x)
#else
#if defined(__linux__)
#include <byteswap.h>
#define B2N_16(x) x = bswap_16(x)
#define B2N_32(x) x = bswap_32(x)
#define B2N_64(x) x = bswap_64(x)
#elif defined(__NetBSD__)
#include <sys/endian.h>
#define B2N_16(x) BE16TOH(x)
#define B2N_32(x) BE32TOH(x)
#define B2N_64(x) BE64TOH(x)
#elif defined(__OpenBSD__)
#include <sys/endian.h>
#define B2N_16(x) x = swap16(x)
#define B2N_32(x) x = swap32(x)
#define B2N_64(x) x = swap64(x)
/* This is a slow but portable implementation, it has multiple evaluation
* problems so beware.
* FreeBSD and Solaris don't have <byteswap.h> or any other such
* functionality!
*/
#elif defined(__FreeBSD__) || defined(__sun) || defined(__bsdi__)
#define B2N_16(x) \
x = ((((x) & 0xff00) >> 8) | \
(((x) & 0x00ff) << 8))
#define B2N_32(x) \
x = ((((x) & 0xff000000) >> 24) | \
(((x) & 0x00ff0000) >> 8) | \
(((x) & 0x0000ff00) << 8) | \
(((x) & 0x000000ff) << 24))
#define B2N_64(x) \
x = ((((x) & 0xff00000000000000) >> 56) | \
(((x) & 0x00ff000000000000) >> 40) | \
(((x) & 0x0000ff0000000000) >> 24) | \
(((x) & 0x000000ff00000000) >> 8) | \
(((x) & 0x00000000ff000000) << 8) | \
(((x) & 0x0000000000ff0000) << 24) | \
(((x) & 0x000000000000ff00) << 40) | \
(((x) & 0x00000000000000ff) << 56))
#else
/* If there isn't a header provided with your system with this functionality
* add the relevant || define( ) to the portable implementation above.
*/
#error "You need to add endian swap macros for you're system"
#endif
#endif /* WORDS_BIGENDIAN */
#endif /* BSWAP_H_INCLUDED */
--- NEW FILE ---
/*****************************************************************************
* common.h: common definitions
* Collection of useful common types and macros definitions
*****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN
* $Id: common.h,v 1.1 2002/04/24 19:28:03 arpi Exp $
*
* Authors: Samuel Hocevar <sam at via.ecp.fr>
* Vincent Seguin <seguin at via.ecp.fr>
*
* 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.
*****************************************************************************/
/*****************************************************************************
* required headers:
* config.h
*****************************************************************************/
/*****************************************************************************
* Basic types definitions
*****************************************************************************/
#include "int_types.h"
typedef u8 byte_t;
/* Boolean type */
typedef int boolean_t;
#ifdef SYS_GNU
# define _MACH_I386_BOOLEAN_H_
#endif
/* ptrdiff_t definition */
#ifdef HAVE_STDDEF_H
# include <stddef.h>
#else
# include <malloc.h>
# ifndef _PTRDIFF_T
# define _PTRDIFF_T
/* Not portable in a 64-bit environment. */
typedef int ptrdiff_t;
# endif
#endif
/* Counter for statistics and profiling */
typedef unsigned long count_t;
/* DCT elements types */
#ifndef VDEC_DFT
typedef short dctelem_t;
#else
typedef int dctelem_t;
#endif
/*****************************************************************************
* Classes declaration
*****************************************************************************/
/* Plugins */
struct plugin_bank_s;
struct plugin_info_s;
typedef struct plugin_bank_s * p_plugin_bank_t;
typedef struct plugin_info_s * p_plugin_info_t;
/* Plugins */
struct playlist_s;
struct playlist_item_s;
typedef struct playlist_s * p_playlist_t;
typedef struct playlist_item_s * p_playlist_item_t;
/* Interface */
struct intf_thread_s;
struct intf_sys_s;
struct intf_console_s;
struct intf_msg_s;
struct intf_channel_s;
typedef struct intf_thread_s * p_intf_thread_t;
typedef struct intf_sys_s * p_intf_sys_t;
typedef struct intf_console_s * p_intf_console_t;
typedef struct intf_msg_s * p_intf_msg_t;
typedef struct intf_channel_s * p_intf_channel_t;
/* Input */
struct input_thread_s;
struct input_channel_s;
struct input_cfg_s;
typedef struct input_thread_s * p_input_thread_t;
typedef struct input_channel_s * p_input_channel_t;
typedef struct input_cfg_s * p_input_cfg_t;
/* Audio */
struct aout_thread_s;
struct aout_sys_s;
typedef struct aout_thread_s * p_aout_thread_t;
typedef struct aout_sys_s * p_aout_sys_t;
/* Video */
struct vout_thread_s;
struct vout_font_s;
struct vout_sys_s;
struct vdec_thread_s;
struct vpar_thread_s;
struct video_parser_s;
typedef struct vout_thread_s * p_vout_thread_t;
typedef struct vout_font_s * p_vout_font_t;
typedef struct vout_sys_s * p_vout_sys_t;
typedef struct vdec_thread_s * p_vdec_thread_t;
typedef struct vpar_thread_s * p_vpar_thread_t;
typedef struct video_parser_s * p_video_parser_t;
/* Misc */
struct macroblock_s;
struct data_packet_s;
struct es_descriptor_s;
struct pgrm_descriptor_s;
/*****************************************************************************
* Macros and inline functions
*****************************************************************************/
#ifdef NTOHL_IN_SYS_PARAM_H
# include <sys/param.h>
#elif defined(WIN32)
# include <winsock.h>
#else
# include <netinet/in.h>
#endif
/* CEIL: division with round to nearest greater integer */
#define CEIL(n, d) ( ((n) / (d)) + ( ((n) % (d)) ? 1 : 0) )
/* PAD: PAD(n, d) = CEIL(n ,d) * d */
#define PAD(n, d) ( ((n) % (d)) ? ((((n) / (d)) + 1) * (d)) : (n) )
/* MAX and MIN: self explanatory */
#ifndef MAX
# define MAX(a, b) ( ((a) > (b)) ? (a) : (b) )
#endif
#ifndef MIN
# define MIN(a, b) ( ((a) < (b)) ? (a) : (b) )
#endif
/* MSB (big endian)/LSB (little endian) conversions - network order is always
* MSB, and should be used for both network communications and files. Note that
* byte orders other than little and big endians are not supported, but only
* the VAX seems to have such exotic properties - note that these 'functions'
* needs <netinet/in.h> or the local equivalent. */
/* FIXME: hton64 should be declared as an extern inline function to avoid
* border effects (see byteorder.h) */
#if WORDS_BIGENDIAN
# define hton16 htons
# define hton32 htonl
# define hton64(i) ( i )
# define ntoh16 ntohs
# define ntoh32 ntohl
# define ntoh64(i) ( i )
#else
# define hton16 htons
# define hton32 htonl
# define hton64(i) ( ((u64)(htonl((i) & 0xffffffff)) << 32) | htonl(((i) >> 32) & 0xffffffff ) )
# define ntoh16 ntohs
# define ntoh32 ntohl
# define ntoh64 hton64
#endif
/* Macros with automatic casts */
#define U64_AT(p) ( ntoh64 ( *( (u64 *)(p) ) ) )
#define U32_AT(p) ( ntoh32 ( *( (u32 *)(p) ) ) )
#define U16_AT(p) ( ntoh16 ( *( (u16 *)(p) ) ) )
/* win32, cl and icl support */
#if defined( _MSC_VER )
# define __attribute__(x)
# define __inline__ __inline
# define strncasecmp strnicmp
# define strcasecmp stricmp
# define S_ISBLK(m) (0)
# define S_ISCHR(m) (0)
# define S_ISFIFO(m) (((m)&_S_IFMT) == _S_IFIFO)
# define S_ISREG(m) (((m)&_S_IFMT) == _S_IFREG)
# define I64C(x) x
#else
# define I64C(x) x##LL
#endif
#if defined( WIN32 )
# ifndef _OFF_T_DEFINED
typedef __int64 off_t;
# define _OFF_T_DEFINED
# endif
# ifndef snprintf
# define snprintf _snprintf /* snprintf not defined in mingw32 (bug?) */
# endif
#endif
--- NEW FILE ---
/* Define if your processor stores words with the most significant
byte first (like Motorola and SPARC, unlike Intel and VAX). */
#ifdef HAVE_MPLAYER
#include "../config.h"
#else
#undef WORDS_BIGENDIAN
/* Define if you have the <stddef.h> header file. */
#define HAVE_STDDEF_H 1
/* Define if <sys/dvdio.h> defines dvd_struct. */
#undef DVD_STRUCT_IN_SYS_DVDIO_H
/* Define if <sys/cdio.h> defines dvd_struct. */
#undef DVD_STRUCT_IN_SYS_CDIO_H
/* Define if <linux/cdrom.h> defines DVD_STRUCT. */
#define DVD_STRUCT_IN_LINUX_CDROM_H 1
/* Define if <dvd.h> defines DVD_STRUCT. */
#undef DVD_STRUCT_IN_DVD_H
/* Define if <extras/BSDI_dvdioctl/dvd.h> defines DVD_STRUCT. */
#undef DVD_STRUCT_IN_BSDI_DVDIOCTL_DVD_H
/* Have userspace SCSI headers. */
#undef SOLARIS_USCSI
/* Define if Linux-like dvd_struct is defined. */
#define HAVE_LINUX_DVD_STRUCT 1
/* Define if BSD-like dvd_struct is defined. */
#undef HAVE_BSD_DVD_STRUCT
#endif
/* assert support */
#undef HAVE_ASSERT_H
#ifndef HAVE_ASSERT_H
#define assert( ... ) do {} while(0)
#endif
--- NEW FILE ---
/*****************************************************************************
* css.c: Functions for DVD authentification and unscrambling
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id: css.c,v 1.1 2002/04/24 19:28:03 arpi Exp $
*
* Author: Stéphane Borel <stef at via.ecp.fr>
*
* based on:
* - css-auth by Derek Fawcus <derek at spider.com>
* - DVD CSS ioctls example program by Andrew T. Veliath <andrewtv at usa.net>
* - The Divide and conquer attack by Frank A. Stevenson <frank at 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.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//#include "config.h"
#include "common.h"
#include "dvdcss.h"
#include "libdvdcss.h"
#include "csstables.h"
#include "ioctl.h"
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static int CSSGetASF ( dvdcss_handle dvdcss );
static void CSSCryptKey ( int i_key_type, int i_varient,
u8 const * p_challenge, u8* p_key );
static int CSSCracker ( int i_start, unsigned char * p_crypted,
unsigned char * p_decrypted,
dvd_key_t * p_sector_key, dvd_key_t * p_key );
/*****************************************************************************
* CSSTest : check if the disc is encrypted or not
*****************************************************************************/
int CSSTest( dvdcss_handle dvdcss )
{
int i_ret, i_copyright;
i_ret = ioctl_ReadCopyright( dvdcss->i_fd, 0 /* i_layer */, &i_copyright );
if( i_ret < 0 )
{
/* Since it's the first ioctl we try to issue, we add a notice */
_dvdcss_error( dvdcss, "css error: ioctl_ReadCopyright failed, "
"make sure DVD ioctls were compiled in" );
return i_ret;
}
return i_copyright;
}
/*****************************************************************************
* CSSInit : CSS Structure initialisation and DVD authentication.
*****************************************************************************
* It simulates the mutual authentication between logical unit and host.
* Since we don't need the disc key to find the title key, we just run the
* basic unavoidable commands to authenticate device and disc.
*****************************************************************************/
int CSSInit( dvdcss_handle dvdcss )
{
/* structures defined in cdrom.h or dvdio.h */
unsigned char p_buffer[2048 + 4 + 1];
char psz_warning[32];
int i_agid = 0;
int i_ret = -1;
int i;
/* Test authentication success */
switch( CSSGetASF( dvdcss ) )
{
case -1:
return -1;
case 1:
_dvdcss_debug( dvdcss, "already authenticated" );
return 0;
case 0:
_dvdcss_debug( dvdcss, "need to authenticate" );
}
/* Init sequence, request AGID */
for( i = 1; i < 4 ; ++i )
{
sprintf( psz_warning, "requesting AGID %d", i );
_dvdcss_debug( dvdcss, psz_warning );
i_ret = ioctl_ReportAgid( dvdcss->i_fd, &i_agid );
if( i_ret != -1 )
{
/* No error during ioctl: we know the device is authenticated */
break;
}
_dvdcss_error( dvdcss, "ioctl_ReportAgid failed, invalidating" );
i_agid = 0;
ioctl_InvalidateAgid( dvdcss->i_fd, &i_agid );
}
/* Unable to authenticate without AGID */
if( i_ret == -1 )
{
_dvdcss_error( dvdcss, "ioctl_ReportAgid failed, fatal" );
return -1;
}
for( i = 0 ; i < 10; ++i )
{
dvdcss->css.disc.p_challenge[i] = i;
}
/* Get challenge from host */
for( i = 0 ; i < 10 ; ++i )
{
p_buffer[9-i] = dvdcss->css.disc.p_challenge[i];
}
/* Send challenge to LU */
if( ioctl_SendChallenge( dvdcss->i_fd, &i_agid, p_buffer ) < 0 )
{
_dvdcss_error( dvdcss, "ioctl_SendChallenge failed" );
return -1;
}
/* Get key1 from LU */
if( ioctl_ReportKey1( dvdcss->i_fd, &i_agid, p_buffer ) < 0)
{
_dvdcss_error( dvdcss, "ioctl_ReportKey1 failed" );
return -1;
}
/* Send key1 to host */
for( i = 0 ; i < KEY_SIZE ; i++ )
{
dvdcss->css.disc.p_key1[i] = p_buffer[4-i];
}
for( i = 0 ; i < 32 ; ++i )
{
CSSCryptKey( 0, i, dvdcss->css.disc.p_challenge,
dvdcss->css.disc.p_key_check );
if( memcmp( dvdcss->css.disc.p_key_check,
dvdcss->css.disc.p_key1, KEY_SIZE ) == 0 )
{
sprintf( psz_warning, "drive authentic, using variant %d", i );
_dvdcss_debug( dvdcss, psz_warning );
dvdcss->css.disc.i_varient = i;
break;
}
}
if( i == 32 )
{
_dvdcss_error( dvdcss, "drive would not authenticate" );
return -1;
}
/* Get challenge from LU */
if( ioctl_ReportChallenge( dvdcss->i_fd, &i_agid, p_buffer ) < 0 )
{
_dvdcss_error( dvdcss, "ioctl_ReportKeyChallenge failed" );
return -1;
}
/* Send challenge to host */
for( i = 0 ; i < 10 ; ++i )
{
dvdcss->css.disc.p_challenge[i] = p_buffer[9-i];
}
CSSCryptKey( 1, dvdcss->css.disc.i_varient,
dvdcss->css.disc.p_challenge,
dvdcss->css.disc.p_key2 );
/* Get key2 from host */
for( i = 0 ; i < KEY_SIZE ; ++i )
{
p_buffer[4-i] = dvdcss->css.disc.p_key2[i];
}
/* Send key2 to LU */
if( ioctl_SendKey2( dvdcss->i_fd, &i_agid, p_buffer ) < 0 )
{
_dvdcss_error( dvdcss, "ioctl_SendKey2 failed" );
return -1;
}
_dvdcss_debug( dvdcss, "authentication established" );
memcpy( dvdcss->css.disc.p_challenge,
dvdcss->css.disc.p_key1, KEY_SIZE );
memcpy( dvdcss->css.disc.p_challenge+KEY_SIZE,
dvdcss->css.disc.p_key2, KEY_SIZE );
CSSCryptKey( 2, dvdcss->css.disc.i_varient,
dvdcss->css.disc.p_challenge,
dvdcss->css.disc.p_key_check );
_dvdcss_debug( dvdcss, "received session key" );
if( i_agid < 0 )
{
return -1;
}
/* Test authentication success */
switch( CSSGetASF( dvdcss ) )
{
case -1:
return -1;
case 1:
_dvdcss_debug( dvdcss, "already authenticated" );
return 0;
case 0:
_dvdcss_debug( dvdcss, "need to get disc key" );
}
/* Get encrypted disc key */
if( ioctl_ReadKey( dvdcss->i_fd, &i_agid, p_buffer ) < 0 )
{
_dvdcss_error( dvdcss, "ioctl_ReadKey failed" );
return -1;
}
/* Unencrypt disc key using bus key */
for( i = 0 ; i < 2048 ; i++ )
{
p_buffer[ i ] ^= dvdcss->css.disc.p_key_check[ 4 - (i % KEY_SIZE) ];
}
memcpy( dvdcss->css.disc.p_key_check, p_buffer, 2048 );
/* Test authentication success */
switch( CSSGetASF( dvdcss ) )
{
case -1:
return -1;
case 1:
_dvdcss_debug( dvdcss, "successfully authenticated" );
return 0;
case 0:
_dvdcss_error( dvdcss, "no way to authenticate" );
return -1;
}
return -1;
}
/*****************************************************************************
* CSSGetKey : get title key.
*****************************************************************************
* The DVD should have been opened and authenticated before.
*****************************************************************************/
int CSSGetKey( dvdcss_handle dvdcss, int i_pos, dvd_key_t p_titlekey )
{
/*
* Title key cracking method from Ethan Hawke,
* with Frank A. Stevenson algorithm.
* Does not use any player key table and ioctls.
*/
u8 p_buf[0x800];
dvd_key_t p_key;
boolean_t b_encrypted;
boolean_t b_stop_scanning;
int i_blocks_read;
int i_best_plen;
int i_best_p;
int i,j;
for( i = 0 ; i < KEY_SIZE ; i++ )
{
p_key[i] = 0;
}
b_encrypted = 0;
b_stop_scanning = 0;
do
{
i_pos = dvdcss_seek( dvdcss, i_pos );
i_blocks_read = dvdcss_read( dvdcss, p_buf, 1, DVDCSS_NOFLAGS );
/* PES_scrambling_control */
if( p_buf[0x14] & 0x30 )
{
b_encrypted = 1;
i_best_plen = 0;
i_best_p = 0;
for( i = 2 ; i < 0x30 ; i++ )
{
for( j = i+1 ;
j < 0x80 && ( p_buf[0x7F - (j%i)] == p_buf[0x7F-j] );
j++ );
{
if( j > i_best_plen )
{
i_best_plen = j;
i_best_p = i;
}
}
}
if( ( i_best_plen > 20 ) && ( i_best_plen / i_best_p >= 2) )
{
i = CSSCracker( 0, &p_buf[0x80],
&p_buf[0x80 - ( i_best_plen / i_best_p) *i_best_p],
(dvd_key_t*)&p_buf[0x54],
&p_key );
b_stop_scanning = ( i >= 0 );
}
}
i_pos += i_blocks_read;
} while( i_blocks_read == 0x1 && !b_stop_scanning );
if( b_stop_scanning )
{
memcpy( p_titlekey, &p_key, sizeof(dvd_key_t) );
_dvdcss_debug( dvdcss, "vts key initialized" );
return 0;
}
if( !b_encrypted )
{
_dvdcss_debug( dvdcss, "file was unscrambled" );
return 0;
}
return -1;
}
/*****************************************************************************
* CSSDescrambleSector
*****************************************************************************
* sec : sector to descramble
* key : title key for this sector
*****************************************************************************/
int CSSDescrambleSector( dvd_key_t p_key, u8* p_sec )
{
unsigned int i_t1, i_t2, i_t3, i_t4, i_t5, i_t6;
u8* p_end = p_sec + 0x800;
/* PES_scrambling_control */
if( p_sec[0x14] & 0x30)
{
i_t1 = ((p_key)[0] ^ p_sec[0x54]) | 0x100;
i_t2 = (p_key)[1] ^ p_sec[0x55];
i_t3 = (((p_key)[2]) | ((p_key)[3] << 8) |
((p_key)[4] << 16)) ^ ((p_sec[0x56]) |
(p_sec[0x57] << 8) | (p_sec[0x58] << 16));
i_t4 = i_t3 & 7;
i_t3 = i_t3 * 2 + 8 - i_t4;
p_sec += 0x80;
i_t5 = 0;
while( p_sec != p_end )
{
i_t4 = p_css_tab2[i_t2] ^ p_css_tab3[i_t1];
i_t2 = i_t1>>1;
i_t1 = ( ( i_t1 & 1 ) << 8 ) ^ i_t4;
i_t4 = p_css_tab5[i_t4];
i_t6 = ((((((( i_t3 >> 3 ) ^ i_t3 ) >> 1 ) ^
i_t3 ) >> 8 ) ^ i_t3 ) >> 5) & 0xff;
i_t3 = (i_t3 << 8 ) | i_t6;
i_t6 = p_css_tab4[i_t6];
i_t5 += i_t6 + i_t4;
*p_sec = p_css_tab1[*p_sec] ^( i_t5 & 0xff );
p_sec++;
i_t5 >>= 8;
}
}
return 0;
}
/* Following functions are local */
/*****************************************************************************
* CSSGetASF : Get Authentification success flag
*****************************************************************************
* Returns :
* -1 on ioctl error,
* 0 if the device needs to be authenticated,
* 1 either.
*****************************************************************************/
static int CSSGetASF( dvdcss_handle dvdcss )
{
int i_agid;
int i_asf = 0;
for( i_agid = 0 ; i_agid < 4 ; i_agid++ )
{
if( ioctl_ReportASF( dvdcss->i_fd, &i_agid, &i_asf ) == 0 )
{
if( i_asf )
{
_dvdcss_debug( dvdcss, "GetASF authenticated" );
}
else
{
_dvdcss_debug( dvdcss, "GetASF not authenticated" );
}
return i_asf;
}
}
/* The ioctl process has failed */
_dvdcss_error( dvdcss, "GetASF fatal error" );
return -1;
}
/*****************************************************************************
* CSSCryptKey : shuffles bits and unencrypt keys.
*****************************************************************************
* Used during authentication and disc key negociation in CSSInit.
* i_key_type : 0->key1, 1->key2, 2->buskey.
* i_varient : between 0 and 31.
*****************************************************************************/
static void CSSCryptKey( int i_key_type, int i_varient,
u8 const * p_challenge, u8* p_key )
{
/* Permutation table for challenge */
u8 pp_perm_challenge[3][10] =
{ { 1, 3, 0, 7, 5, 2, 9, 6, 4, 8 },
{ 6, 1, 9, 3, 8, 5, 7, 4, 0, 2 },
{ 4, 0, 3, 5, 7, 2, 8, 6, 1, 9 } };
/* Permutation table for varient table for key2 and buskey */
u8 pp_perm_varient[2][32] =
{ { 0x0a, 0x08, 0x0e, 0x0c, 0x0b, 0x09, 0x0f, 0x0d,
0x1a, 0x18, 0x1e, 0x1c, 0x1b, 0x19, 0x1f, 0x1d,
0x02, 0x00, 0x06, 0x04, 0x03, 0x01, 0x07, 0x05,
0x12, 0x10, 0x16, 0x14, 0x13, 0x11, 0x17, 0x15 },
{ 0x12, 0x1a, 0x16, 0x1e, 0x02, 0x0a, 0x06, 0x0e,
0x10, 0x18, 0x14, 0x1c, 0x00, 0x08, 0x04, 0x0c,
0x13, 0x1b, 0x17, 0x1f, 0x03, 0x0b, 0x07, 0x0f,
0x11, 0x19, 0x15, 0x1d, 0x01, 0x09, 0x05, 0x0d } };
u8 p_varients[32] =
{ 0xB7, 0x74, 0x85, 0xD0, 0xCC, 0xDB, 0xCA, 0x73,
0x03, 0xFE, 0x31, 0x03, 0x52, 0xE0, 0xB7, 0x42,
0x63, 0x16, 0xF2, 0x2A, 0x79, 0x52, 0xFF, 0x1B,
0x7A, 0x11, 0xCA, 0x1A, 0x9B, 0x40, 0xAD, 0x01 };
/* The "secret" key */
u8 p_secret[5] = { 0x55, 0xD6, 0xC4, 0xC5, 0x28 };
u8 p_bits[30];
u8 p_scratch[10];
u8 p_tmp1[5];
u8 p_tmp2[5];
u8 i_lfsr0_o; /* 1 bit used */
u8 i_lfsr1_o; /* 1 bit used */
u32 i_lfsr0;
u32 i_lfsr1;
u8 i_css_varient;
u8 i_cse;
u8 i_index;
u8 i_combined;
u8 i_carry;
u8 i_val = 0;
int i_term = 0;
int i_bit;
int i;
for (i = 9; i >= 0; --i)
p_scratch[i] = p_challenge[pp_perm_challenge[i_key_type][i]];
i_css_varient = ( i_key_type == 0 ) ? i_varient :
pp_perm_varient[i_key_type-1][i_varient];
/*
* This encryption engine implements one of 32 variations
* one the same theme depending upon the choice in the
* varient parameter (0 - 31).
*
* The algorithm itself manipulates a 40 bit input into
* a 40 bit output.
* The parameter 'input' is 80 bits. It consists of
* the 40 bit input value that is to be encrypted followed
* by a 40 bit seed value for the pseudo random number
* generators.
*/
/* Feed the secret into the input values such that
* we alter the seed to the LFSR's used above, then
* generate the bits to play with.
*/
for( i = 5 ; --i >= 0 ; )
{
p_tmp1[i] = p_scratch[5 + i] ^ p_secret[i] ^ p_crypt_tab2[i];
}
/*
* We use two LFSR's (seeded from some of the input data bytes) to
* generate two streams of pseudo-random bits. These two bit streams
* are then combined by simply adding with carry to generate a final
* sequence of pseudo-random bits which is stored in the buffer that
* 'output' points to the end of - len is the size of this buffer.
*
* The first LFSR is of degree 25, and has a polynomial of:
* x^13 + x^5 + x^4 + x^1 + 1
*
* The second LSFR is of degree 17, and has a (primitive) polynomial of:
* x^15 + x^1 + 1
*
* I don't know if these polynomials are primitive modulo 2, and thus
* represent maximal-period LFSR's.
*
*
* Note that we take the output of each LFSR from the new shifted in
* bit, not the old shifted out bit. Thus for ease of use the LFSR's
* are implemented in bit reversed order.
*
*/
/* In order to ensure that the LFSR works we need to ensure that the
* initial values are non-zero. Thus when we initialise them from
* the seed, we ensure that a bit is set.
*/
i_lfsr0 = ( p_tmp1[0] << 17 ) | ( p_tmp1[1] << 9 ) |
(( p_tmp1[2] & ~7 ) << 1 ) | 8 | ( p_tmp1[2] & 7 );
i_lfsr1 = ( p_tmp1[3] << 9 ) | 0x100 | p_tmp1[4];
i_index = sizeof(p_bits);
i_carry = 0;
do
{
for( i_bit = 0, i_val = 0 ; i_bit < 8 ; ++i_bit )
{
i_lfsr0_o = ( ( i_lfsr0 >> 24 ) ^ ( i_lfsr0 >> 21 ) ^
( i_lfsr0 >> 20 ) ^ ( i_lfsr0 >> 12 ) ) & 1;
i_lfsr0 = ( i_lfsr0 << 1 ) | i_lfsr0_o;
i_lfsr1_o = ( ( i_lfsr1 >> 16 ) ^ ( i_lfsr1 >> 2 ) ) & 1;
i_lfsr1 = ( i_lfsr1 << 1 ) | i_lfsr1_o;
i_combined = !i_lfsr1_o + i_carry + !i_lfsr0_o;
/* taking bit 1 */
i_carry = ( i_combined >> 1 ) & 1;
i_val |= ( i_combined & 1 ) << i_bit;
}
p_bits[--i_index] = i_val;
} while( i_index > 0 );
/* This term is used throughout the following to
* select one of 32 different variations on the
* algorithm.
*/
i_cse = p_varients[i_css_varient] ^ p_crypt_tab2[i_css_varient];
/* Now the actual blocks doing the encryption. Each
* of these works on 40 bits at a time and are quite
* similar.
*/
i_index = 0;
for( i = 5, i_term = 0 ; --i >= 0 ; i_term = p_scratch[i] )
{
i_index = p_bits[25 + i] ^ p_scratch[i];
i_index = p_crypt_tab1[i_index] ^ ~p_crypt_tab2[i_index] ^ i_cse;
p_tmp1[i] = p_crypt_tab2[i_index] ^ p_crypt_tab3[i_index] ^ i_term;
}
p_tmp1[4] ^= p_tmp1[0];
for( i = 5, i_term = 0 ; --i >= 0 ; i_term = p_tmp1[i] )
{
i_index = p_bits[20 + i] ^ p_tmp1[i];
i_index = p_crypt_tab1[i_index] ^ ~p_crypt_tab2[i_index] ^ i_cse;
p_tmp2[i] = p_crypt_tab2[i_index] ^ p_crypt_tab3[i_index] ^ i_term;
}
p_tmp2[4] ^= p_tmp2[0];
for( i = 5, i_term = 0 ; --i >= 0 ; i_term = p_tmp2[i] )
{
i_index = p_bits[15 + i] ^ p_tmp2[i];
i_index = p_crypt_tab1[i_index] ^ ~p_crypt_tab2[i_index] ^ i_cse;
i_index = p_crypt_tab2[i_index] ^ p_crypt_tab3[i_index] ^ i_term;
p_tmp1[i] = p_crypt_tab0[i_index] ^ p_crypt_tab2[i_index];
}
p_tmp1[4] ^= p_tmp1[0];
for( i = 5, i_term = 0 ; --i >= 0 ; i_term = p_tmp1[i] )
{
i_index = p_bits[10 + i] ^ p_tmp1[i];
i_index = p_crypt_tab1[i_index] ^ ~p_crypt_tab2[i_index] ^ i_cse;
i_index = p_crypt_tab2[i_index] ^ p_crypt_tab3[i_index] ^ i_term;
p_tmp2[i] = p_crypt_tab0[i_index] ^ p_crypt_tab2[i_index];
}
p_tmp2[4] ^= p_tmp2[0];
for( i = 5, i_term = 0 ; --i >= 0 ; i_term = p_tmp2[i] )
{
i_index = p_bits[5 + i] ^ p_tmp2[i];
i_index = p_crypt_tab1[i_index] ^ ~p_crypt_tab2[i_index] ^ i_cse;
p_tmp1[i] = p_crypt_tab2[i_index] ^ p_crypt_tab3[i_index] ^ i_term;
}
p_tmp1[4] ^= p_tmp1[0];
for(i = 5, i_term = 0 ; --i >= 0 ; i_term = p_tmp1[i] )
{
i_index = p_bits[i] ^ p_tmp1[i];
i_index = p_crypt_tab1[i_index] ^ ~p_crypt_tab2[i_index] ^ i_cse;
p_key[i] = p_crypt_tab2[i_index] ^ p_crypt_tab3[i_index] ^ i_term;
}
return;
}
/*****************************************************************************
* CSSCracker : title key decryption by cracking
*****************************************************************************
* This function is called by CSSGetKeys to find a key
*****************************************************************************/
static int CSSCracker( int i_start,
unsigned char * p_crypted,
unsigned char * p_decrypted,
dvd_key_t * p_sector_key,
dvd_key_t * p_key )
{
unsigned char p_buffer[10];
unsigned int i_t1, i_t2, i_t3, i_t4, i_t5, i_t6;
unsigned int i_try;
unsigned int i_candidate;
unsigned int i, j;
int i_exit = -1;
for( i = 0 ; i < 10 ; i++ )
{
p_buffer[i] = p_css_tab1[p_crypted[i]] ^ p_decrypted[i];
}
for( i_try = i_start ; i_try < 0x10000 ; i_try++ )
{
i_t1 = i_try >> 8 | 0x100;
i_t2 = i_try & 0xff;
i_t3 = 0; /* not needed */
i_t5 = 0;
/* iterate cipher 4 times to reconstruct LFSR2 */
for( i = 0 ; i < 4 ; i++ )
{
/* advance LFSR1 normaly */
i_t4 = p_css_tab2[i_t2] ^ p_css_tab3[i_t1];
i_t2 = i_t1 >> 1;
i_t1 = ( ( i_t1 & 1 ) << 8 ) ^ i_t4;
i_t4 = p_css_tab5[i_t4];
/* deduce i_t6 & i_t5 */
i_t6 = p_buffer[i];
if( i_t5 )
{
i_t6 = ( i_t6 + 0xff ) & 0x0ff;
}
if( i_t6 < i_t4 )
{
i_t6 += 0x100;
}
i_t6 -= i_t4;
i_t5 += i_t6 + i_t4;
i_t6 = p_css_tab4[ i_t6 ];
/* feed / advance i_t3 / i_t5 */
i_t3 = ( i_t3 << 8 ) | i_t6;
i_t5 >>= 8;
}
i_candidate = i_t3;
/* iterate 6 more times to validate candidate key */
for( ; i < 10 ; i++ )
{
i_t4 = p_css_tab2[i_t2] ^ p_css_tab3[i_t1];
i_t2 = i_t1 >> 1;
i_t1 = ( ( i_t1 & 1 ) << 8 ) ^ i_t4;
i_t4 = p_css_tab5[i_t4];
i_t6 = ((((((( i_t3 >> 3 ) ^ i_t3 ) >> 1 ) ^
i_t3 ) >> 8 ) ^ i_t3 ) >> 5 ) & 0xff;
i_t3 = ( i_t3 << 8 ) | i_t6;
i_t6 = p_css_tab4[i_t6];
i_t5 += i_t6 + i_t4;
if( ( i_t5 & 0xff ) != p_buffer[i] )
{
break;
}
i_t5 >>= 8;
}
if( i == 10 )
{
/* Do 4 backwards steps of iterating t3 to deduce initial state */
i_t3 = i_candidate;
for( i = 0 ; i < 4 ; i++ )
{
i_t1 = i_t3 & 0xff;
i_t3 = ( i_t3 >> 8 );
/* easy to code, and fast enough bruteforce
* search for byte shifted in */
for( j = 0 ; j < 256 ; j++ )
{
i_t3 = ( i_t3 & 0x1ffff) | ( j << 17 );
i_t6 = ((((((( i_t3 >> 3 ) ^ i_t3 ) >> 1 ) ^
i_t3 ) >> 8 ) ^ i_t3 ) >> 5 ) & 0xff;
if( i_t6 == i_t1 )
{
break;
}
}
}
i_t4 = ( i_t3 >> 1 ) - 4;
for( i_t5 = 0 ; i_t5 < 8; i_t5++ )
{
if( ( ( i_t4 + i_t5 ) * 2 + 8 - ( (i_t4 + i_t5 ) & 7 ) )
== i_t3 )
{
(*p_key)[0] = i_try>>8;
(*p_key)[1] = i_try & 0xFF;
(*p_key)[2] = ( ( i_t4 + i_t5 ) >> 0) & 0xFF;
(*p_key)[3] = ( ( i_t4 + i_t5 ) >> 8) & 0xFF;
(*p_key)[4] = ( ( i_t4 + i_t5 ) >> 16) & 0xFF;
i_exit = i_try + 1;
}
}
}
}
if( i_exit >= 0 )
{
(*p_key)[0] ^= (*p_sector_key)[0];
(*p_key)[1] ^= (*p_sector_key)[1];
(*p_key)[2] ^= (*p_sector_key)[2];
(*p_key)[3] ^= (*p_sector_key)[3];
(*p_key)[4] ^= (*p_sector_key)[4];
}
return i_exit;
}
--- NEW FILE ---
/*****************************************************************************
* css.h: Structures for DVD authentification and unscrambling
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id: css.h,v 1.1 2002/04/24 19:28:03 arpi Exp $
*
* Author: Stéphane Borel <stef at via.ecp.fr>
*
* based on:
* - css-auth by Derek Fawcus <derek at spider.com>
* - DVD CSS ioctls example program by Andrew T. Veliath <andrewtv at usa.net>
* - DeCSSPlus by Ethan Hawke
* - The Divide and conquer attack by Frank A. Stevenson <frank at 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 disc_s
{
u8 p_challenge[2*KEY_SIZE];
dvd_key_t p_key1;
dvd_key_t p_key2;
dvd_key_t p_key_check;
u8 i_varient;
} disc_t;
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;
disc_t disc;
u8 p_disc_key[2048];
} css_t;
/*****************************************************************************
* Prototypes in css.c
*****************************************************************************/
struct css_s;
int CSSTest ( dvdcss_handle );
int CSSInit ( dvdcss_handle );
int CSSGetKey ( dvdcss_handle, int, dvd_key_t );
int CSSDescrambleSector ( u8 * , u8 * );
--- NEW FILE ---
/*****************************************************************************
* csstables.h: CSS Tables for DVD unscrambling
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id: csstables.h,v 1.1 2002/04/24 19:28:03 arpi Exp $
*
* Author: Stéphane Borel <stef at via.ecp.fr>
*
* based on:
* - css-auth by Derek Fawcus <derek at spider.com>
* - DVD CSS ioctls example program by Andrew T. Veliath <andrewtv at usa.net>
* - The Divide and conquer attack by Frank A. Stevenson <frank at 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
};
--- NEW FILE ---
/**
* Copyright (C) 2001 Billy Biggs <vektor at dumbterm.net>.
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h> /* For the timing of dvdcss_title crack. */
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
#include <dirent.h>
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__bsdi__)
#define SYS_BSD 1
#endif
#if defined(__sun)
#include <sys/mnttab.h>
#elif defined(SYS_BSD)
#include <fstab.h>
#elif defined(__linux__)
#include <mntent.h>
#endif
#if defined(SYS_BSD)
typedef off_t off64_t;
#define lseek64 lseek
#define stat64 stat
#endif
/* #include "dvdcss.h" */
typedef struct dvdcss_s* dvdcss_handle;
#define DVDCSS_NOFLAGS 0
#define DVDCSS_INIT_QUIET (1 << 0)
#define DVDCSS_INIT_DEBUG (1 << 1)
#define DVDCSS_READ_DECRYPT (1 << 0)
#include "dvd_udf.h"
#include "dvd_reader.h"
struct dvd_reader_s {
/* Basic information. */
int isImageFile;
/* Information required for an image file. */
dvdcss_handle dev;
int init_keys;
int fd;
/* Information required for a directory path drive. */
char *path_root;
};
struct dvd_file_s {
/* Basic information. */
dvd_reader_t *dvd;
/* Information required for an image file. */
uint32_t lb_start;
uint32_t seek_pos;
/* Information required for a directory path drive. */
size_t title_sizes[ 9 ];
int title_fds[ 9 ];
/* Calculated at open-time, size in blocks. */
ssize_t filesize;
};
/* Loop over all titles and call dvdcss_title to crack the keys. */
static int initAllCSSKeys( dvd_reader_t *dvd )
{
struct timeval all_s, all_e;
struct timeval t_s, t_e;
char filename[ MAX_UDF_FILE_NAME_LEN ];
uint32_t start, len;
int title;
fprintf( stderr, "\n" );
fprintf( stderr, "libdvdread: Attempting to retrieve all CSS keys\n" );
fprintf( stderr, "libdvdread: This can take a _long_ time, "
"please be patient\n\n" );
gettimeofday(&all_s, NULL);
for( title = 0; title < 100; title++ ) {
gettimeofday( &t_s, NULL );
if( title == 0 ) {
sprintf( filename, "/VIDEO_TS/VIDEO_TS.VOB" );
} else {
sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, 0 );
}
start = UDFFindFile( dvd, filename, &len );
if( start != 0 && len != 0 ) {
/* Perform CSS key cracking for this title. */
fprintf( stderr, "libdvdread: Get key for %s at 0x%08x\n",
filename, start );
if( dvdcss_title( dvd->dev, (int)start ) < 0 ) {
fprintf( stderr, "libdvdread: Error cracking CSS key!!\n");
}
gettimeofday( &t_e, NULL );
fprintf( stderr, "libdvdread: Elapsed time %ld\n",
(long int) t_e.tv_sec - t_s.tv_sec );
}
if( title == 0 ) continue;
gettimeofday( &t_s, NULL );
sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, 1 );
start = UDFFindFile( dvd, filename, &len );
if( start == 0 || len == 0 ) break;
/* Perform CSS key cracking for this title. */
fprintf( stderr, "libdvdread: Get key for %s at 0x%08x\n",
filename, start );
if( dvdcss_title( dvd->dev, (int)start ) < 0 ) {
fprintf( stderr, "libdvdread: Error cracking CSS key!!\n");
}
gettimeofday( &t_e, NULL );
fprintf( stderr, "libdvdread: Elapsed time %ld\n",
(long int) t_e.tv_sec - t_s.tv_sec );
}
title--;
fprintf( stderr, "libdvdread: Found %d VTS's\n", title );
gettimeofday(&all_e, NULL);
fprintf( stderr, "libdvdread: Elapsed time %ld\n",
(long int) all_e.tv_sec - all_s.tv_sec );
return 0;
}
/**
* Open a DVD image or block device file.
*/
static dvd_reader_t *DVDOpenImageFile( const char *location )
{
dvd_reader_t *dvd;
dvdcss_handle dev = 0;
int fd = -1;
dev = dvdcss_open( (char *) location, DVDCSS_INIT_DEBUG );
if( !dev ) {
fprintf( stderr, "libdvdread: Can't open %s for reading.\n",
location );
return 0;
}
dvd = (dvd_reader_t *) malloc( sizeof( dvd_reader_t ) );
if( !dvd ) return 0;
dvd->isImageFile = 1;
dvd->dev = dev;
dvd->init_keys = 0;
dvd->fd = fd;
dvd->path_root = 0;
return dvd;
}
static dvd_reader_t *DVDOpenPath( const char *path_root )
{
dvd_reader_t *dvd;
dvd = (dvd_reader_t *) malloc( sizeof( dvd_reader_t ) );
if( !dvd ) return 0;
dvd->isImageFile = 0;
dvd->dev = 0;
dvd->init_keys = 0;
dvd->fd = -1;
dvd->path_root = strdup( path_root );
return dvd;
}
#if defined(__sun)
/* /dev/rdsk/c0t6d0s0 (link to /devices/...)
/vol/dev/rdsk/c0t6d0/??
/vol/rdsk/<name> */
static char *sun_block2char( const char *path )
{
char *new_path;
/* Must contain "/dsk/" */
if( !strstr( path, "/dsk/" ) ) return (char *) strdup( path );
/* Replace "/dsk/" with "/rdsk/" */
new_path = malloc( strlen(path) + 2 );
strcpy( new_path, path );
strcpy( strstr( new_path, "/dsk/" ), "" );
strcat( new_path, "/rdsk/" );
strcat( new_path, strstr( path, "/dsk/" ) + strlen( "/dsk/" ) );
return new_path;
}
#endif
#if defined(SYS_BSD)
/* FreeBSD /dev/(r)(a)cd0 (a is for atapi, should work without r)
OpenBSD /dev/rcd0c
NetBSD /dev/rcd0d or /dev/rcd0c (for non x86)
BSD/OS /dev/sr0 (if not mounted) or /dev/rsr0 */
static char *bsd_block2char( const char *path )
{
char *new_path;
/* If it doesn't start with "/dev/" or does start with "/dev/r" exit */
if( !strncmp( path, "/dev/", 5 ) || strncmp( path, "/dev/r", 6 ) )
return (char *) strdup( path );
/* Replace "/dev/" with "/dev/r" */
new_path = malloc( strlen(path) + 2 );
strcpy( new_path, "/dev/r" );
strcat( new_path, path + strlen( "/dev/" ) );
return new_path;
}
#endif
#ifndef HAVE_MPLAYER
#include "get_path.c"
#else
extern char * get_path( char * filename );
#endif
char * dvd_key_dir = NULL;
dvd_reader_t *DVDOpen( const char *path )
{
struct stat64 fileinfo;
int ret;
char * dir;
if( !path ) return 0;
ret = stat64( path, &fileinfo );
if( ret < 0 ) {
/* If we can't stat the file, give up */
fprintf( stderr, "libdvdread: Can't stat %s\n", path );
perror("");
return 0;
}
dir=get_path( "" );
if ( dir ) { mkdir( dir,493 ); free( dir ); }
dir=get_path( "DVDKeys" );
if ( !dir ) dir=strdup( "/tmp" );
mkdir( dir,493 );
/* First check if this is a block/char device or a file*/
if( S_ISBLK( fileinfo.st_mode ) ||
S_ISCHR( fileinfo.st_mode ) ||
S_ISREG( fileinfo.st_mode ) ) {
/**
* Block devices and regular files are assumed to be DVD-Video images.
*/
// ---
char * device;
FILE * img;
char discid[16];
#if defined(__sun)
device = sun_block2char( path );
#elif defined(SYS_BSD)
device = bsd_block2char( path );
#else
device = path;
#endif
if ( (img=fopen( device,"r" )) )
{
fseek( img,0x0000832d,SEEK_SET );
fread( &discid,16,1,img );
fclose( img );
} else strcpy( discid,"tmp" );
if ( (dvd_key_dir=(char *)calloc( 1,strlen( dir ) + 17 )) == NULL ) return 0;
sprintf( dvd_key_dir,"%s/%.16s",dir,discid );
mkdir( dvd_key_dir,493 );
free( dir );
return DVDOpenImageFile( device );
// ---
} else if( S_ISDIR( fileinfo.st_mode ) ) {
dvd_reader_t *auth_drive = 0;
char *path_copy;
#if defined(SYS_BSD)
struct fstab* fe;
#elif defined(__sun) || defined(__linux__)
FILE *mntfile;
#endif
/* XXX: We should scream real loud here. */
if( !(path_copy = strdup( path ) ) ) return 0;
/* Resolve any symlinks and get the absolut dir name. */
{
char *new_path;
int cdir = open( ".", O_RDONLY );
if( cdir >= 0 ) {
chdir( path_copy );
new_path = getcwd( NULL, PATH_MAX );
fchdir( cdir );
close( cdir );
if( new_path ) {
free( path_copy );
path_copy = new_path;
}
}
}
/**
* If we're being asked to open a directory, check if that directory
* is the mountpoint for a DVD-ROM which we can use instead.
*/
if( strlen( path_copy ) > 1 ) {
if( path[ strlen( path_copy ) - 1 ] == '/' )
path_copy[ strlen( path_copy ) - 1 ] = '\0';
}
if( strlen( path_copy ) > 9 ) {
if( !strcasecmp( &(path_copy[ strlen( path_copy ) - 9 ]),
"/video_ts" ) ) {
path_copy[ strlen( path_copy ) - 9 ] = '\0';
}
}
#if defined(SYS_BSD)
if( ( fe = getfsfile( path_copy ) ) ) {
char *dev_name = bsd_block2char( fe->fs_spec );
fprintf( stderr,
"libdvdread: Attempting to use device %s"
" mounted on %s for CSS authentication\n",
dev_name,
fe->fs_file );
auth_drive = DVDOpenImageFile( dev_name );
free( dev_name );
}
#elif defined(__sun)
mntfile = fopen( MNTTAB, "r" );
if( mntfile ) {
struct mnttab mp;
int res;
while( ( res = getmntent( mntfile, &mp ) ) != -1 ) {
if( res == 0 && !strcmp( mp.mnt_mountp, path_copy ) ) {
char *dev_name = sun_block2char( mp.mnt_special );
fprintf( stderr,
"libdvdread: Attempting to use device %s"
" mounted on %s for CSS authentication\n",
dev_name,
mp.mnt_mountp );
auth_drive = DVDOpenImageFile( dev_name );
free( dev_name );
break;
}
}
fclose( mntfile );
}
#elif defined(__linux__)
mntfile = fopen( MOUNTED, "r" );
if( mntfile ) {
struct mntent *me;
while( ( me = getmntent( mntfile ) ) ) {
if( !strcmp( me->mnt_dir, path_copy ) ) {
fprintf( stderr,
"libdvdread: Attempting to use device %s"
" mounted on %s for CSS authentication\n",
me->mnt_fsname,
me->mnt_dir );
auth_drive = DVDOpenImageFile( me->mnt_fsname );
break;
}
}
fclose( mntfile );
}
#endif
if( !auth_drive ) {
fprintf( stderr, "libdvdread: Device inaccessible, "
"CSS authentication not available.\n" );
}
free( path_copy );
// ---
if ( (dvd_key_dir=(char *)calloc( 1,strlen( dir ) + 17 )) == NULL ) return 0;
sprintf( dvd_key_dir,"%s/%.16s",dir,"tmp" );
mkdir( dvd_key_dir,493 );
free( dir );
// ---
/**
* If we've opened a drive, just use that.
*/
if( auth_drive ) return auth_drive;
/**
* Otherwise, we now try to open the directory tree instead.
*/
fprintf( stderr, "libdvdread: Using normal filesystem access.\n" );
return DVDOpenPath( path );
}
/* If it's none of the above, screw it. */
fprintf( stderr, "libdvdread: Could not open %s\n", path );
return 0;
}
void DVDClose( dvd_reader_t *dvd )
{
if ( dvd_key_dir ) free( dvd_key_dir );
if( dvd ) {
if( dvd->dev ) dvdcss_close( dvd->dev );
if( dvd->fd >= 0 ) close( dvd->fd );
if( dvd->path_root ) free( dvd->path_root );
free( dvd );
dvd = 0;
}
}
/**
* Open an unencrypted file on a DVD image file.
*/
static dvd_file_t *DVDOpenFileUDF( dvd_reader_t *dvd, char *filename )
{
uint32_t start, len;
dvd_file_t *dvd_file;
start = UDFFindFile( dvd, filename, &len );
if( !start ) return 0;
dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) );
if( !dvd_file ) return 0;
dvd_file->dvd = dvd;
dvd_file->lb_start = start;
dvd_file->seek_pos = 0;
memset( dvd_file->title_fds, -1, sizeof( dvd_file->title_fds ) );
dvd_file->filesize = len / DVD_VIDEO_LB_LEN;
return dvd_file;
}
/**
* Searches for <file> in directory <path>, ignoring case.
* Returns 0 and full filename in <filename>.
* or -1 on file not found.
* or -2 on path not found.
*/
static int findDirFile( const char *path, const char *file, char *filename )
{
DIR *dir;
struct dirent *ent;
dir = opendir( path );
if( !dir ) return -2;
while( ( ent = readdir( dir ) ) != NULL ) {
if( !strcasecmp( ent->d_name, file ) ) {
sprintf( filename, "%s%s%s", path,
( ( path[ strlen( path ) - 1 ] == '/' ) ? "" : "/" ),
ent->d_name );
return 0;
}
}
return -1;
}
static int findDVDFile( dvd_reader_t *dvd, const char *file, char *filename )
{
char video_path[ PATH_MAX + 1 ];
const char *nodirfile;
int ret;
/* Strip off the directory for our search */
if( !strncasecmp( "/VIDEO_TS/", file, 10 ) ) {
nodirfile = &(file[ 10 ]);
} else {
nodirfile = file;
}
ret = findDirFile( dvd->path_root, nodirfile, filename );
if( ret < 0 ) {
/* Try also with adding the path, just in case. */
sprintf( video_path, "%s/VIDEO_TS/", dvd->path_root );
ret = findDirFile( video_path, nodirfile, filename );
if( ret < 0 ) {
/* Try with the path, but in lower case. */
sprintf( video_path, "%s/video_ts/", dvd->path_root );
ret = findDirFile( video_path, nodirfile, filename );
if( ret < 0 ) {
return 0;
}
}
}
return 1;
}
/**
* Open an unencrypted file from a DVD directory tree.
*/
static dvd_file_t *DVDOpenFilePath( dvd_reader_t *dvd, char *filename )
{
char full_path[ PATH_MAX + 1 ];
dvd_file_t *dvd_file;
struct stat fileinfo;
int fd;
/* Get the full path of the file. */
if( !findDVDFile( dvd, filename, full_path ) ) return 0;
fd = open( full_path, O_RDONLY );
if( fd < 0 ) return 0;
dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) );
if( !dvd_file ) return 0;
dvd_file->dvd = dvd;
dvd_file->lb_start = 0;
dvd_file->seek_pos = 0;
memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) );
memset( dvd_file->title_fds, -1, sizeof( dvd_file->title_fds ) );
dvd_file->filesize = 0;
if( stat( full_path, &fileinfo ) < 0 ) {
fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename );
free( dvd_file );
return 0;
}
dvd_file->title_sizes[ 0 ] = fileinfo.st_size / DVD_VIDEO_LB_LEN;
dvd_file->title_fds[ 0 ] = fd;
dvd_file->filesize = dvd_file->title_sizes[ 0 ];
return dvd_file;
}
static dvd_file_t *DVDOpenVOBUDF( dvd_reader_t *dvd,
int title, int menu )
{
char filename[ MAX_UDF_FILE_NAME_LEN ];
uint32_t start, len;
dvd_file_t *dvd_file;
if( title == 0 ) {
sprintf( filename, "/VIDEO_TS/VIDEO_TS.VOB" );
} else {
sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, menu ? 0 : 1 );
}
start = UDFFindFile( dvd, filename, &len );
if( start == 0 ) return 0;
dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) );
if( !dvd_file ) return 0;
dvd_file->dvd = dvd;
dvd_file->lb_start = start;
dvd_file->seek_pos = 0;
memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) );
memset( dvd_file->title_fds, -1, sizeof( dvd_file->title_fds ) );
dvd_file->filesize = len / DVD_VIDEO_LB_LEN;
/* Calculate the complete file size for every file in the VOBS */
if( !menu ) {
int cur;
for( cur = 2; cur < 10; cur++ ) {
sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, cur );
if( !UDFFindFile( dvd, filename, &len ) ) break;
dvd_file->filesize += len / DVD_VIDEO_LB_LEN;
}
}
/* Hack to crack all the keys on the first open. */
if( !dvd_file->dvd->init_keys ) {
initAllCSSKeys( dvd_file->dvd );
dvd_file->dvd->init_keys = 1;
}
/* Perform CSS key cracking for this title. */
if( dvdcss_title( dvd_file->dvd->dev, (int)start ) < 0 ) {
fprintf( stderr, "libdvdread: Error cracking CSS key for %s\n",
filename );
}
return dvd_file;
}
static dvd_file_t *DVDOpenVOBPath( dvd_reader_t *dvd,
int title, int menu )
{
char filename[ MAX_UDF_FILE_NAME_LEN ];
char full_path[ PATH_MAX + 1 ];
struct stat fileinfo;
dvd_file_t *dvd_file;
int i;
dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) );
if( !dvd_file ) return 0;
dvd_file->dvd = dvd;
dvd_file->lb_start = 0;
dvd_file->seek_pos = 0;
memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) );
memset( dvd_file->title_fds, -1, sizeof( dvd_file->title_fds ) );
dvd_file->filesize = 0;
if( menu ) {
int fd;
if( title == 0 ) {
sprintf( filename, "VIDEO_TS.VOB" );
} else {
sprintf( filename, "VTS_%02i_0.VOB", title );
}
if( !findDVDFile( dvd, filename, full_path ) ) {
free( dvd_file );
return 0;
}
fd = open( full_path, O_RDONLY );
if( fd < 0 ) {
free( dvd_file );
return 0;
}
if( stat( full_path, &fileinfo ) < 0 ) {
fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename );
free( dvd_file );
return 0;
}
dvd_file->title_sizes[ 0 ] = fileinfo.st_size / DVD_VIDEO_LB_LEN;
dvd_file->title_fds[ 0 ] = fd;
dvd_file->filesize = dvd_file->title_sizes[ 0 ];
} else {
for( i = 0; i < 9; ++i ) {
sprintf( filename, "VTS_%02i_%i.VOB", title, i + 1 );
if( !findDVDFile( dvd, filename, full_path ) ) {
break;
}
if( stat( full_path, &fileinfo ) < 0 ) {
fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename );
break;
}
dvd_file->title_sizes[ i ] = fileinfo.st_size / DVD_VIDEO_LB_LEN;
dvd_file->title_fds[ i ] = open( full_path, O_RDONLY );
dvd_file->filesize += dvd_file->title_sizes[ i ];
}
if( !(dvd_file->title_sizes[ 0 ]) ) {
free( dvd_file );
return 0;
}
}
return dvd_file;
}
dvd_file_t *DVDOpenFile( dvd_reader_t *dvd, int titlenum,
dvd_read_domain_t domain )
{
char filename[ MAX_UDF_FILE_NAME_LEN ];
switch( domain ) {
case DVD_READ_INFO_FILE:
if( titlenum == 0 ) {
sprintf( filename, "/VIDEO_TS/VIDEO_TS.IFO" );
} else {
sprintf( filename, "/VIDEO_TS/VTS_%02i_0.IFO", titlenum );
}
break;
case DVD_READ_INFO_BACKUP_FILE:
if( titlenum == 0 ) {
sprintf( filename, "/VIDEO_TS/VIDEO_TS.BUP" );
} else {
sprintf( filename, "/VIDEO_TS/VTS_%02i_0.BUP", titlenum );
}
break;
case DVD_READ_MENU_VOBS:
if( dvd->isImageFile ) {
return DVDOpenVOBUDF( dvd, titlenum, 1 );
} else {
return DVDOpenVOBPath( dvd, titlenum, 1 );
}
break;
case DVD_READ_TITLE_VOBS:
if( titlenum == 0 ) return 0;
if( dvd->isImageFile ) {
return DVDOpenVOBUDF( dvd, titlenum, 0 );
} else {
return DVDOpenVOBPath( dvd, titlenum, 0 );
}
break;
default:
fprintf( stderr, "libdvdread: Invalid domain for file open.\n" );
return 0;
}
if( dvd->isImageFile ) {
return DVDOpenFileUDF( dvd, filename );
} else {
return DVDOpenFilePath( dvd, filename );
}
}
void DVDCloseFile( dvd_file_t *dvd_file )
{
int i;
if( dvd_file ) {
if( !dvd_file->dvd->isImageFile ) {
for( i = 0; i < 9; ++i ) {
if( dvd_file->title_fds[ i ] >= 0 )
close( dvd_file->title_fds[ i ] );
}
}
free( dvd_file );
dvd_file = 0;
}
}
int64_t DVDReadLBUDF( dvd_reader_t *device, uint32_t lb_number,
size_t block_count, unsigned char *data,
int encrypted )
{
int ret;
if( !device->dev ) {
fprintf( stderr, "libdvdread: Fatal error in block read.\n" );
return 0;
}
ret = dvdcss_seek( device->dev, (int) lb_number );
if( ret != (int) lb_number ) {
fprintf( stderr, "libdvdread: Can't seek to block %u\n",
lb_number );
return 0;
}
return (int64_t) ( dvdcss_read( device->dev, (char *) data,
(int) block_count, encrypted )
* (uint64_t) DVD_VIDEO_LB_LEN );
}
static int64_t DVDReadBlocksUDF( dvd_file_t *dvd_file, uint32_t offset,
size_t block_count, unsigned char *data )
{
return DVDReadLBUDF( dvd_file->dvd, dvd_file->lb_start + offset,
block_count, data, DVDCSS_READ_DECRYPT );
}
static int64_t DVDReadBlocksPath( dvd_file_t *dvd_file, size_t offset,
size_t block_count, unsigned char *data )
{
int i;
ssize_t ret, ret2;
off64_t off;
ret = 0;
ret2 = 0;
for( i = 0; i < 9; ++i ) {
if( !dvd_file->title_sizes[ i ] ) return 0;
if( offset < dvd_file->title_sizes[ i ] ) {
if( ( offset + block_count ) <= dvd_file->title_sizes[ i ] ) {
off = lseek64( dvd_file->title_fds[ i ],
offset * (int64_t) DVD_VIDEO_LB_LEN, SEEK_SET );
if( off != ( offset * (int64_t) DVD_VIDEO_LB_LEN ) ) {
fprintf( stderr, "libdvdread: Can't seek to block %d\n",
offset );
return 0;
}
ret = read( dvd_file->title_fds[ i ], data,
block_count * DVD_VIDEO_LB_LEN );
break;
} else {
size_t part1_size
= ( dvd_file->title_sizes[ i ] - offset ) * DVD_VIDEO_LB_LEN;
/* FIXME: Really needs to be a while loop.
(This is only true if you try and read >1GB at a time) */
/* Read part 1 */
off = lseek64( dvd_file->title_fds[ i ],
offset * (int64_t) DVD_VIDEO_LB_LEN, SEEK_SET );
if( off != ( offset * (int64_t) DVD_VIDEO_LB_LEN ) ) {
fprintf( stderr, "libdvdread: Can't seek to block %d\n",
offset );
return 0;
}
ret = read( dvd_file->title_fds[ i ], data, part1_size );
if( ret < 0 ) return ret;
/* FIXME: This is wrong if i is the last file in the set.
also error from this read will not show in ret. */
/* Read part 2 */
lseek64( dvd_file->title_fds[ i + 1 ], (off64_t)0, SEEK_SET );
ret2 = read( dvd_file->title_fds[ i + 1 ], data + part1_size,
block_count * DVD_VIDEO_LB_LEN - part1_size );
if( ret2 < 0 ) return ret2;
break;
}
} else {
offset -= dvd_file->title_sizes[ i ];
}
}
return ( (int64_t) ret + (int64_t) ret2 );
}
/* These are broken for some cases reading more than 2Gb at a time. */
ssize_t DVDReadBlocks( dvd_file_t *dvd_file, int offset,
size_t block_count, unsigned char *data )
{
int64_t ret;
if( dvd_file->dvd->isImageFile ) {
ret = DVDReadBlocksUDF( dvd_file, (uint32_t)offset,
block_count, data );
} else {
ret = DVDReadBlocksPath( dvd_file, (size_t) offset,
block_count, data );
}
if( ret <= 0 ) {
return (ssize_t) ret;
}
{
ssize_t sret = (ssize_t) (ret / (int64_t)DVD_VIDEO_LB_LEN );
if( sret == 0 ) {
fprintf(stderr, "libdvdread: DVDReadBlocks got %d bytes\n", (int)ret );
}
return sret;
}
}
int32_t DVDFileSeek( dvd_file_t *dvd_file, int32_t offset )
{
if( dvd_file->dvd->isImageFile ) {
dvd_file->seek_pos = (uint32_t) offset;
return offset;
} else {
return (int32_t) ( lseek( dvd_file->title_fds[ 0 ],
(off_t) offset, SEEK_SET ) );
}
}
static ssize_t DVDReadBytesUDF( dvd_file_t *dvd_file, void *data,
size_t byte_size )
{
unsigned char *secbuf;
unsigned int numsec, seek_sector, seek_byte;
int64_t len;
seek_sector = dvd_file->seek_pos / DVD_VIDEO_LB_LEN;
seek_byte = dvd_file->seek_pos % DVD_VIDEO_LB_LEN;
numsec = ( ( seek_byte + byte_size ) / DVD_VIDEO_LB_LEN ) + 1;
secbuf = (unsigned char *) malloc( numsec * DVD_VIDEO_LB_LEN );
if( !secbuf ) {
fprintf( stderr, "libdvdread: Can't allocate memory "
"for file read!\n" );
return 0;
}
len = DVDReadLBUDF( dvd_file->dvd, dvd_file->lb_start + seek_sector,
numsec, secbuf, DVDCSS_NOFLAGS );
if( len != numsec * (int64_t) DVD_VIDEO_LB_LEN ) {
free( secbuf );
return 0;
}
dvd_file->seek_pos += byte_size;
memcpy( data, &(secbuf[ seek_byte ]), byte_size );
free( secbuf );
return byte_size;
}
static ssize_t DVDReadBytesPath( dvd_file_t *dvd_file, void *data,
size_t byte_size )
{
return read( dvd_file->title_fds[ 0 ], data, byte_size );
}
ssize_t DVDReadBytes( dvd_file_t *dvd_file, void *data, size_t byte_size )
{
if( dvd_file->dvd->isImageFile ) {
return DVDReadBytesUDF( dvd_file, data, byte_size );
} else {
return DVDReadBytesPath( dvd_file, data, byte_size );
}
}
ssize_t DVDFileSize( dvd_file_t *dvd_file )
{
return dvd_file->filesize;
}
--- NEW FILE ---
/**
* Copyright (C) 2001 Billy Biggs <vektor at dumbterm.net>,
* Håkan Hjort <d95hjort at 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef DVD_READER_H_INCLUDED
#define DVD_READER_H_INCLUDED
#include <sys/types.h>
#include <inttypes.h>
/**
* The length of one Logical Block of a DVD Video.
*/
#define DVD_VIDEO_LB_LEN 2048
/**
* Maximum length of filenames for UDF.
*/
#define MAX_UDF_FILE_NAME_LEN 2048
#ifdef __cplusplus
extern "C" {
#endif
typedef struct dvd_reader_s dvd_reader_t;
typedef struct dvd_file_s dvd_file_t;
/**
* Opens a block device of a DVD-ROM file, or an image file, or a directory
* name for a mounted DVD or HD copy of a DVD. Returns 0 if we can't get any
* of those methods to work.
*
* If the given file is a block device, or is the mountpoint for a block
* device, then that device is used for CSS authentication using libdvdcss.
* If no device is available, then no CSS authentication is performed,
* and we hope that the image is decrypted.
*
* If the path given is a directory, then the files in that directory may be in
* any one of these formats:
*
* path/VIDEO_TS/VTS_01_1.VOB
* path/video_ts/vts_01_1.vob
* path/VTS_01_1.VOB
* path/vts_01_1.vob
*/
dvd_reader_t *DVDOpen( const char *path );
/**
* Closes and cleans up the DVD reader object. You must close all open files
* before calling this function.
*/
void DVDClose( dvd_reader_t *dvd );
/**
* INFO_FILE : VIDEO_TS.IFO (manager)
* VTS_XX_0.IFO (title)
*
* INFO_BACKUP_FILE: VIDEO_TS.BUP (manager)
* VTS_XX_0.BUP (title)
*
* MENU_VOBS : VIDEO_TS.VOB (manager)
* VTS_XX_0.VOB (title)
*
* TITLE_VOBS : VTS_XX_[1-9].VOB (title)
* All files in the title set are opened and read as a single
* file.
*/
typedef enum {
DVD_READ_INFO_FILE,
DVD_READ_INFO_BACKUP_FILE,
DVD_READ_MENU_VOBS,
DVD_READ_TITLE_VOBS
} dvd_read_domain_t;
/**
* Opens a file on the DVD given the title number and domain. If the title
* number is 0, the video manager information is opened
* (VIDEO_TS.[IFO,BUP,VOB]). Returns a file structure which may be used for
* reads, or 0 if the file was not found.
*/
dvd_file_t *DVDOpenFile( dvd_reader_t *dvd, int titlenum,
dvd_read_domain_t domain );
/**
* Closes a file and frees the associated structure.
*/
void DVDCloseFile( dvd_file_t *dvd_file );
/**
* Reads block_count number of blocks from the file at the given block offset.
* Returns number of blocks read on success, -1 on error. This call is only
* for reading VOB data, and should not be used when reading the IFO files.
* When reading from an encrypted drive, blocks are decrypted using libdvdcss
* where required.
*/
ssize_t DVDReadBlocks( dvd_file_t *dvd_file, int offset,
size_t block_count, unsigned char *data );
/**
* Seek to the given position in the file. Returns the resulting position in
* bytes from the beginning of the file. The seek position is only used for
* byte reads from the file, the block read call always reads from the given
* offset.
*/
int DVDFileSeek( dvd_file_t *dvd_file, int offset );
/**
* Reads the given number of bytes from the file. This call can only be used
* on the information files, and may not be used for reading from a VOB. This
* reads from and increments the currrent seek position for the file.
*/
ssize_t DVDReadBytes( dvd_file_t *dvd_file, void *data, size_t byte_size );
/**
* Returns the file size in blocks.
*/
ssize_t DVDFileSize( dvd_file_t *dvd_file );
/**
* DVD CSS Key chahe dir.
*/
extern char * dvd_key_dir;
#ifdef __cplusplus
};
#endif
#endif /* DVD_READER_H_INCLUDED */
--- NEW FILE ---
/**
* This code is based on dvdudf by:
* Christian Wolff <scarabaeus at convergence.de>.
*
* Modifications by:
* Billy Biggs <vektor at dumbterm.net>.
*
* dvdudf: parse and read the UDF volume information of a DVD Video
* Copyright (C) 1999 Christian Wolff for convergence integrated media
* GmbH The author can be reached at scarabaeus at convergence.de, the
* project's page is at http://linuxtv.org/dvd/
*
* 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-1307, USA. Or, point your browser to
* http://www.gnu.org/copyleft/gpl.html
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <inttypes.h>
#include "dvd_udf.h"
extern int64_t DVDReadLBUDF( dvd_reader_t *device, uint32_t lb_number,
size_t block_count, unsigned char *data,
int encrypted );
#ifndef NULL
#define NULL ((void *)0)
#endif
struct Partition {
int valid;
char VolumeDesc[128];
uint16_t Flags;
uint16_t Number;
char Contents[32];
uint32_t AccessType;
uint32_t Start;
uint32_t Length;
};
struct AD {
uint32_t Location;
uint32_t Length;
uint8_t Flags;
uint16_t Partition;
};
/* For direct data access, LSB first */
#define GETN1(p) ((uint8_t)data[p])
#define GETN2(p) ((uint16_t)data[p] | ((uint16_t)data[(p) + 1] << 8))
#define GETN3(p) ((uint32_t)data[p] | ((uint32_t)data[(p) + 1] << 8) \
| ((uint32_t)data[(p) + 2] << 16))
#define GETN4(p) ((uint32_t)data[p] \
| ((uint32_t)data[(p) + 1] << 8) \
| ((uint32_t)data[(p) + 2] << 16) \
| ((uint32_t)data[(p) + 3] << 24))
/* This is wrong with regard to endianess */
#define GETN(p, n, target) memcpy(target, &data[p], n)
static int Unicodedecode( uint8_t *data, int len, char *target )
{
int p = 1, i = 0;
if( ( data[ 0 ] == 8 ) || ( data[ 0 ] == 16 ) ) do {
if( data[ 0 ] == 16 ) p++; /* Ignore MSB of unicode16 */
if( p < len ) {
target[ i++ ] = data[ p++ ];
}
} while( p < len );
target[ i ] = '\0';
return 0;
}
static int UDFDescriptor( uint8_t *data, uint16_t *TagID )
{
*TagID = GETN2(0);
// TODO: check CRC 'n stuff
return 0;
}
static int UDFExtentAD( uint8_t *data, uint32_t *Length, uint32_t *Location )
{
*Length = GETN4(0);
*Location = GETN4(4);
return 0;
}
static int UDFShortAD( uint8_t *data, struct AD *ad,
struct Partition *partition )
{
ad->Length = GETN4(0);
ad->Flags = ad->Length >> 30;
ad->Length &= 0x3FFFFFFF;
ad->Location = GETN4(4);
ad->Partition = partition->Number; // use number of current partition
return 0;
}
static int UDFLongAD( uint8_t *data, struct AD *ad )
{
ad->Length = GETN4(0);
ad->Flags = ad->Length >> 30;
ad->Length &= 0x3FFFFFFF;
ad->Location = GETN4(4);
ad->Partition = GETN2(8);
//GETN(10, 6, Use);
return 0;
}
static int UDFExtAD( uint8_t *data, struct AD *ad )
{
ad->Length = GETN4(0);
ad->Flags = ad->Length >> 30;
ad->Length &= 0x3FFFFFFF;
ad->Location = GETN4(12);
ad->Partition = GETN2(16);
//GETN(10, 6, Use);
return 0;
}
static int UDFICB( uint8_t *data, uint8_t *FileType, uint16_t *Flags )
{
*FileType = GETN1(11);
*Flags = GETN2(18);
return 0;
}
static int UDFPartition( uint8_t *data, uint16_t *Flags, uint16_t *Number,
char *Contents, uint32_t *Start, uint32_t *Length )
{
*Flags = GETN2(20);
*Number = GETN2(22);
GETN(24, 32, Contents);
*Start = GETN4(188);
*Length = GETN4(192);
return 0;
}
/**
* Reads the volume descriptor and checks the parameters. Returns 0 on OK, 1
* on error.
*/
static int UDFLogVolume( uint8_t *data, char *VolumeDescriptor )
{
uint32_t lbsize, MT_L, N_PM;
Unicodedecode(&data[84], 128, VolumeDescriptor);
lbsize = GETN4(212); // should be 2048
MT_L = GETN4(264); // should be 6
N_PM = GETN4(268); // should be 1
if (lbsize != DVD_VIDEO_LB_LEN) return 1;
return 0;
}
static int UDFFileEntry( uint8_t *data, uint8_t *FileType,
struct Partition *partition, struct AD *ad )
{
uint16_t flags;
uint32_t L_EA, L_AD;
unsigned int p;
UDFICB( &data[ 16 ], FileType, &flags );
/* Init ad for an empty file (i.e. there isn't a AD, L_AD == 0 ) */
ad->Length = GETN4( 60 ); // Really 8 bytes a 56
ad->Flags = 0;
ad->Location = 0; // what should we put here?
ad->Partition = partition->Number; // use number of current partition
L_EA = GETN4( 168 );
L_AD = GETN4( 172 );
p = 176 + L_EA;
while( p < 176 + L_EA + L_AD ) {
switch( flags & 0x0007 ) {
case 0: UDFShortAD( &data[ p ], ad, partition ); p += 8; break;
case 1: UDFLongAD( &data[ p ], ad ); p += 16; break;
case 2: UDFExtAD( &data[ p ], ad ); p += 20; break;
case 3:
switch( L_AD ) {
case 8: UDFShortAD( &data[ p ], ad, partition ); break;
case 16: UDFLongAD( &data[ p ], ad ); break;
case 20: UDFExtAD( &data[ p ], ad ); break;
}
p += L_AD;
break;
default:
p += L_AD; break;
}
}
return 0;
}
static int UDFFileIdentifier( uint8_t *data, uint8_t *FileCharacteristics,
char *FileName, struct AD *FileICB )
{
uint8_t L_FI;
uint16_t L_IU;
*FileCharacteristics = GETN1(18);
L_FI = GETN1(19);
UDFLongAD(&data[20], FileICB);
L_IU = GETN2(36);
if (L_FI) Unicodedecode(&data[38 + L_IU], L_FI, FileName);
else FileName[0] = '\0';
return 4 * ((38 + L_FI + L_IU + 3) / 4);
}
/**
* Maps ICB to FileAD
* ICB: Location of ICB of directory to scan
* FileType: Type of the file
* File: Location of file the ICB is pointing to
* return 1 on success, 0 on error;
*/
static int UDFMapICB( dvd_reader_t *device, struct AD ICB, uint8_t *FileType,
struct Partition *partition, struct AD *File )
{
uint8_t LogBlock[DVD_VIDEO_LB_LEN];
uint32_t lbnum;
uint16_t TagID;
lbnum = partition->Start + ICB.Location;
do {
if( DVDReadLBUDF( device, lbnum++, 1, LogBlock, 0 ) <= 0 ) {
TagID = 0;
} else {
UDFDescriptor( LogBlock, &TagID );
}
if( TagID == 261 ) {
UDFFileEntry( LogBlock, FileType, partition, File );
return 1;
};
} while( ( lbnum <= partition->Start + ICB.Location + ( ICB.Length - 1 )
/ DVD_VIDEO_LB_LEN ) && ( TagID != 261 ) );
return 0;
}
/**
* Dir: Location of directory to scan
* FileName: Name of file to look for
* FileICB: Location of ICB of the found file
* return 1 on success, 0 on error;
*/
static int UDFScanDir( dvd_reader_t *device, struct AD Dir, char *FileName,
struct Partition *partition, struct AD *FileICB )
{
char filename[ MAX_UDF_FILE_NAME_LEN ];
uint8_t directory[ 2 * DVD_VIDEO_LB_LEN ];
uint32_t lbnum;
uint16_t TagID;
uint8_t filechar;
unsigned int p;
/* Scan dir for ICB of file */
lbnum = partition->Start + Dir.Location;
if( DVDReadLBUDF( device, lbnum, 2, directory, 0 ) <= 0 ) {
return 0;
}
p = 0;
while( p < Dir.Length ) {
if( p > DVD_VIDEO_LB_LEN ) {
++lbnum;
p -= DVD_VIDEO_LB_LEN;
Dir.Length -= DVD_VIDEO_LB_LEN;
if( DVDReadLBUDF( device, lbnum, 2, directory, 0 ) <= 0 ) {
return 0;
}
}
UDFDescriptor( &directory[ p ], &TagID );
if( TagID == 257 ) {
p += UDFFileIdentifier( &directory[ p ], &filechar,
filename, FileICB );
if( !strcasecmp( FileName, filename ) ) {
return 1;
}
} else {
return 0;
}
}
return 0;
}
/**
* Looks for partition on the disc. Returns 1 if partition found, 0 on error.
* partnum: Number of the partition, starting at 0.
* part: structure to fill with the partition information
*/
static int UDFFindPartition( dvd_reader_t *device, int partnum,
struct Partition *part )
{
uint8_t LogBlock[ DVD_VIDEO_LB_LEN ], Anchor[ DVD_VIDEO_LB_LEN ];
uint32_t lbnum, MVDS_location, MVDS_length;
uint16_t TagID;
uint32_t lastsector;
int i, terminate, volvalid;
/* Find Anchor */
lastsector = 0;
lbnum = 256; /* Try #1, prime anchor */
terminate = 0;
for(;;) {
if( DVDReadLBUDF( device, lbnum, 1, Anchor, 0 ) > 0 ) {
UDFDescriptor( Anchor, &TagID );
} else {
TagID = 0;
}
if (TagID != 2) {
/* Not an anchor */
if( terminate ) return 0; /* Final try failed */
if( lastsector ) {
/* We already found the last sector. Try #3, alternative
* backup anchor. If that fails, don't try again.
*/
lbnum = lastsector;
terminate = 1;
} else {
/* TODO: Find last sector of the disc (this is optional). */
if( lastsector ) {
/* Try #2, backup anchor */
lbnum = lastsector - 256;
} else {
/* Unable to find last sector */
return 0;
}
}
} else {
/* It's an anchor! We can leave */
break;
}
}
/* Main volume descriptor */
UDFExtentAD( &Anchor[ 16 ], &MVDS_length, &MVDS_location );
part->valid = 0;
volvalid = 0;
part->VolumeDesc[ 0 ] = '\0';
i = 1;
do {
/* Find Volume Descriptor */
lbnum = MVDS_location;
do {
if( DVDReadLBUDF( device, lbnum++, 1, LogBlock, 0 ) <= 0 ) {
TagID = 0;
} else {
UDFDescriptor( LogBlock, &TagID );
}
if( ( TagID == 5 ) && ( !part->valid ) ) {
/* Partition Descriptor */
UDFPartition( LogBlock, &part->Flags, &part->Number,
part->Contents, &part->Start, &part->Length );
part->valid = ( partnum == part->Number );
} else if( ( TagID == 6 ) && ( !volvalid ) ) {
/* Logical Volume Descriptor */
if( UDFLogVolume( LogBlock, part->VolumeDesc ) ) {
/* TODO: sector size wrong! */
} else {
volvalid = 1;
}
}
} while( ( lbnum <= MVDS_location + ( MVDS_length - 1 )
/ DVD_VIDEO_LB_LEN ) && ( TagID != 8 )
&& ( ( !part->valid ) || ( !volvalid ) ) );
if( ( !part->valid) || ( !volvalid ) ) {
/* Backup volume descriptor */
UDFExtentAD( &Anchor[ 24 ], &MVDS_length, &MVDS_location );
}
} while( i-- && ( ( !part->valid ) || ( !volvalid ) ) );
/* We only care for the partition, not the volume */
return part->valid;
}
uint32_t UDFFindFile( dvd_reader_t *device, char *filename,
uint32_t *filesize )
{
uint8_t LogBlock[ DVD_VIDEO_LB_LEN ];
uint32_t lbnum;
uint16_t TagID;
struct Partition partition;
struct AD RootICB, File, ICB;
char tokenline[ MAX_UDF_FILE_NAME_LEN ];
char *token;
uint8_t filetype;
*filesize = 0;
tokenline[0] = '\0';
strcat( tokenline, filename );
/* Find partition, 0 is the standard location for DVD Video.*/
if( !UDFFindPartition( device, 0, &partition ) ) return 0;
/* Find root dir ICB */
lbnum = partition.Start;
do {
if( DVDReadLBUDF( device, lbnum++, 1, LogBlock, 0 ) <= 0 ) {
TagID = 0;
} else {
UDFDescriptor( LogBlock, &TagID );
}
/* File Set Descriptor */
if( TagID == 256 ) { // File Set Descriptor
UDFLongAD( &LogBlock[ 400 ], &RootICB );
}
} while( ( lbnum < partition.Start + partition.Length )
&& ( TagID != 8 ) && ( TagID != 256 ) );
/* Sanity checks. */
if( TagID != 256 ) return 0;
if( RootICB.Partition != 0 ) return 0;
/* Find root dir */
if( !UDFMapICB( device, RootICB, &filetype, &partition, &File ) ) return 0;
if( filetype != 4 ) return 0; /* Root dir should be dir */
/* Tokenize filepath */
token = strtok(tokenline, "/");
while( token != NULL ) {
if( !UDFScanDir( device, File, token, &partition, &ICB ) ) return 0;
if( !UDFMapICB( device, ICB, &filetype, &partition, &File ) ) return 0;
token = strtok( NULL, "/" );
}
/* Sanity check. */
if( File.Partition != 0 ) return 0;
*filesize = File.Length;
/* Hack to not return partition.Start for empty files. */
if( !File.Location )
return 0;
else
return partition.Start + File.Location;
}
--- NEW FILE ---
/**
* This code is based on dvdudf by:
* Christian Wolff <scarabaeus at convergence.de>.
*
* Modifications by:
* Billy Biggs <vektor at dumbterm.net>.
*
* dvdudf: parse and read the UDF volume information of a DVD Video
* Copyright (C) 1999 Christian Wolff for convergence integrated media
* GmbH The author can be reached at scarabaeus at convergence.de, the
* project's page is at http://linuxtv.org/dvd/
*
* 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-1307, USA. Or, point your browser to
* http://www.gnu.org/copyleft/gpl.html
*/
#ifndef DVD_UDF_H_INCLUDED
#define DVD_UDF_H_INCLUDED
#include "dvd_reader.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* Looks for a file on the UDF disc/imagefile and returns the block number
* where it begins, or 0 if it is not found. The filename should be an
* absolute pathname on the UDF filesystem, starting with '/'. For example,
* '/VIDEO_TS/VTS_01_1.IFO'. On success, filesize will be set to the size of
* the file in bytes.
*/
uint32_t UDFFindFile( dvd_reader_t *device, char *filename, uint32_t *size );
#ifdef __cplusplus
};
#endif
#endif /* DVD_UDF_H_INCLUDED */
--- NEW FILE ---
/*****************************************************************************
* libdvdcss.h: DVD reading library, exported functions.
*****************************************************************************
* Copyright (C) 1998-2001 VideoLAN
* $Id: dvdcss.h,v 1.1 2002/04/24 19:28:03 arpi Exp $
*
* Authors: Stéphane Borel <stef at via.ecp.fr>
* Samuel Hocevar <sam at 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
*****************************************************************************/
typedef struct dvdcss_s* dvdcss_handle;
/*****************************************************************************
* Flags
*****************************************************************************/
#define DVDCSS_NOFLAGS 0
#define DVDCSS_INIT_QUIET (1 << 0)
#define DVDCSS_INIT_DEBUG (1 << 1)
#define DVDCSS_READ_DECRYPT (1 << 0)
#define DVDCSS_BLOCK_SIZE 2048
/*****************************************************************************
* Exported prototypes
*****************************************************************************/
extern dvdcss_handle dvdcss_open ( char *psz_target, int i_flags );
extern int dvdcss_close ( dvdcss_handle );
extern int dvdcss_title ( dvdcss_handle, int i_block );
extern int dvdcss_seek ( dvdcss_handle, int i_blocks );
extern int dvdcss_read ( dvdcss_handle, void *p_buffer, int i_blocks, int i_flags );
extern int dvdcss_readv ( dvdcss_handle, void *p_iovec, int i_blocks, int i_flags );
extern char * dvdcss_error ( dvdcss_handle );
--- NEW FILE ---
static char *get_path(char *filename){
char *homedir;
char *buff;
static char *config_dir = "/.mplayer";
int len;
if ((homedir = getenv("HOME")) == NULL)
return NULL;
len = strlen(homedir) + strlen(config_dir) + 1;
if (filename == NULL) {
if ((buff = (char *) malloc(len)) == NULL)
return NULL;
sprintf(buff, "%s%s", homedir, config_dir);
} else {
len += strlen(filename) + 1;
if ((buff = (char *) malloc(len)) == NULL)
return NULL;
sprintf(buff, "%s%s/%s", homedir, config_dir, filename);
}
// mp_msg(MSGT_GLOBAL,MSGL_V,"get_path('%s') -> '%s'\n",filename,buff);
return buff;
}
--- NEW FILE ---
/*
* Copyright (C) 2000 Björn Englund <d4bjorn at dtek.chalmers.se>,
* Håkan Hjort <d95hjort at 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-1307 USA
*/
[...1009 lines suppressed...]
printf("\nVideo Title Set Menu VOBU address map\n");
printf( "-----------------\n");
if(ifohandle->menu_vobu_admap) {
ifoPrint_VOBU_ADMAP(ifohandle->menu_vobu_admap);
} else {
printf("No Menu VOBU address map present\n");
}
printf("\nCell Adress table\n");
printf( "-----------------\n");
ifoPrint_C_ADT(ifohandle->vts_c_adt);
printf("\nVideo Title Set VOBU address map\n");
printf( "-----------------\n");
ifoPrint_VOBU_ADMAP(ifohandle->vts_vobu_admap);
}
ifoClose(ifohandle);
}
--- NEW FILE ---
/**
* Copyright (C) 2000 Björn Englund <d4bjorn at dtek.chalmers.se>,
* Håkan Hjort <d95hjort at 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-1307 USA
*/
#ifndef IFO_PRINT_H_INCLUDED
#define IFO_PRINT_H_INCLUDED
#include <dvdread/ifo_types.h>
#include <dvdread/dvd_reader.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* This file provides example functions for printing information about the IFO
* file to stdout.
*/
/**
* Print the complete parsing information for the given file.
*/
void ifoPrint(dvd_reader_t *dvd, int title);
void ifoPrint_VMGI_MAT(vmgi_mat_t *vmgi_mat);
void ifoPrint_VTSI_MAT(vtsi_mat_t *vtsi_mat);
void ifoPrint_PTL_MAIT(ptl_mait_t *ptl_mait);
void ifoPrint_VTS_ATRT(vts_atrt_t *vts_atrt);
void ifoPrint_TT_SRPT(tt_srpt_t *vmg_ptt_srpt);
void ifoPrint_VTS_PTT_SRPT(vts_ptt_srpt_t *vts_ptt_srpt);
void ifoPrint_PGC(pgc_t *pgc);
void ifoPrint_PGCIT(pgcit_t *pgcit);
void ifoPrint_PGCI_UT(pgci_ut_t *pgci_ut);
void ifoPrint_C_ADT(c_adt_t *c_adt);
void ifoPrint_VOBU_ADMAP(vobu_admap_t *vobu_admap);
#ifdef __cplusplus
};
#endif
#endif /* IFO_PRINT_H_INCLUDED */
--- NEW FILE ---
/*
* Copyright (C) 2000 Björn Englund <d4bjorn at dtek.chalmers.se>,
* Håkan Hjort <d95hjort at 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-1307 USA
*/
[...1743 lines suppressed...]
fprintf(stderr, "libdvdread: Unable to read TXTDT_MGI.\n");
free(txtdt_mgi);
ifofile->txtdt_mgi = 0;
return 0;
}
// fprintf(stderr, "-- Not done yet --\n");
return 1;
}
void ifoFree_TXTDT_MGI(ifo_handle_t *ifofile) {
if(!ifofile)
return;
if(ifofile->txtdt_mgi) {
free(ifofile->txtdt_mgi);
ifofile->txtdt_mgi = 0;
}
}
--- NEW FILE ---
/**
* Copyright (C) 2000 Björn Englund <d4bjorn at dtek.chalmers.se>,
* Håkan Hjort <d95hjort at 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-1307 USA
*/
#ifndef IFO_READ_H_INCLUDED
#define IFO_READ_H_INCLUDED
#include <dvdread/ifo_types.h>
#include <dvdread/dvd_reader.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* Opens an IFO and reads in all the data for the IFO file corresponding to the
* given title. If title 0 is given, the video manager IFO file is read.
* Returns a handle to a completely parsed structure.
*/
ifo_handle_t *ifoOpen(dvd_reader_t *dvd, int title);
/**
* Opens an IFO and reads in _only_ the vmgi_mat data. This call can be used
* together with the calls below to read in each segment of the IFO file on
* demand.
*/
ifo_handle_t *ifoOpenVMGI(dvd_reader_t *dvd);
/**
* Opens an IFO and reads in _only_ the vtsi_mat data. This call can be used
* together with the calls below to read in each segment of the IFO file on
* demand.
*/
ifo_handle_t *ifoOpenVTSI(dvd_reader_t *dvd, int title);
/**
* Cleans up the IFO information. This will free all data allocated for the
* substructures.
*/
void ifoClose(ifo_handle_t *ifofile);
/**
* The following functions are for reading only part of the VMGI/VTSI files.
* Returns 1 if the data was successfully read and 0 on error.
*/
/**
* Read in the Parental Management Information table, filling the
* ifofile->ptl_mait structure and its substructures. This data is only
* located in the video manager information file. This fills the
* ifofile->ptl_mait structure and all its substructures.
*/
int ifoRead_PTL_MAIT(ifo_handle_t *ifofile);
/**
* Read in the attribute table for the main menu vob, filling the
* ifofile->vts_atrt structure and its substructures. Only located in the
* video manager information file. This fills in the ifofile->vts_atrt
* structure and all its substructures.
*/
int ifoRead_VTS_ATRT(ifo_handle_t *ifofile);
/**
* Reads the title info for the main menu, filling the ifofile->tt_srpt
* structure and its substructures. This data is only located in the video
* manager information file. This structure is mandatory in the IFO file.
*/
int ifoRead_TT_SRPT(ifo_handle_t *ifofile);
/**
* Reads in the part of title search pointer table, filling the
* ifofile->vts_ptt_srpt structure and its substructures. This data is only
* located in the video title set information file. This structure is
* mandatory, and must be included in the VTSI file.
*/
int ifoRead_VTS_PTT_SRPT(ifo_handle_t *ifofile);
/**
* Reads in the first play program chain data, filling the
* ifofile->first_play_pgc structure. This data is only located in the video
* manager information file. This structure is mandatory, and must be included
* in the VMGI file.
*/
int ifoRead_FP_PGC(ifo_handle_t *ifofile);
/**
* Reads in the program chain information table for the video title set. Fills
* in the ifofile->vts_pgcit structure and its substructures, which includes
* the data for each program chain in the set. This data is only located in
* the video title set information file. This structure is mandatory, and must
* be included in the VTSI file.
*/
int ifoRead_PGCIT(ifo_handle_t *ifofile);
/**
* Reads in the menu PGCI unit table for the menu VOB. For the video manager,
* this corresponds to the VIDEO_TS.VOB file, and for each title set, this
* corresponds to the VTS_XX_0.VOB file. This data is located in both the
* video manager and video title set information files. For VMGI files, this
* fills the ifofile->vmgi_pgci_ut structure and all its substructures. For
* VTSI files, this fills the ifofile->vtsm_pgci_ut structure.
*/
int ifoRead_PGCI_UT(ifo_handle_t *ifofile);
/**
* Reads in the cell address table for the menu VOB. For the video manager,
* this corresponds to the VIDEO_TS.VOB file, and for each title set, this
* corresponds to the VTS_XX_0.VOB file. This data is located in both the
* video manager and video title set information files. For VMGI files, this
* fills the ifofile->vmgm_c_adt structure and all its substructures. For VTSI
* files, this fills the ifofile->vtsm_c_adt structure.
*/
int ifoRead_C_ADT(ifo_handle_t *ifofile);
/**
* Reads in the cell address table for the video title set corresponding to
* this IFO file. This data is only located in the video title set information
* file. This structure is mandatory, and must be included in the VTSI file.
* This call fills the ifofile->vts_c_adt structure and its substructures.
*/
int ifoRead_TITLE_C_ADT(ifo_handle_t *ifofile);
/**
* Reads in the VOBU address map for the menu VOB. For the video manager, this
* corresponds to the VIDEO_TS.VOB file, and for each title set, this
* corresponds to the VTS_XX_0.VOB file. This data is located in both the
* video manager and video title set information files. For VMGI files, this
* fills the ifofile->vmgm_vobu_admap structure and all its substructures. For
* VTSI files, this fills the ifofile->vtsm_vobu_admap structure.
*/
int ifoRead_VOBU_ADMAP(ifo_handle_t *ifofile);
/**
* Reads in the VOBU address map for the associated video title set. This data
* is only located in the video title set information file. This structure is
* mandatory, and must be included in the VTSI file. Fills the
* ifofile->vts_vobu_admap structure and its substructures.
*/
int ifoRead_TITLE_VOBU_ADMAP(ifo_handle_t *ifofile);
/**
* Reads in the text data strings for the DVD. Fills the ifofile->txtdt_mgi
* structure and all its substructures. This data is only located in the video
* manager information file. This structure is mandatory, and must be included
* in the VMGI file.
*/
int ifoRead_TXTDT_MGI(ifo_handle_t *ifofile);
/**
* The following functions are used for freeing parsed sections of the
* ifo_handle_t structure and the allocated substructures. The free calls
* below are safe: they will not mind if you attempt to free part of an IFO
* file which was not read in or which does not exist.
*/
void ifoFree_PTL_MAIT(ifo_handle_t *ifofile);
void ifoFree_VTS_ATRT(ifo_handle_t *ifofile);
void ifoFree_TT_SRPT(ifo_handle_t *ifofile);
void ifoFree_VTS_PTT_SRPT(ifo_handle_t *ifofile);
void ifoFree_FP_PGC(ifo_handle_t *ifofile);
void ifoFree_PGCIT(ifo_handle_t *ifofile);
void ifoFree_PGCI_UT(ifo_handle_t *ifofile);
void ifoFree_C_ADT(ifo_handle_t *ifofile);
void ifoFree_TITLE_C_ADT(ifo_handle_t *ifofile);
void ifoFree_VOBU_ADMAP(ifo_handle_t *ifofile);
void ifoFree_TITLE_VOBU_ADMAP(ifo_handle_t *ifofile);
void ifoFree_TXTDT_MGI(ifo_handle_t *ifofile);
#ifdef __cplusplus
};
#endif
#endif /* IFO_READ_H_INCLUDED */
--- NEW FILE ---
/**
* Copyright (C) 2000 Björn Englund <d4bjorn at dtek.chalmers.se>,
* Håkan Hjort <d95hjort at 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-1307 USA
*/
#ifndef IFO_TYPES_H_INCLUDED
#define IFO_TYPES_H_INCLUDED
#include <inttypes.h>
#include <dvdread/dvd_reader.h>
#undef ATTRIBUTE_PACKED
#undef PRAGMA_PACK_BEGIN
#undef PRAGMA_PACK_END
#if defined(__GNUC__)
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)
#define ATTRIBUTE_PACKED __attribute__ ((packed))
#define PRAGMA_PACK 0
#endif
#endif
#if !defined(ATTRIBUTE_PACKED)
#define ATTRIBUTE_PACKED
#define PRAGMA_PACK 1
#endif
#if PRAGMA_PACK
#pragma pack(1)
#endif
/**
* Common
*
* The following structures are used in both the VMGI and VTSI.
*/
/**
* DVD Time Information.
*/
typedef struct {
uint8_t hour;
uint8_t minute;
uint8_t second;
uint8_t frame_u; // The two high bits are the frame rate.
} ATTRIBUTE_PACKED dvd_time_t;
/**
* Type to store per-command data.
*/
typedef struct {
uint8_t bytes[8];
} ATTRIBUTE_PACKED vm_cmd_t;
#define COMMAND_DATA_SIZE 8
/**
* Video Attributes.
*/
typedef struct {
#ifdef WORDS_BIGENDIAN
unsigned int mpeg_version : 2;
unsigned int video_format : 2;
unsigned int display_aspect_ratio : 2;
unsigned int permitted_df : 2;
unsigned int line21_cc_1 : 1;
unsigned int line21_cc_2 : 1;
unsigned int unknown1 : 2;
unsigned int picture_size : 2;
unsigned int letterboxed : 1;
unsigned int film_mode : 1;
#else
unsigned int permitted_df : 2;
unsigned int display_aspect_ratio : 2;
unsigned int video_format : 2;
unsigned int mpeg_version : 2;
unsigned int film_mode : 1;
unsigned int letterboxed : 1;
unsigned int picture_size : 2;
unsigned int unknown1 : 2;
unsigned int line21_cc_2 : 1;
unsigned int line21_cc_1 : 1;
#endif
} ATTRIBUTE_PACKED video_attr_t;
/**
* Audio Attributes. (Incomplete/Wrong?)
*/
typedef struct {
#ifdef WORDS_BIGENDIAN
unsigned int audio_format : 3;
unsigned int multichannel_extension : 1;
unsigned int lang_type : 2;
unsigned int application_mode : 2;
unsigned int quantization : 2;
unsigned int sample_frequency : 2;
unsigned int unknown1 : 1;
unsigned int channels : 3;
#else
unsigned int application_mode : 2;
unsigned int lang_type : 2;
unsigned int multichannel_extension : 1;
unsigned int audio_format : 3;
unsigned int channels : 3;
unsigned int unknown1 : 1;
unsigned int sample_frequency : 2;
unsigned int quantization : 2;
#endif
uint16_t lang_code;
uint8_t lang_code2; // ??
uint8_t lang_extension;
uint16_t unknown2;
} ATTRIBUTE_PACKED audio_attr_t;
/**
* Subpicture Attributes.(Incomplete/Wrong)
*/
typedef struct {
/*
* type: 0 not specified
* 1 language
* 2 other
* coding mode: 0 run length
* 1 extended
* 2 other
* language: indicates language if type == 1
* lang extension: if type == 1 contains the lang extension
*/
uint8_t type;
uint8_t zero1;
uint16_t lang_code;
uint8_t lang_extension;
uint8_t zero2;
} ATTRIBUTE_PACKED subp_attr_t;
/**
* PGC Command Table.
*/
typedef struct {
uint16_t nr_of_pre;
uint16_t nr_of_post;
uint16_t nr_of_cell;
uint16_t zero_1;
vm_cmd_t *pre_cmds;
vm_cmd_t *post_cmds;
vm_cmd_t *cell_cmds;
} ATTRIBUTE_PACKED pgc_command_tbl_t;
#define PGC_COMMAND_TBL_SIZE 8
/**
* PGC Program Map
*/
typedef uint8_t pgc_program_map_t;
/**
* Cell Playback Information.
*/
typedef struct {
#ifdef WORDS_BIGENDIAN
unsigned int block_mode : 2;
unsigned int block_type : 2;
unsigned int seamless_play : 1;
unsigned int interleaved : 1;
unsigned int stc_discontinuity: 1;
unsigned int seamless_angle : 1;
unsigned int unknown1 : 1;
unsigned int restricted : 1;
unsigned int unknown2 : 6;
#else
unsigned int seamless_angle : 1;
unsigned int stc_discontinuity: 1;
unsigned int interleaved : 1;
unsigned int seamless_play : 1;
unsigned int block_type : 2;
unsigned int block_mode : 2;
unsigned int unknown2 : 6;
unsigned int restricted : 1;
unsigned int unknown1 : 1;
#endif
uint8_t still_time;
uint8_t cell_cmd_nr;
dvd_time_t playback_time;
uint32_t first_sector;
uint32_t first_ilvu_end_sector;
uint32_t last_vobu_start_sector;
uint32_t last_sector;
} ATTRIBUTE_PACKED cell_playback_t;
#define BLOCK_TYPE_NONE 0x0
#define BLOCK_TYPE_ANGLE_BLOCK 0x1
#define BLOCK_MODE_NOT_IN_BLOCK 0x0
#define BLOCK_MODE_FIRST_CELL 0x1
#define BLOCK_MODE_IN_BLOCK 0x2
#define BLOCK_MODE_LAST_CELL 0x3
/**
* Cell Position Information.
*/
typedef struct {
uint16_t vob_id_nr;
uint8_t zero_1;
uint8_t cell_nr;
} ATTRIBUTE_PACKED cell_position_t;
/**
* User Operations.
*/
typedef struct {
#ifdef WORDS_BIGENDIAN
unsigned int zero : 7; // 25-31
unsigned int video_pres_mode_change : 1; // 24
unsigned int karaoke_audio_pres_mode_change : 1; // 23
unsigned int angle_change : 1; // 22
unsigned int subpic_stream_change : 1; // 21
unsigned int audio_stream_change : 1; // 20
unsigned int pause_on : 1; // 19
unsigned int still_off : 1; // 18
unsigned int button_select_or_activate : 1; // 17
unsigned int resume : 1; // 16
unsigned int chapter_menu_call : 1; // 15
unsigned int angle_menu_call : 1; // 14
unsigned int audio_menu_call : 1; // 13
unsigned int subpic_menu_call : 1; // 12
unsigned int root_menu_call : 1; // 11
unsigned int title_menu_call : 1; // 10
unsigned int backward_scan : 1; // 9
unsigned int forward_scan : 1; // 8
unsigned int next_pg_search : 1; // 7
unsigned int prev_or_top_pg_search : 1; // 6
unsigned int time_or_chapter_search : 1; // 5
unsigned int go_up : 1; // 4
unsigned int stop : 1; // 3
unsigned int title_play : 1; // 2
unsigned int chapter_search_or_play : 1; // 1
unsigned int title_or_time_play : 1; // 0
#else
unsigned int video_pres_mode_change : 1; // 24
unsigned int zero : 7; // 25-31
unsigned int resume : 1; // 16
unsigned int button_select_or_activate : 1; // 17
unsigned int still_off : 1; // 18
unsigned int pause_on : 1; // 19
unsigned int audio_stream_change : 1; // 20
unsigned int subpic_stream_change : 1; // 21
unsigned int angle_change : 1; // 22
unsigned int karaoke_audio_pres_mode_change : 1; // 23
unsigned int forward_scan : 1; // 8
unsigned int backward_scan : 1; // 9
unsigned int title_menu_call : 1; // 10
unsigned int root_menu_call : 1; // 11
unsigned int subpic_menu_call : 1; // 12
unsigned int audio_menu_call : 1; // 13
unsigned int angle_menu_call : 1; // 14
unsigned int chapter_menu_call : 1; // 15
unsigned int title_or_time_play : 1; // 0
unsigned int chapter_search_or_play : 1; // 1
unsigned int title_play : 1; // 2
unsigned int stop : 1; // 3
unsigned int go_up : 1; // 4
unsigned int time_or_chapter_search : 1; // 5
unsigned int prev_or_top_pg_search : 1; // 6
unsigned int next_pg_search : 1; // 7
#endif
} ATTRIBUTE_PACKED user_ops_t;
/**
* Program Chain Information.
*/
typedef struct {
uint16_t zero_1;
uint8_t nr_of_programs;
uint8_t nr_of_cells;
dvd_time_t playback_time;
user_ops_t prohibited_ops;
uint16_t audio_control[8]; /* New type? */
uint32_t subp_control[32]; /* New type? */
uint16_t next_pgc_nr;
uint16_t prev_pgc_nr;
uint16_t goup_pgc_nr;
uint8_t still_time;
uint8_t pg_playback_mode;
uint32_t palette[16]; /* New type struct {zero_1, Y, Cr, Cb} ? */
uint16_t command_tbl_offset;
uint16_t program_map_offset;
uint16_t cell_playback_offset;
uint16_t cell_position_offset;
pgc_command_tbl_t *command_tbl;
pgc_program_map_t *program_map;
cell_playback_t *cell_playback;
cell_position_t *cell_position;
} ATTRIBUTE_PACKED pgc_t;
#define PGC_SIZE 236
/**
* Program Chain Information Search Pointer.
*/
typedef struct {
uint8_t entry_id;
#ifdef WORDS_BIGENDIAN
unsigned int block_mode : 2;
unsigned int block_type : 2;
unsigned int unknown1 : 4;
#else
unsigned int unknown1 : 4;
unsigned int block_type : 2;
unsigned int block_mode : 2;
#endif
uint16_t ptl_id_mask;
uint32_t pgc_start_byte;
pgc_t *pgc;
} ATTRIBUTE_PACKED pgci_srp_t;
#define PGCI_SRP_SIZE 8
/**
* Program Chain Information Table.
*/
typedef struct {
uint16_t nr_of_pgci_srp;
uint16_t zero_1;
uint32_t last_byte;
pgci_srp_t *pgci_srp;
} ATTRIBUTE_PACKED pgcit_t;
#define PGCIT_SIZE 8
/**
* Menu PGCI Language Unit.
*/
typedef struct {
uint16_t lang_code;
uint8_t zero_1;
uint8_t exists;
uint32_t lang_start_byte;
pgcit_t *pgcit;
} ATTRIBUTE_PACKED pgci_lu_t;
#define PGCI_LU_SIZE 8
/**
* Menu PGCI Unit Table.
*/
typedef struct {
uint16_t nr_of_lus;
uint16_t zero_1;
uint32_t last_byte;
pgci_lu_t *lu;
} ATTRIBUTE_PACKED pgci_ut_t;
#define PGCI_UT_SIZE 8
/**
* Cell Address Information.
*/
typedef struct {
uint16_t vob_id;
uint8_t cell_id;
uint8_t zero_1;
uint32_t start_sector;
uint32_t last_sector;
} ATTRIBUTE_PACKED cell_adr_t;
/**
* Cell Address Table.
*/
typedef struct {
uint16_t nr_of_vobs; /* VOBs */
uint16_t zero_1;
uint32_t last_byte;
cell_adr_t *cell_adr_table;
} ATTRIBUTE_PACKED c_adt_t;
#define C_ADT_SIZE 8
/**
* VOBU Address Map.
*/
typedef struct {
uint32_t last_byte;
uint32_t *vobu_start_sectors;
} ATTRIBUTE_PACKED vobu_admap_t;
#define VOBU_ADMAP_SIZE 4
/**
* VMGI
*
* The following structures relate to the Video Manager.
*/
/**
* Video Manager Information Management Table.
*/
typedef struct {
char vmg_identifier[12];
uint32_t vmg_last_sector;
uint8_t zero_1[12];
uint32_t vmgi_last_sector;
uint8_t zero_2;
uint8_t specification_version;
uint32_t vmg_category;
uint16_t vmg_nr_of_volumes;
uint16_t vmg_this_volume_nr;
uint8_t disc_side;
uint8_t zero_3[19];
uint16_t vmg_nr_of_title_sets; /* Number of VTSs. */
char provider_identifier[32];
uint64_t vmg_pos_code;
uint8_t zero_4[24];
uint32_t vmgi_last_byte;
uint32_t first_play_pgc;
uint8_t zero_5[56];
uint32_t vmgm_vobs; /* sector */
uint32_t tt_srpt; /* sector */
uint32_t vmgm_pgci_ut; /* sector */
uint32_t ptl_mait; /* sector */
uint32_t vts_atrt; /* sector */
uint32_t txtdt_mgi; /* sector */
uint32_t vmgm_c_adt; /* sector */
uint32_t vmgm_vobu_admap; /* sector */
uint8_t zero_6[32];
video_attr_t vmgm_video_attr;
uint8_t zero_7;
uint8_t nr_of_vmgm_audio_streams; // should be 0 or 1
audio_attr_t vmgm_audio_attr;
audio_attr_t zero_8[7];
uint8_t zero_9[17];
uint8_t nr_of_vmgm_subp_streams; // should be 0 or 1
subp_attr_t vmgm_subp_attr;
subp_attr_t zero_10[27]; /* XXX: how much 'padding' here? */
} ATTRIBUTE_PACKED vmgi_mat_t;
typedef struct {
#ifdef WORDS_BIGENDIAN
unsigned int zero_1 : 1;
unsigned int multi_or_random_pgc_title : 1; // 0 == one sequential pgc title
unsigned int jlc_exists_in_cell_cmd : 1;
unsigned int jlc_exists_in_prepost_cmd : 1;
unsigned int jlc_exists_in_button_cmd : 1;
unsigned int jlc_exists_in_tt_dom : 1;
unsigned int chapter_search_or_play : 1; // UOP 1
unsigned int title_or_time_play : 1; // UOP 0
#else
unsigned int title_or_time_play : 1; // UOP 0
unsigned int chapter_search_or_play : 1; // UOP 1
unsigned int jlc_exists_in_tt_dom : 1;
unsigned int jlc_exists_in_button_cmd : 1;
unsigned int jlc_exists_in_prepost_cmd : 1;
unsigned int jlc_exists_in_cell_cmd : 1;
unsigned int multi_or_random_pgc_title : 1; // 0 == one sequential pgc title
unsigned int zero_1 : 1;
#endif
} ATTRIBUTE_PACKED playback_type_t;
/**
* Title Information.
*/
typedef struct {
playback_type_t pb_ty;
uint8_t nr_of_angles;
uint16_t nr_of_ptts;
uint16_t parental_id;
uint8_t title_set_nr;
uint8_t vts_ttn;
uint32_t title_set_sector;
} ATTRIBUTE_PACKED title_info_t;
/**
* PartOfTitle Search Pointer Table.
*/
typedef struct {
uint16_t nr_of_srpts;
uint16_t zero_1;
uint32_t last_byte;
title_info_t *title;
} ATTRIBUTE_PACKED tt_srpt_t;
#define TT_SRPT_SIZE 8
/**
* Parental Management Information Unit Table.
*/
typedef struct {
uint16_t country_code;
uint16_t zero_1;
uint16_t pf_ptl_mai_start_byte;
uint16_t zero_2;
/* uint16_t *pf_ptl_mai // table of nr_of_vtss+1 x 8 */
} ATTRIBUTE_PACKED ptl_mait_country_t;
#define PTL_MAIT_COUNTRY_SIZE 8
/**
* Parental Management Information Table.
*/
typedef struct {
uint16_t nr_of_countries;
uint16_t nr_of_vtss;
uint32_t last_byte;
ptl_mait_country_t *countries;
} ATTRIBUTE_PACKED ptl_mait_t;
#define PTL_MAIT_SIZE 8
/**
* Video Title Set Attributes.
*/
typedef struct {
uint32_t last_byte;
uint32_t vts_cat;
video_attr_t vtsm_vobs_attr;
uint8_t zero_1;
uint8_t nr_of_vtsm_audio_streams; // should be 0 or 1
audio_attr_t vtsm_audio_attr;
audio_attr_t zero_2[7];
uint8_t zero_3[16];
uint8_t zero_4;
uint8_t nr_of_vtsm_subp_streams; // should be 0 or 1
subp_attr_t vtsm_subp_attr;
subp_attr_t zero_5[27];
uint8_t zero_6[2];
video_attr_t vtstt_vobs_video_attr;
uint8_t zero_7;
uint8_t nr_of_vtstt_audio_streams;
audio_attr_t vtstt_audio_attr[8];
uint8_t zero_8[16];
uint8_t zero_9;
uint8_t nr_of_vtstt_subp_streams;
subp_attr_t vtstt_subp_attr[32];
} ATTRIBUTE_PACKED vts_attributes_t;
#define VTS_ATTRIBUTES_SIZE 542
#define VTS_ATTRIBUTES_MIN_SIZE 356
/**
* Video Title Set Attribute Table.
*/
typedef struct {
uint16_t nr_of_vtss;
uint16_t zero_1;
uint32_t last_byte;
vts_attributes_t *vts;
} ATTRIBUTE_PACKED vts_atrt_t;
#define VTS_ATRT_SIZE 8
/**
* Text Data. (Incomplete)
*/
typedef struct {
uint32_t last_byte; /* offsets are relative here */
uint16_t offsets[100]; /* == nr_of_srpts + 1 (first is disc title) */
#if 0
uint16_t unknown; // 0x48 ?? 0x48 words (16bit) info following
uint16_t zero_1;
uint8_t type_of_info;//?? 01 == disc, 02 == Title, 04 == Title part
uint8_t unknown1;
uint8_t unknown2;
uint8_t unknown3;
uint8_t unknown4;//?? allways 0x30 language?, text format?
uint8_t unknown5;
uint16_t offset; // from first
char text[12]; // ended by 0x09
#endif
} ATTRIBUTE_PACKED txtdt_t;
/**
* Text Data Language Unit. (Incomplete)
*/
typedef struct {
uint16_t lang_code;
uint16_t unknown; /* 0x0001, title 1? disc 1? side 1? */
uint32_t txtdt_start_byte; /* prt, rel start of vmg_txtdt_mgi */
txtdt_t *txtdt;
} ATTRIBUTE_PACKED txtdt_lu_t;
#define TXTDT_LU_SIZE 8
/**
* Text Data Manager Information. (Incomplete)
*/
typedef struct {
char disc_name[14]; /* how many bytes?? */
uint16_t nr_of_language_units; /* 32bit?? */
uint32_t last_byte;
txtdt_lu_t *lu;
} ATTRIBUTE_PACKED txtdt_mgi_t;
#define TXTDT_MGI_SIZE 20
/**
* VTS
*
* Structures relating to the Video Title Set (VTS).
*/
/**
* Video Title Set Information Management Table.
*/
typedef struct {
char vts_identifier[12];
uint32_t vts_last_sector;
uint8_t zero_1[12];
uint32_t vtsi_last_sector;
uint8_t zero_2;
uint8_t specification_version;
uint32_t vts_category;
uint16_t zero_3;
uint16_t zero_4;
uint8_t zero_5;
uint8_t zero_6[19];
uint16_t zero_7;
uint8_t zero_8[32];
uint64_t zero_9;
uint8_t zero_10[24];
uint32_t vtsi_last_byte;
uint32_t zero_11;
uint8_t zero_12[56];
uint32_t vtsm_vobs; /* sector */
uint32_t vtstt_vobs; /* sector */
uint32_t vts_ptt_srpt; /* sector */
uint32_t vts_pgcit; /* sector */
uint32_t vtsm_pgci_ut; /* sector */
uint32_t vts_tmapt; /* sector */ // XXX: FIXME TODO Implement
uint32_t vtsm_c_adt; /* sector */
uint32_t vtsm_vobu_admap; /* sector */
uint32_t vts_c_adt; /* sector */
uint32_t vts_vobu_admap; /* sector */
uint8_t zero_13[24];
video_attr_t vtsm_video_attr;
uint8_t zero_14;
uint8_t nr_of_vtsm_audio_streams; // should be 0 or 1
audio_attr_t vtsm_audio_attr;
audio_attr_t zero_15[7];
uint8_t zero_16[17];
uint8_t nr_of_vtsm_subp_streams; // should be 0 or 1
subp_attr_t vtsm_subp_attr;
subp_attr_t zero_17[27];
uint8_t zero_18[2];
video_attr_t vts_video_attr;
uint8_t zero_19;
uint8_t nr_of_vts_audio_streams;
audio_attr_t vts_audio_attr[8];
uint8_t zero_20[17];
uint8_t nr_of_vts_subp_streams;
subp_attr_t vts_subp_attr[32];
/* XXX: how much 'padding' here, if any? */
} ATTRIBUTE_PACKED vtsi_mat_t;
/**
* PartOfTitle Unit Information.
*/
typedef struct {
uint16_t pgcn;
uint16_t pgn;
} ATTRIBUTE_PACKED ptt_info_t;
/**
* PartOfTitle Information.
*/
typedef struct {
uint16_t nr_of_ptts;
ptt_info_t *ptt;
} ATTRIBUTE_PACKED ttu_t;
/**
* PartOfTitle Search Pointer Table.
*/
typedef struct {
uint16_t nr_of_srpts;
uint16_t zero_1;
uint32_t last_byte;
ttu_t *title;
} ATTRIBUTE_PACKED vts_ptt_srpt_t;
#define VTS_PTT_SRPT_SIZE 8
#if PRAGMA_PACK
#pragma pack()
#endif
/**
* The following structure defines an IFO file. The structure is divided into
* two parts, the VMGI, or Video Manager Information, which is read from the
* VIDEO_TS.[IFO,BUP] file, and the VTSI, or Video Title Set Information, which
* is read in from the VTS_XX_0.[IFO,BUP] files.
*/
typedef struct {
dvd_file_t *file;
/* VMGI */
vmgi_mat_t *vmgi_mat;
tt_srpt_t *tt_srpt;
pgc_t *first_play_pgc;
ptl_mait_t *ptl_mait;
vts_atrt_t *vts_atrt;
txtdt_mgi_t *txtdt_mgi;
/* Common */
pgci_ut_t *pgci_ut;
c_adt_t *menu_c_adt;
vobu_admap_t *menu_vobu_admap;
/* VTSI */
vtsi_mat_t *vtsi_mat;
vts_ptt_srpt_t *vts_ptt_srpt;
pgcit_t *vts_pgcit;
int *vts_tmapt; // FIXME add/correct the type
c_adt_t *vts_c_adt;
vobu_admap_t *vts_vobu_admap;
} ifo_handle_t;
#endif /* IFO_TYPES_H_INCLUDED */
--- NEW FILE ---
/*****************************************************************************
* int_types.h: internal types
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
* $Id: int_types.h,v 1.1 2002/04/24 19:28:03 arpi Exp $
*
* Authors: Vincent Seguin <seguin at via.ecp.fr>
*
* 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 */
typedef unsigned char u8;
typedef signed char s8;
typedef unsigned short u16;
typedef signed short s16;
typedef unsigned int u32;
typedef signed int s32;
#if defined( _MSC_VER )
typedef unsigned __int64 u64;
typedef signed __int64 s64;
#else
typedef unsigned long long u64;
typedef signed long long s64;
#endif
--- NEW FILE ---
/*****************************************************************************
* ioctl.c: DVD ioctl replacement function
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id: ioctl.c,v 1.1 2002/04/24 19:28:03 arpi Exp $
*
* Authors: Markus Kuespert <ltlBeBoy at beosmail.com>
* Samuel Hocevar <sam at zoy.org>
* Jon Lech Johansen <jon-vl at nanocrew.net>
* Håkan Hjort <d95hjort at 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
[...1129 lines suppressed...]
hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
if( hEvent == NULL )
{
return -1;
}
p_ssc->SRB_PostProc = hEvent;
p_ssc->SRB_HaId = LOBYTE( fd->i_sid );
p_ssc->SRB_Target = HIBYTE( fd->i_sid );
ResetEvent( hEvent );
if( fd->lpSendCommand( (void*) p_ssc ) == SS_PENDING )
WaitForSingleObject( hEvent, INFINITE );
CloseHandle( hEvent );
return p_ssc->SRB_Status == SS_COMP ? 0 : -1;
}
#endif
--- NEW FILE ---
/*****************************************************************************
* ioctl.h: DVD ioctl replacement function
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id: ioctl.h,v 1.1 2002/04/24 19:28:03 arpi Exp $
*
* Authors: Samuel Hocevar <sam at 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_ReadKey ( 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 * );
/*****************************************************************************
* 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, 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( SYS_DARWIN )
#define INIT_DVDIOCTL( SIZE ) \
dvdioctl_data_t dvdioctl; \
u8 p_buffer[ (SIZE) ]; \
dvdioctl.p_buffer = p_buffer; \
dvdioctl.i_size = (SIZE); \
dvdioctl.i_keyclass = kCSS_CSS2_CPRM; \
memset( p_buffer, 0, (SIZE) );
#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
/*****************************************************************************
* Various DVD I/O tables
*****************************************************************************/
#if defined( SYS_BEOS ) || defined( WIN32 ) || defined ( SOLARIS_USCSI )
/* 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_ASF 0x05
# define DVD_INVALIDATE_AGID 0x3f
#endif
#if defined( WIN32 )
/*****************************************************************************
* win32 ioctl specific
*****************************************************************************/
#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_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_DISK_KEY_LENGTH (2048 + sizeof(DVD_COPY_PROTECT_KEY))
#define DVD_ASF_LENGTH (sizeof(DVD_ASF) + sizeof(DVD_COPY_PROTECT_KEY))
#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 _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
--- NEW FILE ---
/*****************************************************************************
* libdvdcss.c: DVD reading library.
*****************************************************************************
* Copyright (C) 1998-2001 VideoLAN
* $Id: libdvdcss.c,v 1.1 2002/04/24 19:28:03 arpi Exp $
*
* Authors: Stéphane Borel <stef at via.ecp.fr>
* Samuel Hocevar <sam at 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.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#if defined( WIN32 )
# include <io.h> /* read() */
#else
# include <sys/uio.h> /* struct iovec */
#endif
#include "common.h"
#if defined( WIN32 )
# include "input_iovec.h"
#endif
#include "dvdcss.h"
#include "dvd_reader.h"
#include "libdvdcss.h"
#include "ioctl.h"
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static int _dvdcss_open ( dvdcss_handle, char *psz_target );
static int _dvdcss_close ( dvdcss_handle );
static int _dvdcss_seek ( dvdcss_handle, int i_blocks );
static int _dvdcss_read ( dvdcss_handle, void *p_buffer, int i_blocks );
static int _dvdcss_readv ( dvdcss_handle, struct iovec *p_iovec, int i_blocks );
/*****************************************************************************
* Local prototypes, win32 specific
*****************************************************************************/
#if defined( WIN32 )
static int _win32_dvdcss_readv ( int i_fd, struct iovec *p_iovec,
int i_num_buffers, char *p_tmp_buffer );
static int _win32_dvdcss_aopen ( char c_drive, dvdcss_handle dvdcss );
static int _win32_dvdcss_aclose ( int i_fd );
static int _win32_dvdcss_aseek ( int i_fd, int i_blocks, int i_method );
static int _win32_dvdcss_aread ( int i_fd, void *p_data, int i_blocks );
#endif
/*****************************************************************************
* dvdcss_open: initialize library, open a DVD device, crack CSS key
*****************************************************************************/
extern dvdcss_handle dvdcss_open ( char *psz_target, int i_flags )
{
int i_ret;
dvdcss_handle dvdcss;
/* Allocate the library structure */
dvdcss = malloc( sizeof( struct dvdcss_s ) );
if( dvdcss == NULL )
{
if( ! (i_flags & DVDCSS_INIT_QUIET) )
{
DVDCSS_ERROR( "could not initialize library" );
}
return NULL;
}
/* Initialize structure */
dvdcss->p_titles = NULL;
dvdcss->b_debug = i_flags & DVDCSS_INIT_DEBUG;
dvdcss->b_errors = !(i_flags & DVDCSS_INIT_QUIET);
dvdcss->psz_error = "no error";
i_ret = _dvdcss_open( dvdcss, psz_target );
if( i_ret < 0 )
{
free( dvdcss );
return NULL;
}
i_ret = CSSTest( dvdcss );
if( i_ret < 0 )
{
_dvdcss_error( dvdcss, "css test failed" );
_dvdcss_close( dvdcss );
free( dvdcss );
return NULL;
}
dvdcss->b_encrypted = i_ret;
/* If drive is encrypted, crack its key */
if( dvdcss->b_encrypted )
{
i_ret = CSSInit( dvdcss );
if( i_ret < 0 )
{
_dvdcss_close( dvdcss );
free( dvdcss );
return NULL;
}
}
return dvdcss;
}
/*****************************************************************************
* dvdcss_error: return the last libdvdcss error message
*****************************************************************************/
extern char * dvdcss_error ( dvdcss_handle dvdcss )
{
return dvdcss->psz_error;
}
/*****************************************************************************
* dvdcss_seek: seek into the device
*****************************************************************************/
extern int dvdcss_seek ( dvdcss_handle dvdcss, int i_blocks )
{
return _dvdcss_seek( dvdcss, i_blocks );
}
/*****************************************************************************
* dvdcss_title: crack the current title key if needed
*****************************************************************************/
extern int dvdcss_title ( dvdcss_handle dvdcss, int i_block )
{
dvd_title_t *p_title;
dvd_key_t p_key;
int i_ret;
char * key_file = NULL;
if( ! dvdcss->b_encrypted )
{
return 0;
}
//fprintf( stderr, "looking for a key for offset %i\n", i_block );
/* Check if we've already cracked this key */
p_title = dvdcss->p_titles;
while( p_title != NULL
&& p_title->p_next != NULL
&& p_title->p_next->i_startlb <= i_block )
{
p_title = p_title->p_next;
}
if( p_title != NULL
&& p_title->i_startlb == i_block )
{
/* We've already cracked this key, nothing to do */
return 0;
}
if ( dvd_key_dir )
{
int fd;
if ( (key_file=calloc( 1,strlen( dvd_key_dir ) + 11 )) == NULL ) return -1;
sprintf( key_file,"%s/%0.10x",dvd_key_dir,i_block );
fprintf( stderr,"dvdcss: opening %s to look for key\n",key_file );
if ( (fd=open( key_file,O_RDONLY ) ) < 0 )
{
fprintf(stderr, "dvdcss: no such file, cracking normal\n");
goto normal;
}
read(fd, p_key, 5);
close( fd );
goto goon;
}
normal:
/* Crack CSS title key for current VTS */
i_ret = CSSGetKey( dvdcss, i_block, p_key );
if( i_ret < 0 )
{
_dvdcss_error( dvdcss, "fatal error in vts css key" );
return i_ret;
}
else if( i_ret > 0 )
{
_dvdcss_error( dvdcss, "decryption unavailable" );
return -1;
}
goon:
//fprintf(stderr, "cracked key is %.2x %.2x %.2x %.2x %.2x\n",
// p_key[0], p_key[1], p_key[2], p_key[3], p_key[4] );
/* Add key to keytable if it isn't empty */
if( p_key[0] | p_key[1] | p_key[2] | p_key[3] | p_key[4] )
{
dvd_title_t *p_newtitle;
if ( dvd_key_dir )
{
int fd;
fprintf( stderr,"dvdcss: writing key to %s\n",key_file );
if ( (fd=open( key_file,O_RDWR|O_CREAT|O_EXCL,0644 ) ) < 0 )
{
// fprintf(stderr, "dvdcss: file %s exists or write/permission error, doing nothing\n", tmp);
goto normal2;
}
write( fd,p_key,5 );
close( fd );
free( key_file );
}
normal2:
/* Find our spot in the list */
p_newtitle = NULL;
p_title = dvdcss->p_titles;
while( p_title != NULL && p_title->i_startlb < i_block )
{
p_newtitle = p_title;
p_title = p_title->p_next;
}
/* Save the found title */
p_title = p_newtitle;
/* Write in the new title and its key */
p_newtitle = malloc( sizeof( dvd_title_t ) );
p_newtitle->i_startlb = i_block;
memcpy( p_newtitle->p_key, p_key, KEY_SIZE );
/* Link the new title, either at the beginning or inside the list */
if( p_title == NULL )
{
dvdcss->p_titles = p_newtitle;
p_newtitle->p_next = NULL;
}
else
{
p_newtitle->p_next = p_title->p_next;
p_title->p_next = p_newtitle;
}
}
return 0;
}
/*****************************************************************************
* dvdcss_read: read data from the device, decrypt if requested
*****************************************************************************/
extern int dvdcss_read ( dvdcss_handle dvdcss, void *p_buffer,
int i_blocks,
int i_flags )
{
dvd_title_t *p_title;
int i_ret, i_index;
i_ret = _dvdcss_read( dvdcss, p_buffer, i_blocks );
if( i_ret <= 0
|| !dvdcss->b_encrypted
|| !(i_flags & DVDCSS_READ_DECRYPT) )
{
return i_ret;
}
/* find our key */
p_title = dvdcss->p_titles;
while( p_title != NULL
&& p_title->p_next
&& p_title->p_next->i_startlb <= dvdcss->i_seekpos )
{
p_title = p_title->p_next;
}
if( p_title == NULL )
{
/* no css key found to use, so no decryption to do */
return 0;
}
/* Decrypt the blocks we managed to read */
for( i_index = i_ret; i_index; i_index-- )
{
CSSDescrambleSector( p_title->p_key, p_buffer );
((u8*)p_buffer)[0x14] &= 0x8f;
(u8*)p_buffer += DVDCSS_BLOCK_SIZE;
}
return i_ret;
}
/*****************************************************************************
* dvdcss_readv: read data to an iovec structure, decrypt if reaquested
*****************************************************************************/
extern int dvdcss_readv ( dvdcss_handle dvdcss, void *p_iovec,
int i_blocks,
int i_flags )
{
#define P_IOVEC ((struct iovec*)p_iovec)
dvd_title_t *p_title;
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_encrypted
|| !(i_flags & DVDCSS_READ_DECRYPT) )
{
return i_ret;
}
/* Find our key */
p_title = dvdcss->p_titles;
while( p_title != NULL
&& p_title->p_next != NULL
&& p_title->p_next->i_startlb <= dvdcss->i_seekpos )
{
p_title = p_title->p_next;
}
if( p_title == NULL )
{
/* no css key found to use, so no decryption to do */
return 0;
}
/* 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;
}
CSSDescrambleSector( p_title->p_key, iov_base );
((u8*)iov_base)[0x14] &= 0x8f;
(u8*)iov_base += DVDCSS_BLOCK_SIZE;
(u8*)iov_len -= DVDCSS_BLOCK_SIZE;
}
return i_ret;
#undef P_IOVEC
}
/*****************************************************************************
* dvdcss_close: close the DVD device and clean up the library
*****************************************************************************/
extern int dvdcss_close ( dvdcss_handle 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 );
return 0;
}
/* Following functions are local */
static int _dvdcss_open ( dvdcss_handle dvdcss, char *psz_target )
{
#if defined( WIN32 )
if( WIN2K )
{
char psz_dvd[7];
_snprintf( psz_dvd, 7, "\\\\.\\%c:", psz_target[0] );
(HANDLE) dvdcss->i_fd =
CreateFile( psz_dvd, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL );
if( (HANDLE) dvdcss->i_fd == INVALID_HANDLE_VALUE )
{
_dvdcss_error( dvdcss, "failed opening device" );
return -1;
}
}
else
{
dvdcss->i_fd = _win32_dvdcss_aopen( psz_target[0], dvdcss );
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 = open( psz_target, 0 );
if( dvdcss->i_fd == -1 )
{
_dvdcss_error( dvdcss, "failed opening device" );
return -1;
}
#endif
return 0;
}
static int _dvdcss_close ( dvdcss_handle 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 );
#endif
return 0;
}
static int _dvdcss_seek ( dvdcss_handle 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_fd,
(off_t)i_blocks * (off_t)DVDCSS_BLOCK_SIZE, SEEK_SET );
return i_read / DVDCSS_BLOCK_SIZE;
#endif
}
static int _dvdcss_read ( dvdcss_handle 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_bytes;
i_bytes = read( dvdcss->i_fd, p_buffer,
(size_t)i_blocks * DVDCSS_BLOCK_SIZE );
return i_bytes / DVDCSS_BLOCK_SIZE;
#endif
}
static int _dvdcss_readv ( dvdcss_handle 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_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
*****************************************************************************/
static 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)
*****************************************************************************/
static int _win32_dvdcss_aopen( char c_drive, dvdcss_handle dvdcss )
{
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)
*****************************************************************************/
static 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.
*****************************************************************************/
static 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.
*****************************************************************************/
static 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
--- NEW FILE ---
/*****************************************************************************
* private.h: private DVD reading library data
*****************************************************************************
* Copyright (C) 1998-2001 VideoLAN
* $Id: libdvdcss.h,v 1.1 2002/04/24 19:28:03 arpi Exp $
*
* Authors: Stéphane Borel <stef at via.ecp.fr>
* Samuel Hocevar <sam at 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.
*****************************************************************************/
/*****************************************************************************
* Needed headers
*****************************************************************************/
#include "css.h"
/*****************************************************************************
* The libdvdcss structure
*****************************************************************************/
struct dvdcss_s
{
/* File descriptor */
int i_fd;
int i_seekpos;
/* Decryption stuff */
css_t css;
boolean_t b_encrypted;
dvd_title_t *p_titles;
/* Error management */
char *psz_error;
boolean_t b_errors;
boolean_t b_debug;
#if defined( WIN32 )
char *p_readv_buffer;
int i_readv_buf_size;
#endif
};
/*****************************************************************************
* Error management
*****************************************************************************/
#if defined( _WIN32 ) && defined( _MSC_VER )
# define DVDCSS_ERROR( x ) fprintf( stderr, "libdvdcss error: %s\n", x );
# define DVDCSS_DEBUG( x ) fprintf( stderr, "libdvdcss debug: %s\n", x );
#else
# define DVDCSS_ERROR( x... ) fprintf( stderr, "libdvdcss error: %s\n", ##x );
# define DVDCSS_DEBUG( x... ) fprintf( stderr, "libdvdcss debug: %s\n", ##x );
#endif
static __inline__ void _dvdcss_error( dvdcss_handle dvdcss, char *psz_string )
{
if( dvdcss->b_errors )
{
DVDCSS_ERROR( psz_string );
}
dvdcss->psz_error = psz_string;
}
static __inline__ void _dvdcss_debug( dvdcss_handle dvdcss, char *psz_string )
{
if( dvdcss->b_debug )
{
DVDCSS_DEBUG( psz_string );
}
}
--- NEW FILE ---
/*
* Copyright (C) 2000 Håkan Hjort <d95hjort at dtek.chalmers.se>
*
* Much of the contents in this file is based on VOBDUMP.
*
* VOBDUMP: a program for examining DVD .VOB filse
*
* Copyright 1998, 1999 Eric Smith <eric at brouhaha.com>
*
* VOBDUMP is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. Note that I am not
* granting permission to redistribute or modify VOBDUMP under the
* terms of any later version of the General Public License.
*
* This program is distributed in the hope that it will be useful (or
* at least amusing), 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-1307 USA
*/
#include <stdio.h>
#include <inttypes.h>
#include "config.h"
#ifdef HAVE_ASSERT_H
#include <assert.h>
#endif
#include "nav_types.h"
#include "nav_print.h"
static void print_time(dvd_time_t *dtime) {
const char *rate;
assert((dtime->hour>>4) < 0xa && (dtime->hour&0xf) < 0xa);
assert((dtime->minute>>4) < 0x7 && (dtime->minute&0xf) < 0xa);
assert((dtime->second>>4) < 0x7 && (dtime->second&0xf) < 0xa);
assert((dtime->frame_u&0xf) < 0xa);
printf("%02x:%02x:%02x.%02x",
dtime->hour,
dtime->minute,
dtime->second,
dtime->frame_u & 0x3f);
switch((dtime->frame_u & 0xc0) >> 6) {
case 1:
rate = "25.00";
break;
case 3:
rate = "29.97";
break;
default:
rate = "(please send a bug report)";
break;
}
printf(" @ %s fps", rate);
}
static void navPrint_PCI_GI(pci_gi_t *pci_gi) {
int i;
printf("pci_gi:\n");
printf("nv_pck_lbn 0x%08x\n", pci_gi->nv_pck_lbn);
printf("vobu_cat 0x%04x\n", pci_gi->vobu_cat);
printf("vobu_uop_ctl 0x%08x\n", *(uint32_t*)&pci_gi->vobu_uop_ctl);
printf("vobu_s_ptm 0x%08x\n", pci_gi->vobu_s_ptm);
printf("vobu_e_ptm 0x%08x\n", pci_gi->vobu_e_ptm);
printf("vobu_se_e_ptm 0x%08x\n", pci_gi->vobu_se_e_ptm);
printf("e_eltm ");
print_time(&pci_gi->e_eltm);
printf("\n");
printf("vobu_isrc \"");
for(i = 0; i < 32; i++) {
char c = pci_gi->vobu_isrc[i];
if((c >= ' ') && (c <= '~'))
printf("%c", c);
else
printf(".");
}
printf("\"\n");
}
static void navPrint_NSML_AGLI(nsml_agli_t *nsml_agli) {
int i, j = 0;
for(i = 0; i < 9; i++)
j |= nsml_agli->nsml_agl_dsta[i];
if(j == 0)
return;
printf("nsml_agli:\n");
for(i = 0; i < 9; i++)
if(nsml_agli->nsml_agl_dsta[i])
printf("nsml_agl_c%d_dsta 0x%08x\n", i + 1,
nsml_agli->nsml_agl_dsta[i]);
}
static void navPrint_HL_GI(hl_gi_t *hl_gi, int *btngr_ns, int *btn_ns) {
if((hl_gi->hli_ss & 0x03) == 0)
return;
printf("hl_gi:\n");
printf("hli_ss 0x%01x\n", hl_gi->hli_ss & 0x03);
printf("hli_s_ptm 0x%08x\n", hl_gi->hli_s_ptm);
printf("hli_e_ptm 0x%08x\n", hl_gi->hli_e_ptm);
printf("btn_se_e_ptm 0x%08x\n", hl_gi->btn_se_e_ptm);
*btngr_ns = hl_gi->btngr_ns;
printf("btngr_ns %d\n", hl_gi->btngr_ns);
printf("btngr%d_dsp_ty 0x%02x\n", 1, hl_gi->btngr1_dsp_ty);
printf("btngr%d_dsp_ty 0x%02x\n", 2, hl_gi->btngr2_dsp_ty);
printf("btngr%d_dsp_ty 0x%02x\n", 3, hl_gi->btngr3_dsp_ty);
printf("btn_ofn %d\n", hl_gi->btn_ofn);
*btn_ns = hl_gi->btn_ns;
printf("btn_ns %d\n", hl_gi->btn_ns);
printf("nsl_btn_ns %d\n", hl_gi->nsl_btn_ns);
printf("fosl_btnn %d\n", hl_gi->fosl_btnn);
printf("foac_btnn %d\n", hl_gi->foac_btnn);
}
static void navPrint_BTN_COLIT(btn_colit_t *btn_colit) {
int i, j;
j = 0;
for(i = 0; i < 6; i++)
j |= btn_colit->btn_coli[i/2][i&1];
if(j == 0)
return;
printf("btn_colit:\n");
for(i = 0; i < 3; i++)
for(j = 0; j < 2; j++)
printf("btn_cqoli %d %s_coli: %08x\n",
i, (j == 0) ? "sl" : "ac",
btn_colit->btn_coli[i][j]);
}
static void navPrint_BTNIT(btni_t *btni_table, int btngr_ns, int btn_ns) {
int i, j;
printf("btnit:\n");
printf("btngr_ns: %i\n", btngr_ns);
printf("btn_ns: %i\n", btn_ns);
if(btngr_ns == 0)
return;
for(i = 0; i < btngr_ns; i++) {
for(j = 0; j < (36 / btngr_ns); j++) {
if(j < btn_ns) {
btni_t *btni = &btni_table[(36 / btngr_ns) * i + j];
printf("group %d btni %d: ", i+1, j+1);
printf("btn_coln %d, auto_action_mode %d\n",
btni->btn_coln, btni->auto_action_mode);
printf("coords (%d, %d) .. (%d, %d)\n",
btni->x_start, btni->y_start, btni->x_end, btni->y_end);
printf("up %d, ", btni->up);
printf("down %d, ", btni->down);
printf("left %d, ", btni->left);
printf("right %d\n", btni->right);
// ifoPrint_COMMAND(&btni->cmd);
printf("\n");
}
}
}
}
static void navPrint_HLI(hli_t *hli) {
int btngr_ns = 0, btn_ns = 0;
printf("hli:\n");
navPrint_HL_GI(&hli->hl_gi, & btngr_ns, & btn_ns);
navPrint_BTN_COLIT(&hli->btn_colit);
navPrint_BTNIT(hli->btnit, btngr_ns, btn_ns);
}
void navPrint_PCI(pci_t *pci) {
printf("pci packet:\n");
navPrint_PCI_GI(&pci->pci_gi);
navPrint_NSML_AGLI(&pci->nsml_agli);
navPrint_HLI(&pci->hli);
}
static void navPrint_DSI_GI(dsi_gi_t *dsi_gi) {
printf("dsi_gi:\n");
printf("nv_pck_scr 0x%08x\n", dsi_gi->nv_pck_scr);
printf("nv_pck_lbn 0x%08x\n", dsi_gi->nv_pck_lbn );
printf("vobu_ea 0x%08x\n", dsi_gi->vobu_ea);
printf("vobu_1stref_ea 0x%08x\n", dsi_gi->vobu_1stref_ea);
printf("vobu_2ndref_ea 0x%08x\n", dsi_gi->vobu_2ndref_ea);
printf("vobu_3rdref_ea 0x%08x\n", dsi_gi->vobu_3rdref_ea);
printf("vobu_vob_idn 0x%04x\n", dsi_gi->vobu_vob_idn);
printf("vobu_c_idn 0x%02x\n", dsi_gi->vobu_c_idn);
printf("c_eltm ");
print_time(&dsi_gi->c_eltm);
printf("\n");
}
static void navPrint_SML_PBI(sml_pbi_t *sml_pbi) {
printf("sml_pbi:\n");
printf("category 0x%04x\n", sml_pbi->category);
if(sml_pbi->category & 0x8000)
printf("VOBU is in preunit\n");
if(sml_pbi->category & 0x4000)
printf("VOBU is in ILVU\n");
if(sml_pbi->category & 0x2000)
printf("VOBU at the beginning of ILVU\n");
if(sml_pbi->category & 0x1000)
printf("VOBU at end of PREU of ILVU\n");
printf("ilvu_ea 0x%08x\n", sml_pbi->ilvu_ea);
printf("nxt_ilvu_sa 0x%08x\n", sml_pbi->ilvu_sa);
printf("nxt_ilvu_size 0x%04x\n", sml_pbi->size);
printf("vob_v_s_s_ptm 0x%08x\n", sml_pbi->vob_v_s_s_ptm);
printf("vob_v_e_e_ptm 0x%08x\n", sml_pbi->vob_v_e_e_ptm);
/* $$$ more code needed here */
}
static void navPrint_SML_AGLI(sml_agli_t *sml_agli) {
int i;
printf("sml_agli:\n");
for(i = 0; i < 9; i++) {
printf("agl_c%d address: 0x%08x size 0x%04x\n", i,
sml_agli->data[i].address, sml_agli->data[i].size);
}
}
static void navPrint_VOBU_SRI(vobu_sri_t *vobu_sri) {
int i;
int stime[19] = { 240, 120, 60, 20, 15, 14, 13, 12, 11,
10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
printf("vobu_sri:\n");
printf("Next VOBU with Video %08x\n", vobu_sri->next_video);
for(i = 0; i < 19; i++) {
printf("%3.1f %08x ", stime[i]/2.0, vobu_sri->fwda[i]);
}
printf("\n");
printf("Next VOBU %08x\n", vobu_sri->next_vobu);
printf("--\n");
printf("Prev VOBU %08x\n", vobu_sri->prev_vobu);
for(i = 0; i < 19; i++) {
printf("%3.1f %08x ", stime[18 - i]/2.0, vobu_sri->bwda[i]);
}
printf("\n");
printf("Prev VOBU with Video %08x\n", vobu_sri->prev_video);
}
static void navPrint_SYNCI(synci_t *synci) {
int i;
printf("synci:\n");
/* $$$ more code needed here */
for(i = 0; i < 8; i++)
printf("%04x ", synci->a_synca[i]);
for(i = 0; i < 32; i++)
printf("%08x ", synci->sp_synca[i]);
}
void navPrint_DSI(dsi_t *dsi) {
printf("dsi packet:\n");
navPrint_DSI_GI(&dsi->dsi_gi);
navPrint_SML_PBI(&dsi->sml_pbi);
navPrint_SML_AGLI(&dsi->sml_agli);
navPrint_VOBU_SRI(&dsi->vobu_sri);
navPrint_SYNCI(&dsi->synci);
}
--- NEW FILE ---
/**
* Copyright (C) 2001 Billy Biggs <vektor at dumbterm.net>,
* Håkan Hjort <d95hjort at 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef NAV_PRINT_H_INCLUDED
#define NAV_PRINT_H_INCLUDED
#include <stdio.h>
#include <dvdread/nav_types.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* This file provides example functions for printing information about the NAV
* packet to stdout.
*/
void navPrint_PCI(pci_t *pci);
void navPrint_DSI(dsi_t *dsi);
#ifdef __cplusplus
};
#endif
#endif /* NAV_PRINT_H_INCLUDED */
--- NEW FILE ---
/**
* Copyright (C) 2000 Håkan Hjort <d95hjort at 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-1307 USA
*/
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include "config.h"
#ifdef HAVE_ASSERT_H
#include <assert.h>
#endif
#include "bswap.h"
#include "nav_types.h"
#include "nav_read.h"
void navRead_PCI(pci_t *pci, unsigned char *buffer) {
int i, j;
assert(sizeof(pci_t) == PCI_BYTES - 1); // -1 for substream id
memcpy(pci, buffer, sizeof(pci_t));
/* Endian conversions */
/* pci pci_gi */
B2N_32(pci->pci_gi.nv_pck_lbn);
B2N_16(pci->pci_gi.vobu_cat);
B2N_32(pci->pci_gi.vobu_s_ptm);
B2N_32(pci->pci_gi.vobu_e_ptm);
B2N_32(pci->pci_gi.vobu_se_e_ptm);
/* pci nsml_agli */
for(i = 0; i < 9; i++)
B2N_32(pci->nsml_agli.nsml_agl_dsta[i]);
/* pci hli hli_gi */
B2N_16(pci->hli.hl_gi.hli_ss);
B2N_32(pci->hli.hl_gi.hli_s_ptm);
B2N_32(pci->hli.hl_gi.hli_e_ptm);
B2N_32(pci->hli.hl_gi.btn_se_e_ptm);
/* pci hli btn_colit */
for(i = 0; i < 3; i++)
for(j = 0; j < 2; j++)
B2N_32(pci->hli.btn_colit.btn_coli[i][j]);
/* pci hli btni */
/* There are some issues with this bitfiled with some compilers
because they stradle word boundaries. */
#if !defined(WORDS_BIGENDIAN)
for(i = 0; i < 36; i++) {
#if 0 /* Wierd Sun CC code that does not work */
unsigned char m[6];
memcpy(m, &pci->hli.btnit[i], 6);
pci->hli.btnit[i].zero1 = (m[1] >> 2);
pci->hli.btnit[i].x_start = (m[0] << 4) | (m[1] >> 4);
pci->hli.btnit[i].x_end = (m[1] << 8) | m[2];
pci->hli.btnit[i].y_start = (m[3] << 4) | (m[4] >> 4);
pci->hli.btnit[i].y_end = (m[4] << 8) | m[5];
pci->hli.btnit[i].zero2 = (m[4] >> 2);
pci->hli.btnit[i].btn_coln = (m[0] >> 6);
pci->hli.btnit[i].auto_action_mode = (m[3] >> 6);
#else
char tmp[6], swap;
memcpy(tmp, &(pci->hli.btnit[i]), 6);
/* This is a B2N_24() */
swap = tmp[0]; tmp[0] = tmp[2]; tmp[2] = swap;
/* This is a B2N_24() */
swap = tmp[3]; tmp[3] = tmp[5]; tmp[5] = swap;
memcpy(&(pci->hli.btnit[i]), tmp, 6);
#endif
}
#endif
/* Asserts */
/* pci pci gi */
assert(pci->pci_gi.zero1 == 0);
/* pci hli hli_gi */
assert(pci->hli.hl_gi.zero1 == 0);
assert(pci->hli.hl_gi.zero2 == 0);
assert(pci->hli.hl_gi.zero3 == 0);
assert(pci->hli.hl_gi.zero4 == 0);
assert(pci->hli.hl_gi.zero5 == 0);
/* Are there buttons defined here? */
if((pci->hli.hl_gi.hli_ss & 0x03) != 0) {
assert(pci->hli.hl_gi.btn_ns != 0);
assert(pci->hli.hl_gi.btngr_ns != 0);
} else {
assert((pci->hli.hl_gi.btn_ns != 0 && pci->hli.hl_gi.btngr_ns != 0)
|| (pci->hli.hl_gi.btn_ns == 0 && pci->hli.hl_gi.btngr_ns == 0));
}
/* pci hli btnit */
#if NDEBUG
for(i = 0; i < pci->hli.hl_gi.btngr_ns; i++) {
for(j = 0; j < (36 / pci->hli.hl_gi.btngr_ns); j++) {
int n = (36 / pci->hli.hl_gi.btngr_ns) * i + j;
assert(pci->hli.btnit[n].zero1 == 0);
assert(pci->hli.btnit[n].zero2 == 0);
assert(pci->hli.btnit[n].zero3 == 0);
assert(pci->hli.btnit[n].zero4 == 0);
assert(pci->hli.btnit[n].zero5 == 0);
assert(pci->hli.btnit[n].zero6 == 0);
if (j < pci->hli.hl_gi.btn_ns) {
assert(pci->hli.btnit[n].x_start <= pci->hli.btnit[n].x_end);
assert(pci->hli.btnit[n].y_start <= pci->hli.btnit[n].y_end);
assert(pci->hli.btnit[n].up <= pci->hli.hl_gi.btn_ns);
assert(pci->hli.btnit[n].down <= pci->hli.hl_gi.btn_ns);
assert(pci->hli.btnit[n].left <= pci->hli.hl_gi.btn_ns);
assert(pci->hli.btnit[n].right <= pci->hli.hl_gi.btn_ns);
//vmcmd_verify(pci->hli.btnit[n].cmd);
} else {
int k;
assert(pci->hli.btnit[n].btn_coln == 0);
assert(pci->hli.btnit[n].auto_action_mode == 0);
assert(pci->hli.btnit[n].x_start == 0);
assert(pci->hli.btnit[n].y_start == 0);
assert(pci->hli.btnit[n].x_end == 0);
assert(pci->hli.btnit[n].y_end == 0);
assert(pci->hli.btnit[n].up == 0);
assert(pci->hli.btnit[n].down == 0);
assert(pci->hli.btnit[n].left == 0);
assert(pci->hli.btnit[n].right == 0);
for (k = 0; k < 8; k++)
assert(pci->hli.btnit[n].cmd.bytes[k] == 0); //CHECK_ZERO?
}
}
}
#endif
}
void navRead_DSI(dsi_t *dsi, unsigned char *buffer) {
int i;
assert(sizeof(dsi_t) == DSI_BYTES - 1); // -1 for substream id
memcpy(dsi, buffer, sizeof(dsi_t));
/* Endian conversions */
/* dsi dsi gi */
B2N_32(dsi->dsi_gi.nv_pck_scr);
B2N_32(dsi->dsi_gi.nv_pck_lbn);
B2N_32(dsi->dsi_gi.vobu_ea);
B2N_32(dsi->dsi_gi.vobu_1stref_ea);
B2N_32(dsi->dsi_gi.vobu_2ndref_ea);
B2N_32(dsi->dsi_gi.vobu_3rdref_ea);
B2N_16(dsi->dsi_gi.vobu_vob_idn);
/* dsi sml pbi */
B2N_16(dsi->sml_pbi.category);
B2N_32(dsi->sml_pbi.ilvu_ea);
B2N_32(dsi->sml_pbi.ilvu_sa);
B2N_16(dsi->sml_pbi.size);
B2N_32(dsi->sml_pbi.vob_v_s_s_ptm);
B2N_32(dsi->sml_pbi.vob_v_e_e_ptm);
/* dsi sml agli */
for(i = 0; i < 9; i++) {
B2N_32(dsi->sml_agli.data[ i ].address);
B2N_16(dsi->sml_agli.data[ i ].size);
}
/* dsi vobu sri */
B2N_32(dsi->vobu_sri.next_video);
for(i = 0; i < 19; i++)
B2N_32(dsi->vobu_sri.fwda[i]);
B2N_32(dsi->vobu_sri.next_vobu);
B2N_32(dsi->vobu_sri.prev_vobu);
for(i = 0; i < 19; i++)
B2N_32(dsi->vobu_sri.bwda[i]);
B2N_32(dsi->vobu_sri.prev_video);
/* dsi synci */
for(i = 0; i < 8; i++)
B2N_16(dsi->synci.a_synca[i]);
for(i = 0; i < 32; i++)
B2N_32(dsi->synci.sp_synca[i]);
/* Asserts */
/* dsi dsi gi */
assert(dsi->dsi_gi.zero1 == 0);
}
--- NEW FILE ---
/**
* Copyright (C) 2000, 2001 Håkan Hjort <d95hjort at 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-1307 USA
*/
#ifndef NAV_READ_H_INCLUDED
#define NAV_READ_H_INCLUDED
#include <dvdread/nav_types.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* Reads the PCI packet which begins at buffer into pci.
*/
void navRead_PCI(pci_t *pci, unsigned char *buffer);
/**
* Reads the DSI packet which begins at buffer into dsi.
*/
void navRead_DSI(dsi_t *dsi, unsigned char *buffer);
#ifdef __cplusplus
};
#endif
#endif /* NAV_READ_H_INCLUDED */
--- NEW FILE ---
/**
* Copyright (C) 2000 Håkan Hjort <d95hjort at dtek.chalmers.se>
*
* The data structures in this file should represent the layout of the
* pci and dsi packets as they are stored in the stream. Information
* found by reading the source to VOBDUMP is the base for the structure
* and names of these data types.
*
* VOBDUMP: a program for examining DVD .VOB files.
* Copyright 1998, 1999 Eric Smith <eric at brouhaha.com>
*
* VOBDUMP is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. Note that I am not
* granting permission to redistribute or modify VOBDUMP under the terms
* of any later version of the General Public License.
*
* This program is distributed in the hope that it will be useful (or at
* least amusing), 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-1307
* USA
*/
#ifndef NAV_TYPES_H_INCLUDED
#define NAV_TYPES_H_INCLUDED
#include <inttypes.h>
#include <dvdread/ifo_types.h> // only dvd_time_t, vm_cmd_t and user_ops_t
#undef ATTRIBUTE_PACKED
#undef PRAGMA_PACK_BEGIN
#undef PRAGMA_PACK_END
#if defined(__GNUC__)
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)
#define ATTRIBUTE_PACKED __attribute__ ((packed))
#define PRAGMA_PACK 0
#endif
#endif
#if !defined(ATTRIBUTE_PACKED)
#define ATTRIBUTE_PACKED
#define PRAGMA_PACK 1
#endif
/* The length including the substream id byte. */
#define PCI_BYTES 0x3d4
#define DSI_BYTES 0x3fa
#define PS2_PCI_SUBSTREAM_ID 0x00
#define PS2_DSI_SUBSTREAM_ID 0x01
/* Remove this */
#define DSI_START_BYTE 1031
#if PRAGMA_PACK
#pragma pack(1)
#endif
/**
* PCI General Information
*/
typedef struct {
uint32_t nv_pck_lbn;
uint16_t vobu_cat;
uint16_t zero1;
user_ops_t vobu_uop_ctl;
uint32_t vobu_s_ptm;
uint32_t vobu_e_ptm;
uint32_t vobu_se_e_ptm;
dvd_time_t e_eltm;
char vobu_isrc[32];
} ATTRIBUTE_PACKED pci_gi_t;
/**
* Non Seamless Angle Information
*/
typedef struct {
uint32_t nsml_agl_dsta[9];
} ATTRIBUTE_PACKED nsml_agli_t;
/**
* Highlight General Information
*/
typedef struct {
uint16_t hli_ss; // only low 2 bits
uint32_t hli_s_ptm;
uint32_t hli_e_ptm;
uint32_t btn_se_e_ptm;
#ifdef WORDS_BIGENDIAN
unsigned int zero1 : 2;
unsigned int btngr_ns : 2;
unsigned int zero2 : 1;
unsigned int btngr1_dsp_ty : 3;
unsigned int zero3 : 1;
unsigned int btngr2_dsp_ty : 3;
unsigned int zero4 : 1;
unsigned int btngr3_dsp_ty : 3;
#else
unsigned int btngr1_dsp_ty : 3;
unsigned int zero2 : 1;
unsigned int btngr_ns : 2;
unsigned int zero1 : 2;
unsigned int btngr3_dsp_ty : 3;
unsigned int zero4 : 1;
unsigned int btngr2_dsp_ty : 3;
unsigned int zero3 : 1;
#endif
uint8_t btn_ofn;
uint8_t btn_ns; // only low 6 bits
uint8_t nsl_btn_ns; // only low 6 bits
uint8_t zero5;
uint8_t fosl_btnn; // only low 6 bits
uint8_t foac_btnn; // only low 6 bits
} ATTRIBUTE_PACKED hl_gi_t;
/**
* Button Color Information Table
*/
typedef struct {
uint32_t btn_coli[3][2];
} ATTRIBUTE_PACKED btn_colit_t;
/*
btn_coln 11000000 00000000 00000000 00000000 00000000 00000000
x_start 00111111 11110000 00000000 00000000 00000000 00000000
zero1 00000000 00001100 00000000 00000000 00000000 00000000
x_end 00000000 00000011 11111111 00000000 00000000 00000000
auto_action_mode 00000000 00000000 00000000 11000000 00000000 00000000
y_start 00000000 00000000 00000000 00111111 11110000 00000000
zero2 00000000 00000000 00000000 00000000 00001100 00000000
y_end 00000000 00000000 00000000 00000000 00000011 11111111
unsigned int btn_coln : 2; // 0 - m[0]>>6
unsigned int x_start : 10; // 2 - m[0]<<4 | m[1]>>4
unsigned int zero1 : 2; // 12 - m[1]>>2
unsigned int x_end : 10; // 14 - m[1]<<8 | m[2]
unsigned int auto_action_mode : 2; // 24 - m[3]>>6
unsigned int y_start : 10; // 26 - m[3]<<4 | m[4]>>4
unsigned int zero2 : 2; // 36 - m[4]>>2
unsigned int y_end : 10; // 38 - m[4]<<8 | m[5]
*/
/**
* Button Information
*/
typedef struct {
#if 0 /* Wierd Sun CC code that does not work */
unsigned int zero1 : 2;
unsigned int x_start : 10;
unsigned int x_end : 10;
unsigned int y_start : 10;
unsigned int zero2 : 2;
unsigned int btn_coln : 2;
unsigned int auto_action_mode : 2;
unsigned int y_end : 10;
#endif
#ifdef WORDS_BIGENDIAN
unsigned int btn_coln : 2;
unsigned int x_start : 10;
unsigned int zero1 : 2;
unsigned int x_end : 10;
unsigned int auto_action_mode : 2;
unsigned int y_start : 10;
unsigned int zero2 : 2;
unsigned int y_end : 10;
unsigned int zero3 : 2;
unsigned int up : 6;
unsigned int zero4 : 2;
unsigned int down : 6;
unsigned int zero5 : 2;
unsigned int left : 6;
unsigned int zero6 : 2;
unsigned int right : 6;
#else
unsigned int x_end : 10;
unsigned int zero1 : 2;
unsigned int x_start : 10;
unsigned int btn_coln : 2;
unsigned int y_end : 10;
unsigned int zero2 : 2;
unsigned int y_start : 10;
unsigned int auto_action_mode : 2;
unsigned int up : 6;
unsigned int zero3 : 2;
unsigned int down : 6;
unsigned int zero4 : 2;
unsigned int left : 6;
unsigned int zero5 : 2;
unsigned int right : 6;
unsigned int zero6 : 2;
#endif
vm_cmd_t cmd;
} ATTRIBUTE_PACKED btni_t;
/**
* Highlight Information
*/
typedef struct {
hl_gi_t hl_gi;
btn_colit_t btn_colit;
btni_t btnit[36];
} ATTRIBUTE_PACKED hli_t;
/**
* PCI packet
*/
typedef struct {
pci_gi_t pci_gi;
nsml_agli_t nsml_agli;
hli_t hli;
uint8_t zero1[189];
} ATTRIBUTE_PACKED pci_t;
/**
* DSI General Information
*/
typedef struct {
uint32_t nv_pck_scr;
uint32_t nv_pck_lbn;
uint32_t vobu_ea;
uint32_t vobu_1stref_ea;
uint32_t vobu_2ndref_ea;
uint32_t vobu_3rdref_ea;
uint16_t vobu_vob_idn;
uint8_t zero1;
uint8_t vobu_c_idn;
dvd_time_t c_eltm;
} ATTRIBUTE_PACKED dsi_gi_t;
/**
* Seamless Playback Information
*/
typedef struct {
uint16_t category; // category of seamless VOBU
uint32_t ilvu_ea; // end address of interleaved Unit (sectors)
uint32_t ilvu_sa; // start address of next interleaved unit (sectors)
uint16_t size; // size of next interleaved unit (sectors)
uint32_t vob_v_s_s_ptm; /* video start ptm in vob */
uint32_t vob_v_e_e_ptm; /* video end ptm in vob */
struct {
uint32_t stp_ptm1;
uint32_t stp_ptm2;
uint32_t gap_len1;
uint32_t gap_len2;
} vob_a[8];
} ATTRIBUTE_PACKED sml_pbi_t;
/**
* Seamless Angle Infromation for one angle
*/
typedef struct {
uint32_t address; // Sector offset to next ILVU, high bit is before/after
uint16_t size; // Byte size of the ILVU poited to by address.
} ATTRIBUTE_PACKED sml_agl_data_t;
/**
* Seamless Angle Infromation
*/
typedef struct {
sml_agl_data_t data[9];
} ATTRIBUTE_PACKED sml_agli_t;
/**
* VOBU Search Information
*/
typedef struct {
uint32_t next_video; // Next vobu that contains video
uint32_t fwda[19]; // Forwards, time
uint32_t next_vobu;
uint32_t prev_vobu;
uint32_t bwda[19]; // Backwards, time
uint32_t prev_video;
} ATTRIBUTE_PACKED vobu_sri_t;
#define SRI_END_OF_CELL 0x3fffffff
/**
* Synchronous Information
*/
typedef struct {
uint16_t a_synca[8]; // Sector offset to first audio packet for this VOBU
uint32_t sp_synca[32]; // Sector offset to first subpicture packet
} ATTRIBUTE_PACKED synci_t;
/**
* DSI packet
*/
typedef struct {
dsi_gi_t dsi_gi;
sml_pbi_t sml_pbi;
sml_agli_t sml_agli;
vobu_sri_t vobu_sri;
synci_t synci;
uint8_t zero1[471];
} ATTRIBUTE_PACKED dsi_t;
#if PRAGMA_PACK
#pragma pack()
#endif
#endif /* NAV_TYPES_H_INCLUDED */
More information about the MPlayer-cvslog
mailing list