1 /*****************************************************************************
2 * ioctl.c: DVD ioctl replacement function
3 *****************************************************************************
4 * Copyright (C) 1999-2001 VideoLAN
5 * $Id: ioctl.c,v 1.8 2001/08/08 02:48:44 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
61 # include </usr/include/sys/scsi/scsi_types.h>
62 # include <sys/scsi/impl/uscsi.h>
69 # include "DVDioctl/DVDioctl.h"
74 /*****************************************************************************
75 * Local prototypes, BeOS specific
76 *****************************************************************************/
77 #if defined( SYS_BEOS )
78 static void BeInitRDC ( raw_device_command *, int );
81 /*****************************************************************************
82 * Local prototypes, Solaris specific
83 *****************************************************************************/
84 #if defined( SOLARIS_USCSI )
85 static void SolarisInitUSCSI( struct uscsi_cmd *p_sc, int i_type );
88 /*****************************************************************************
89 * Local prototypes, win32 (aspi) specific
90 *****************************************************************************/
92 static void WinInitSSC ( struct SRB_ExecSCSICmd *, int );
93 static int WinSendSSC ( int, struct SRB_ExecSCSICmd * );
96 /*****************************************************************************
97 * ioctl_ReadCopyright: check whether the disc is encrypted or not
98 *****************************************************************************/
99 int ioctl_ReadCopyright( int i_fd, int i_layer, int *pi_copyright )
103 #if defined( HAVE_LINUX_DVD_STRUCT )
106 dvd.type = DVD_STRUCT_COPYRIGHT;
107 dvd.copyright.layer_num = i_layer;
109 i_ret = ioctl( i_fd, DVD_READ_STRUCT, &dvd );
111 *pi_copyright = dvd.copyright.cpst;
113 #elif defined( HAVE_BSD_DVD_STRUCT )
114 struct dvd_struct dvd;
116 dvd.format = DVD_STRUCT_COPYRIGHT;
117 dvd.layer_num = i_layer;
119 i_ret = ioctl( i_fd, DVDIOCREADSTRUCTURE, &dvd );
121 *pi_copyright = dvd.cpst;
123 #elif defined( SYS_BEOS )
124 INIT_RDC( GPCMD_READ_DVD_STRUCTURE, 8 );
126 rdc.command[ 6 ] = i_layer;
127 rdc.command[ 7 ] = DVD_STRUCT_COPYRIGHT;
129 i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
131 *pi_copyright = p_buffer[ 4 ];
133 #elif defined( SOLARIS_USCSI )
134 INIT_USCSI( GPCMD_READ_DVD_STRUCTURE, 8 );
136 rs_cdb.cdb_opaque[ 6 ] = i_layer;
137 rs_cdb.cdb_opaque[ 7 ] = DVD_STRUCT_COPYRIGHT;
139 i_ret = ioctl(i_fd, USCSICMD, &sc);
141 if( i_ret < 0 || sc.uscsi_status ) {
145 *pi_copyright = p_buffer[ 4 ];
146 // s->copyright.rmi = p_buffer[ 5 ];
148 #elif defined( SYS_DARWIN )
153 #elif defined( WIN32 )
154 if( WIN2K ) /* NT/Win2000/Whistler */
158 SCSI_PASS_THROUGH_DIRECT sptd;
160 memset( &sptd, 0, sizeof( sptd ) );
161 memset( &p_buffer, 0, sizeof( p_buffer ) );
163 /* When using IOCTL_DVD_READ_STRUCTURE and
164 DVD_COPYRIGHT_DESCRIPTOR, CopyrightProtectionType
165 is always 6. So we send a raw scsi command instead. */
167 sptd.Length = sizeof( SCSI_PASS_THROUGH_DIRECT );
169 sptd.DataIn = SCSI_IOCTL_DATA_IN;
170 sptd.DataTransferLength = 8;
171 sptd.TimeOutValue = 2;
172 sptd.DataBuffer = p_buffer;
173 sptd.Cdb[ 0 ] = GPCMD_READ_DVD_STRUCTURE;
174 sptd.Cdb[ 6 ] = i_layer;
175 sptd.Cdb[ 7 ] = DVD_STRUCT_COPYRIGHT;
176 sptd.Cdb[ 8 ] = (8 >> 8) & 0xff;
177 sptd.Cdb[ 9 ] = 8 & 0xff;
179 i_ret = DeviceIoControl( (HANDLE) i_fd,
180 IOCTL_SCSI_PASS_THROUGH_DIRECT,
181 &sptd, sizeof( SCSI_PASS_THROUGH_DIRECT ),
182 &sptd, sizeof( SCSI_PASS_THROUGH_DIRECT ),
183 &tmp, NULL ) ? 0 : -1;
185 *pi_copyright = p_buffer[4];
189 INIT_SSC( GPCMD_READ_DVD_STRUCTURE, 8 );
191 ssc.CDBByte[ 6 ] = i_layer;
192 ssc.CDBByte[ 7 ] = DVD_STRUCT_COPYRIGHT;
194 i_ret = WinSendSSC( i_fd, &ssc );
196 *pi_copyright = p_buffer[ 4 ];
199 #elif defined( __QNXNTO__ )
201 QNX RTOS currently doesn't have a CAM
202 interface (they're working on it though).
203 Assume DVD is not encrypted.
210 /* DVD ioctls unavailable - do as if the ioctl failed */
217 /*****************************************************************************
218 * ioctl_ReadKey: get the disc key
219 *****************************************************************************/
220 int ioctl_ReadKey( int i_fd, int *pi_agid, u8 *p_key )
224 #if defined( HAVE_LINUX_DVD_STRUCT )
227 dvd.type = DVD_STRUCT_DISCKEY;
228 dvd.disckey.agid = *pi_agid;
229 memset( dvd.disckey.value, 0, 2048 );
231 i_ret = ioctl( i_fd, DVD_READ_STRUCT, &dvd );
238 memcpy( p_key, dvd.disckey.value, 2048 );
240 #elif defined( HAVE_BSD_DVD_STRUCT )
241 struct dvd_struct dvd;
243 dvd.format = DVD_STRUCT_DISCKEY;
245 memset( dvd.data, 0, 2048 );
247 i_ret = ioctl( i_fd, DVDIOCREADSTRUCTURE, &dvd );
254 memcpy( p_key, dvd.data, 2048 );
256 #elif defined( SYS_BEOS )
257 INIT_RDC( GPCMD_READ_DVD_STRUCTURE, 2048 + 4 );
259 rdc.command[ 7 ] = DVD_STRUCT_DISCKEY;
260 rdc.command[ 10 ] = *pi_agid << 6;
262 i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
269 memcpy( p_key, p_buffer + 4, 2048 );
271 #elif defined( SOLARIS_USCSI )
272 INIT_USCSI( GPCMD_READ_DVD_STRUCTURE, 2048 + 4 );
274 rs_cdb.cdb_opaque[ 7 ] = DVD_STRUCT_DISCKEY;
275 rs_cdb.cdb_opaque[ 10 ] = *pi_agid << 6;
277 i_ret = ioctl( i_fd, USCSICMD, &sc );
279 if( i_ret < 0 || sc.uscsi_status )
285 memcpy( p_key, p_buffer + 4, 2048 );
287 #elif defined( SYS_DARWIN )
290 memset( p_key, 0x00, 2048 );
292 #elif defined( WIN32 )
293 if( WIN2K ) /* NT/Win2000/Whistler */
296 u8 buffer[DVD_DISK_KEY_LENGTH];
297 PDVD_COPY_PROTECT_KEY key = (PDVD_COPY_PROTECT_KEY) &buffer;
299 memset( &buffer, 0, sizeof( buffer ) );
301 key->KeyLength = DVD_DISK_KEY_LENGTH;
302 key->SessionId = *pi_agid;
303 key->KeyType = DvdDiskKey;
306 i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_READ_KEY, key,
307 key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1;
314 memcpy( p_key, key->KeyData, 2048 );
318 INIT_SSC( GPCMD_READ_DVD_STRUCTURE, 2048 + 4 );
320 ssc.CDBByte[ 7 ] = DVD_STRUCT_DISCKEY;
321 ssc.CDBByte[ 10 ] = *pi_agid << 6;
323 i_ret = WinSendSSC( i_fd, &ssc );
330 memcpy( p_key, p_buffer + 4, 2048 );
334 /* DVD ioctls unavailable - do as if the ioctl failed */
341 /*****************************************************************************
342 * ioctl_ReportAgid: get AGID from the drive
343 *****************************************************************************/
344 int ioctl_ReportAgid( int i_fd, int *pi_agid )
348 #if defined( HAVE_LINUX_DVD_STRUCT )
349 dvd_authinfo auth_info;
351 auth_info.type = DVD_LU_SEND_AGID;
352 auth_info.lsa.agid = *pi_agid;
354 i_ret = ioctl( i_fd, DVD_AUTH, &auth_info );
356 *pi_agid = auth_info.lsa.agid;
358 #elif defined( HAVE_BSD_DVD_STRUCT )
359 struct dvd_authinfo auth_info;
361 auth_info.format = DVD_REPORT_AGID;
362 auth_info.agid = *pi_agid;
364 i_ret = ioctl( i_fd, DVDIOCREPORTKEY, &auth_info );
366 *pi_agid = auth_info.agid;
368 #elif defined( SYS_BEOS )
369 INIT_RDC( GPCMD_REPORT_KEY, 8 );
371 rdc.command[ 10 ] = DVD_REPORT_AGID | (*pi_agid << 6);
373 i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
375 *pi_agid = p_buffer[ 7 ] >> 6;
377 #elif defined( SOLARIS_USCSI )
378 INIT_USCSI( GPCMD_REPORT_KEY, 8 );
380 rs_cdb.cdb_opaque[ 10 ] = DVD_REPORT_AGID | (*pi_agid << 6);
382 i_ret = ioctl( i_fd, USCSICMD, &sc );
384 if( i_ret < 0 || sc.uscsi_status )
389 *pi_agid = p_buffer[ 7 ] >> 6;
391 #elif defined( SYS_DARWIN )
394 dvdioctl.i_keyformat = kCSSAGID;
395 dvdioctl.i_agid = *pi_agid;
398 i_ret = ioctl( i_fd, IODVD_REPORT_KEY, &dvdioctl );
400 *pi_agid = p_buffer[ 7 ] >> 6;
402 #elif defined( WIN32 )
403 if( WIN2K ) /* NT/Win2000/Whistler */
408 i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_START_SESSION,
409 &tmp, 4, &id, sizeof( id ), &tmp, NULL ) ? 0 : -1;
415 INIT_SSC( GPCMD_REPORT_KEY, 8 );
417 ssc.CDBByte[ 10 ] = DVD_REPORT_AGID | (*pi_agid << 6);
419 i_ret = WinSendSSC( i_fd, &ssc );
421 *pi_agid = p_buffer[ 7 ] >> 6;
425 /* DVD ioctls unavailable - do as if the ioctl failed */
432 /*****************************************************************************
433 * ioctl_ReportChallenge: get challenge from the drive
434 *****************************************************************************/
435 int ioctl_ReportChallenge( int i_fd, int *pi_agid, u8 *p_challenge )
439 #if defined( HAVE_LINUX_DVD_STRUCT )
440 dvd_authinfo auth_info;
442 auth_info.type = DVD_LU_SEND_CHALLENGE;
443 auth_info.lsc.agid = *pi_agid;
445 i_ret = ioctl( i_fd, DVD_AUTH, &auth_info );
447 memcpy( p_challenge, auth_info.lsc.chal, sizeof(dvd_challenge) );
449 #elif defined( HAVE_BSD_DVD_STRUCT )
450 struct dvd_authinfo auth_info;
452 auth_info.format = DVD_REPORT_CHALLENGE;
453 auth_info.agid = *pi_agid;
455 i_ret = ioctl( i_fd, DVDIOCREPORTKEY, &auth_info );
457 memcpy( p_challenge, auth_info.keychal, 10 );
459 #elif defined( SYS_BEOS )
460 INIT_RDC( GPCMD_REPORT_KEY, 16 );
462 rdc.command[ 10 ] = DVD_REPORT_CHALLENGE | (*pi_agid << 6);
464 i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
466 memcpy( p_challenge, p_buffer + 4, 12 );
468 #elif defined( SOLARIS_USCSI )
469 INIT_USCSI( GPCMD_REPORT_KEY, 16 );
471 rs_cdb.cdb_opaque[ 10 ] = DVD_REPORT_CHALLENGE | (*pi_agid << 6);
473 i_ret = ioctl( i_fd, USCSICMD, &sc );
475 if( i_ret < 0 || sc.uscsi_status )
480 memcpy( p_challenge, p_buffer + 4, 12 );
482 #elif defined( SYS_DARWIN )
485 dvdioctl.i_keyformat = kChallengeKey;
486 dvdioctl.i_agid = *pi_agid;
489 i_ret = ioctl( i_fd, IODVD_REPORT_KEY, &dvdioctl );
491 memcpy( p_challenge, p_buffer + 4, 12 );
493 #elif defined( WIN32 )
494 if( WIN2K ) /* NT/Win2000/Whistler */
497 u8 buffer[DVD_CHALLENGE_KEY_LENGTH];
498 PDVD_COPY_PROTECT_KEY key = (PDVD_COPY_PROTECT_KEY) &buffer;
500 memset( &buffer, 0, sizeof( buffer ) );
502 key->KeyLength = DVD_CHALLENGE_KEY_LENGTH;
503 key->SessionId = *pi_agid;
504 key->KeyType = DvdChallengeKey;
507 i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_READ_KEY, key,
508 key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1;
515 memcpy( p_challenge, key->KeyData, 10 );
519 INIT_SSC( GPCMD_REPORT_KEY, 16 );
521 ssc.CDBByte[ 10 ] = DVD_REPORT_CHALLENGE | (*pi_agid << 6);
523 i_ret = WinSendSSC( i_fd, &ssc );
525 memcpy( p_challenge, p_buffer + 4, 12 );
529 /* DVD ioctls unavailable - do as if the ioctl failed */
536 /*****************************************************************************
537 * ioctl_ReportASF: get ASF from the drive
538 *****************************************************************************/
539 int ioctl_ReportASF( int i_fd, int *pi_agid, int *pi_asf )
543 #if defined( HAVE_LINUX_DVD_STRUCT )
544 dvd_authinfo auth_info;
546 auth_info.type = DVD_LU_SEND_ASF;
547 auth_info.lsasf.agid = *pi_agid;
548 auth_info.lsasf.asf = *pi_asf;
550 i_ret = ioctl( i_fd, DVD_AUTH, &auth_info );
552 *pi_asf = auth_info.lsasf.asf;
554 #elif defined( HAVE_BSD_DVD_STRUCT )
555 struct dvd_authinfo auth_info;
557 auth_info.format = DVD_REPORT_ASF;
558 auth_info.agid = *pi_agid;
559 auth_info.asf = *pi_asf;
561 i_ret = ioctl( i_fd, DVDIOCREPORTKEY, &auth_info );
563 *pi_asf = auth_info.asf;
565 #elif defined( SYS_BEOS )
566 INIT_RDC( GPCMD_REPORT_KEY, 8 );
568 rdc.command[ 10 ] = DVD_REPORT_ASF | (*pi_agid << 6);
570 i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
572 *pi_asf = p_buffer[ 7 ] & 1;
574 #elif defined( SOLARIS_USCSI )
575 INIT_USCSI( GPCMD_REPORT_KEY, 8 );
577 rs_cdb.cdb_opaque[ 10 ] = DVD_REPORT_ASF | (*pi_agid << 6);
579 i_ret = ioctl( i_fd, USCSICMD, &sc );
581 if( i_ret < 0 || sc.uscsi_status )
586 *pi_asf = p_buffer[ 7 ] & 1;
588 #elif defined( SYS_DARWIN )
591 dvdioctl.i_keyformat = kASF;
592 dvdioctl.i_agid = *pi_agid;
595 i_ret = ioctl( i_fd, IODVD_REPORT_KEY, &dvdioctl );
597 *pi_asf = p_buffer[ 7 ] & 1;
599 #elif defined( WIN32 )
600 if( WIN2K ) /* NT/Win2000/Whistler */
603 u8 buffer[DVD_ASF_LENGTH];
604 PDVD_COPY_PROTECT_KEY key = (PDVD_COPY_PROTECT_KEY) &buffer;
606 memset( &buffer, 0, sizeof( buffer ) );
608 key->KeyLength = DVD_ASF_LENGTH;
609 key->SessionId = *pi_agid;
610 key->KeyType = DvdAsf;
613 ((PDVD_ASF)key->KeyData)->SuccessFlag = *pi_asf;
615 i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_READ_KEY, key,
616 key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1;
623 *pi_asf = ((PDVD_ASF)key->KeyData)->SuccessFlag;
627 INIT_SSC( GPCMD_REPORT_KEY, 8 );
629 ssc.CDBByte[ 10 ] = DVD_REPORT_ASF | (*pi_agid << 6);
631 i_ret = WinSendSSC( i_fd, &ssc );
633 *pi_asf = p_buffer[ 7 ] & 1;
637 /* DVD ioctls unavailable - do as if the ioctl failed */
644 /*****************************************************************************
645 * ioctl_ReportKey1: get the first key from the drive
646 *****************************************************************************/
647 int ioctl_ReportKey1( int i_fd, int *pi_agid, u8 *p_key )
651 #if defined( HAVE_LINUX_DVD_STRUCT )
652 dvd_authinfo auth_info;
654 auth_info.type = DVD_LU_SEND_KEY1;
655 auth_info.lsk.agid = *pi_agid;
657 i_ret = ioctl( i_fd, DVD_AUTH, &auth_info );
659 memcpy( p_key, auth_info.lsk.key, sizeof(dvd_key) );
661 #elif defined( HAVE_BSD_DVD_STRUCT )
662 struct dvd_authinfo auth_info;
664 auth_info.format = DVD_REPORT_KEY1;
665 auth_info.agid = *pi_agid;
667 i_ret = ioctl( i_fd, DVDIOCREPORTKEY, &auth_info );
669 memcpy( p_key, auth_info.keychal, 8 );
671 #elif defined( SYS_BEOS )
672 INIT_RDC( GPCMD_REPORT_KEY, 12 );
674 rdc.command[ 10 ] = DVD_REPORT_KEY1 | (*pi_agid << 6);
676 i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
678 memcpy( p_key, p_buffer + 4, 8 );
680 #elif defined( SOLARIS_USCSI )
681 INIT_USCSI( GPCMD_REPORT_KEY, 12 );
683 rs_cdb.cdb_opaque[ 10 ] = DVD_REPORT_KEY1 | (*pi_agid << 6);
685 i_ret = ioctl( i_fd, USCSICMD, &sc );
687 if( i_ret < 0 || sc.uscsi_status )
692 memcpy( p_key, p_buffer + 4, 8 );;
694 #elif defined( SYS_DARWIN )
697 dvdioctl.i_keyformat = kKey1;
698 dvdioctl.i_agid = *pi_agid;
700 i_ret = ioctl( i_fd, IODVD_SEND_KEY, &dvdioctl );
702 memcpy( p_key, p_buffer + 4, 8 );
704 #elif defined( WIN32 )
705 if( WIN2K ) /* NT/Win2000/Whistler */
708 u8 buffer[DVD_BUS_KEY_LENGTH];
709 PDVD_COPY_PROTECT_KEY key = (PDVD_COPY_PROTECT_KEY) &buffer;
711 memset( &buffer, 0, sizeof( buffer ) );
713 key->KeyLength = DVD_BUS_KEY_LENGTH;
714 key->SessionId = *pi_agid;
715 key->KeyType = DvdBusKey1;
718 i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_READ_KEY, key,
719 key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1;
721 memcpy( p_key, key->KeyData, 8 );
725 INIT_SSC( GPCMD_REPORT_KEY, 12 );
727 ssc.CDBByte[ 10 ] = DVD_REPORT_KEY1 | (*pi_agid << 6);
729 i_ret = WinSendSSC( i_fd, &ssc );
731 memcpy( p_key, p_buffer + 4, 8 );
735 /* DVD ioctls unavailable - do as if the ioctl failed */
742 /*****************************************************************************
743 * ioctl_InvalidateAgid: invalidate the current AGID
744 *****************************************************************************/
745 int ioctl_InvalidateAgid( int i_fd, int *pi_agid )
749 #if defined( HAVE_LINUX_DVD_STRUCT )
750 dvd_authinfo auth_info;
752 auth_info.type = DVD_INVALIDATE_AGID;
753 auth_info.lsa.agid = *pi_agid;
755 i_ret = ioctl( i_fd, DVD_AUTH, &auth_info );
757 *pi_agid = auth_info.lsa.agid;
759 #elif defined( HAVE_BSD_DVD_STRUCT )
760 struct dvd_authinfo auth_info;
762 auth_info.format = DVD_INVALIDATE_AGID;
763 auth_info.agid = *pi_agid;
765 i_ret = ioctl( i_fd, DVDIOCREPORTKEY, &auth_info );
767 *pi_agid = auth_info.agid;
769 #elif defined( SYS_BEOS )
770 INIT_RDC( GPCMD_REPORT_KEY, 0 );
772 rdc.command[ 10 ] = DVD_INVALIDATE_AGID | (*pi_agid << 6);
774 i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
776 #elif defined( SOLARIS_USCSI )
777 INIT_USCSI( GPCMD_REPORT_KEY, 0 );
779 rs_cdb.cdb_opaque[ 10 ] = DVD_INVALIDATE_AGID | (*pi_agid << 6);
781 i_ret = ioctl( i_fd, USCSICMD, &sc );
783 if( i_ret < 0 || sc.uscsi_status )
788 #elif defined( SYS_DARWIN )
791 dvdioctl.i_keyformat = kInvalidateAGID;
792 dvdioctl.i_agid = *pi_agid;
794 i_ret = ioctl( i_fd, IODVD_SEND_KEY, &dvdioctl );
796 #elif defined( WIN32 )
797 if( WIN2K ) /* NT/Win2000/Whistler */
801 i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_END_SESSION,
802 pi_agid, sizeof( *pi_agid ), NULL, 0, &tmp, NULL ) ? 0 : -1;
806 #if defined( __MINGW32__ )
807 INIT_SSC( GPCMD_REPORT_KEY, 0 );
809 INIT_SSC( GPCMD_REPORT_KEY, 1 );
812 ssc.CDBByte[ 8 ] = 0;
813 ssc.CDBByte[ 9 ] = 0;
816 ssc.CDBByte[ 10 ] = DVD_INVALIDATE_AGID | (*pi_agid << 6);
818 i_ret = WinSendSSC( i_fd, &ssc );
822 /* DVD ioctls unavailable - do as if the ioctl failed */
829 /*****************************************************************************
830 * ioctl_SendChallenge: send challenge to the drive
831 *****************************************************************************/
832 int ioctl_SendChallenge( int i_fd, int *pi_agid, u8 *p_challenge )
834 #if defined( HAVE_LINUX_DVD_STRUCT )
835 dvd_authinfo auth_info;
837 auth_info.type = DVD_HOST_SEND_CHALLENGE;
838 auth_info.hsc.agid = *pi_agid;
840 memcpy( auth_info.hsc.chal, p_challenge, sizeof(dvd_challenge) );
842 return ioctl( i_fd, DVD_AUTH, &auth_info );
844 #elif defined( HAVE_BSD_DVD_STRUCT )
845 struct dvd_authinfo auth_info;
847 auth_info.format = DVD_SEND_CHALLENGE;
848 auth_info.agid = *pi_agid;
850 memcpy( auth_info.keychal, p_challenge, 12 );
852 return ioctl( i_fd, DVDIOCSENDKEY, &auth_info );
854 #elif defined( SYS_BEOS )
855 INIT_RDC( GPCMD_SEND_KEY, 16 );
857 rdc.command[ 10 ] = DVD_SEND_CHALLENGE | (*pi_agid << 6);
860 memcpy( p_buffer + 4, p_challenge, 12 );
862 return ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
864 #elif defined( SOLARIS_USCSI )
865 INIT_USCSI( GPCMD_SEND_KEY, 16 );
867 rs_cdb.cdb_opaque[ 10 ] = DVD_SEND_CHALLENGE | (*pi_agid << 6);
870 memcpy( p_buffer + 4, p_challenge, 12 );
872 if( ioctl( i_fd, USCSICMD, &sc ) < 0 || sc.uscsi_status )
879 #elif defined( SYS_DARWIN )
882 dvdioctl.i_keyformat = kChallengeKey;
883 dvdioctl.i_agid = *pi_agid;
886 memcpy( p_buffer + 4, p_challenge, 12 );
888 return ioctl( i_fd, IODVD_SEND_KEY, &dvdioctl );
890 #elif defined( WIN32 )
891 if( WIN2K ) /* NT/Win2000/Whistler */
894 u8 buffer[DVD_CHALLENGE_KEY_LENGTH];
895 PDVD_COPY_PROTECT_KEY key = (PDVD_COPY_PROTECT_KEY) &buffer;
897 memset( &buffer, 0, sizeof( buffer ) );
899 key->KeyLength = DVD_CHALLENGE_KEY_LENGTH;
900 key->SessionId = *pi_agid;
901 key->KeyType = DvdChallengeKey;
904 memcpy( key->KeyData, p_challenge, 10 );
906 return DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_SEND_KEY, key,
907 key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1;
911 INIT_SSC( GPCMD_SEND_KEY, 16 );
913 ssc.CDBByte[ 10 ] = DVD_SEND_CHALLENGE | (*pi_agid << 6);
916 memcpy( p_buffer + 4, p_challenge, 12 );
918 return WinSendSSC( i_fd, &ssc );
922 /* DVD ioctls unavailable - do as if the ioctl failed */
928 /*****************************************************************************
929 * ioctl_SendKey2: send the second key to the drive
930 *****************************************************************************/
931 int ioctl_SendKey2( int i_fd, int *pi_agid, u8 *p_key )
933 #if defined( HAVE_LINUX_DVD_STRUCT )
934 dvd_authinfo auth_info;
936 auth_info.type = DVD_HOST_SEND_KEY2;
937 auth_info.hsk.agid = *pi_agid;
939 memcpy( auth_info.hsk.key, p_key, sizeof(dvd_key) );
941 return ioctl( i_fd, DVD_AUTH, &auth_info );
943 #elif defined( HAVE_BSD_DVD_STRUCT )
944 struct dvd_authinfo auth_info;
946 auth_info.format = DVD_SEND_KEY2;
947 auth_info.agid = *pi_agid;
949 memcpy( auth_info.keychal, p_key, 8 );
951 return ioctl( i_fd, DVDIOCSENDKEY, &auth_info );
953 #elif defined( SYS_BEOS )
954 INIT_RDC( GPCMD_SEND_KEY, 12 );
956 rdc.command[ 10 ] = DVD_SEND_KEY2 | (*pi_agid << 6);
959 memcpy( p_buffer + 4, p_key, 8 );
961 return ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
963 #elif defined( SOLARIS_USCSI )
964 INIT_USCSI( GPCMD_SEND_KEY, 12 );
966 rs_cdb.cdb_opaque[ 10 ] = DVD_SEND_KEY2 | (*pi_agid << 6);
969 memcpy( p_buffer + 4, p_key, 8 );
971 if( ioctl( i_fd, USCSICMD, &sc ) < 0 || sc.uscsi_status )
978 #elif defined( WIN32 )
979 if( WIN2K ) /* NT/Win2000/Whistler */
982 u8 buffer[DVD_BUS_KEY_LENGTH];
983 PDVD_COPY_PROTECT_KEY key = (PDVD_COPY_PROTECT_KEY) &buffer;
985 memset( &buffer, 0, sizeof( buffer ) );
987 key->KeyLength = DVD_BUS_KEY_LENGTH;
988 key->SessionId = *pi_agid;
989 key->KeyType = DvdBusKey2;
992 memcpy( key->KeyData, p_key, 8 );
994 return DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_SEND_KEY, key,
995 key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1;
999 INIT_SSC( GPCMD_SEND_KEY, 12 );
1001 ssc.CDBByte[ 10 ] = DVD_SEND_KEY2 | (*pi_agid << 6);
1003 p_buffer[ 1 ] = 0xa;
1004 memcpy( p_buffer + 4, p_key, 8 );
1006 return WinSendSSC( i_fd, &ssc );
1009 #elif defined( SYS_DARWIN )
1010 INIT_DVDIOCTL( 12 );
1012 dvdioctl.i_keyformat = kKey2;
1013 dvdioctl.i_agid = *pi_agid;
1015 p_buffer[ 1 ] = 0xa;
1016 memcpy( p_buffer + 4, p_key, 8 );
1018 return ioctl( i_fd, IODVD_SEND_KEY, &dvdioctl );
1021 /* DVD ioctls unavailable - do as if the ioctl failed */
1027 /* Local prototypes */
1029 #if defined( SYS_BEOS )
1030 /*****************************************************************************
1031 * BeInitRDC: initialize a RDC structure for the BeOS kernel
1032 *****************************************************************************
1033 * This function initializes a BeOS raw device command structure for future
1034 * use, either a read command or a write command.
1035 *****************************************************************************/
1036 static void BeInitRDC( raw_device_command *p_rdc, int i_type )
1038 memset( p_rdc->data, 0, p_rdc->data_length );
1042 case GPCMD_SEND_KEY:
1043 /* leave the flags to 0 */
1046 case GPCMD_READ_DVD_STRUCTURE:
1047 case GPCMD_REPORT_KEY:
1048 p_rdc->flags = B_RAW_DEVICE_DATA_IN;
1052 p_rdc->command[ 0 ] = i_type;
1054 p_rdc->command[ 8 ] = (p_rdc->data_length >> 8) & 0xff;
1055 p_rdc->command[ 9 ] = p_rdc->data_length & 0xff;
1056 p_rdc->command_length = 12;
1058 p_rdc->sense_data = NULL;
1059 p_rdc->sense_data_length = 0;
1061 p_rdc->timeout = 1000000;
1065 #if defined( SOLARIS_USCSI )
1066 /*****************************************************************************
1067 * SolarisInitUSCSI: initialize a USCSICMD structure for the Solaris kernel
1068 *****************************************************************************
1069 * This function initializes a Solaris userspace scsi command structure for
1070 * future use, either a read command or a write command.
1071 *****************************************************************************/
1072 static void SolarisInitUSCSI( struct uscsi_cmd *p_sc, int i_type )
1074 union scsi_cdb *rs_cdb;
1075 memset( p_sc->uscsi_cdb, 0, sizeof( union scsi_cdb ) );
1076 memset( p_sc->uscsi_bufaddr, 0, p_sc->uscsi_buflen );
1080 case GPCMD_SEND_KEY:
1081 p_sc->uscsi_flags = USCSI_ISOLATE | USCSI_WRITE;
1084 case GPCMD_READ_DVD_STRUCTURE:
1085 case GPCMD_REPORT_KEY:
1086 p_sc->uscsi_flags = USCSI_ISOLATE | USCSI_READ;
1090 rs_cdb = (union scsi_cdb *)p_sc->uscsi_cdb;
1092 rs_cdb->scc_cmd = i_type;
1094 rs_cdb->cdb_opaque[ 8 ] = (p_sc->uscsi_buflen >> 8) & 0xff;
1095 rs_cdb->cdb_opaque[ 9 ] = p_sc->uscsi_buflen & 0xff;
1096 p_sc->uscsi_cdblen = 12;
1098 USCSI_TIMEOUT( p_sc, 15 );
1102 #if defined( WIN32 )
1103 /*****************************************************************************
1104 * WinInitSSC: initialize a ssc structure for the win32 aspi layer
1105 *****************************************************************************
1106 * This function initializes a ssc raw device command structure for future
1107 * use, either a read command or a write command.
1108 *****************************************************************************/
1109 static void WinInitSSC( struct SRB_ExecSCSICmd *p_ssc, int i_type )
1111 memset( p_ssc->SRB_BufPointer, 0, p_ssc->SRB_BufLen );
1115 case GPCMD_SEND_KEY:
1116 p_ssc->SRB_Flags = SRB_DIR_OUT;
1119 case GPCMD_READ_DVD_STRUCTURE:
1120 case GPCMD_REPORT_KEY:
1121 p_ssc->SRB_Flags = SRB_DIR_IN;
1125 p_ssc->SRB_Cmd = SC_EXEC_SCSI_CMD;
1126 p_ssc->SRB_Flags |= SRB_EVENT_NOTIFY;
1128 p_ssc->CDBByte[ 0 ] = i_type;
1130 p_ssc->CDBByte[ 8 ] = (u8)(p_ssc->SRB_BufLen >> 8) & 0xff;
1131 p_ssc->CDBByte[ 9 ] = (u8) p_ssc->SRB_BufLen & 0xff;
1132 p_ssc->SRB_CDBLen = 12;
1134 p_ssc->SRB_SenseLen = SENSE_LEN;
1137 /*****************************************************************************
1138 * WinSendSSC: send a ssc structure to the aspi layer
1139 *****************************************************************************/
1140 static int WinSendSSC( int i_fd, struct SRB_ExecSCSICmd *p_ssc )
1142 HANDLE hEvent = NULL;
1143 struct w32_aspidev *fd = (struct w32_aspidev *) i_fd;
1145 hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
1146 if( hEvent == NULL )
1151 p_ssc->SRB_PostProc = hEvent;
1152 p_ssc->SRB_HaId = LOBYTE( fd->i_sid );
1153 p_ssc->SRB_Target = HIBYTE( fd->i_sid );
1155 ResetEvent( hEvent );
1156 if( fd->lpSendCommand( (void*) p_ssc ) == SS_PENDING )
1157 WaitForSingleObject( hEvent, INFINITE );
1159 CloseHandle( hEvent );
1161 return p_ssc->SRB_Status == SS_COMP ? 0 : -1;