1 /*****************************************************************************
2 * ioctl.c: DVD ioctl replacement function
3 *****************************************************************************
4 * Copyright (C) 1999-2001 VideoLAN
5 * $Id: ioctl.c,v 1.4 2001/07/19 11:50:50 massiot 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>
60 # include "DVDioctl/DVDioctl.h"
65 /*****************************************************************************
66 * Local prototypes, BeOS specific
67 *****************************************************************************/
68 #if defined( SYS_BEOS )
69 static void BeInitRDC ( raw_device_command *, int );
72 /*****************************************************************************
73 * Local prototypes, win32 (aspi) specific
74 *****************************************************************************/
76 static void WinInitSSC ( struct SRB_ExecSCSICmd *, int );
77 static int WinSendSSC ( int, struct SRB_ExecSCSICmd * );
80 /*****************************************************************************
81 * ioctl_ReadCopyright: check whether the disc is encrypted or not
82 *****************************************************************************/
83 int ioctl_ReadCopyright( int i_fd, int i_layer, int *pi_copyright )
87 #if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
90 dvd.type = DVD_STRUCT_COPYRIGHT;
91 dvd.copyright.layer_num = i_layer;
93 i_ret = ioctl( i_fd, DVD_READ_STRUCT, &dvd );
95 *pi_copyright = dvd.copyright.cpst;
97 #elif defined( HAVE_BSD_DVD_STRUCT )
98 struct dvd_struct dvd;
100 dvd.format = DVD_STRUCT_COPYRIGHT;
101 dvd.layer_num = i_layer;
103 i_ret = ioctl( i_fd, DVDIOCREADSTRUCTURE, &dvd );
105 *pi_copyright = dvd.cpst;
107 #elif defined( SYS_BEOS )
108 INIT_RDC( GPCMD_READ_DVD_STRUCTURE, 8 );
110 rdc.command[ 6 ] = i_layer;
111 rdc.command[ 7 ] = DVD_STRUCT_COPYRIGHT;
113 i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
115 *pi_copyright = p_buffer[ 4 ];
117 #elif defined( SYS_DARWIN )
118 _dvd_error( dvdcss, "DVD ioctls not fully functional yet, "
119 "assuming disc is encrypted" );
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( DVD_STRUCT_IN_LINUX_CDROM_H )
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 )
244 _dvd_error( dvdcss, "DVD ioctls not fully functional yet, "
245 "sending an empty key" );
249 memset( p_key, 0x00, 2048 );
251 #elif defined( WIN32 )
252 if( WIN2K ) /* NT/Win2000/Whistler */
255 u8 buffer[DVD_DISK_KEY_LENGTH];
256 PDVD_COPY_PROTECT_KEY key = (PDVD_COPY_PROTECT_KEY) &buffer;
258 memset( &buffer, 0, sizeof( buffer ) );
260 key->KeyLength = DVD_DISK_KEY_LENGTH;
261 key->SessionId = *pi_agid;
262 key->KeyType = DvdDiskKey;
265 i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_READ_KEY, key,
266 key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1;
273 memcpy( p_key, key->KeyData, 2048 );
277 INIT_SSC( GPCMD_READ_DVD_STRUCTURE, 2048 + 4 );
279 ssc.CDBByte[ 7 ] = DVD_STRUCT_DISCKEY;
280 ssc.CDBByte[ 10 ] = *pi_agid << 6;
282 i_ret = WinSendSSC( i_fd, &ssc );
289 memcpy( p_key, p_buffer + 4, 2048 );
293 /* DVD ioctls unavailable - do as if the ioctl failed */
300 /*****************************************************************************
301 * ioctl_ReportAgid: get AGID from the drive
302 *****************************************************************************/
303 int ioctl_ReportAgid( int i_fd, int *pi_agid )
307 #if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
308 dvd_authinfo auth_info;
310 auth_info.type = DVD_LU_SEND_AGID;
311 auth_info.lsa.agid = *pi_agid;
313 i_ret = ioctl( i_fd, DVD_AUTH, &auth_info );
315 *pi_agid = auth_info.lsa.agid;
317 #elif defined( HAVE_BSD_DVD_STRUCT )
318 struct dvd_authinfo auth_info;
320 auth_info.format = DVD_REPORT_AGID;
321 auth_info.agid = *pi_agid;
323 i_ret = ioctl( i_fd, DVDIOCREPORTKEY, &auth_info );
325 *pi_agid = auth_info.agid;
327 #elif defined( SYS_BEOS )
328 INIT_RDC( GPCMD_REPORT_KEY, 8 );
330 rdc.command[ 10 ] = DVD_REPORT_AGID | (*pi_agid << 6);
332 i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
334 *pi_agid = p_buffer[ 7 ] >> 6;
336 #elif defined( SYS_DARWIN )
339 dvdioctl.i_keyformat = kCSSAGID;
340 dvdioctl.i_agid = *pi_agid;
343 i_ret = ioctl( i_fd, IODVD_REPORT_KEY, &dvdioctl );
345 *pi_agid = p_buffer[ 7 ] >> 6;
347 #elif defined( WIN32 )
348 if( WIN2K ) /* NT/Win2000/Whistler */
353 i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_START_SESSION,
354 &tmp, 4, &id, sizeof( id ), &tmp, NULL ) ? 0 : -1;
360 INIT_SSC( GPCMD_REPORT_KEY, 8 );
362 ssc.CDBByte[ 10 ] = DVD_REPORT_AGID | (*pi_agid << 6);
364 i_ret = WinSendSSC( i_fd, &ssc );
366 *pi_agid = p_buffer[ 7 ] >> 6;
370 /* DVD ioctls unavailable - do as if the ioctl failed */
377 /*****************************************************************************
378 * ioctl_ReportChallenge: get challenge from the drive
379 *****************************************************************************/
380 int ioctl_ReportChallenge( int i_fd, int *pi_agid, u8 *p_challenge )
384 #if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
385 dvd_authinfo auth_info;
387 auth_info.type = DVD_LU_SEND_CHALLENGE;
388 auth_info.lsc.agid = *pi_agid;
390 i_ret = ioctl( i_fd, DVD_AUTH, &auth_info );
392 memcpy( p_challenge, auth_info.lsc.chal, sizeof(dvd_challenge) );
394 #elif defined( HAVE_BSD_DVD_STRUCT )
395 struct dvd_authinfo auth_info;
397 auth_info.format = DVD_REPORT_CHALLENGE;
398 auth_info.agid = *pi_agid;
400 i_ret = ioctl( i_fd, DVDIOCREPORTKEY, &auth_info );
402 memcpy( p_challenge, auth_info.keychal, 10 );
404 #elif defined( SYS_BEOS )
405 INIT_RDC( GPCMD_REPORT_KEY, 16 );
407 rdc.command[ 10 ] = DVD_REPORT_CHALLENGE | (*pi_agid << 6);
409 i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
411 memcpy( p_challenge, p_buffer + 4, 12 );
413 #elif defined( SYS_DARWIN )
416 dvdioctl.i_keyformat = kChallengeKey;
417 dvdioctl.i_agid = *pi_agid;
420 i_ret = ioctl( i_fd, IODVD_REPORT_KEY, &dvdioctl );
422 memcpy( p_challenge, p_buffer + 4, 12 );
424 #elif defined( WIN32 )
425 if( WIN2K ) /* NT/Win2000/Whistler */
428 u8 buffer[DVD_CHALLENGE_KEY_LENGTH];
429 PDVD_COPY_PROTECT_KEY key = (PDVD_COPY_PROTECT_KEY) &buffer;
431 memset( &buffer, 0, sizeof( buffer ) );
433 key->KeyLength = DVD_CHALLENGE_KEY_LENGTH;
434 key->SessionId = *pi_agid;
435 key->KeyType = DvdChallengeKey;
438 i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_READ_KEY, key,
439 key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1;
446 memcpy( p_challenge, key->KeyData, 10 );
450 INIT_SSC( GPCMD_REPORT_KEY, 16 );
452 ssc.CDBByte[ 10 ] = DVD_REPORT_CHALLENGE | (*pi_agid << 6);
454 i_ret = WinSendSSC( i_fd, &ssc );
456 memcpy( p_challenge, p_buffer + 4, 12 );
460 /* DVD ioctls unavailable - do as if the ioctl failed */
467 /*****************************************************************************
468 * ioctl_ReportASF: get ASF from the drive
469 *****************************************************************************/
470 int ioctl_ReportASF( int i_fd, int *pi_agid, int *pi_asf )
474 #if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
475 dvd_authinfo auth_info;
477 auth_info.type = DVD_LU_SEND_ASF;
478 auth_info.lsasf.agid = *pi_agid;
479 auth_info.lsasf.asf = *pi_asf;
481 i_ret = ioctl( i_fd, DVD_AUTH, &auth_info );
483 *pi_asf = auth_info.lsasf.asf;
485 #elif defined( HAVE_BSD_DVD_STRUCT )
486 struct dvd_authinfo auth_info;
488 auth_info.format = DVD_REPORT_ASF;
489 auth_info.agid = *pi_agid;
490 auth_info.asf = *pi_asf;
492 i_ret = ioctl( i_fd, DVDIOCREPORTKEY, &auth_info );
494 *pi_asf = auth_info.asf;
496 #elif defined( SYS_BEOS )
497 INIT_RDC( GPCMD_REPORT_KEY, 8 );
499 rdc.command[ 10 ] = DVD_REPORT_ASF | (*pi_agid << 6);
501 i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
503 *pi_asf = p_buffer[ 7 ] & 1;
505 #elif defined( SYS_DARWIN )
508 dvdioctl.i_keyformat = kASF;
509 dvdioctl.i_agid = *pi_agid;
512 i_ret = ioctl( i_fd, IODVD_REPORT_KEY, &dvdioctl );
514 *pi_asf = p_buffer[ 7 ] & 1;
516 #elif defined( WIN32 )
517 if( WIN2K ) /* NT/Win2000/Whistler */
520 u8 buffer[DVD_ASF_LENGTH];
521 PDVD_COPY_PROTECT_KEY key = (PDVD_COPY_PROTECT_KEY) &buffer;
523 memset( &buffer, 0, sizeof( buffer ) );
525 key->KeyLength = DVD_ASF_LENGTH;
526 key->SessionId = *pi_agid;
527 key->KeyType = DvdAsf;
530 ((PDVD_ASF)key->KeyData)->SuccessFlag = *pi_asf;
532 i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_READ_KEY, key,
533 key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1;
540 *pi_asf = ((PDVD_ASF)key->KeyData)->SuccessFlag;
544 INIT_SSC( GPCMD_REPORT_KEY, 8 );
546 ssc.CDBByte[ 10 ] = DVD_REPORT_ASF | (*pi_agid << 6);
548 i_ret = WinSendSSC( i_fd, &ssc );
550 *pi_asf = p_buffer[ 7 ] & 1;
554 /* DVD ioctls unavailable - do as if the ioctl failed */
561 /*****************************************************************************
562 * ioctl_ReportKey1: get the first key from the drive
563 *****************************************************************************/
564 int ioctl_ReportKey1( int i_fd, int *pi_agid, u8 *p_key )
568 #if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
569 dvd_authinfo auth_info;
571 auth_info.type = DVD_LU_SEND_KEY1;
572 auth_info.lsk.agid = *pi_agid;
574 i_ret = ioctl( i_fd, DVD_AUTH, &auth_info );
576 memcpy( p_key, auth_info.lsk.key, sizeof(dvd_key) );
578 #elif defined( HAVE_BSD_DVD_STRUCT )
579 struct dvd_authinfo auth_info;
581 auth_info.format = DVD_REPORT_KEY1;
582 auth_info.agid = *pi_agid;
584 i_ret = ioctl( i_fd, DVDIOCREPORTKEY, &auth_info );
586 memcpy( p_key, auth_info.keychal, 8 );
588 #elif defined( SYS_BEOS )
589 INIT_RDC( GPCMD_REPORT_KEY, 12 );
591 rdc.command[ 10 ] = DVD_REPORT_KEY1 | (*pi_agid << 6);
593 i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
595 memcpy( p_key, p_buffer + 4, 8 );
597 #elif defined( SYS_DARWIN )
600 dvdioctl.i_keyformat = kKey1;
601 dvdioctl.i_agid = *pi_agid;
603 i_ret = ioctl( i_fd, IODVD_SEND_KEY, &dvdioctl );
605 memcpy( p_key, p_buffer + 4, 8 );
607 #elif defined( WIN32 )
608 if( WIN2K ) /* NT/Win2000/Whistler */
611 u8 buffer[DVD_BUS_KEY_LENGTH];
612 PDVD_COPY_PROTECT_KEY key = (PDVD_COPY_PROTECT_KEY) &buffer;
614 memset( &buffer, 0, sizeof( buffer ) );
616 key->KeyLength = DVD_BUS_KEY_LENGTH;
617 key->SessionId = *pi_agid;
618 key->KeyType = DvdBusKey1;
621 i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_READ_KEY, key,
622 key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1;
624 memcpy( p_key, key->KeyData, 8 );
628 INIT_SSC( GPCMD_REPORT_KEY, 12 );
630 ssc.CDBByte[ 10 ] = DVD_REPORT_KEY1 | (*pi_agid << 6);
632 i_ret = WinSendSSC( i_fd, &ssc );
634 memcpy( p_key, p_buffer + 4, 8 );
638 /* DVD ioctls unavailable - do as if the ioctl failed */
645 /*****************************************************************************
646 * ioctl_InvalidateAgid: invalidate the current AGID
647 *****************************************************************************/
648 int ioctl_InvalidateAgid( int i_fd, int *pi_agid )
652 #if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
653 dvd_authinfo auth_info;
655 auth_info.type = DVD_INVALIDATE_AGID;
656 auth_info.lsa.agid = *pi_agid;
658 i_ret = ioctl( i_fd, DVD_AUTH, &auth_info );
660 *pi_agid = auth_info.lsa.agid;
662 #elif defined( HAVE_BSD_DVD_STRUCT )
663 struct dvd_authinfo auth_info;
665 auth_info.format = DVD_INVALIDATE_AGID;
666 auth_info.agid = *pi_agid;
668 i_ret = ioctl( i_fd, DVDIOCREPORTKEY, &auth_info );
670 *pi_agid = auth_info.agid;
672 #elif defined( SYS_BEOS )
673 INIT_RDC( GPCMD_REPORT_KEY, 0 );
675 rdc.command[ 10 ] = DVD_INVALIDATE_AGID | (*pi_agid << 6);
677 i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
679 #elif defined( SYS_DARWIN )
682 dvdioctl.i_keyformat = kInvalidateAGID;
683 dvdioctl.i_agid = *pi_agid;
685 i_ret = ioctl( i_fd, IODVD_SEND_KEY, &dvdioctl );
687 #elif defined( WIN32 )
688 if( WIN2K ) /* NT/Win2000/Whistler */
692 i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_END_SESSION,
693 pi_agid, sizeof( *pi_agid ), NULL, 0, &tmp, NULL ) ? 0 : -1;
697 #if defined( __MINGW32__ )
698 INIT_SSC( GPCMD_REPORT_KEY, 0 );
700 INIT_SSC( GPCMD_REPORT_KEY, 1 );
703 ssc.CDBByte[ 8 ] = 0;
704 ssc.CDBByte[ 9 ] = 0;
707 ssc.CDBByte[ 10 ] = DVD_INVALIDATE_AGID | (*pi_agid << 6);
709 i_ret = WinSendSSC( i_fd, &ssc );
713 /* DVD ioctls unavailable - do as if the ioctl failed */
720 /*****************************************************************************
721 * ioctl_SendChallenge: send challenge to the drive
722 *****************************************************************************/
723 int ioctl_SendChallenge( int i_fd, int *pi_agid, u8 *p_challenge )
725 #if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
726 dvd_authinfo auth_info;
728 auth_info.type = DVD_HOST_SEND_CHALLENGE;
729 auth_info.hsc.agid = *pi_agid;
731 memcpy( auth_info.hsc.chal, p_challenge, sizeof(dvd_challenge) );
733 return ioctl( i_fd, DVD_AUTH, &auth_info );
735 #elif defined( HAVE_BSD_DVD_STRUCT )
736 struct dvd_authinfo auth_info;
738 auth_info.format = DVD_SEND_CHALLENGE;
739 auth_info.agid = *pi_agid;
741 memcpy( auth_info.keychal, p_challenge, 12 );
743 return ioctl( i_fd, DVDIOCSENDKEY, &auth_info );
745 #elif defined( SYS_BEOS )
746 INIT_RDC( GPCMD_SEND_KEY, 16 );
748 rdc.command[ 10 ] = DVD_SEND_CHALLENGE | (*pi_agid << 6);
751 memcpy( p_buffer + 4, p_challenge, 12 );
753 return ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
755 #elif defined( SYS_DARWIN )
758 dvdioctl.i_keyformat = kChallengeKey;
759 dvdioctl.i_agid = *pi_agid;
762 memcpy( p_buffer + 4, p_challenge, 12 );
764 return ioctl( i_fd, IODVD_SEND_KEY, &dvdioctl );
766 #elif defined( WIN32 )
767 if( WIN2K ) /* NT/Win2000/Whistler */
770 u8 buffer[DVD_CHALLENGE_KEY_LENGTH];
771 PDVD_COPY_PROTECT_KEY key = (PDVD_COPY_PROTECT_KEY) &buffer;
773 memset( &buffer, 0, sizeof( buffer ) );
775 key->KeyLength = DVD_CHALLENGE_KEY_LENGTH;
776 key->SessionId = *pi_agid;
777 key->KeyType = DvdChallengeKey;
780 memcpy( key->KeyData, p_challenge, 10 );
782 return DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_SEND_KEY, key,
783 key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1;
787 INIT_SSC( GPCMD_SEND_KEY, 16 );
789 ssc.CDBByte[ 10 ] = DVD_SEND_CHALLENGE | (*pi_agid << 6);
792 memcpy( p_buffer + 4, p_challenge, 12 );
794 return WinSendSSC( i_fd, &ssc );
798 /* DVD ioctls unavailable - do as if the ioctl failed */
804 /*****************************************************************************
805 * ioctl_SendKey2: send the second key to the drive
806 *****************************************************************************/
807 int ioctl_SendKey2( int i_fd, int *pi_agid, u8 *p_key )
809 #if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
810 dvd_authinfo auth_info;
812 auth_info.type = DVD_HOST_SEND_KEY2;
813 auth_info.hsk.agid = *pi_agid;
815 memcpy( auth_info.hsk.key, p_key, sizeof(dvd_key) );
817 return ioctl( i_fd, DVD_AUTH, &auth_info );
819 #elif defined( HAVE_BSD_DVD_STRUCT )
820 struct dvd_authinfo auth_info;
822 auth_info.format = DVD_SEND_KEY2;
823 auth_info.agid = *pi_agid;
825 memcpy( auth_info.keychal, p_key, 8 );
827 return ioctl( i_fd, DVDIOCSENDKEY, &auth_info );
829 #elif defined( SYS_BEOS )
830 INIT_RDC( GPCMD_SEND_KEY, 12 );
832 rdc.command[ 10 ] = DVD_SEND_KEY2 | (*pi_agid << 6);
835 memcpy( p_buffer + 4, p_key, 8 );
837 return ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
839 #elif defined( WIN32 )
840 if( WIN2K ) /* NT/Win2000/Whistler */
843 u8 buffer[DVD_BUS_KEY_LENGTH];
844 PDVD_COPY_PROTECT_KEY key = (PDVD_COPY_PROTECT_KEY) &buffer;
846 memset( &buffer, 0, sizeof( buffer ) );
848 key->KeyLength = DVD_BUS_KEY_LENGTH;
849 key->SessionId = *pi_agid;
850 key->KeyType = DvdBusKey2;
853 memcpy( key->KeyData, p_key, 8 );
855 return DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_SEND_KEY, key,
856 key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1;
860 INIT_SSC( GPCMD_SEND_KEY, 12 );
862 ssc.CDBByte[ 10 ] = DVD_SEND_KEY2 | (*pi_agid << 6);
865 memcpy( p_buffer + 4, p_key, 8 );
867 return WinSendSSC( i_fd, &ssc );
870 #elif defined( SYS_DARWIN )
873 dvdioctl.i_keyformat = kKey2;
874 dvdioctl.i_agid = *pi_agid;
877 memcpy( p_buffer + 4, p_key, 8 );
879 return ioctl( i_fd, IODVD_SEND_KEY, &dvdioctl );
882 /* DVD ioctls unavailable - do as if the ioctl failed */
888 /* Local prototypes */
890 #if defined( SYS_BEOS )
891 /*****************************************************************************
892 * BeInitRDC: initialize a RDC structure for the BeOS kernel
893 *****************************************************************************
894 * This function initializes a BeOS raw device command structure for future
895 * use, either a read command or a write command.
896 *****************************************************************************/
897 static void BeInitRDC( raw_device_command *p_rdc, int i_type )
899 memset( p_rdc->data, 0, p_rdc->data_length );
904 /* leave the flags to 0 */
907 case GPCMD_READ_DVD_STRUCTURE:
908 case GPCMD_REPORT_KEY:
909 p_rdc->flags = B_RAW_DEVICE_DATA_IN;
913 p_rdc->command[ 0 ] = i_type;
915 p_rdc->command[ 8 ] = (p_rdc->data_length >> 8) & 0xff;
916 p_rdc->command[ 9 ] = p_rdc->data_length & 0xff;
917 p_rdc->command_length = 12;
919 p_rdc->sense_data = NULL;
920 p_rdc->sense_data_length = 0;
922 p_rdc->timeout = 1000000;
927 /*****************************************************************************
928 * WinInitSSC: initialize a ssc structure for the win32 aspi layer
929 *****************************************************************************
930 * This function initializes a ssc raw device command structure for future
931 * use, either a read command or a write command.
932 *****************************************************************************/
933 static void WinInitSSC( struct SRB_ExecSCSICmd *p_ssc, int i_type )
935 memset( p_ssc->SRB_BufPointer, 0, p_ssc->SRB_BufLen );
940 p_ssc->SRB_Flags = SRB_DIR_OUT;
943 case GPCMD_READ_DVD_STRUCTURE:
944 case GPCMD_REPORT_KEY:
945 p_ssc->SRB_Flags = SRB_DIR_IN;
949 p_ssc->SRB_Cmd = SC_EXEC_SCSI_CMD;
950 p_ssc->SRB_Flags |= SRB_EVENT_NOTIFY;
952 p_ssc->CDBByte[ 0 ] = i_type;
954 p_ssc->CDBByte[ 8 ] = (u8)(p_ssc->SRB_BufLen >> 8) & 0xff;
955 p_ssc->CDBByte[ 9 ] = (u8) p_ssc->SRB_BufLen & 0xff;
956 p_ssc->SRB_CDBLen = 12;
958 p_ssc->SRB_SenseLen = SENSE_LEN;
961 /*****************************************************************************
962 * WinSendSSC: send a ssc structure to the aspi layer
963 *****************************************************************************/
964 static int WinSendSSC( int i_fd, struct SRB_ExecSCSICmd *p_ssc )
966 HANDLE hEvent = NULL;
967 struct w32_aspidev *fd = (struct w32_aspidev *) i_fd;
969 hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
975 p_ssc->SRB_PostProc = hEvent;
976 p_ssc->SRB_HaId = LOBYTE( fd->i_sid );
977 p_ssc->SRB_Target = HIBYTE( fd->i_sid );
979 ResetEvent( hEvent );
980 if( fd->lpSendCommand( (void*) p_ssc ) == SS_PENDING )
981 WaitForSingleObject( hEvent, INFINITE );
983 CloseHandle( hEvent );
985 return p_ssc->SRB_Status == SS_COMP ? 0 : -1;