1 /*****************************************************************************
2 * ioctl.c: DVD ioctl replacement function
3 *****************************************************************************
4 * Copyright (C) 1999-2001 VideoLAN
5 * $Id: ioctl.c,v 1.7 2001/08/07 02:48:24 sam Exp $
7 * Authors: Markus Kuespert <ltlBeBoy@beosmail.com>
8 * Samuel Hocevar <sam@zoy.org>
9 * Jon Lech Johansen <jon-vl@nanocrew.net>
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
24 *****************************************************************************/
26 /*****************************************************************************
28 *****************************************************************************/
31 #include <string.h> /* memcpy(), memset() */
32 #include <sys/types.h>
36 # include <winioctl.h>
38 # include <netinet/in.h>
39 # include <sys/ioctl.h>
42 #ifdef DVD_STRUCT_IN_SYS_CDIO_H
43 # include <sys/cdio.h>
45 #ifdef DVD_STRUCT_IN_SYS_DVDIO_H
46 # include <sys/dvdio.h>
48 #ifdef DVD_STRUCT_IN_LINUX_CDROM_H
49 # include <linux/cdrom.h>
51 #ifdef DVD_STRUCT_IN_DVD_H
63 # include "DVDioctl/DVDioctl.h"
68 /*****************************************************************************
69 * Local prototypes, BeOS specific
70 *****************************************************************************/
71 #if defined( SYS_BEOS )
72 static void BeInitRDC ( raw_device_command *, int );
75 /*****************************************************************************
76 * Local prototypes, win32 (aspi) specific
77 *****************************************************************************/
79 static void WinInitSSC ( struct SRB_ExecSCSICmd *, int );
80 static int WinSendSSC ( int, struct SRB_ExecSCSICmd * );
83 /*****************************************************************************
84 * ioctl_ReadCopyright: check whether the disc is encrypted or not
85 *****************************************************************************/
86 int ioctl_ReadCopyright( int i_fd, int i_layer, int *pi_copyright )
90 #if defined( HAVE_LINUX_DVD_STRUCT )
93 dvd.type = DVD_STRUCT_COPYRIGHT;
94 dvd.copyright.layer_num = i_layer;
96 i_ret = ioctl( i_fd, DVD_READ_STRUCT, &dvd );
98 *pi_copyright = dvd.copyright.cpst;
100 #elif defined( HAVE_BSD_DVD_STRUCT )
101 struct dvd_struct dvd;
103 dvd.format = DVD_STRUCT_COPYRIGHT;
104 dvd.layer_num = i_layer;
106 i_ret = ioctl( i_fd, DVDIOCREADSTRUCTURE, &dvd );
108 *pi_copyright = dvd.cpst;
110 #elif defined( SYS_BEOS )
111 INIT_RDC( GPCMD_READ_DVD_STRUCTURE, 8 );
113 rdc.command[ 6 ] = i_layer;
114 rdc.command[ 7 ] = DVD_STRUCT_COPYRIGHT;
116 i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
118 *pi_copyright = p_buffer[ 4 ];
120 #elif defined( SYS_DARWIN )
125 #elif defined( WIN32 )
126 if( WIN2K ) /* NT/Win2000/Whistler */
130 SCSI_PASS_THROUGH_DIRECT sptd;
132 memset( &sptd, 0, sizeof( sptd ) );
133 memset( &p_buffer, 0, sizeof( p_buffer ) );
135 /* When using IOCTL_DVD_READ_STRUCTURE and
136 DVD_COPYRIGHT_DESCRIPTOR, CopyrightProtectionType
137 is always 6. So we send a raw scsi command instead. */
139 sptd.Length = sizeof( SCSI_PASS_THROUGH_DIRECT );
141 sptd.DataIn = SCSI_IOCTL_DATA_IN;
142 sptd.DataTransferLength = 8;
143 sptd.TimeOutValue = 2;
144 sptd.DataBuffer = p_buffer;
145 sptd.Cdb[ 0 ] = GPCMD_READ_DVD_STRUCTURE;
146 sptd.Cdb[ 6 ] = i_layer;
147 sptd.Cdb[ 7 ] = DVD_STRUCT_COPYRIGHT;
148 sptd.Cdb[ 8 ] = (8 >> 8) & 0xff;
149 sptd.Cdb[ 9 ] = 8 & 0xff;
151 i_ret = DeviceIoControl( (HANDLE) i_fd,
152 IOCTL_SCSI_PASS_THROUGH_DIRECT,
153 &sptd, sizeof( SCSI_PASS_THROUGH_DIRECT ),
154 &sptd, sizeof( SCSI_PASS_THROUGH_DIRECT ),
155 &tmp, NULL ) ? 0 : -1;
157 *pi_copyright = p_buffer[4];
161 INIT_SSC( GPCMD_READ_DVD_STRUCTURE, 8 );
163 ssc.CDBByte[ 6 ] = i_layer;
164 ssc.CDBByte[ 7 ] = DVD_STRUCT_COPYRIGHT;
166 i_ret = WinSendSSC( i_fd, &ssc );
168 *pi_copyright = p_buffer[ 4 ];
171 #elif defined( __QNXNTO__ )
173 QNX RTOS currently doesn't have a CAM
174 interface (they're working on it though).
175 Assume DVD is not encrypted.
182 /* DVD ioctls unavailable - do as if the ioctl failed */
189 /*****************************************************************************
190 * ioctl_ReadKey: get the disc key
191 *****************************************************************************/
192 int ioctl_ReadKey( int i_fd, int *pi_agid, u8 *p_key )
196 #if defined( HAVE_LINUX_DVD_STRUCT )
199 dvd.type = DVD_STRUCT_DISCKEY;
200 dvd.disckey.agid = *pi_agid;
201 memset( dvd.disckey.value, 0, 2048 );
203 i_ret = ioctl( i_fd, DVD_READ_STRUCT, &dvd );
210 memcpy( p_key, dvd.disckey.value, 2048 );
212 #elif defined( HAVE_BSD_DVD_STRUCT )
213 struct dvd_struct dvd;
215 dvd.format = DVD_STRUCT_DISCKEY;
217 memset( dvd.data, 0, 2048 );
219 i_ret = ioctl( i_fd, DVDIOCREADSTRUCTURE, &dvd );
226 memcpy( p_key, dvd.data, 2048 );
228 #elif defined( SYS_BEOS )
229 INIT_RDC( GPCMD_READ_DVD_STRUCTURE, 2048 + 4 );
231 rdc.command[ 7 ] = DVD_STRUCT_DISCKEY;
232 rdc.command[ 10 ] = *pi_agid << 6;
234 i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
241 memcpy( p_key, p_buffer + 4, 2048 );
243 #elif defined( SYS_DARWIN )
246 memset( p_key, 0x00, 2048 );
248 #elif defined( WIN32 )
249 if( WIN2K ) /* NT/Win2000/Whistler */
252 u8 buffer[DVD_DISK_KEY_LENGTH];
253 PDVD_COPY_PROTECT_KEY key = (PDVD_COPY_PROTECT_KEY) &buffer;
255 memset( &buffer, 0, sizeof( buffer ) );
257 key->KeyLength = DVD_DISK_KEY_LENGTH;
258 key->SessionId = *pi_agid;
259 key->KeyType = DvdDiskKey;
262 i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_READ_KEY, key,
263 key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1;
270 memcpy( p_key, key->KeyData, 2048 );
274 INIT_SSC( GPCMD_READ_DVD_STRUCTURE, 2048 + 4 );
276 ssc.CDBByte[ 7 ] = DVD_STRUCT_DISCKEY;
277 ssc.CDBByte[ 10 ] = *pi_agid << 6;
279 i_ret = WinSendSSC( i_fd, &ssc );
286 memcpy( p_key, p_buffer + 4, 2048 );
290 /* DVD ioctls unavailable - do as if the ioctl failed */
297 /*****************************************************************************
298 * ioctl_ReportAgid: get AGID from the drive
299 *****************************************************************************/
300 int ioctl_ReportAgid( int i_fd, int *pi_agid )
304 #if defined( HAVE_LINUX_DVD_STRUCT )
305 dvd_authinfo auth_info;
307 auth_info.type = DVD_LU_SEND_AGID;
308 auth_info.lsa.agid = *pi_agid;
310 i_ret = ioctl( i_fd, DVD_AUTH, &auth_info );
312 *pi_agid = auth_info.lsa.agid;
314 #elif defined( HAVE_BSD_DVD_STRUCT )
315 struct dvd_authinfo auth_info;
317 auth_info.format = DVD_REPORT_AGID;
318 auth_info.agid = *pi_agid;
320 i_ret = ioctl( i_fd, DVDIOCREPORTKEY, &auth_info );
322 *pi_agid = auth_info.agid;
324 #elif defined( SYS_BEOS )
325 INIT_RDC( GPCMD_REPORT_KEY, 8 );
327 rdc.command[ 10 ] = DVD_REPORT_AGID | (*pi_agid << 6);
329 i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
331 *pi_agid = p_buffer[ 7 ] >> 6;
333 #elif defined( SYS_DARWIN )
336 dvdioctl.i_keyformat = kCSSAGID;
337 dvdioctl.i_agid = *pi_agid;
340 i_ret = ioctl( i_fd, IODVD_REPORT_KEY, &dvdioctl );
342 *pi_agid = p_buffer[ 7 ] >> 6;
344 #elif defined( WIN32 )
345 if( WIN2K ) /* NT/Win2000/Whistler */
350 i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_START_SESSION,
351 &tmp, 4, &id, sizeof( id ), &tmp, NULL ) ? 0 : -1;
357 INIT_SSC( GPCMD_REPORT_KEY, 8 );
359 ssc.CDBByte[ 10 ] = DVD_REPORT_AGID | (*pi_agid << 6);
361 i_ret = WinSendSSC( i_fd, &ssc );
363 *pi_agid = p_buffer[ 7 ] >> 6;
367 /* DVD ioctls unavailable - do as if the ioctl failed */
374 /*****************************************************************************
375 * ioctl_ReportChallenge: get challenge from the drive
376 *****************************************************************************/
377 int ioctl_ReportChallenge( int i_fd, int *pi_agid, u8 *p_challenge )
381 #if defined( HAVE_LINUX_DVD_STRUCT )
382 dvd_authinfo auth_info;
384 auth_info.type = DVD_LU_SEND_CHALLENGE;
385 auth_info.lsc.agid = *pi_agid;
387 i_ret = ioctl( i_fd, DVD_AUTH, &auth_info );
389 memcpy( p_challenge, auth_info.lsc.chal, sizeof(dvd_challenge) );
391 #elif defined( HAVE_BSD_DVD_STRUCT )
392 struct dvd_authinfo auth_info;
394 auth_info.format = DVD_REPORT_CHALLENGE;
395 auth_info.agid = *pi_agid;
397 i_ret = ioctl( i_fd, DVDIOCREPORTKEY, &auth_info );
399 memcpy( p_challenge, auth_info.keychal, 10 );
401 #elif defined( SYS_BEOS )
402 INIT_RDC( GPCMD_REPORT_KEY, 16 );
404 rdc.command[ 10 ] = DVD_REPORT_CHALLENGE | (*pi_agid << 6);
406 i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
408 memcpy( p_challenge, p_buffer + 4, 12 );
410 #elif defined( SYS_DARWIN )
413 dvdioctl.i_keyformat = kChallengeKey;
414 dvdioctl.i_agid = *pi_agid;
417 i_ret = ioctl( i_fd, IODVD_REPORT_KEY, &dvdioctl );
419 memcpy( p_challenge, p_buffer + 4, 12 );
421 #elif defined( WIN32 )
422 if( WIN2K ) /* NT/Win2000/Whistler */
425 u8 buffer[DVD_CHALLENGE_KEY_LENGTH];
426 PDVD_COPY_PROTECT_KEY key = (PDVD_COPY_PROTECT_KEY) &buffer;
428 memset( &buffer, 0, sizeof( buffer ) );
430 key->KeyLength = DVD_CHALLENGE_KEY_LENGTH;
431 key->SessionId = *pi_agid;
432 key->KeyType = DvdChallengeKey;
435 i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_READ_KEY, key,
436 key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1;
443 memcpy( p_challenge, key->KeyData, 10 );
447 INIT_SSC( GPCMD_REPORT_KEY, 16 );
449 ssc.CDBByte[ 10 ] = DVD_REPORT_CHALLENGE | (*pi_agid << 6);
451 i_ret = WinSendSSC( i_fd, &ssc );
453 memcpy( p_challenge, p_buffer + 4, 12 );
457 /* DVD ioctls unavailable - do as if the ioctl failed */
464 /*****************************************************************************
465 * ioctl_ReportASF: get ASF from the drive
466 *****************************************************************************/
467 int ioctl_ReportASF( int i_fd, int *pi_agid, int *pi_asf )
471 #if defined( HAVE_LINUX_DVD_STRUCT )
472 dvd_authinfo auth_info;
474 auth_info.type = DVD_LU_SEND_ASF;
475 auth_info.lsasf.agid = *pi_agid;
476 auth_info.lsasf.asf = *pi_asf;
478 i_ret = ioctl( i_fd, DVD_AUTH, &auth_info );
480 *pi_asf = auth_info.lsasf.asf;
482 #elif defined( HAVE_BSD_DVD_STRUCT )
483 struct dvd_authinfo auth_info;
485 auth_info.format = DVD_REPORT_ASF;
486 auth_info.agid = *pi_agid;
487 auth_info.asf = *pi_asf;
489 i_ret = ioctl( i_fd, DVDIOCREPORTKEY, &auth_info );
491 *pi_asf = auth_info.asf;
493 #elif defined( SYS_BEOS )
494 INIT_RDC( GPCMD_REPORT_KEY, 8 );
496 rdc.command[ 10 ] = DVD_REPORT_ASF | (*pi_agid << 6);
498 i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
500 *pi_asf = p_buffer[ 7 ] & 1;
502 #elif defined( SYS_DARWIN )
505 dvdioctl.i_keyformat = kASF;
506 dvdioctl.i_agid = *pi_agid;
509 i_ret = ioctl( i_fd, IODVD_REPORT_KEY, &dvdioctl );
511 *pi_asf = p_buffer[ 7 ] & 1;
513 #elif defined( WIN32 )
514 if( WIN2K ) /* NT/Win2000/Whistler */
517 u8 buffer[DVD_ASF_LENGTH];
518 PDVD_COPY_PROTECT_KEY key = (PDVD_COPY_PROTECT_KEY) &buffer;
520 memset( &buffer, 0, sizeof( buffer ) );
522 key->KeyLength = DVD_ASF_LENGTH;
523 key->SessionId = *pi_agid;
524 key->KeyType = DvdAsf;
527 ((PDVD_ASF)key->KeyData)->SuccessFlag = *pi_asf;
529 i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_READ_KEY, key,
530 key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1;
537 *pi_asf = ((PDVD_ASF)key->KeyData)->SuccessFlag;
541 INIT_SSC( GPCMD_REPORT_KEY, 8 );
543 ssc.CDBByte[ 10 ] = DVD_REPORT_ASF | (*pi_agid << 6);
545 i_ret = WinSendSSC( i_fd, &ssc );
547 *pi_asf = p_buffer[ 7 ] & 1;
551 /* DVD ioctls unavailable - do as if the ioctl failed */
558 /*****************************************************************************
559 * ioctl_ReportKey1: get the first key from the drive
560 *****************************************************************************/
561 int ioctl_ReportKey1( int i_fd, int *pi_agid, u8 *p_key )
565 #if defined( HAVE_LINUX_DVD_STRUCT )
566 dvd_authinfo auth_info;
568 auth_info.type = DVD_LU_SEND_KEY1;
569 auth_info.lsk.agid = *pi_agid;
571 i_ret = ioctl( i_fd, DVD_AUTH, &auth_info );
573 memcpy( p_key, auth_info.lsk.key, sizeof(dvd_key) );
575 #elif defined( HAVE_BSD_DVD_STRUCT )
576 struct dvd_authinfo auth_info;
578 auth_info.format = DVD_REPORT_KEY1;
579 auth_info.agid = *pi_agid;
581 i_ret = ioctl( i_fd, DVDIOCREPORTKEY, &auth_info );
583 memcpy( p_key, auth_info.keychal, 8 );
585 #elif defined( SYS_BEOS )
586 INIT_RDC( GPCMD_REPORT_KEY, 12 );
588 rdc.command[ 10 ] = DVD_REPORT_KEY1 | (*pi_agid << 6);
590 i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
592 memcpy( p_key, p_buffer + 4, 8 );
594 #elif defined( SYS_DARWIN )
597 dvdioctl.i_keyformat = kKey1;
598 dvdioctl.i_agid = *pi_agid;
600 i_ret = ioctl( i_fd, IODVD_SEND_KEY, &dvdioctl );
602 memcpy( p_key, p_buffer + 4, 8 );
604 #elif defined( WIN32 )
605 if( WIN2K ) /* NT/Win2000/Whistler */
608 u8 buffer[DVD_BUS_KEY_LENGTH];
609 PDVD_COPY_PROTECT_KEY key = (PDVD_COPY_PROTECT_KEY) &buffer;
611 memset( &buffer, 0, sizeof( buffer ) );
613 key->KeyLength = DVD_BUS_KEY_LENGTH;
614 key->SessionId = *pi_agid;
615 key->KeyType = DvdBusKey1;
618 i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_READ_KEY, key,
619 key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1;
621 memcpy( p_key, key->KeyData, 8 );
625 INIT_SSC( GPCMD_REPORT_KEY, 12 );
627 ssc.CDBByte[ 10 ] = DVD_REPORT_KEY1 | (*pi_agid << 6);
629 i_ret = WinSendSSC( i_fd, &ssc );
631 memcpy( p_key, p_buffer + 4, 8 );
635 /* DVD ioctls unavailable - do as if the ioctl failed */
642 /*****************************************************************************
643 * ioctl_InvalidateAgid: invalidate the current AGID
644 *****************************************************************************/
645 int ioctl_InvalidateAgid( int i_fd, int *pi_agid )
649 #if defined( HAVE_LINUX_DVD_STRUCT )
650 dvd_authinfo auth_info;
652 auth_info.type = DVD_INVALIDATE_AGID;
653 auth_info.lsa.agid = *pi_agid;
655 i_ret = ioctl( i_fd, DVD_AUTH, &auth_info );
657 *pi_agid = auth_info.lsa.agid;
659 #elif defined( HAVE_BSD_DVD_STRUCT )
660 struct dvd_authinfo auth_info;
662 auth_info.format = DVD_INVALIDATE_AGID;
663 auth_info.agid = *pi_agid;
665 i_ret = ioctl( i_fd, DVDIOCREPORTKEY, &auth_info );
667 *pi_agid = auth_info.agid;
669 #elif defined( SYS_BEOS )
670 INIT_RDC( GPCMD_REPORT_KEY, 0 );
672 rdc.command[ 10 ] = DVD_INVALIDATE_AGID | (*pi_agid << 6);
674 i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
676 #elif defined( SYS_DARWIN )
679 dvdioctl.i_keyformat = kInvalidateAGID;
680 dvdioctl.i_agid = *pi_agid;
682 i_ret = ioctl( i_fd, IODVD_SEND_KEY, &dvdioctl );
684 #elif defined( WIN32 )
685 if( WIN2K ) /* NT/Win2000/Whistler */
689 i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_END_SESSION,
690 pi_agid, sizeof( *pi_agid ), NULL, 0, &tmp, NULL ) ? 0 : -1;
694 #if defined( __MINGW32__ )
695 INIT_SSC( GPCMD_REPORT_KEY, 0 );
697 INIT_SSC( GPCMD_REPORT_KEY, 1 );
700 ssc.CDBByte[ 8 ] = 0;
701 ssc.CDBByte[ 9 ] = 0;
704 ssc.CDBByte[ 10 ] = DVD_INVALIDATE_AGID | (*pi_agid << 6);
706 i_ret = WinSendSSC( i_fd, &ssc );
710 /* DVD ioctls unavailable - do as if the ioctl failed */
717 /*****************************************************************************
718 * ioctl_SendChallenge: send challenge to the drive
719 *****************************************************************************/
720 int ioctl_SendChallenge( int i_fd, int *pi_agid, u8 *p_challenge )
722 #if defined( HAVE_LINUX_DVD_STRUCT )
723 dvd_authinfo auth_info;
725 auth_info.type = DVD_HOST_SEND_CHALLENGE;
726 auth_info.hsc.agid = *pi_agid;
728 memcpy( auth_info.hsc.chal, p_challenge, sizeof(dvd_challenge) );
730 return ioctl( i_fd, DVD_AUTH, &auth_info );
732 #elif defined( HAVE_BSD_DVD_STRUCT )
733 struct dvd_authinfo auth_info;
735 auth_info.format = DVD_SEND_CHALLENGE;
736 auth_info.agid = *pi_agid;
738 memcpy( auth_info.keychal, p_challenge, 12 );
740 return ioctl( i_fd, DVDIOCSENDKEY, &auth_info );
742 #elif defined( SYS_BEOS )
743 INIT_RDC( GPCMD_SEND_KEY, 16 );
745 rdc.command[ 10 ] = DVD_SEND_CHALLENGE | (*pi_agid << 6);
748 memcpy( p_buffer + 4, p_challenge, 12 );
750 return ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
752 #elif defined( SYS_DARWIN )
755 dvdioctl.i_keyformat = kChallengeKey;
756 dvdioctl.i_agid = *pi_agid;
759 memcpy( p_buffer + 4, p_challenge, 12 );
761 return ioctl( i_fd, IODVD_SEND_KEY, &dvdioctl );
763 #elif defined( WIN32 )
764 if( WIN2K ) /* NT/Win2000/Whistler */
767 u8 buffer[DVD_CHALLENGE_KEY_LENGTH];
768 PDVD_COPY_PROTECT_KEY key = (PDVD_COPY_PROTECT_KEY) &buffer;
770 memset( &buffer, 0, sizeof( buffer ) );
772 key->KeyLength = DVD_CHALLENGE_KEY_LENGTH;
773 key->SessionId = *pi_agid;
774 key->KeyType = DvdChallengeKey;
777 memcpy( key->KeyData, p_challenge, 10 );
779 return DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_SEND_KEY, key,
780 key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1;
784 INIT_SSC( GPCMD_SEND_KEY, 16 );
786 ssc.CDBByte[ 10 ] = DVD_SEND_CHALLENGE | (*pi_agid << 6);
789 memcpy( p_buffer + 4, p_challenge, 12 );
791 return WinSendSSC( i_fd, &ssc );
795 /* DVD ioctls unavailable - do as if the ioctl failed */
801 /*****************************************************************************
802 * ioctl_SendKey2: send the second key to the drive
803 *****************************************************************************/
804 int ioctl_SendKey2( int i_fd, int *pi_agid, u8 *p_key )
806 #if defined( HAVE_LINUX_DVD_STRUCT )
807 dvd_authinfo auth_info;
809 auth_info.type = DVD_HOST_SEND_KEY2;
810 auth_info.hsk.agid = *pi_agid;
812 memcpy( auth_info.hsk.key, p_key, sizeof(dvd_key) );
814 return ioctl( i_fd, DVD_AUTH, &auth_info );
816 #elif defined( HAVE_BSD_DVD_STRUCT )
817 struct dvd_authinfo auth_info;
819 auth_info.format = DVD_SEND_KEY2;
820 auth_info.agid = *pi_agid;
822 memcpy( auth_info.keychal, p_key, 8 );
824 return ioctl( i_fd, DVDIOCSENDKEY, &auth_info );
826 #elif defined( SYS_BEOS )
827 INIT_RDC( GPCMD_SEND_KEY, 12 );
829 rdc.command[ 10 ] = DVD_SEND_KEY2 | (*pi_agid << 6);
832 memcpy( p_buffer + 4, p_key, 8 );
834 return ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
836 #elif defined( WIN32 )
837 if( WIN2K ) /* NT/Win2000/Whistler */
840 u8 buffer[DVD_BUS_KEY_LENGTH];
841 PDVD_COPY_PROTECT_KEY key = (PDVD_COPY_PROTECT_KEY) &buffer;
843 memset( &buffer, 0, sizeof( buffer ) );
845 key->KeyLength = DVD_BUS_KEY_LENGTH;
846 key->SessionId = *pi_agid;
847 key->KeyType = DvdBusKey2;
850 memcpy( key->KeyData, p_key, 8 );
852 return DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_SEND_KEY, key,
853 key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1;
857 INIT_SSC( GPCMD_SEND_KEY, 12 );
859 ssc.CDBByte[ 10 ] = DVD_SEND_KEY2 | (*pi_agid << 6);
862 memcpy( p_buffer + 4, p_key, 8 );
864 return WinSendSSC( i_fd, &ssc );
867 #elif defined( SYS_DARWIN )
870 dvdioctl.i_keyformat = kKey2;
871 dvdioctl.i_agid = *pi_agid;
874 memcpy( p_buffer + 4, p_key, 8 );
876 return ioctl( i_fd, IODVD_SEND_KEY, &dvdioctl );
879 /* DVD ioctls unavailable - do as if the ioctl failed */
885 /* Local prototypes */
887 #if defined( SYS_BEOS )
888 /*****************************************************************************
889 * BeInitRDC: initialize a RDC structure for the BeOS kernel
890 *****************************************************************************
891 * This function initializes a BeOS raw device command structure for future
892 * use, either a read command or a write command.
893 *****************************************************************************/
894 static void BeInitRDC( raw_device_command *p_rdc, int i_type )
896 memset( p_rdc->data, 0, p_rdc->data_length );
901 /* leave the flags to 0 */
904 case GPCMD_READ_DVD_STRUCTURE:
905 case GPCMD_REPORT_KEY:
906 p_rdc->flags = B_RAW_DEVICE_DATA_IN;
910 p_rdc->command[ 0 ] = i_type;
912 p_rdc->command[ 8 ] = (p_rdc->data_length >> 8) & 0xff;
913 p_rdc->command[ 9 ] = p_rdc->data_length & 0xff;
914 p_rdc->command_length = 12;
916 p_rdc->sense_data = NULL;
917 p_rdc->sense_data_length = 0;
919 p_rdc->timeout = 1000000;
924 /*****************************************************************************
925 * WinInitSSC: initialize a ssc structure for the win32 aspi layer
926 *****************************************************************************
927 * This function initializes a ssc raw device command structure for future
928 * use, either a read command or a write command.
929 *****************************************************************************/
930 static void WinInitSSC( struct SRB_ExecSCSICmd *p_ssc, int i_type )
932 memset( p_ssc->SRB_BufPointer, 0, p_ssc->SRB_BufLen );
937 p_ssc->SRB_Flags = SRB_DIR_OUT;
940 case GPCMD_READ_DVD_STRUCTURE:
941 case GPCMD_REPORT_KEY:
942 p_ssc->SRB_Flags = SRB_DIR_IN;
946 p_ssc->SRB_Cmd = SC_EXEC_SCSI_CMD;
947 p_ssc->SRB_Flags |= SRB_EVENT_NOTIFY;
949 p_ssc->CDBByte[ 0 ] = i_type;
951 p_ssc->CDBByte[ 8 ] = (u8)(p_ssc->SRB_BufLen >> 8) & 0xff;
952 p_ssc->CDBByte[ 9 ] = (u8) p_ssc->SRB_BufLen & 0xff;
953 p_ssc->SRB_CDBLen = 12;
955 p_ssc->SRB_SenseLen = SENSE_LEN;
958 /*****************************************************************************
959 * WinSendSSC: send a ssc structure to the aspi layer
960 *****************************************************************************/
961 static int WinSendSSC( int i_fd, struct SRB_ExecSCSICmd *p_ssc )
963 HANDLE hEvent = NULL;
964 struct w32_aspidev *fd = (struct w32_aspidev *) i_fd;
966 hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
972 p_ssc->SRB_PostProc = hEvent;
973 p_ssc->SRB_HaId = LOBYTE( fd->i_sid );
974 p_ssc->SRB_Target = HIBYTE( fd->i_sid );
976 ResetEvent( hEvent );
977 if( fd->lpSendCommand( (void*) p_ssc ) == SS_PENDING )
978 WaitForSingleObject( hEvent, INFINITE );
980 CloseHandle( hEvent );
982 return p_ssc->SRB_Status == SS_COMP ? 0 : -1;