1 /*****************************************************************************
2 * ioctl.c: DVD ioctl replacement function
3 *****************************************************************************
4 * Copyright (C) 1999-2001 VideoLAN
5 * $Id: ioctl.c,v 1.5 2001/07/25 00:23:40 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>
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 )
122 #elif defined( WIN32 )
123 if( WIN2K ) /* NT/Win2000/Whistler */
127 SCSI_PASS_THROUGH_DIRECT sptd;
129 memset( &sptd, 0, sizeof( sptd ) );
130 memset( &p_buffer, 0, sizeof( p_buffer ) );
132 /* When using IOCTL_DVD_READ_STRUCTURE and
133 DVD_COPYRIGHT_DESCRIPTOR, CopyrightProtectionType
134 is always 6. So we send a raw scsi command instead. */
136 sptd.Length = sizeof( SCSI_PASS_THROUGH_DIRECT );
138 sptd.DataIn = SCSI_IOCTL_DATA_IN;
139 sptd.DataTransferLength = 8;
140 sptd.TimeOutValue = 2;
141 sptd.DataBuffer = p_buffer;
142 sptd.Cdb[ 0 ] = GPCMD_READ_DVD_STRUCTURE;
143 sptd.Cdb[ 6 ] = i_layer;
144 sptd.Cdb[ 7 ] = DVD_STRUCT_COPYRIGHT;
145 sptd.Cdb[ 8 ] = (8 >> 8) & 0xff;
146 sptd.Cdb[ 9 ] = 8 & 0xff;
148 i_ret = DeviceIoControl( (HANDLE) i_fd,
149 IOCTL_SCSI_PASS_THROUGH_DIRECT,
150 &sptd, sizeof( SCSI_PASS_THROUGH_DIRECT ),
151 &sptd, sizeof( SCSI_PASS_THROUGH_DIRECT ),
152 &tmp, NULL ) ? 0 : -1;
154 *pi_copyright = p_buffer[4];
158 INIT_SSC( GPCMD_READ_DVD_STRUCTURE, 8 );
160 ssc.CDBByte[ 6 ] = i_layer;
161 ssc.CDBByte[ 7 ] = DVD_STRUCT_COPYRIGHT;
163 i_ret = WinSendSSC( i_fd, &ssc );
165 *pi_copyright = p_buffer[ 4 ];
168 #elif defined( __QNXNTO__ )
170 QNX RTOS currently doesn't have a CAM
171 interface (they're working on it though).
172 Assume DVD is not encrypted.
179 /* DVD ioctls unavailable - do as if the ioctl failed */
186 /*****************************************************************************
187 * ioctl_ReadKey: get the disc key
188 *****************************************************************************/
189 int ioctl_ReadKey( int i_fd, int *pi_agid, u8 *p_key )
193 #if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
196 dvd.type = DVD_STRUCT_DISCKEY;
197 dvd.disckey.agid = *pi_agid;
198 memset( dvd.disckey.value, 0, 2048 );
200 i_ret = ioctl( i_fd, DVD_READ_STRUCT, &dvd );
207 memcpy( p_key, dvd.disckey.value, 2048 );
209 #elif defined( HAVE_BSD_DVD_STRUCT )
210 struct dvd_struct dvd;
212 dvd.format = DVD_STRUCT_DISCKEY;
214 memset( dvd.data, 0, 2048 );
216 i_ret = ioctl( i_fd, DVDIOCREADSTRUCTURE, &dvd );
223 memcpy( p_key, dvd.data, 2048 );
225 #elif defined( SYS_BEOS )
226 INIT_RDC( GPCMD_READ_DVD_STRUCTURE, 2048 + 4 );
228 rdc.command[ 7 ] = DVD_STRUCT_DISCKEY;
229 rdc.command[ 10 ] = *pi_agid << 6;
231 i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
238 memcpy( p_key, p_buffer + 4, 2048 );
240 #elif defined( SYS_DARWIN )
243 memset( p_key, 0x00, 2048 );
245 #elif defined( WIN32 )
246 if( WIN2K ) /* NT/Win2000/Whistler */
249 u8 buffer[DVD_DISK_KEY_LENGTH];
250 PDVD_COPY_PROTECT_KEY key = (PDVD_COPY_PROTECT_KEY) &buffer;
252 memset( &buffer, 0, sizeof( buffer ) );
254 key->KeyLength = DVD_DISK_KEY_LENGTH;
255 key->SessionId = *pi_agid;
256 key->KeyType = DvdDiskKey;
259 i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_READ_KEY, key,
260 key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1;
267 memcpy( p_key, key->KeyData, 2048 );
271 INIT_SSC( GPCMD_READ_DVD_STRUCTURE, 2048 + 4 );
273 ssc.CDBByte[ 7 ] = DVD_STRUCT_DISCKEY;
274 ssc.CDBByte[ 10 ] = *pi_agid << 6;
276 i_ret = WinSendSSC( i_fd, &ssc );
283 memcpy( p_key, p_buffer + 4, 2048 );
287 /* DVD ioctls unavailable - do as if the ioctl failed */
294 /*****************************************************************************
295 * ioctl_ReportAgid: get AGID from the drive
296 *****************************************************************************/
297 int ioctl_ReportAgid( int i_fd, int *pi_agid )
301 #if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
302 dvd_authinfo auth_info;
304 auth_info.type = DVD_LU_SEND_AGID;
305 auth_info.lsa.agid = *pi_agid;
307 i_ret = ioctl( i_fd, DVD_AUTH, &auth_info );
309 *pi_agid = auth_info.lsa.agid;
311 #elif defined( HAVE_BSD_DVD_STRUCT )
312 struct dvd_authinfo auth_info;
314 auth_info.format = DVD_REPORT_AGID;
315 auth_info.agid = *pi_agid;
317 i_ret = ioctl( i_fd, DVDIOCREPORTKEY, &auth_info );
319 *pi_agid = auth_info.agid;
321 #elif defined( SYS_BEOS )
322 INIT_RDC( GPCMD_REPORT_KEY, 8 );
324 rdc.command[ 10 ] = DVD_REPORT_AGID | (*pi_agid << 6);
326 i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
328 *pi_agid = p_buffer[ 7 ] >> 6;
330 #elif defined( SYS_DARWIN )
333 dvdioctl.i_keyformat = kCSSAGID;
334 dvdioctl.i_agid = *pi_agid;
337 i_ret = ioctl( i_fd, IODVD_REPORT_KEY, &dvdioctl );
339 *pi_agid = p_buffer[ 7 ] >> 6;
341 #elif defined( WIN32 )
342 if( WIN2K ) /* NT/Win2000/Whistler */
347 i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_START_SESSION,
348 &tmp, 4, &id, sizeof( id ), &tmp, NULL ) ? 0 : -1;
354 INIT_SSC( GPCMD_REPORT_KEY, 8 );
356 ssc.CDBByte[ 10 ] = DVD_REPORT_AGID | (*pi_agid << 6);
358 i_ret = WinSendSSC( i_fd, &ssc );
360 *pi_agid = p_buffer[ 7 ] >> 6;
364 /* DVD ioctls unavailable - do as if the ioctl failed */
371 /*****************************************************************************
372 * ioctl_ReportChallenge: get challenge from the drive
373 *****************************************************************************/
374 int ioctl_ReportChallenge( int i_fd, int *pi_agid, u8 *p_challenge )
378 #if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
379 dvd_authinfo auth_info;
381 auth_info.type = DVD_LU_SEND_CHALLENGE;
382 auth_info.lsc.agid = *pi_agid;
384 i_ret = ioctl( i_fd, DVD_AUTH, &auth_info );
386 memcpy( p_challenge, auth_info.lsc.chal, sizeof(dvd_challenge) );
388 #elif defined( HAVE_BSD_DVD_STRUCT )
389 struct dvd_authinfo auth_info;
391 auth_info.format = DVD_REPORT_CHALLENGE;
392 auth_info.agid = *pi_agid;
394 i_ret = ioctl( i_fd, DVDIOCREPORTKEY, &auth_info );
396 memcpy( p_challenge, auth_info.keychal, 10 );
398 #elif defined( SYS_BEOS )
399 INIT_RDC( GPCMD_REPORT_KEY, 16 );
401 rdc.command[ 10 ] = DVD_REPORT_CHALLENGE | (*pi_agid << 6);
403 i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
405 memcpy( p_challenge, p_buffer + 4, 12 );
407 #elif defined( SYS_DARWIN )
410 dvdioctl.i_keyformat = kChallengeKey;
411 dvdioctl.i_agid = *pi_agid;
414 i_ret = ioctl( i_fd, IODVD_REPORT_KEY, &dvdioctl );
416 memcpy( p_challenge, p_buffer + 4, 12 );
418 #elif defined( WIN32 )
419 if( WIN2K ) /* NT/Win2000/Whistler */
422 u8 buffer[DVD_CHALLENGE_KEY_LENGTH];
423 PDVD_COPY_PROTECT_KEY key = (PDVD_COPY_PROTECT_KEY) &buffer;
425 memset( &buffer, 0, sizeof( buffer ) );
427 key->KeyLength = DVD_CHALLENGE_KEY_LENGTH;
428 key->SessionId = *pi_agid;
429 key->KeyType = DvdChallengeKey;
432 i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_READ_KEY, key,
433 key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1;
440 memcpy( p_challenge, key->KeyData, 10 );
444 INIT_SSC( GPCMD_REPORT_KEY, 16 );
446 ssc.CDBByte[ 10 ] = DVD_REPORT_CHALLENGE | (*pi_agid << 6);
448 i_ret = WinSendSSC( i_fd, &ssc );
450 memcpy( p_challenge, p_buffer + 4, 12 );
454 /* DVD ioctls unavailable - do as if the ioctl failed */
461 /*****************************************************************************
462 * ioctl_ReportASF: get ASF from the drive
463 *****************************************************************************/
464 int ioctl_ReportASF( int i_fd, int *pi_agid, int *pi_asf )
468 #if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
469 dvd_authinfo auth_info;
471 auth_info.type = DVD_LU_SEND_ASF;
472 auth_info.lsasf.agid = *pi_agid;
473 auth_info.lsasf.asf = *pi_asf;
475 i_ret = ioctl( i_fd, DVD_AUTH, &auth_info );
477 *pi_asf = auth_info.lsasf.asf;
479 #elif defined( HAVE_BSD_DVD_STRUCT )
480 struct dvd_authinfo auth_info;
482 auth_info.format = DVD_REPORT_ASF;
483 auth_info.agid = *pi_agid;
484 auth_info.asf = *pi_asf;
486 i_ret = ioctl( i_fd, DVDIOCREPORTKEY, &auth_info );
488 *pi_asf = auth_info.asf;
490 #elif defined( SYS_BEOS )
491 INIT_RDC( GPCMD_REPORT_KEY, 8 );
493 rdc.command[ 10 ] = DVD_REPORT_ASF | (*pi_agid << 6);
495 i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
497 *pi_asf = p_buffer[ 7 ] & 1;
499 #elif defined( SYS_DARWIN )
502 dvdioctl.i_keyformat = kASF;
503 dvdioctl.i_agid = *pi_agid;
506 i_ret = ioctl( i_fd, IODVD_REPORT_KEY, &dvdioctl );
508 *pi_asf = p_buffer[ 7 ] & 1;
510 #elif defined( WIN32 )
511 if( WIN2K ) /* NT/Win2000/Whistler */
514 u8 buffer[DVD_ASF_LENGTH];
515 PDVD_COPY_PROTECT_KEY key = (PDVD_COPY_PROTECT_KEY) &buffer;
517 memset( &buffer, 0, sizeof( buffer ) );
519 key->KeyLength = DVD_ASF_LENGTH;
520 key->SessionId = *pi_agid;
521 key->KeyType = DvdAsf;
524 ((PDVD_ASF)key->KeyData)->SuccessFlag = *pi_asf;
526 i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_READ_KEY, key,
527 key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1;
534 *pi_asf = ((PDVD_ASF)key->KeyData)->SuccessFlag;
538 INIT_SSC( GPCMD_REPORT_KEY, 8 );
540 ssc.CDBByte[ 10 ] = DVD_REPORT_ASF | (*pi_agid << 6);
542 i_ret = WinSendSSC( i_fd, &ssc );
544 *pi_asf = p_buffer[ 7 ] & 1;
548 /* DVD ioctls unavailable - do as if the ioctl failed */
555 /*****************************************************************************
556 * ioctl_ReportKey1: get the first key from the drive
557 *****************************************************************************/
558 int ioctl_ReportKey1( int i_fd, int *pi_agid, u8 *p_key )
562 #if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
563 dvd_authinfo auth_info;
565 auth_info.type = DVD_LU_SEND_KEY1;
566 auth_info.lsk.agid = *pi_agid;
568 i_ret = ioctl( i_fd, DVD_AUTH, &auth_info );
570 memcpy( p_key, auth_info.lsk.key, sizeof(dvd_key) );
572 #elif defined( HAVE_BSD_DVD_STRUCT )
573 struct dvd_authinfo auth_info;
575 auth_info.format = DVD_REPORT_KEY1;
576 auth_info.agid = *pi_agid;
578 i_ret = ioctl( i_fd, DVDIOCREPORTKEY, &auth_info );
580 memcpy( p_key, auth_info.keychal, 8 );
582 #elif defined( SYS_BEOS )
583 INIT_RDC( GPCMD_REPORT_KEY, 12 );
585 rdc.command[ 10 ] = DVD_REPORT_KEY1 | (*pi_agid << 6);
587 i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
589 memcpy( p_key, p_buffer + 4, 8 );
591 #elif defined( SYS_DARWIN )
594 dvdioctl.i_keyformat = kKey1;
595 dvdioctl.i_agid = *pi_agid;
597 i_ret = ioctl( i_fd, IODVD_SEND_KEY, &dvdioctl );
599 memcpy( p_key, p_buffer + 4, 8 );
601 #elif defined( WIN32 )
602 if( WIN2K ) /* NT/Win2000/Whistler */
605 u8 buffer[DVD_BUS_KEY_LENGTH];
606 PDVD_COPY_PROTECT_KEY key = (PDVD_COPY_PROTECT_KEY) &buffer;
608 memset( &buffer, 0, sizeof( buffer ) );
610 key->KeyLength = DVD_BUS_KEY_LENGTH;
611 key->SessionId = *pi_agid;
612 key->KeyType = DvdBusKey1;
615 i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_READ_KEY, key,
616 key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1;
618 memcpy( p_key, key->KeyData, 8 );
622 INIT_SSC( GPCMD_REPORT_KEY, 12 );
624 ssc.CDBByte[ 10 ] = DVD_REPORT_KEY1 | (*pi_agid << 6);
626 i_ret = WinSendSSC( i_fd, &ssc );
628 memcpy( p_key, p_buffer + 4, 8 );
632 /* DVD ioctls unavailable - do as if the ioctl failed */
639 /*****************************************************************************
640 * ioctl_InvalidateAgid: invalidate the current AGID
641 *****************************************************************************/
642 int ioctl_InvalidateAgid( int i_fd, int *pi_agid )
646 #if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
647 dvd_authinfo auth_info;
649 auth_info.type = DVD_INVALIDATE_AGID;
650 auth_info.lsa.agid = *pi_agid;
652 i_ret = ioctl( i_fd, DVD_AUTH, &auth_info );
654 *pi_agid = auth_info.lsa.agid;
656 #elif defined( HAVE_BSD_DVD_STRUCT )
657 struct dvd_authinfo auth_info;
659 auth_info.format = DVD_INVALIDATE_AGID;
660 auth_info.agid = *pi_agid;
662 i_ret = ioctl( i_fd, DVDIOCREPORTKEY, &auth_info );
664 *pi_agid = auth_info.agid;
666 #elif defined( SYS_BEOS )
667 INIT_RDC( GPCMD_REPORT_KEY, 0 );
669 rdc.command[ 10 ] = DVD_INVALIDATE_AGID | (*pi_agid << 6);
671 i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
673 #elif defined( SYS_DARWIN )
676 dvdioctl.i_keyformat = kInvalidateAGID;
677 dvdioctl.i_agid = *pi_agid;
679 i_ret = ioctl( i_fd, IODVD_SEND_KEY, &dvdioctl );
681 #elif defined( WIN32 )
682 if( WIN2K ) /* NT/Win2000/Whistler */
686 i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_END_SESSION,
687 pi_agid, sizeof( *pi_agid ), NULL, 0, &tmp, NULL ) ? 0 : -1;
691 #if defined( __MINGW32__ )
692 INIT_SSC( GPCMD_REPORT_KEY, 0 );
694 INIT_SSC( GPCMD_REPORT_KEY, 1 );
697 ssc.CDBByte[ 8 ] = 0;
698 ssc.CDBByte[ 9 ] = 0;
701 ssc.CDBByte[ 10 ] = DVD_INVALIDATE_AGID | (*pi_agid << 6);
703 i_ret = WinSendSSC( i_fd, &ssc );
707 /* DVD ioctls unavailable - do as if the ioctl failed */
714 /*****************************************************************************
715 * ioctl_SendChallenge: send challenge to the drive
716 *****************************************************************************/
717 int ioctl_SendChallenge( int i_fd, int *pi_agid, u8 *p_challenge )
719 #if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
720 dvd_authinfo auth_info;
722 auth_info.type = DVD_HOST_SEND_CHALLENGE;
723 auth_info.hsc.agid = *pi_agid;
725 memcpy( auth_info.hsc.chal, p_challenge, sizeof(dvd_challenge) );
727 return ioctl( i_fd, DVD_AUTH, &auth_info );
729 #elif defined( HAVE_BSD_DVD_STRUCT )
730 struct dvd_authinfo auth_info;
732 auth_info.format = DVD_SEND_CHALLENGE;
733 auth_info.agid = *pi_agid;
735 memcpy( auth_info.keychal, p_challenge, 12 );
737 return ioctl( i_fd, DVDIOCSENDKEY, &auth_info );
739 #elif defined( SYS_BEOS )
740 INIT_RDC( GPCMD_SEND_KEY, 16 );
742 rdc.command[ 10 ] = DVD_SEND_CHALLENGE | (*pi_agid << 6);
745 memcpy( p_buffer + 4, p_challenge, 12 );
747 return ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
749 #elif defined( SYS_DARWIN )
752 dvdioctl.i_keyformat = kChallengeKey;
753 dvdioctl.i_agid = *pi_agid;
756 memcpy( p_buffer + 4, p_challenge, 12 );
758 return ioctl( i_fd, IODVD_SEND_KEY, &dvdioctl );
760 #elif defined( WIN32 )
761 if( WIN2K ) /* NT/Win2000/Whistler */
764 u8 buffer[DVD_CHALLENGE_KEY_LENGTH];
765 PDVD_COPY_PROTECT_KEY key = (PDVD_COPY_PROTECT_KEY) &buffer;
767 memset( &buffer, 0, sizeof( buffer ) );
769 key->KeyLength = DVD_CHALLENGE_KEY_LENGTH;
770 key->SessionId = *pi_agid;
771 key->KeyType = DvdChallengeKey;
774 memcpy( key->KeyData, p_challenge, 10 );
776 return DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_SEND_KEY, key,
777 key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1;
781 INIT_SSC( GPCMD_SEND_KEY, 16 );
783 ssc.CDBByte[ 10 ] = DVD_SEND_CHALLENGE | (*pi_agid << 6);
786 memcpy( p_buffer + 4, p_challenge, 12 );
788 return WinSendSSC( i_fd, &ssc );
792 /* DVD ioctls unavailable - do as if the ioctl failed */
798 /*****************************************************************************
799 * ioctl_SendKey2: send the second key to the drive
800 *****************************************************************************/
801 int ioctl_SendKey2( int i_fd, int *pi_agid, u8 *p_key )
803 #if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
804 dvd_authinfo auth_info;
806 auth_info.type = DVD_HOST_SEND_KEY2;
807 auth_info.hsk.agid = *pi_agid;
809 memcpy( auth_info.hsk.key, p_key, sizeof(dvd_key) );
811 return ioctl( i_fd, DVD_AUTH, &auth_info );
813 #elif defined( HAVE_BSD_DVD_STRUCT )
814 struct dvd_authinfo auth_info;
816 auth_info.format = DVD_SEND_KEY2;
817 auth_info.agid = *pi_agid;
819 memcpy( auth_info.keychal, p_key, 8 );
821 return ioctl( i_fd, DVDIOCSENDKEY, &auth_info );
823 #elif defined( SYS_BEOS )
824 INIT_RDC( GPCMD_SEND_KEY, 12 );
826 rdc.command[ 10 ] = DVD_SEND_KEY2 | (*pi_agid << 6);
829 memcpy( p_buffer + 4, p_key, 8 );
831 return ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
833 #elif defined( WIN32 )
834 if( WIN2K ) /* NT/Win2000/Whistler */
837 u8 buffer[DVD_BUS_KEY_LENGTH];
838 PDVD_COPY_PROTECT_KEY key = (PDVD_COPY_PROTECT_KEY) &buffer;
840 memset( &buffer, 0, sizeof( buffer ) );
842 key->KeyLength = DVD_BUS_KEY_LENGTH;
843 key->SessionId = *pi_agid;
844 key->KeyType = DvdBusKey2;
847 memcpy( key->KeyData, p_key, 8 );
849 return DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_SEND_KEY, key,
850 key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1;
854 INIT_SSC( GPCMD_SEND_KEY, 12 );
856 ssc.CDBByte[ 10 ] = DVD_SEND_KEY2 | (*pi_agid << 6);
859 memcpy( p_buffer + 4, p_key, 8 );
861 return WinSendSSC( i_fd, &ssc );
864 #elif defined( SYS_DARWIN )
867 dvdioctl.i_keyformat = kKey2;
868 dvdioctl.i_agid = *pi_agid;
871 memcpy( p_buffer + 4, p_key, 8 );
873 return ioctl( i_fd, IODVD_SEND_KEY, &dvdioctl );
876 /* DVD ioctls unavailable - do as if the ioctl failed */
882 /* Local prototypes */
884 #if defined( SYS_BEOS )
885 /*****************************************************************************
886 * BeInitRDC: initialize a RDC structure for the BeOS kernel
887 *****************************************************************************
888 * This function initializes a BeOS raw device command structure for future
889 * use, either a read command or a write command.
890 *****************************************************************************/
891 static void BeInitRDC( raw_device_command *p_rdc, int i_type )
893 memset( p_rdc->data, 0, p_rdc->data_length );
898 /* leave the flags to 0 */
901 case GPCMD_READ_DVD_STRUCTURE:
902 case GPCMD_REPORT_KEY:
903 p_rdc->flags = B_RAW_DEVICE_DATA_IN;
907 p_rdc->command[ 0 ] = i_type;
909 p_rdc->command[ 8 ] = (p_rdc->data_length >> 8) & 0xff;
910 p_rdc->command[ 9 ] = p_rdc->data_length & 0xff;
911 p_rdc->command_length = 12;
913 p_rdc->sense_data = NULL;
914 p_rdc->sense_data_length = 0;
916 p_rdc->timeout = 1000000;
921 /*****************************************************************************
922 * WinInitSSC: initialize a ssc structure for the win32 aspi layer
923 *****************************************************************************
924 * This function initializes a ssc raw device command structure for future
925 * use, either a read command or a write command.
926 *****************************************************************************/
927 static void WinInitSSC( struct SRB_ExecSCSICmd *p_ssc, int i_type )
929 memset( p_ssc->SRB_BufPointer, 0, p_ssc->SRB_BufLen );
934 p_ssc->SRB_Flags = SRB_DIR_OUT;
937 case GPCMD_READ_DVD_STRUCTURE:
938 case GPCMD_REPORT_KEY:
939 p_ssc->SRB_Flags = SRB_DIR_IN;
943 p_ssc->SRB_Cmd = SC_EXEC_SCSI_CMD;
944 p_ssc->SRB_Flags |= SRB_EVENT_NOTIFY;
946 p_ssc->CDBByte[ 0 ] = i_type;
948 p_ssc->CDBByte[ 8 ] = (u8)(p_ssc->SRB_BufLen >> 8) & 0xff;
949 p_ssc->CDBByte[ 9 ] = (u8) p_ssc->SRB_BufLen & 0xff;
950 p_ssc->SRB_CDBLen = 12;
952 p_ssc->SRB_SenseLen = SENSE_LEN;
955 /*****************************************************************************
956 * WinSendSSC: send a ssc structure to the aspi layer
957 *****************************************************************************/
958 static int WinSendSSC( int i_fd, struct SRB_ExecSCSICmd *p_ssc )
960 HANDLE hEvent = NULL;
961 struct w32_aspidev *fd = (struct w32_aspidev *) i_fd;
963 hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
969 p_ssc->SRB_PostProc = hEvent;
970 p_ssc->SRB_HaId = LOBYTE( fd->i_sid );
971 p_ssc->SRB_Target = HIBYTE( fd->i_sid );
973 ResetEvent( hEvent );
974 if( fd->lpSendCommand( (void*) p_ssc ) == SS_PENDING )
975 WaitForSingleObject( hEvent, INFINITE );
977 CloseHandle( hEvent );
979 return p_ssc->SRB_Status == SS_COMP ? 0 : -1;