1 /*****************************************************************************
2 * dvd_ioctl.c: DVD ioctl replacement function
3 *****************************************************************************
4 * Copyright (C) 1999-2001 VideoLAN
5 * $Id: dvd_ioctl.c,v 1.15 2001/05/31 01:37:08 sam Exp $
7 * Authors: Markus Kuespert <ltlBeBoy@beosmail.com>
8 * Samuel Hocevar <sam@zoy.org>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
23 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
30 #include <string.h> /* memcpy(), memset() */
31 #include <sys/types.h>
34 #include <netinet/in.h>
35 #include <sys/ioctl.h>
38 #ifdef DVD_STRUCT_IN_SYS_CDIO_H
39 # include <sys/cdio.h>
41 #ifdef DVD_STRUCT_IN_SYS_DVDIO_H
42 # include <sys/dvdio.h>
44 #ifdef DVD_STRUCT_IN_LINUX_CDROM_H
45 # include <linux/cdrom.h>
57 # include "DVDioctl/DVDioctl.h"
61 #include "dvd_ioctl.h"
63 /*****************************************************************************
64 * Local prototypes, BeOS specific
65 *****************************************************************************/
66 #if defined( SYS_BEOS )
67 static void BeInitRDC ( raw_device_command
*, int );
68 #define INIT_RDC( TYPE, SIZE ) \
69 raw_device_command rdc; \
70 u8 p_buffer[ (SIZE) ]; \
71 memset( &rdc, 0, sizeof( raw_device_command ) ); \
72 rdc.data = (char *)p_buffer; \
73 rdc.data_length = (SIZE); \
74 BeInitRDC( &rdc, (TYPE) );
77 /*****************************************************************************
78 * Local prototypes, Darwin specific
79 *****************************************************************************/
80 #if defined( SYS_DARWIN1_3 )
81 #define INIT_DVDIOCTL( SIZE ) \
82 dvdioctl_data_t dvdioctl; \
83 u8 p_buffer[ (SIZE) ]; \
84 dvdioctl.p_buffer = p_buffer; \
85 dvdioctl.i_size = (SIZE); \
86 dvdioctl.i_keyclass = kCSS_CSS2_CPRM; \
87 memset( p_buffer, 0, (SIZE) );
90 /*****************************************************************************
91 * ioctl_ReadCopyright: check whether the disc is encrypted or not
92 *****************************************************************************/
93 int ioctl_ReadCopyright( int i_fd
, int i_layer
, int *pi_copyright
)
97 #if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
100 dvd
.type
= DVD_STRUCT_COPYRIGHT
;
101 dvd
.copyright
.layer_num
= i_layer
;
103 i_ret
= ioctl( i_fd
, DVD_READ_STRUCT
, &dvd
);
105 *pi_copyright
= dvd
.copyright
.cpst
;
107 #elif defined( HAVE_BSD_DVD_STRUCT )
108 struct dvd_struct dvd
;
110 dvd
.format
= DVD_STRUCT_COPYRIGHT
;
111 dvd
.layer_num
= i_layer
;
113 i_ret
= ioctl( i_fd
, DVDIOCREADSTRUCTURE
, &dvd
);
115 *pi_copyright
= dvd
.cpst
;
117 #elif defined( SYS_BEOS )
118 INIT_RDC( GPCMD_READ_DVD_STRUCTURE
, 8 );
120 rdc
.command
[ 6 ] = i_layer
;
121 rdc
.command
[ 7 ] = DVD_STRUCT_COPYRIGHT
;
123 i_ret
= ioctl( i_fd
, B_RAW_DEVICE_COMMAND
, &rdc
, sizeof(rdc
) );
125 *pi_copyright
= p_buffer
[ 4 ];
127 #elif defined( SYS_DARWIN1_3 )
128 intf_ErrMsg( "css error: DVD ioctls not fully functional yet" );
129 intf_ErrMsg( "css error: assuming disc is encrypted" );
136 /* DVD ioctls unavailable - do as if the ioctl failed */
143 /*****************************************************************************
144 * ioctl_ReadKey: get the disc key
145 *****************************************************************************/
146 int ioctl_ReadKey( int i_fd
, int *pi_agid
, u8
*p_key
)
150 #if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
153 dvd
.type
= DVD_STRUCT_DISCKEY
;
154 dvd
.disckey
.agid
= *pi_agid
;
155 memset( dvd
.disckey
.value
, 0, 2048 );
157 i_ret
= ioctl( i_fd
, DVD_READ_STRUCT
, &dvd
);
164 memcpy( p_key
, dvd
.disckey
.value
, 2048 );
166 #elif defined( HAVE_BSD_DVD_STRUCT )
167 struct dvd_struct dvd
;
169 dvd
.format
= DVD_STRUCT_DISCKEY
;
171 memset( dvd
.data
, 0, 2048 );
173 i_ret
= ioctl( i_fd
, DVDIOCREADSTRUCTURE
, &dvd
);
180 memcpy( p_key
, dvd
.data
, 2048 );
182 #elif defined( SYS_BEOS )
183 INIT_RDC( GPCMD_READ_DVD_STRUCTURE
, 2048 + 4 );
185 rdc
.command
[ 7 ] = DVD_STRUCT_DISCKEY
;
186 rdc
.command
[ 10 ] = *pi_agid
<< 6;
188 i_ret
= ioctl( i_fd
, B_RAW_DEVICE_COMMAND
, &rdc
, sizeof(rdc
) );
195 memcpy( p_key
, p_buffer
+ 4, 2048 );
197 #elif defined( SYS_DARWIN1_3 )
198 intf_ErrMsg( "css error: DVD ioctls not fully functional yet" );
199 intf_ErrMsg( "css error: sending an empty key" );
203 memset( p_key
, 0x00, 2048 );
206 /* DVD ioctls unavailable - do as if the ioctl failed */
213 /*****************************************************************************
214 * ioctl_ReportAgid: get AGID from the drive
215 *****************************************************************************/
216 int ioctl_ReportAgid( int i_fd
, int *pi_agid
)
220 #if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
221 dvd_authinfo auth_info
;
223 auth_info
.type
= DVD_LU_SEND_AGID
;
224 auth_info
.lsa
.agid
= *pi_agid
;
226 i_ret
= ioctl( i_fd
, DVD_AUTH
, &auth_info
);
228 *pi_agid
= auth_info
.lsa
.agid
;
230 #elif defined( HAVE_BSD_DVD_STRUCT )
231 struct dvd_authinfo auth_info
;
233 auth_info
.format
= DVD_REPORT_AGID
;
234 auth_info
.agid
= *pi_agid
;
236 i_ret
= ioctl( i_fd
, DVDIOCREPORTKEY
, &auth_info
);
238 *pi_agid
= auth_info
.agid
;
240 #elif defined( SYS_BEOS )
241 INIT_RDC( GPCMD_REPORT_KEY
, 8 );
243 rdc
.command
[ 10 ] = DVD_REPORT_AGID
| (*pi_agid
<< 6);
245 i_ret
= ioctl( i_fd
, B_RAW_DEVICE_COMMAND
, &rdc
, sizeof(rdc
) );
247 *pi_agid
= p_buffer
[ 7 ] >> 6;
249 #elif defined( SYS_DARWIN1_3 )
252 dvdioctl
.i_keyformat
= kCSSAGID
;
253 dvdioctl
.i_agid
= *pi_agid
;
256 i_ret
= ioctl( i_fd
, IODVD_REPORT_KEY
, &dvdioctl
);
258 *pi_agid
= p_buffer
[ 7 ] >> 6;
261 /* DVD ioctls unavailable - do as if the ioctl failed */
268 /*****************************************************************************
269 * ioctl_ReportChallenge: get challenge from the drive
270 *****************************************************************************/
271 int ioctl_ReportChallenge( int i_fd
, int *pi_agid
, u8
*p_challenge
)
275 #if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
276 dvd_authinfo auth_info
;
278 auth_info
.type
= DVD_LU_SEND_CHALLENGE
;
279 auth_info
.lsc
.agid
= *pi_agid
;
281 i_ret
= ioctl( i_fd
, DVD_AUTH
, &auth_info
);
283 memcpy( p_challenge
, auth_info
.lsc
.chal
, sizeof(dvd_challenge
) );
285 #elif defined( HAVE_BSD_DVD_STRUCT )
286 struct dvd_authinfo auth_info
;
288 auth_info
.format
= DVD_REPORT_CHALLENGE
;
289 auth_info
.agid
= *pi_agid
;
291 i_ret
= ioctl( i_fd
, DVDIOCREPORTKEY
, &auth_info
);
293 memcpy( p_challenge
, auth_info
.keychal
, 10 );
295 #elif defined( SYS_BEOS )
296 INIT_RDC( GPCMD_REPORT_KEY
, 16 );
298 rdc
.command
[ 10 ] = DVD_REPORT_CHALLENGE
| (*pi_agid
<< 6);
300 i_ret
= ioctl( i_fd
, B_RAW_DEVICE_COMMAND
, &rdc
, sizeof(rdc
) );
302 memcpy( p_challenge
, p_buffer
+ 4, 12 );
304 #elif defined( SYS_DARWIN1_3 )
307 dvdioctl
.i_keyformat
= kChallengeKey
;
308 dvdioctl
.i_agid
= *pi_agid
;
311 i_ret
= ioctl( i_fd
, IODVD_REPORT_KEY
, &dvdioctl
);
313 memcpy( p_challenge
, p_buffer
+ 4, 12 );
316 /* DVD ioctls unavailable - do as if the ioctl failed */
323 /*****************************************************************************
324 * ioctl_ReportASF: get ASF from the drive
325 *****************************************************************************/
326 int ioctl_ReportASF( int i_fd
, int *pi_agid
, int *pi_asf
)
330 #if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
331 dvd_authinfo auth_info
;
333 auth_info
.type
= DVD_LU_SEND_ASF
;
334 auth_info
.lsasf
.agid
= *pi_agid
;
335 auth_info
.lsasf
.asf
= *pi_asf
;
337 i_ret
= ioctl( i_fd
, DVD_AUTH
, &auth_info
);
339 *pi_asf
= auth_info
.lsasf
.asf
;
341 #elif defined( HAVE_BSD_DVD_STRUCT )
342 struct dvd_authinfo auth_info
;
344 auth_info
.format
= DVD_REPORT_ASF
;
345 auth_info
.agid
= *pi_agid
;
346 auth_info
.asf
= *pi_asf
;
348 i_ret
= ioctl( i_fd
, DVDIOCREPORTKEY
, &auth_info
);
350 *pi_asf
= auth_info
.asf
;
352 #elif defined( SYS_BEOS )
353 INIT_RDC( GPCMD_REPORT_KEY
, 8 );
355 rdc
.command
[ 10 ] = DVD_REPORT_ASF
| (*pi_agid
<< 6);
357 i_ret
= ioctl( i_fd
, B_RAW_DEVICE_COMMAND
, &rdc
, sizeof(rdc
) );
359 *pi_asf
= p_buffer
[ 7 ] & 1;
361 #elif defined( SYS_DARWIN1_3 )
364 dvdioctl
.i_keyformat
= kASF
;
365 dvdioctl
.i_agid
= *pi_agid
;
368 i_ret
= ioctl( i_fd
, IODVD_REPORT_KEY
, &dvdioctl
);
370 *pi_asf
= p_buffer
[ 7 ] & 1;
373 /* DVD ioctls unavailable - do as if the ioctl failed */
380 /*****************************************************************************
381 * ioctl_ReportKey1: get the first key from the drive
382 *****************************************************************************/
383 int ioctl_ReportKey1( int i_fd
, int *pi_agid
, u8
*p_key
)
387 #if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
388 dvd_authinfo auth_info
;
390 auth_info
.type
= DVD_LU_SEND_KEY1
;
391 auth_info
.lsk
.agid
= *pi_agid
;
393 i_ret
= ioctl( i_fd
, DVD_AUTH
, &auth_info
);
395 memcpy( p_key
, auth_info
.lsk
.key
, sizeof(dvd_key
) );
397 #elif defined( HAVE_BSD_DVD_STRUCT )
398 struct dvd_authinfo auth_info
;
400 auth_info
.format
= DVD_REPORT_KEY1
;
401 auth_info
.agid
= *pi_agid
;
403 i_ret
= ioctl( i_fd
, DVDIOCREPORTKEY
, &auth_info
);
405 memcpy( p_key
, auth_info
.keychal
, 8 );
407 #elif defined( SYS_BEOS )
408 INIT_RDC( GPCMD_REPORT_KEY
, 12 );
410 rdc
.command
[ 10 ] = DVD_REPORT_KEY1
| (*pi_agid
<< 6);
412 i_ret
= ioctl( i_fd
, B_RAW_DEVICE_COMMAND
, &rdc
, sizeof(rdc
) );
414 memcpy( p_key
, p_buffer
+ 4, 8 );
416 #elif defined( SYS_DARWIN1_3 )
419 dvdioctl
.i_keyformat
= kKey1
;
420 dvdioctl
.i_agid
= *pi_agid
;
422 i_ret
= ioctl( i_fd
, IODVD_SEND_KEY
, &dvdioctl
);
424 memcpy( p_key
, p_buffer
+ 4, 8 );
427 /* DVD ioctls unavailable - do as if the ioctl failed */
434 /*****************************************************************************
435 * ioctl_InvalidateAgid: invalidate the current AGID
436 *****************************************************************************/
437 int ioctl_InvalidateAgid( int i_fd
, int *pi_agid
)
441 #if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
442 dvd_authinfo auth_info
;
444 auth_info
.type
= DVD_INVALIDATE_AGID
;
445 auth_info
.lsa
.agid
= *pi_agid
;
447 i_ret
= ioctl( i_fd
, DVD_AUTH
, &auth_info
);
449 *pi_agid
= auth_info
.lsa
.agid
;
451 #elif defined( HAVE_BSD_DVD_STRUCT )
452 struct dvd_authinfo auth_info
;
454 auth_info
.format
= DVD_INVALIDATE_AGID
;
455 auth_info
.agid
= *pi_agid
;
457 i_ret
= ioctl( i_fd
, DVDIOCREPORTKEY
, &auth_info
);
459 *pi_agid
= auth_info
.agid
;
461 #elif defined( SYS_BEOS )
462 INIT_RDC( GPCMD_REPORT_KEY
, 0 );
464 rdc
.command
[ 10 ] = DVD_INVALIDATE_AGID
| (*pi_agid
<< 6);
466 i_ret
= ioctl( i_fd
, B_RAW_DEVICE_COMMAND
, &rdc
, sizeof(rdc
) );
468 #elif defined( SYS_DARWIN1_3 )
471 dvdioctl
.i_keyformat
= kInvalidateAGID
;
472 dvdioctl
.i_agid
= *pi_agid
;
474 i_ret
= ioctl( i_fd
, IODVD_SEND_KEY
, &dvdioctl
);
477 /* DVD ioctls unavailable - do as if the ioctl failed */
484 /*****************************************************************************
485 * ioctl_SendChallenge: send challenge to the drive
486 *****************************************************************************/
487 int ioctl_SendChallenge( int i_fd
, int *pi_agid
, u8
*p_challenge
)
489 #if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
490 dvd_authinfo auth_info
;
492 auth_info
.type
= DVD_HOST_SEND_CHALLENGE
;
493 auth_info
.hsc
.agid
= *pi_agid
;
495 memcpy( auth_info
.hsc
.chal
, p_challenge
, sizeof(dvd_challenge
) );
497 return ioctl( i_fd
, DVD_AUTH
, &auth_info
);
499 #elif defined( HAVE_BSD_DVD_STRUCT )
500 struct dvd_authinfo auth_info
;
502 auth_info
.format
= DVD_SEND_CHALLENGE
;
503 auth_info
.agid
= *pi_agid
;
505 memcpy( auth_info
.keychal
, p_challenge
, 12 );
507 return ioctl( i_fd
, DVDIOCSENDKEY
, &auth_info
);
509 #elif defined( SYS_BEOS )
510 INIT_RDC( GPCMD_SEND_KEY
, 16 );
512 rdc
.command
[ 10 ] = DVD_SEND_CHALLENGE
| (*pi_agid
<< 6);
515 memcpy( p_buffer
+ 4, p_challenge
, 12 );
517 return ioctl( i_fd
, B_RAW_DEVICE_COMMAND
, &rdc
, sizeof(rdc
) );
519 #elif defined( SYS_DARWIN1_3 )
522 dvdioctl
.i_keyformat
= kChallengeKey
;
523 dvdioctl
.i_agid
= *pi_agid
;
526 memcpy( p_buffer
+ 4, p_challenge
, 12 );
528 return ioctl( i_fd
, IODVD_SEND_KEY
, &dvdioctl
);
531 /* DVD ioctls unavailable - do as if the ioctl failed */
537 /*****************************************************************************
538 * ioctl_SendKey2: send the second key to the drive
539 *****************************************************************************/
540 int ioctl_SendKey2( int i_fd
, int *pi_agid
, u8
*p_key
)
542 #if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
543 dvd_authinfo auth_info
;
545 auth_info
.type
= DVD_HOST_SEND_KEY2
;
546 auth_info
.hsk
.agid
= *pi_agid
;
548 memcpy( auth_info
.hsk
.key
, p_key
, sizeof(dvd_key
) );
550 return ioctl( i_fd
, DVD_AUTH
, &auth_info
);
552 #elif defined( HAVE_BSD_DVD_STRUCT )
553 struct dvd_authinfo auth_info
;
555 auth_info
.format
= DVD_SEND_KEY2
;
556 auth_info
.agid
= *pi_agid
;
558 memcpy( auth_info
.keychal
, p_key
, 8 );
560 return ioctl( i_fd
, DVDIOCSENDKEY
, &auth_info
);
562 #elif defined( SYS_BEOS )
563 INIT_RDC( GPCMD_SEND_KEY
, 12 );
565 rdc
.command
[ 10 ] = DVD_SEND_KEY2
| (*pi_agid
<< 6);
568 memcpy( p_buffer
+ 4, p_key
, 8 );
570 return ioctl( i_fd
, B_RAW_DEVICE_COMMAND
, &rdc
, sizeof(rdc
) );
572 #elif defined( SYS_DARWIN1_3 )
575 dvdioctl
.i_keyformat
= kKey2
;
576 dvdioctl
.i_agid
= *pi_agid
;
579 memcpy( p_buffer
+ 4, p_key
, 8 );
581 return ioctl( i_fd
, IODVD_SEND_KEY
, &dvdioctl
);
584 /* DVD ioctls unavailable - do as if the ioctl failed */
590 /* Local prototypes */
592 #if defined( SYS_BEOS )
593 /*****************************************************************************
594 * BeInitRDC: initialize a RDC structure for the BeOS kernel
595 *****************************************************************************
596 * This function initializes a BeOS raw device command structure for future
597 * use, either a read command or a write command.
598 *****************************************************************************/
599 static void BeInitRDC( raw_device_command
*p_rdc
, int i_type
)
601 memset( p_rdc
->data
, 0, p_rdc
->data_length
);
606 /* leave the flags to 0 */
609 case GPCMD_READ_DVD_STRUCTURE
:
610 case GPCMD_REPORT_KEY
:
611 p_rdc
->flags
= B_RAW_DEVICE_DATA_IN
;
615 p_rdc
->command
[ 0 ] = i_type
;
617 p_rdc
->command
[ 8 ] = (p_rdc
->data_length
>> 8) & 0xff;
618 p_rdc
->command
[ 9 ] = p_rdc
->data_length
& 0xff;
619 p_rdc
->command_length
= 12;
621 p_rdc
->sense_data
= NULL
;
622 p_rdc
->sense_data_length
= 0;
624 p_rdc
->timeout
= 1000000;