* Applied patch from Jon Lech Johansen <jon-vl@nanocrew.net> to compile
[vlc.git] / plugins / dvd / dvd_ioctl.c
blob67903b1187dad61f79cf63d614938de4cc83efca
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 /*****************************************************************************
26 * Preamble
27 *****************************************************************************/
28 #include "defs.h"
30 #include <string.h> /* memcpy(), memset() */
31 #include <sys/types.h>
33 #if !defined( WIN32 )
34 #include <netinet/in.h>
35 #include <sys/ioctl.h>
36 #endif
38 #ifdef DVD_STRUCT_IN_SYS_CDIO_H
39 # include <sys/cdio.h>
40 #endif
41 #ifdef DVD_STRUCT_IN_SYS_DVDIO_H
42 # include <sys/dvdio.h>
43 #endif
44 #ifdef DVD_STRUCT_IN_LINUX_CDROM_H
45 # include <linux/cdrom.h>
46 #endif
47 #ifdef SYS_BEOS
48 # include <malloc.h>
49 # include <scsi.h>
50 #endif
52 #include "common.h"
54 #include "intf_msg.h"
56 #ifdef SYS_DARWIN1_3
57 # include "DVDioctl/DVDioctl.h"
58 #endif
60 #include "dvd_css.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) );
75 #endif
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) );
88 #endif
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 )
95 int i_ret;
97 #if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
98 dvd_struct dvd;
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" );
131 *pi_copyright = 1;
133 i_ret = 0;
135 #else
136 /* DVD ioctls unavailable - do as if the ioctl failed */
137 i_ret = -1;
139 #endif
140 return i_ret;
143 /*****************************************************************************
144 * ioctl_ReadKey: get the disc key
145 *****************************************************************************/
146 int ioctl_ReadKey( int i_fd, int *pi_agid, u8 *p_key )
148 int i_ret;
150 #if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
151 dvd_struct dvd;
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 );
159 if( i_ret < 0 )
161 return i_ret;
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;
170 dvd.agid = *pi_agid;
171 memset( dvd.data, 0, 2048 );
173 i_ret = ioctl( i_fd, DVDIOCREADSTRUCTURE, &dvd );
175 if( i_ret < 0 )
177 return i_ret;
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) );
190 if( i_ret < 0 )
192 return i_ret;
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" );
201 i_ret = 0;
203 memset( p_key, 0x00, 2048 );
205 #else
206 /* DVD ioctls unavailable - do as if the ioctl failed */
207 i_ret = -1;
209 #endif
210 return i_ret;
213 /*****************************************************************************
214 * ioctl_ReportAgid: get AGID from the drive
215 *****************************************************************************/
216 int ioctl_ReportAgid( int i_fd, int *pi_agid )
218 int i_ret;
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 )
250 INIT_DVDIOCTL( 8 );
252 dvdioctl.i_keyformat = kCSSAGID;
253 dvdioctl.i_agid = *pi_agid;
254 dvdioctl.i_lba = 0;
256 i_ret = ioctl( i_fd, IODVD_REPORT_KEY, &dvdioctl );
258 *pi_agid = p_buffer[ 7 ] >> 6;
260 #else
261 /* DVD ioctls unavailable - do as if the ioctl failed */
262 i_ret = -1;
264 #endif
265 return i_ret;
268 /*****************************************************************************
269 * ioctl_ReportChallenge: get challenge from the drive
270 *****************************************************************************/
271 int ioctl_ReportChallenge( int i_fd, int *pi_agid, u8 *p_challenge )
273 int i_ret;
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 )
305 INIT_DVDIOCTL( 16 );
307 dvdioctl.i_keyformat = kChallengeKey;
308 dvdioctl.i_agid = *pi_agid;
309 dvdioctl.i_lba = 0;
311 i_ret = ioctl( i_fd, IODVD_REPORT_KEY, &dvdioctl );
313 memcpy( p_challenge, p_buffer + 4, 12 );
315 #else
316 /* DVD ioctls unavailable - do as if the ioctl failed */
317 i_ret = -1;
319 #endif
320 return i_ret;
323 /*****************************************************************************
324 * ioctl_ReportASF: get ASF from the drive
325 *****************************************************************************/
326 int ioctl_ReportASF( int i_fd, int *pi_agid, int *pi_asf )
328 int i_ret;
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 )
362 INIT_DVDIOCTL( 8 );
364 dvdioctl.i_keyformat = kASF;
365 dvdioctl.i_agid = *pi_agid;
366 dvdioctl.i_lba = 0;
368 i_ret = ioctl( i_fd, IODVD_REPORT_KEY, &dvdioctl );
370 *pi_asf = p_buffer[ 7 ] & 1;
372 #else
373 /* DVD ioctls unavailable - do as if the ioctl failed */
374 i_ret = -1;
376 #endif
377 return i_ret;
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 )
385 int i_ret;
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 )
417 INIT_DVDIOCTL( 12 );
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 );
426 #else
427 /* DVD ioctls unavailable - do as if the ioctl failed */
428 i_ret = -1;
430 #endif
431 return i_ret;
434 /*****************************************************************************
435 * ioctl_InvalidateAgid: invalidate the current AGID
436 *****************************************************************************/
437 int ioctl_InvalidateAgid( int i_fd, int *pi_agid )
439 int i_ret;
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 )
469 INIT_DVDIOCTL( 0 );
471 dvdioctl.i_keyformat = kInvalidateAGID;
472 dvdioctl.i_agid = *pi_agid;
474 i_ret = ioctl( i_fd, IODVD_SEND_KEY, &dvdioctl );
476 #else
477 /* DVD ioctls unavailable - do as if the ioctl failed */
478 i_ret = -1;
480 #endif
481 return i_ret;
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);
514 p_buffer[ 1 ] = 0xe;
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 )
520 INIT_DVDIOCTL( 16 );
522 dvdioctl.i_keyformat = kChallengeKey;
523 dvdioctl.i_agid = *pi_agid;
525 p_buffer[ 1 ] = 0xe;
526 memcpy( p_buffer + 4, p_challenge, 12 );
528 return ioctl( i_fd, IODVD_SEND_KEY, &dvdioctl );
530 #else
531 /* DVD ioctls unavailable - do as if the ioctl failed */
532 return -1;
534 #endif
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);
567 p_buffer[ 1 ] = 0xa;
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 )
573 INIT_DVDIOCTL( 12 );
575 dvdioctl.i_keyformat = kKey2;
576 dvdioctl.i_agid = *pi_agid;
578 p_buffer[ 1 ] = 0xa;
579 memcpy( p_buffer + 4, p_key, 8 );
581 return ioctl( i_fd, IODVD_SEND_KEY, &dvdioctl );
583 #else
584 /* DVD ioctls unavailable - do as if the ioctl failed */
585 return -1;
587 #endif
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 );
603 switch( i_type )
605 case GPCMD_SEND_KEY:
606 /* leave the flags to 0 */
607 break;
609 case GPCMD_READ_DVD_STRUCTURE:
610 case GPCMD_REPORT_KEY:
611 p_rdc->flags = B_RAW_DEVICE_DATA_IN;
612 break;
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;
626 #endif