1 /*****************************************************************************
2 * dvd_ioctl.c: DVD ioctl replacement function
3 *****************************************************************************
4 * Copyright (C) 1999-2001 VideoLAN
5 * $Id: dvd_ioctl.c,v 1.12 2001/05/25 04:23:37 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>
32 #include <netinet/in.h>
34 #include <sys/ioctl.h>
36 #ifdef DVD_STRUCT_IN_SYS_CDIO_H
37 # include <sys/cdio.h>
39 #ifdef DVD_STRUCT_IN_SYS_DVDIO_H
40 # include <sys/dvdio.h>
42 #ifdef DVD_STRUCT_IN_LINUX_CDROM_H
43 # include <linux/cdrom.h>
55 # include "DVDioctl/DVDioctl.h"
59 #include "dvd_ioctl.h"
61 /*****************************************************************************
62 * Local prototypes, BeOS specific
63 *****************************************************************************/
64 #if defined( SYS_BEOS )
65 static void BeInitRDC ( raw_device_command *, int );
66 #define INIT_RDC( TYPE, SIZE ) \
67 raw_device_command rdc; \
68 u8 p_buffer[ (SIZE) ]; \
69 rdc.data = (char *)p_buffer; \
70 rdc.data_length = (SIZE); \
71 BeInitRDC( &rdc, (TYPE) );
74 /*****************************************************************************
75 * Local prototypes, Darwin specific
76 *****************************************************************************/
77 #if defined( SYS_DARWIN1_3 )
78 #define INIT_DVDIOCTL( SIZE ) \
79 dvdioctl_data_t dvdioctl; \
80 u8 p_buffer[ (SIZE) ]; \
81 dvdioctl.p_buffer = p_buffer; \
82 dvdioctl.i_size = (SIZE); \
83 dvdioctl.i_keyclass = kCSS_CSS2_CPRM; \
84 memset( p_buffer, 0, (SIZE) );
87 /*****************************************************************************
88 * ioctl_ReadCopyright: check whether the disc is encrypted or not
89 *****************************************************************************/
90 int ioctl_ReadCopyright( int i_fd, int i_layer, int *pi_copyright )
94 #if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
97 dvd.type = DVD_STRUCT_COPYRIGHT;
98 dvd.copyright.layer_num = i_layer;
100 i_ret = ioctl( i_fd, DVD_READ_STRUCT, &dvd );
102 *pi_copyright = dvd.copyright.cpst;
104 #elif defined( HAVE_BSD_DVD_STRUCT )
105 struct dvd_struct dvd;
107 dvd.format = DVD_STRUCT_COPYRIGHT;
108 dvd.layer_num = i_layer;
110 i_ret = ioctl( i_fd, DVDIOCREADSTRUCTURE, &dvd );
112 *pi_copyright = dvd.cpst;
114 #elif defined( SYS_BEOS )
115 INIT_RDC( GPCMD_READ_DVD_STRUCTURE, 8 );
117 rdc.command[ 6 ] = i_layer;
118 rdc.command[ 7 ] = DVD_STRUCT_COPYRIGHT;
120 i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
122 *pi_copyright = p_buffer[ 4 ];
124 #elif defined( SYS_DARWIN1_3 )
125 intf_ErrMsg( "css error: DVD ioctls not fully functional yet" );
126 intf_ErrMsg( "css error: assuming disc is encrypted" );
133 /* DVD ioctls unavailable - do as if the ioctl failed */
140 /*****************************************************************************
141 * ioctl_ReadKey: get the disc key
142 *****************************************************************************/
143 int ioctl_ReadKey( int i_fd, int *pi_agid, u8 *p_key )
147 #if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
150 dvd.type = DVD_STRUCT_DISCKEY;
151 dvd.disckey.agid = *pi_agid;
152 memset( dvd.disckey.value, 0, 2048 );
154 i_ret = ioctl( i_fd, DVD_READ_STRUCT, &dvd );
161 memcpy( p_key, dvd.disckey.value, 2048 );
163 #elif defined( HAVE_BSD_DVD_STRUCT )
164 struct dvd_struct dvd;
166 dvd.format = DVD_STRUCT_DISCKEY;
168 memset( dvd.data, 0, 2048 );
170 i_ret = ioctl( i_fd, DVDIOCREADSTRUCTURE, &dvd );
177 memcpy( p_key, dvd.data, 2048 );
179 #elif defined( SYS_BEOS )
180 INIT_RDC( GPCMD_READ_DVD_STRUCTURE, 2048 + 4 );
182 rdc.command[ 7 ] = DVD_STRUCT_DISCKEY;
183 rdc.command[ 10 ] = *pi_agid << 6;
185 i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
192 memcpy( p_key, p_buffer + 4, 2048 );
194 #elif defined( SYS_DARWIN1_3 )
195 intf_ErrMsg( "css error: DVD ioctls not fully functional yet" );
196 intf_ErrMsg( "css error: sending an empty key" );
200 memset( p_key, 0x00, 2048 );
203 /* DVD ioctls unavailable - do as if the ioctl failed */
210 /*****************************************************************************
211 * ioctl_ReportAgid: get AGID from the drive
212 *****************************************************************************/
213 int ioctl_ReportAgid( int i_fd, int *pi_agid )
217 #if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
218 dvd_authinfo auth_info;
220 auth_info.type = DVD_LU_SEND_AGID;
221 auth_info.lsa.agid = *pi_agid;
223 i_ret = ioctl( i_fd, DVD_AUTH, &auth_info );
225 *pi_agid = auth_info.lsa.agid;
227 #elif defined( HAVE_BSD_DVD_STRUCT )
228 struct dvd_authinfo auth_info;
230 auth_info.format = DVD_REPORT_AGID;
231 auth_info.agid = *pi_agid;
233 i_ret = ioctl( i_fd, DVDIOCREPORTKEY, &auth_info );
235 *pi_agid = auth_info.agid;
237 #elif defined( SYS_BEOS )
238 INIT_RDC( GPCMD_REPORT_KEY, 8 );
240 rdc.command[ 10 ] = DVD_REPORT_AGID | (*pi_agid << 6);
242 i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
244 *pi_agid = p_buffer[ 7 ] >> 6;
246 #elif defined( SYS_DARWIN1_3 )
249 dvdioctl.i_keyformat = kCSSAGID;
250 dvdioctl.i_agid = *pi_agid;
253 i_ret = ioctl( i_fd, IODVD_REPORT_KEY, &dvdioctl );
255 *pi_asf = p_buffer[ 7 ] >> 6;
258 /* DVD ioctls unavailable - do as if the ioctl failed */
265 /*****************************************************************************
266 * ioctl_ReportChallenge: get challenge from the drive
267 *****************************************************************************/
268 int ioctl_ReportChallenge( int i_fd, int *pi_agid, u8 *p_challenge )
272 #if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
273 dvd_authinfo auth_info;
275 auth_info.type = DVD_LU_SEND_CHALLENGE;
276 auth_info.lsc.agid = *pi_agid;
278 i_ret = ioctl( i_fd, DVD_AUTH, &auth_info );
280 memcpy( p_challenge, auth_info.lsc.chal, sizeof(dvd_challenge) );
282 #elif defined( HAVE_BSD_DVD_STRUCT )
283 struct dvd_authinfo auth_info;
285 auth_info.format = DVD_REPORT_CHALLENGE;
286 auth_info.agid = *pi_agid;
288 i_ret = ioctl( i_fd, DVDIOCREPORTKEY, &auth_info );
290 memcpy( p_challenge, auth_info.keychal, 10 );
292 #elif defined( SYS_BEOS )
293 INIT_RDC( GPCMD_REPORT_KEY, 16 );
295 rdc.command[ 10 ] = DVD_REPORT_CHALLENGE | (*pi_agid << 6);
297 i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
299 memcpy( p_challenge, p_buffer + 4, 12 );
301 #elif defined( SYS_DARWIN1_3 )
304 dvdioctl.i_keyformat = kChallengeKey;
305 dvdioctl.i_agid = *pi_agid;
308 i_ret = ioctl( i_fd, IODVD_REPORT_KEY, &dvdioctl );
310 memcpy( p_challenge, p_buffer + 4, 12 );
313 /* DVD ioctls unavailable - do as if the ioctl failed */
320 /*****************************************************************************
321 * ioctl_ReportASF: get ASF from the drive
322 *****************************************************************************/
323 int ioctl_ReportASF( int i_fd, int *pi_agid, int *pi_asf )
327 #if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
328 dvd_authinfo auth_info;
330 auth_info.type = DVD_LU_SEND_ASF;
331 auth_info.lsasf.agid = *pi_agid;
332 auth_info.lsasf.asf = *pi_asf;
334 i_ret = ioctl( i_fd, DVD_AUTH, &auth_info );
336 *pi_asf = auth_info.lsasf.asf;
338 #elif defined( HAVE_BSD_DVD_STRUCT )
339 struct dvd_authinfo auth_info;
341 auth_info.format = DVD_REPORT_ASF;
342 auth_info.agid = *pi_agid;
343 auth_info.asf = *pi_asf;
345 i_ret = ioctl( i_fd, DVDIOCREPORTKEY, &auth_info );
347 *pi_asf = auth_info.asf;
349 #elif defined( SYS_BEOS )
350 INIT_RDC( GPCMD_REPORT_KEY, 8 );
352 rdc.command[ 10 ] = DVD_REPORT_ASF | (*pi_agid << 6);
354 i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
356 *pi_asf = p_buffer[ 7 ] & 1;
358 #elif defined( SYS_DARWIN1_3 )
361 dvdioctl.i_keyformat = kASF;
362 dvdioctl.i_agid = *pi_agid;
365 i_ret = ioctl( i_fd, IODVD_REPORT_KEY, &dvdioctl );
367 *pi_asf = p_buffer[ 7 ] & 1;
370 /* DVD ioctls unavailable - do as if the ioctl failed */
377 /*****************************************************************************
378 * ioctl_ReportKey1: get the first key from the drive
379 *****************************************************************************/
380 int ioctl_ReportKey1( int i_fd, int *pi_agid, u8 *p_key )
384 #if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
385 dvd_authinfo auth_info;
387 auth_info.type = DVD_LU_SEND_KEY1;
388 auth_info.lsk.agid = *pi_agid;
390 i_ret = ioctl( i_fd, DVD_AUTH, &auth_info );
392 memcpy( p_key, auth_info.lsk.key, sizeof(dvd_key) );
394 #elif defined( HAVE_BSD_DVD_STRUCT )
395 struct dvd_authinfo auth_info;
397 auth_info.format = DVD_REPORT_KEY1;
398 auth_info.agid = *pi_agid;
400 i_ret = ioctl( i_fd, DVDIOCREPORTKEY, &auth_info );
402 memcpy( p_key, auth_info.keychal, 8 );
404 #elif defined( SYS_BEOS )
405 INIT_RDC( GPCMD_REPORT_KEY, 12 );
407 rdc.command[ 10 ] = DVD_REPORT_KEY1 | (*pi_agid << 6);
409 i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
411 memcpy( p_key, p_buffer + 4, 8 );
413 #elif defined( SYS_DARWIN1_3 )
416 dvdioctl.i_keyformat = kKey1;
417 dvdioctl.i_agid = *pi_agid;
419 i_ret = ioctl( i_fd, IODVD_SEND_KEY, &dvdioctl );
421 memcpy( p_key, p_buffer + 4, 8 );
424 /* DVD ioctls unavailable - do as if the ioctl failed */
431 /*****************************************************************************
432 * ioctl_InvalidateAgid: invalidate the current AGID
433 *****************************************************************************/
434 int ioctl_InvalidateAgid( int i_fd, int *pi_agid )
438 #if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
439 dvd_authinfo auth_info;
441 auth_info.type = DVD_INVALIDATE_AGID;
442 auth_info.lsa.agid = *pi_agid;
444 i_ret = ioctl( i_fd, DVD_AUTH, &auth_info );
446 *pi_agid = auth_info.lsa.agid;
448 #elif defined( HAVE_BSD_DVD_STRUCT )
449 struct dvd_authinfo auth_info;
451 auth_info.format = DVD_INVALIDATE_AGID;
452 auth_info.agid = *pi_agid;
454 i_ret = ioctl( i_fd, DVDIOCREPORTKEY, &auth_info );
456 *pi_agid = auth_info.agid;
458 #elif defined( SYS_BEOS )
459 INIT_RDC( GPCMD_REPORT_KEY, 0 );
461 rdc.command[ 10 ] = DVD_INVALIDATE_AGID | (*pi_agid << 6);
463 i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
465 #elif defined( SYS_DARWIN1_3 )
468 dvdioctl.i_keyformat = kInvalidateAGID;
469 dvdioctl.i_agid = *pi_agid;
471 i_ret = ioctl( i_fd, IODVD_SEND_KEY, &dvdioctl );
474 /* DVD ioctls unavailable - do as if the ioctl failed */
481 /*****************************************************************************
482 * ioctl_SendChallenge: send challenge to the drive
483 *****************************************************************************/
484 int ioctl_SendChallenge( int i_fd, int *pi_agid, u8 *p_challenge )
486 #if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
487 dvd_authinfo auth_info;
489 auth_info.type = DVD_HOST_SEND_CHALLENGE;
490 auth_info.hsc.agid = *pi_agid;
492 memcpy( auth_info.hsc.chal, p_challenge, sizeof(dvd_challenge) );
494 return ioctl( i_fd, DVD_AUTH, &auth_info );
496 #elif defined( HAVE_BSD_DVD_STRUCT )
497 struct dvd_authinfo auth_info;
499 auth_info.format = DVD_SEND_CHALLENGE;
500 auth_info.agid = *pi_agid;
502 memcpy( auth_info.keychal, p_challenge, 12 );
504 return ioctl( i_fd, DVDIOCSENDKEY, &auth_info );
506 #elif defined( SYS_BEOS )
507 INIT_RDC( GPCMD_SEND_KEY, 16 );
509 rdc.command[ 10 ] = DVD_SEND_CHALLENGE | (*pi_agid << 6);
512 memcpy( p_buffer + 4, p_challenge, 12 );
514 return ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
516 #elif defined( SYS_DARWIN1_3 )
519 dvdioctl.i_keyformat = kChallengeKey;
520 dvdioctl.i_agid = *pi_agid;
523 memcpy( p_buffer + 4, p_challenge, 12 );
525 return ioctl( i_fd, IODVD_SEND_KEY, &dvdioctl );
528 /* DVD ioctls unavailable - do as if the ioctl failed */
534 /*****************************************************************************
535 * ioctl_SendKey2: send the second key to the drive
536 *****************************************************************************/
537 int ioctl_SendKey2( int i_fd, int *pi_agid, u8 *p_key )
539 #if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
540 dvd_authinfo auth_info;
542 auth_info.type = DVD_HOST_SEND_KEY2;
543 auth_info.hsk.agid = *pi_agid;
545 memcpy( auth_info.hsk.key, p_key, sizeof(dvd_key) );
547 return ioctl( i_fd, DVD_AUTH, &auth_info );
549 #elif defined( HAVE_BSD_DVD_STRUCT )
550 struct dvd_authinfo auth_info;
552 auth_info.format = DVD_SEND_KEY2;
553 auth_info.agid = *pi_agid;
555 memcpy( auth_info.keychal, p_key, 8 );
557 return ioctl( i_fd, DVDIOCSENDKEY, &auth_info );
559 #elif defined( SYS_BEOS )
560 INIT_RDC( GPCMD_SEND_KEY, 12 );
562 rdc.command[ 10 ] = DVD_SEND_KEY2 | (*pi_agid << 6);
565 memcpy( p_buffer + 4, p_key, 8 );
567 return ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
569 #elif defined( SYS_DARWIN1_3 )
572 dvdioctl.i_keyformat = kKey2;
573 dvdioctl.i_agid = *pi_agid;
576 memcpy( p_buffer + 4, p_key, 8 );
578 return ioctl( i_fd, IODVD_SEND_KEY, &dvdioctl );
581 /* DVD ioctls unavailable - do as if the ioctl failed */
587 /* Local prototypes */
589 #if defined( SYS_BEOS )
590 /*****************************************************************************
591 * BeInitRDC: initialize a RDC structure for the BeOS kernel
592 *****************************************************************************
593 * This function initializes a BeOS raw device command structure for future
594 * use, either a read command or a write command.
595 *****************************************************************************/
596 static void BeInitRDC( raw_device_command *p_rdc, int i_type )
598 memset( p_rdc, 0, sizeof( raw_device_command ) );
599 memset( p_rdc->data, 0, p_rdc->data_length );
604 /* leave the flags to 0 */
607 case GPCMD_READ_DVD_STRUCTURE:
608 case GPCMD_REPORT_KEY:
609 p_rdc->flags = B_RAW_DEVICE_DATA_IN;
613 p_rdc->command[ 0 ] = i_type;
615 p_rdc->command[ 8 ] = (p_rdc->data_length >> 8) & 0xff;
616 p_rdc->command[ 9 ] = p_rdc->data_length & 0xff;
617 p_rdc->command_length = 12;
619 p_rdc->sense_data = NULL;
620 p_rdc->sense_data_length = 0;
622 p_rdc->timeout = 1000000;