@ -2,7 +2,7 @@
* dvd_ioctl . c : DVD ioctl replacement function
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright ( C ) 1999 - 2001 VideoLAN
* $ Id : dvd_ioctl . c , v 1.1 2001 / 02 / 20 07 : 49 : 12 sam Exp $
* $ Id : dvd_ioctl . c , v 1.2 2001 / 02 / 26 12 : 16 : 28 sam Exp $
*
* Authors : Markus Kuespert < ltlBeBoy @ beosmail . com >
* Samuel Hocevar < sam @ zoy . org >
@ -48,24 +48,23 @@
# include "dvd_ioctl.h"
/*****************************************************************************
* Local prototypes
* Local prototypes - BeOS specific
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# if defined( SYS_BEOS )
static int dvd_do_auth ( int i_fd , dvd_authinfo * p_authinfo ) ;
static int dvd_read_struct ( int i_fd , dvd_struct * p_dvd ) ;
static int dvd_read_physical ( int i_fd , dvd_struct * p_dvd ) ;
static int dvd_read_copyright ( int i_fd , dvd_struct * p_dvd ) ;
static int dvd_read_disckey ( int i_fd , dvd_struct * p_dvd ) ;
static int dvd_read_bca ( int i_fd , dvd_struct * p_dvd ) ;
static int dvd_read_manufact ( int i_fd , dvd_struct * p_dvd ) ;
static int communicate_with_dvd ( int i_fd ,
struct cdrom_generic_command * p_cgc ) ;
static void init_cdrom_command ( struct cdrom_generic_command * p_cgc ,
void * buf , int i_len , int i_type ) ;
static void setup_report_key ( struct cdrom_generic_command * p_cgc ,
unsigned i_agid , unsigned i_type ) ;
static void setup_send_key ( struct cdrom_generic_command * p_cgc ,
unsigned i_agid , unsigned i_type ) ;
static int ReadData ( int i_fd , dvd_struct * p_dvd ) ;
static int ReadCopyright ( int i_fd , dvd_struct * p_dvd ) ;
static int ReadKey ( int i_fd , dvd_struct * p_dvd ) ;
static int ReadBCA ( int i_fd , dvd_struct * p_dvd ) ;
static int ReadManufacturer ( int i_fd , dvd_struct * p_dvd ) ;
static void InitGenericCommand ( struct cdrom_generic_command * p_cgc ,
void * buf , int i_len , int i_type ) ;
static void InitReadCommand ( struct cdrom_generic_command * p_cgc ,
unsigned i_agid , unsigned i_type ) ;
static void InitWriteCommand ( struct cdrom_generic_command * p_cgc ,
unsigned i_agid , unsigned i_type ) ;
static int SendCommand ( int i_fd , struct cdrom_generic_command * p_cgc ) ;
# endif
/*****************************************************************************
@ -80,382 +79,262 @@ int dvd_ioctl( int i_fd, unsigned long i_op, void *p_arg )
return ( ioctl ( i_fd , i_op , p_arg ) ) ;
# elif defined( SYS_BEOS )
switch ( i_op )
{
case DVD_AUTH :
return dvd_do_auth ( i_fd , ( dvd_authinfo * ) p_arg ) ;
case DVD_READ_STRUCT :
return dvd_read_struct ( i_fd , ( dvd_struct * ) p_arg ) ;
default :
intf_ErrMsg ( " css error: unknown command 0x%x " , i_op ) ;
return - 1 ;
}
# else
int i_ret ;
unsigned char buf [ 20 ] ;
return - 1 ;
# endif
}
struct cdrom_generic_command p_cgc ;
# if defined( SYS_BEOS )
dvd_struct * p_dvd = ( dvd_struct * ) p_arg ;
dvd_authinfo * p_authinfo = ( dvd_authinfo * ) p_arg ;
/*****************************************************************************
* setup_report_key
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void setup_report_key ( struct cdrom_generic_command * p_cgc ,
unsigned i_agid , unsigned i_type )
{
p_cgc - > cmd [ 0 ] = GPCMD_REPORT_KEY ;
p_cgc - > cmd [ 10 ] = i_type | ( i_agid < < 6 ) ;
switch ( i_type )
switch ( i_op )
{
case 0 :
case 8 :
case 5 :
p_cgc - > buflen = 8 ;
break ;
case DVD_AUTH : /* Request type is "authentication" */
{
memset ( buf , 0 , sizeof ( buf ) ) ;
InitGenericCommand ( & p_cgc , buf , 0 , CGC_DATA_READ ) ;
case 1 :
p_cgc - > buflen = 16 ;
break ;
switch ( p_authinfo - > type )
{
case DVD_LU_SEND_AGID : /* LU data send */
case 2 :
case 4 :
p_cgc - > buflen = 12 ;
break ;
}
intf_WarnMsg ( 2 , " css DoAuth: DVD_LU_SEND_AGID " ) ;
p_cgc - > cmd [ 9 ] = p_cgc - > buflen ;
p_cgc - > data_direction = CGC_DATA_READ ;
}
InitReadCommand ( & p_cgc , p_authinfo - > lsa . agid , 0 ) ;
/*****************************************************************************
* setup_send_key
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void setup_send_key ( struct cdrom_generic_command * p_cgc ,
unsigned i_agid , unsigned i_type )
{
p_cgc - > cmd [ 0 ] = GPCMD_SEND_KEY ;
p_cgc - > cmd [ 10 ] = i_type | ( i_agid < < 6 ) ;
i_ret = SendCommand ( i_fd , & p_cgc ) ;
switch ( i_type )
{
case 1 :
p_cgc - > buflen = 16 ;
break ;
p_authinfo - > lsa . agid = buf [ 7 ] > > 6 ;
case 3 :
p_cgc - > buflen = 12 ;
break ;
return i_ret ;
case 6 :
p_cgc - > buflen = 8 ;
break ;
}
case DVD_LU_SEND_KEY1 :
p_cgc - > cmd [ 9 ] = p_cgc - > buflen ;
p_cgc - > data_direction = CGC_DATA_WRITE ;
}
intf_WarnMsg ( 2 , " css DoAuth: DVD_LU_SEND_KEY1 " ) ;
/*****************************************************************************
* init_cdrom_command
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void init_cdrom_command ( struct cdrom_generic_command * p_cgc ,
void * buf , int i_len , int i_type )
{
memset ( p_cgc , 0 , sizeof ( struct cdrom_generic_command ) ) ;
InitReadCommand ( & p_cgc , p_authinfo - > lsk . agid , 2 ) ;
if ( buf )
{
memset ( buf , 0 , i_len ) ;
}
i_ret = SendCommand ( i_fd , & p_cgc ) ;
p_cgc - > buffer = ( char * ) buf ;
p_cgc - > buflen = i_len ;
p_cgc - > data_direction = i_type ;
p_cgc - > timeout = 255 ;
}
/* Copy the key */
memcpy ( p_authinfo - > lsk . key , & buf [ 4 ] , sizeof ( dvd_key ) ) ;
/* DVD handling */
return i_ret ;
/*****************************************************************************
* dvd_do_auth
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int dvd_do_auth ( int i_fd , dvd_authinfo * p_authinfo )
{
int i_ret ;
unsigned char buf [ 20 ] ;
struct cdrom_generic_command p_cgc ;
case DVD_LU_SEND_CHALLENGE :
# define copy_key(dest,src) memcpy((dest), (src), sizeof(dvd_key))
# define copy_chal(dest,src) memcpy((dest), (src), sizeof(dvd_challenge))
intf_WarnMsg ( 2 , " css DoAuth: DVD_LU_SEND_CHALLENGE " ) ;
#if 0
struct rpc_state_t rpc_state ;
# endif
InitReadCommand ( & p_cgc , p_authinfo - > lsc . agid , 1 ) ;
memset ( buf , 0 , sizeof ( buf ) ) ;
init_cdrom_command ( & p_cgc , buf , 0 , CGC_DATA_READ ) ;
i_ret = SendCommand ( i_fd , & p_cgc ) ;
switch ( p_authinfo - > type )
{
/* LU data send */
case DVD_LU_SEND_AGID :
/* Copy the challenge */
memcpy ( p_authinfo - > lsc . chal , & buf [ 4 ] ,
sizeof ( dvd_challenge ) ) ;
intf_WarnMsg ( 2 , " css dvd_do_auth: DVD_LU_SEND_AGID " ) ;
return i_ret ;
setup_report_key ( & p_cgc , p_authinfo - > lsa . agid , 0 ) ;
case DVD_LU_SEND_TITLE_KEY : /* Post-auth key */
/* handle uniform packets for scsi type devices (scsi,atapi) */
if ( ( i_ret = communicate_with_dvd ( i_fd , & p_cgc ) ) )
{
return i_ret ;
}
intf_WarnMsg ( 2 , " css DoAuth: DVD_LU_SEND_TITLE_KEY " ) ;
p_authinfo - > lsa . agid = buf [ 7 ] > > 6 ;
/* Returning data, let host change state */
InitReadCommand ( & p_cgc , p_authinfo - > lstk . agid , 4 ) ;
break ;
p_cgc . cmd [ 5 ] = p_authinfo - > lstk . lba ;
p_cgc . cmd [ 4 ] = p_authinfo - > lstk . lba > > 8 ;
p_cgc . cmd [ 3 ] = p_authinfo - > lstk . lba > > 16 ;
p_cgc . cmd [ 2 ] = p_authinfo - > lstk . lba > > 24 ;
case DVD_LU_SEND_KEY1 :
i_ret = SendCommand ( i_fd , & p_cgc ) ;
intf_WarnMsg ( 2 , " css dvd_do_auth: DVD_LU_SEND_KEY1 " ) ;
p_authinfo - > lstk . cpm = ( buf [ 4 ] > > 7 ) & 1 ;
p_authinfo - > lstk . cp_sec = ( buf [ 4 ] > > 6 ) & 1 ;
p_authinfo - > lstk . cgms = ( buf [ 4 ] > > 4 ) & 3 ;
setup_report_key ( & p_cgc , p_authinfo - > lsk . agid , 2 ) ;
/* Copy the key */
memcpy ( p_authinfo - > lstk . title_key , & buf [ 5 ] ,
sizeof ( dvd_key ) ) ;
/* handle uniform packets for scsi type devices (scsi,atapi) */
if ( ( i_ret = communicate_with_dvd ( i_fd , & p_cgc ) ) )
{
return i_ret ;
}
return i_ret ;
copy_key ( p_authinfo - > lsk . key , & buf [ 4 ] ) ;
/* Returning data, let host change state */
case DVD_LU_SEND_ASF :
break ;
intf_WarnMsg ( 2 , " css DoAuth: DVD_LU_SEND_ASF " ) ;
case DVD_LU_SEND_CHALLENGE :
InitReadCommand ( & p_cgc , p_authinfo - > lsasf . agid , 5 ) ;
intf_WarnMsg ( 2 , " css dvd_do_auth: DVD_LU_SEND_CHALLENGE " ) ;
i_ret = SendCommand ( i_fd , & p_cgc ) ;
setup_report_key ( & p_cgc , p_authinfo - > lsc . agid , 1 ) ;
p_authinfo - > lsasf . asf = buf [ 7 ] & 1 ;
/* handle uniform packets for scsi type devices (scsi,atapi) */
if ( ( i_ret = communicate_with_dvd ( i_fd , & p_cgc ) ) )
{
return i_ret ;
}
copy_chal ( p_authinfo - > lsc . chal , & buf [ 4 ] ) ;
/* Returning data, let host change state */
return i_ret ;
break ;
case DVD_HOST_SEND_CHALLENGE : /* LU data receive */
/* Post-auth key */
case DVD_LU_SEND_TITLE_KEY :
intf_WarnMsg ( 2 , " css DoAuth: DVD_LU_SEND_CHALLENGE " ) ;
intf_WarnMsg ( 2 , " css dvd_do_auth: DVD_LU_SEND_TITLE_KEY " ) ;
InitWriteCommand ( & p_cgc , p_authinfo - > hsc . agid , 1 ) ;
buf [ 1 ] = 0xe ;
setup_report_key ( & p_cgc , p_authinfo - > lstk . agid , 4 ) ;
p_cgc . cmd [ 5 ] = p_authinfo - > lstk . lba ;
p_cgc . cmd [ 4 ] = p_authinfo - > lstk . lba > > 8 ;
p_cgc . cmd [ 3 ] = p_authinfo - > lstk . lba > > 16 ;
p_cgc . cmd [ 2 ] = p_authinfo - > lstk . lba > > 24 ;
/* handle uniform packets for scsi type devices (scsi,atapi) */
if ( ( i_ret = communicate_with_dvd ( i_fd , & p_cgc ) ) )
{
return i_ret ;
}
p_authinfo - > lstk . cpm = ( buf [ 4 ] > > 7 ) & 1 ;
p_authinfo - > lstk . cp_sec = ( buf [ 4 ] > > 6 ) & 1 ;
p_authinfo - > lstk . cgms = ( buf [ 4 ] > > 4 ) & 3 ;
copy_key ( p_authinfo - > lstk . title_key , & buf [ 5 ] ) ;
/* Returning data, let host change state */
break ;
/* Copy the challenge */
memcpy ( & buf [ 4 ] , p_authinfo - > hsc . chal ,
sizeof ( dvd_challenge ) ) ;
case DVD_LU_SEND_ASF :
if ( ( i_ret = SendCommand ( i_fd , & p_cgc ) ) )
{
return i_ret ;
}
intf_WarnMsg ( 2 , " css dvd_do_auth: DVD_LU_SEND_ASF " ) ;
p_authinfo - > type = DVD_LU_SEND_KEY1 ;
setup_report_key ( & p_cgc , p_authinfo - > lsasf . agid , 5 ) ;
return 0 ;
/* handle uniform packets for scsi type devices (scsi,atapi) */
if ( ( i_ret = communicate_with_dvd ( i_fd , & p_cgc ) ) )
{
return i_ret ;
}
case DVD_HOST_SEND_KEY2 :
p_authinfo - > lsasf . asf = buf [ 7 ] & 1 ;
intf_WarnMsg ( 2 , " css DoAuth: DVD_LU_SEND_KEY2 " ) ;
break ;
InitWriteCommand ( & p_cgc , p_authinfo - > hsk . agid , 3 ) ;
buf [ 1 ] = 0xa ;
/* LU data receive (LU changes state) */
case DVD_HOST_SEND_CHALLENGE :
/* Copy the key */
memcpy ( & buf [ 4 ] , p_authinfo - > hsk . key , sizeof ( dvd_key ) ) ;
intf_WarnMsg ( 2 , " css dvd_do_auth: DVD_LU_SEND_CHALLENGE " ) ;
if ( ( i_ret = SendCommand ( i_fd , & p_cgc ) ) )
{
p_authinfo - > type = DVD_AUTH_FAILURE ;
return i_ret ;
}
setup_send_key ( & p_cgc , p_authinfo - > hsc . agid , 1 ) ;
buf [ 1 ] = 0xe ;
copy_chal ( & buf [ 4 ] , p_authinfo - > hsc . chal ) ;
p_authinfo - > type = DVD_AUTH_ESTABLISHED ;
/* handle uniform packets for scsi type devices (scsi,atapi) */
if ( ( i_ret = communicate_with_dvd ( i_fd , & p_cgc ) ) )
{
return i_ret ;
}
return 0 ;
p_authinfo - > type = DVD_LU_SEND_KEY1 ;
case DVD_INVALIDATE_AGID : /* Misc */
break ;
intf_WarnMsg ( 2 , " css DoAuth: DVD_INVALIDATE_AGID " ) ;
case DVD_HOST_SEND_KEY2 :
InitReadCommand ( & p_cgc , p_authinfo - > lsa . agid , 0x3f ) ;
intf_WarnMsg ( 2 , " css dvd_do_auth: DVD_LU_SEND_KEY2 " ) ;
return SendCommand ( i_fd , & p_cgc ) ;
setup_send_key ( & p_cgc , p_authinfo - > hsk . agid , 3 ) ;
buf [ 1 ] = 0xa ;
copy_key ( & buf [ 4 ] , p_authinfo - > hsk . key ) ;
case DVD_LU_SEND_RPC_STATE : /* Get region settings */
/* handle uniform packets for scsi type devices (scsi,atapi) */
if ( ( i_ret = communicate_with_dvd ( i_fd , & p_cgc ) ) )
{
p_authinfo - > type = DVD_AUTH_FAILURE ;
return i_ret ;
}
p_authinfo - > type = DVD_AUTH_ESTABLISHED ;
intf_WarnMsg ( 2 , " css DoAuth: DVD_LU_SEND_RPC_STATE "
" (unimplemented) " ) ;
break ;
#if 0
p_dvdetup_report_key ( & p_cgc , 0 , 8 ) ;
memset ( & rpc_state , 0 , sizeof ( rpc_state_t ) ) ;
p_cgc . buffer = ( char * ) & rpc_state ;
/* Misc */
case DVD_INVALIDATE_AGID :
if ( ( i_ret = SendCommand ( i_fd , & p_cgc ) ) )
{
return i_ret ;
}
intf_WarnMsg ( 2 , " css dvd_do_auth: DVD_INVALIDATE_AGID " ) ;
p_authinfo - > lrpcs . type = rpc_state . type_code ;
p_authinfo - > lrpcs . vra = rpc_state . vra ;
p_authinfo - > lrpcs . ucca = rpc_state . ucca ;
p_authinfo - > lrpcs . region_mask = rpc_state . region_mask ;
p_authinfo - > lrpcs . rpc_scheme = rpc_state . rpc_scheme ;
# endif
setup_report_key ( & p_cgc , p_authinfo - > lsa . agid , 0x3f ) ;
return 0 ;
/* handle uniform packets for scsi type devices (scsi,atapi) */
if ( ( i_ret = communicate_with_dvd ( i_fd , & p_cgc ) ) )
{
return i_ret ;
}
case DVD_HOST_SEND_RPC_STATE : /* Set region settings */
break ;
intf_WarnMsg ( 2 , " css DoAuth: DVD_HOST_SEND_RPC_STATE " ) ;
/* Get region settings */
case DVD_LU_SEND_RPC_STATE :
InitWriteCommand ( & p_cgc , 0 , 6 ) ;
buf [ 1 ] = 6 ;
buf [ 4 ] = p_authinfo - > hrpcs . pdrc ;
intf_WarnMsg ( 2 , " css dvd_do_auth: DVD_LU_SEND_RPC_STATE "
" (unimplemented) " ) ;
return SendCommand ( i_fd , & p_cgc ) ;
#if 0
p_dvdetup_report_key ( & p_cgc , 0 , 8 ) ;
memset ( & rpc_state , 0 , sizeof ( rpc_state_t ) ) ;
p_cgc . buffer = ( char * ) & rpc_state ;
default :
intf_ErrMsg ( " css DoAuth: invalid DVD key ioctl " ) ;
return - 1 ;
/* handle uniform packets for scsi type devices (scsi,atapi) */
if ( ( i_ret = communicate_with_dvd ( i_fd , & p_cgc ) ) )
{
return i_ret ;
}
}
p_authinfo - > lrpcs . type = rpc_state . type_code ;
p_authinfo - > lrpcs . vra = rpc_state . vra ;
p_authinfo - > lrpcs . ucca = rpc_state . ucca ;
p_authinfo - > lrpcs . region_mask = rpc_state . region_mask ;
p_authinfo - > lrpcs . rpc_scheme = rpc_state . rpc_scheme ;
# endif
case DVD_READ_STRUCT : /* Request type is "read structure" */
{
switch ( p_dvd - > type )
{
case DVD_STRUCT_PHYSICAL :
break ;
intf_WarnMsg ( 2 , " css ReadStruct: DVD_STRUCT_PHYSICAL " ) ;
/* Set region settings */
case DVD_HOST_SEND_RPC_STATE :
return ReadData ( i_fd , p_dvd ) ;
intf_WarnMsg ( 2 , " css dvd_do_auth: DVD_HOST_SEND_RPC_STATE " ) ;
case DVD_STRUCT_COPYRIGHT :
setup_send_key ( & p_cgc , 0 , 6 ) ;
buf [ 1 ] = 6 ;
buf [ 4 ] = p_authinfo - > hrpcs . pdrc ;
intf_WarnMsg ( 2 , " css ReadStruct: DVD_STRUCT_COPYRIGHT " ) ;
/* handle uniform packets for scsi type devices (scsi,atapi) */
if ( ( i_ret = communicate_with_dvd ( i_fd , & p_cgc ) ) )
{
return i_ret ;
}
return ReadCopyright ( i_fd , p_dvd ) ;
break ;
case DVD_STRUCT_DISCKEY :
default :
intf_ErrMsg ( " css dvd_do_auth: invalid DVD key ioctl " ) ;
return - 1 ;
intf_WarnMsg ( 2 , " css ReadStruct: DVD_STRUCT_DISCKEY " ) ;
}
return ReadKey ( i_fd , p_dvd ) ;
return 0 ;
}
case DVD_STRUCT_BCA :
/*****************************************************************************
* dvd_read_struct
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int dvd_read_struct ( int i_fd , dvd_struct * p_dvd )
{
switch ( p_dvd - > type )
{
case DVD_STRUCT_PHYSICAL :
intf_WarnMsg ( 2 , " css dvd_read_struct: DVD_STRUCT_PHYSICAL " ) ;
return dvd_read_physical ( i_fd , p_dvd ) ;
case DVD_STRUCT_COPYRIGHT :
intf_WarnMsg ( 2 , " css dvd_read_struct: DVD_STRUCT_COPYRIGHT " ) ;
return dvd_read_copyright ( i_fd , p_dvd ) ;
intf_WarnMsg ( 2 , " css ReadStruct: DVD_STRUCT_BCA " ) ;
case DVD_STRUCT_DISCKEY :
return ReadBCA ( i_fd , p_dvd ) ;
intf_WarnMsg ( 2 , " css dvd_read_struct: DVD_STRUCT_DISCKEY " ) ;
return dvd_read_disckey ( i_fd , p_dvd ) ;
case DVD_STRUCT_MANUFACT :
case DVD_STRUCT_BCA :
intf_WarnMsg ( 2 , " css ReadStruct: DVD_STRUCT_MANUFACT " ) ;
intf_WarnMsg ( 2 , " css dvd_read_struct: DVD_STRUCT_BCA " ) ;
return dvd_read_bca ( i_fd , p_dvd ) ;
return ReadManufacturer ( i_fd , p_dvd ) ;
case DVD_STRUCT_MANUFACT :
default :
intf_WarnMsg ( 2 , " css ReadStruct: invalid request (%d) " ,
p_dvd - > type ) ;
intf_WarnMsg ( 2 , " css dvd_read_struct: DVD_STRUCT_MANUFACT " ) ;
return dvd_read_manufact ( i_fd , p_dvd ) ;
return - 1 ;
}
}
default :
intf_WarnMsg ( 2 , " css dvd_read_struct: invalid request (%d) " ,
p_dvd - > type ) ;
default : /* Unknown request type */
{
intf_ErrMsg ( " css error: unknown command 0x%x " , i_op ) ;
return - 1 ;
}
}
# else
return - 1 ;
# endif
}
/* Local prototypes */
# if defined( SYS_BEOS )
/*****************************************************************************
* dvd_read_physical
* ReadData : Get data structure information from the DVD .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int dvd_read_physical ( int i_fd , dvd_struct * p_dvd )
static int ReadData ( int i_fd , dvd_struct * p_dvd )
{
int i_ret , i ;
u_char buf [ 4 + 4 * 20 ] , * base ;
struct dvd_layer * layer ;
struct cdrom_generic_command cgc ;
init_cdrom_c ommand( & cgc , buf , sizeof ( buf ) , CGC_DATA_READ ) ;
InitGenericC ommand( & cgc , buf , sizeof ( buf ) , CGC_DATA_READ ) ;
cgc . cmd [ 0 ] = GPCMD_READ_DVD_STRUCTURE ;
cgc . cmd [ 6 ] = p_dvd - > physical . layer_num ;
cgc . cmd [ 7 ] = p_dvd - > type ;
cgc . cmd [ 9 ] = cgc . buflen & 0xff ;
/* handle uniform packets for scsi type devices (scsi,atapi) */
if ( ( i_ret = communicate_with_dvd ( i_fd , & cgc ) ) )
if ( ( i_ret = SendCommand ( i_fd , & cgc ) ) )
{
return i_ret ;
}
@ -488,15 +367,15 @@ static int dvd_read_physical( int i_fd, dvd_struct *p_dvd )
}
/*****************************************************************************
* dvd_read_copyright
* ReadCopyright : get copyright information from the DVD .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int dvd_read_c opyright( int i_fd , dvd_struct * p_dvd )
static int ReadC opyright( int i_fd , dvd_struct * p_dvd )
{
int i_ret ;
u_char buf [ 8 ] ;
struct cdrom_generic_command cgc ;
init_cdrom_c ommand( & cgc , buf , sizeof ( buf ) , CGC_DATA_READ ) ;
InitGenericC ommand( & cgc , buf , sizeof ( buf ) , CGC_DATA_READ ) ;
cgc . cmd [ 0 ] = GPCMD_READ_DVD_STRUCTURE ;
cgc . cmd [ 6 ] = p_dvd - > copyright . layer_num ;
@ -504,8 +383,7 @@ static int dvd_read_copyright( int i_fd, dvd_struct *p_dvd )
cgc . cmd [ 8 ] = cgc . buflen > > 8 ;
cgc . cmd [ 9 ] = cgc . buflen & 0xff ;
/* handle uniform packets for scsi type devices (scsi,atapi) */
if ( ( i_ret = communicate_with_dvd ( i_fd , & cgc ) ) )
if ( ( i_ret = SendCommand ( i_fd , & cgc ) ) )
{
return i_ret ;
}
@ -517,9 +395,9 @@ static int dvd_read_copyright( int i_fd, dvd_struct *p_dvd )
}
/*****************************************************************************
* dvd_read_disckey
* ReadKey : get a key from the DVD .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int dvd_read_disck ey( int i_fd , dvd_struct * p_dvd )
static int ReadK ey( int i_fd , dvd_struct * p_dvd )
{
int i_ret , size ;
u_char * buf ;
@ -533,17 +411,17 @@ static int dvd_read_disckey( int i_fd, dvd_struct *p_dvd )
return - ENOMEM ;
}
# endif
buf = ( u_char * ) malloc ( size ) ;
buf = ( u_char * ) malloc ( size ) ;
InitGenericCommand ( & cgc , buf , size , CGC_DATA_READ ) ;
init_cdrom_command ( & cgc , buf , size , CGC_DATA_READ ) ;
cgc . cmd [ 0 ] = GPCMD_READ_DVD_STRUCTURE ;
cgc . cmd [ 7 ] = p_dvd - > type ;
cgc . cmd [ 8 ] = size > > 8 ;
cgc . cmd [ 9 ] = size & 0xff ;
cgc . cmd [ 10 ] = p_dvd - > disckey . agid < < 6 ;
/* handle uniform packets for scsi type devices (scsi,atapi) */
if ( ! ( i_ret = communicate_with_dvd ( i_fd , & cgc ) ) )
if ( ! ( i_ret = SendCommand ( i_fd , & cgc ) ) )
{
memcpy ( p_dvd - > disckey . value , & buf [ 4 ] , sizeof ( p_dvd - > disckey . value ) ) ;
}
@ -553,21 +431,24 @@ static int dvd_read_disckey( int i_fd, dvd_struct *p_dvd )
}
/*****************************************************************************
* dvd_read_bca
* ReadBCA : read the Burst Cutting Area of a DVD .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* The BCA is a special part of the DVD which is used to burn additional
* data after it has been manufactured . DIVX is an exemple .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int dvd_read_bca ( int i_fd , dvd_struct * p_dvd )
static int ReadBCA ( int i_fd , dvd_struct * p_dvd )
{
int i_ret ;
u_char buf [ 4 + 188 ] ;
struct cdrom_generic_command cgc ;
init_cdrom_command ( & cgc , buf , sizeof ( buf ) , CGC_DATA_READ ) ;
InitGenericCommand ( & cgc , buf , sizeof ( buf ) , CGC_DATA_READ ) ;
cgc . cmd [ 0 ] = GPCMD_READ_DVD_STRUCTURE ;
cgc . cmd [ 7 ] = p_dvd - > type ;
cgc . cmd [ 9 ] = cgc . buflen = 0xff ;
/* handle uniform packets for scsi type devices (scsi,atapi) */
if ( ( i_ret = communicate_with_dvd ( i_fd , & cgc ) ) )
if ( ( i_ret = SendCommand ( i_fd , & cgc ) ) )
{
return i_ret ;
}
@ -575,7 +456,7 @@ static int dvd_read_bca( int i_fd, dvd_struct *p_dvd )
p_dvd - > bca . len = buf [ 0 ] < < 8 | buf [ 1 ] ;
if ( p_dvd - > bca . len < 12 | | p_dvd - > bca . len > 188 )
{
intf_ErrMsg ( " css error: invalid BCA length (%d) " , p_dvd - > bca . len ) ;
intf_ErrMsg ( " css error: invalid BCA length (%d) " , p_dvd - > bca . len ) ;
return - 1 ;
}
@ -585,15 +466,15 @@ static int dvd_read_bca( int i_fd, dvd_struct *p_dvd )
}
/*****************************************************************************
* dvd_read_manufact
* ReadManufacturer : get manufacturer information from the DVD .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int dvd_read_manufact ( int i_fd , dvd_struct * p_dvd )
static int ReadManufacturer ( int i_fd , dvd_struct * p_dvd )
{
int i_ret = 0 , size ;
u_char * buf ;
struct cdrom_generic_command cgc ;
size = sizeof ( p_dvd - > manufact . value ) + 4 ;
size = sizeof ( p_dvd - > manufact . value ) + 4 ;
#if 0
if ( ( buf = ( u_char * ) kmalloc ( size , GFP_KERNEL ) ) = = NULL )
@ -603,14 +484,14 @@ static int dvd_read_manufact( int i_fd, dvd_struct *p_dvd )
# endif
buf = ( u_char * ) malloc ( size ) ;
init_cdrom_command ( & cgc , buf , size , CGC_DATA_READ ) ;
InitGenericCommand ( & cgc , buf , size , CGC_DATA_READ ) ;
cgc . cmd [ 0 ] = GPCMD_READ_DVD_STRUCTURE ;
cgc . cmd [ 7 ] = p_dvd - > type ;
cgc . cmd [ 8 ] = size > > 8 ;
cgc . cmd [ 9 ] = size & 0xff ;
/* handle uniform packets for scsi type devices (scsi,atapi) */
if ( ( i_ret = communicate_with_dvd ( i_fd , & cgc ) ) )
if ( ( i_ret = SendCommand ( i_fd , & cgc ) ) )
{
return i_ret ;
}
@ -618,8 +499,8 @@ static int dvd_read_manufact( int i_fd, dvd_struct *p_dvd )
p_dvd - > manufact . len = buf [ 0 ] < < 8 | buf [ 1 ] ;
if ( p_dvd - > manufact . len < 0 | | p_dvd - > manufact . len > 2048 )
{
intf_ErrMsg ( " css error: invalid manufacturer info length "
" (%d) \n " , p_dvd - > bca . len ) ;
intf_ErrMsg ( " css error: invalid manufacturer info length (%d) " ,
p_dvd - > bca . len ) ;
i_ret = - 1 ;
}
else
@ -632,11 +513,104 @@ static int dvd_read_manufact( int i_fd, dvd_struct *p_dvd )
}
/*****************************************************************************
* communicate_with_dvd
* InitGenericCommand : initialize a CGC structure
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* This function initializes a CDRom Generic Command structure for
* future use , either a read command or a write command .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int communicate_with_dvd ( int i_fd ,
struct cdrom_generic_command * p_cgc )
static void InitGenericCommand ( struct cdrom_generic_command * p_cgc ,
void * buf , int i_len , int i_type )
{
memset ( p_cgc , 0 , sizeof ( struct cdrom_generic_command ) ) ;
if ( buf ! = NULL )
{
memset ( buf , 0 , i_len ) ;
}
p_cgc - > buffer = ( char * ) buf ;
p_cgc - > buflen = i_len ;
p_cgc - > data_direction = i_type ;
p_cgc - > timeout = 255 ;
}
/*****************************************************************************
* InitReadCommand : fill a CGC structure for reading purposes .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* This function fills a CDRom Generic Command for a command which will
* read data from the DVD .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void InitReadCommand ( struct cdrom_generic_command * p_cgc ,
unsigned i_agid , unsigned i_type )
{
p_cgc - > cmd [ 0 ] = GPCMD_REPORT_KEY ;
p_cgc - > cmd [ 10 ] = i_type | ( i_agid < < 6 ) ;
/* FIXME: check what i_type means */
switch ( i_type )
{
case 0 :
case 8 :
case 5 :
p_cgc - > buflen = 8 ;
break ;
case 1 :
p_cgc - > buflen = 16 ;
break ;
case 2 :
case 4 :
p_cgc - > buflen = 12 ;
break ;
}
p_cgc - > cmd [ 9 ] = p_cgc - > buflen ;
p_cgc - > data_direction = CGC_DATA_READ ;
}
/*****************************************************************************
* InitWriteCommand : fill a CGC structure for writing purposes .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* This function fills a CDRom Generic Command for a command which will
* send data to the DVD .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void InitWriteCommand ( struct cdrom_generic_command * p_cgc ,
unsigned i_agid , unsigned i_type )
{
p_cgc - > cmd [ 0 ] = GPCMD_SEND_KEY ;
p_cgc - > cmd [ 10 ] = i_type | ( i_agid < < 6 ) ;
/* FIXME: check what i_type means */
switch ( i_type )
{
case 1 :
p_cgc - > buflen = 16 ;
break ;
case 3 :
p_cgc - > buflen = 12 ;
break ;
case 6 :
p_cgc - > buflen = 8 ;
break ;
}
p_cgc - > cmd [ 9 ] = p_cgc - > buflen ;
p_cgc - > data_direction = CGC_DATA_WRITE ;
}
/*****************************************************************************
* SendCommand : send a raw device command to the DVD drive .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* This is the most important part of the ioctl emulation , the place where
* data is really sent to the DVD .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int SendCommand ( int i_fd , struct cdrom_generic_command * p_cgc )
{
int i ;
raw_device_command rdc ;
memset ( & rdc , 0 , sizeof ( rdc ) ) ;
@ -654,22 +628,14 @@ static int communicate_with_dvd( int i_fd,
}
rdc . command_length = 12 ;
rdc . command [ 0 ] = p_cgc - > cmd [ 0 ] ;
rdc . command [ 1 ] = p_cgc - > cmd [ 1 ] ;
rdc . command [ 2 ] = p_cgc - > cmd [ 2 ] ;
rdc . command [ 3 ] = p_cgc - > cmd [ 3 ] ;
rdc . command [ 4 ] = p_cgc - > cmd [ 4 ] ;
rdc . command [ 5 ] = p_cgc - > cmd [ 5 ] ;
rdc . command [ 6 ] = p_cgc - > cmd [ 6 ] ;
rdc . command [ 7 ] = p_cgc - > cmd [ 7 ] ;
rdc . command [ 8 ] = p_cgc - > cmd [ 8 ] ;
rdc . command [ 9 ] = p_cgc - > cmd [ 9 ] ;
rdc . command [ 10 ] = p_cgc - > cmd [ 10 ] ;
rdc . command [ 11 ] = p_cgc - > cmd [ 11 ] ;
rdc . command [ 12 ] = p_cgc - > cmd [ 12 ] ;
/* FIXME: check if this _really_ should go up to [12] */
for ( i = 0 ; i < 13 ; i + + )
{
rdc . command [ i ] = p_cgc - > cmd [ i ] ;
}
return ioctl ( i_fd , B_RAW_DEVICE_COMMAND , & rdc , sizeof ( rdc ) ) ;
}
# endif