1 /*****************************************************************************
2 * ioctl.c: DVD ioctl replacement function
3 *****************************************************************************
4 * Copyright (C) 1999-2001 VideoLAN
5 * $Id: ioctl.c,v 1.9 2001/08/09 08:20:26 sam Exp $
7 * Authors: Markus Kuespert <ltlBeBoy@beosmail.com>
8 * Samuel Hocevar <sam@zoy.org>
9 * Jon Lech Johansen <jon-vl@nanocrew.net>
10 * HÃ¥kan Hjort <d95hjort@dtek.chalmers.se>
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
25 *****************************************************************************/
27 /*****************************************************************************
29 *****************************************************************************/
32 #include <string.h> /* memcpy(), memset() */
33 #include <sys/types.h>
37 # include <winioctl.h>
39 # include <netinet/in.h>
40 # include <sys/ioctl.h>
43 #ifdef DVD_STRUCT_IN_SYS_CDIO_H
44 # include <sys/cdio.h>
46 #ifdef DVD_STRUCT_IN_SYS_DVDIO_H
47 # include <sys/dvdio.h>
49 #ifdef DVD_STRUCT_IN_LINUX_CDROM_H
50 # include <linux/cdrom.h>
52 #ifdef DVD_STRUCT_IN_DVD_H
62 # include </usr/include/sys/scsi/scsi_types.h>
63 # include <sys/scsi/impl/uscsi.h>
70 # include "DVDioctl/DVDioctl.h"
75 /*****************************************************************************
76 * Local prototypes, BeOS specific
77 *****************************************************************************/
78 #if defined( SYS_BEOS )
79 static void BeInitRDC ( raw_device_command
*, int );
82 /*****************************************************************************
83 * Local prototypes, Solaris specific
84 *****************************************************************************/
85 #if defined( SOLARIS_USCSI )
86 static void SolarisInitUSCSI( struct uscsi_cmd
*p_sc
, int i_type
);
89 /*****************************************************************************
90 * Local prototypes, win32 (aspi) specific
91 *****************************************************************************/
93 static void WinInitSSC ( struct SRB_ExecSCSICmd
*, int );
94 static int WinSendSSC ( int, struct SRB_ExecSCSICmd
* );
97 /*****************************************************************************
98 * ioctl_ReadCopyright: check whether the disc is encrypted or not
99 *****************************************************************************/
100 int ioctl_ReadCopyright( int i_fd
, int i_layer
, int *pi_copyright
)
104 #if defined( HAVE_LINUX_DVD_STRUCT )
107 dvd
.type
= DVD_STRUCT_COPYRIGHT
;
108 dvd
.copyright
.layer_num
= i_layer
;
110 i_ret
= ioctl( i_fd
, DVD_READ_STRUCT
, &dvd
);
112 *pi_copyright
= dvd
.copyright
.cpst
;
114 #elif defined( HAVE_BSD_DVD_STRUCT )
115 struct dvd_struct dvd
;
117 dvd
.format
= DVD_STRUCT_COPYRIGHT
;
118 dvd
.layer_num
= i_layer
;
120 i_ret
= ioctl( i_fd
, DVDIOCREADSTRUCTURE
, &dvd
);
122 *pi_copyright
= dvd
.cpst
;
124 #elif defined( SYS_BEOS )
125 INIT_RDC( GPCMD_READ_DVD_STRUCTURE
, 8 );
127 rdc
.command
[ 6 ] = i_layer
;
128 rdc
.command
[ 7 ] = DVD_STRUCT_COPYRIGHT
;
130 i_ret
= ioctl( i_fd
, B_RAW_DEVICE_COMMAND
, &rdc
, sizeof(rdc
) );
132 *pi_copyright
= p_buffer
[ 4 ];
134 #elif defined( SOLARIS_USCSI )
135 INIT_USCSI( GPCMD_READ_DVD_STRUCTURE
, 8 );
137 rs_cdb
.cdb_opaque
[ 6 ] = i_layer
;
138 rs_cdb
.cdb_opaque
[ 7 ] = DVD_STRUCT_COPYRIGHT
;
140 i_ret
= ioctl(i_fd
, USCSICMD
, &sc
);
142 if( i_ret
< 0 || sc
.uscsi_status
) {
146 *pi_copyright
= p_buffer
[ 4 ];
147 // s->copyright.rmi = p_buffer[ 5 ];
149 #elif defined( SYS_DARWIN )
154 #elif defined( WIN32 )
155 if( WIN2K
) /* NT/Win2000/Whistler */
159 SCSI_PASS_THROUGH_DIRECT sptd
;
161 memset( &sptd
, 0, sizeof( sptd
) );
162 memset( &p_buffer
, 0, sizeof( p_buffer
) );
164 /* When using IOCTL_DVD_READ_STRUCTURE and
165 DVD_COPYRIGHT_DESCRIPTOR, CopyrightProtectionType
166 is always 6. So we send a raw scsi command instead. */
168 sptd
.Length
= sizeof( SCSI_PASS_THROUGH_DIRECT
);
170 sptd
.DataIn
= SCSI_IOCTL_DATA_IN
;
171 sptd
.DataTransferLength
= 8;
172 sptd
.TimeOutValue
= 2;
173 sptd
.DataBuffer
= p_buffer
;
174 sptd
.Cdb
[ 0 ] = GPCMD_READ_DVD_STRUCTURE
;
175 sptd
.Cdb
[ 6 ] = i_layer
;
176 sptd
.Cdb
[ 7 ] = DVD_STRUCT_COPYRIGHT
;
177 sptd
.Cdb
[ 8 ] = (8 >> 8) & 0xff;
178 sptd
.Cdb
[ 9 ] = 8 & 0xff;
180 i_ret
= DeviceIoControl( (HANDLE
) i_fd
,
181 IOCTL_SCSI_PASS_THROUGH_DIRECT
,
182 &sptd
, sizeof( SCSI_PASS_THROUGH_DIRECT
),
183 &sptd
, sizeof( SCSI_PASS_THROUGH_DIRECT
),
184 &tmp
, NULL
) ? 0 : -1;
186 *pi_copyright
= p_buffer
[4];
190 INIT_SSC( GPCMD_READ_DVD_STRUCTURE
, 8 );
192 ssc
.CDBByte
[ 6 ] = i_layer
;
193 ssc
.CDBByte
[ 7 ] = DVD_STRUCT_COPYRIGHT
;
195 i_ret
= WinSendSSC( i_fd
, &ssc
);
197 *pi_copyright
= p_buffer
[ 4 ];
200 #elif defined( __QNXNTO__ )
202 QNX RTOS currently doesn't have a CAM
203 interface (they're working on it though).
204 Assume DVD is not encrypted.
211 /* DVD ioctls unavailable - do as if the ioctl failed */
218 /*****************************************************************************
219 * ioctl_ReadKey: get the disc key
220 *****************************************************************************/
221 int ioctl_ReadKey( int i_fd
, int *pi_agid
, u8
*p_key
)
225 #if defined( HAVE_LINUX_DVD_STRUCT )
228 dvd
.type
= DVD_STRUCT_DISCKEY
;
229 dvd
.disckey
.agid
= *pi_agid
;
230 memset( dvd
.disckey
.value
, 0, 2048 );
232 i_ret
= ioctl( i_fd
, DVD_READ_STRUCT
, &dvd
);
239 memcpy( p_key
, dvd
.disckey
.value
, 2048 );
241 #elif defined( HAVE_BSD_DVD_STRUCT )
242 struct dvd_struct dvd
;
244 dvd
.format
= DVD_STRUCT_DISCKEY
;
246 memset( dvd
.data
, 0, 2048 );
248 i_ret
= ioctl( i_fd
, DVDIOCREADSTRUCTURE
, &dvd
);
255 memcpy( p_key
, dvd
.data
, 2048 );
257 #elif defined( SYS_BEOS )
258 INIT_RDC( GPCMD_READ_DVD_STRUCTURE
, 2048 + 4 );
260 rdc
.command
[ 7 ] = DVD_STRUCT_DISCKEY
;
261 rdc
.command
[ 10 ] = *pi_agid
<< 6;
263 i_ret
= ioctl( i_fd
, B_RAW_DEVICE_COMMAND
, &rdc
, sizeof(rdc
) );
270 memcpy( p_key
, p_buffer
+ 4, 2048 );
272 #elif defined( SOLARIS_USCSI )
273 INIT_USCSI( GPCMD_READ_DVD_STRUCTURE
, 2048 + 4 );
275 rs_cdb
.cdb_opaque
[ 7 ] = DVD_STRUCT_DISCKEY
;
276 rs_cdb
.cdb_opaque
[ 10 ] = *pi_agid
<< 6;
278 i_ret
= ioctl( i_fd
, USCSICMD
, &sc
);
280 if( i_ret
< 0 || sc
.uscsi_status
)
286 memcpy( p_key
, p_buffer
+ 4, 2048 );
288 #elif defined( SYS_DARWIN )
291 memset( p_key
, 0x00, 2048 );
293 #elif defined( WIN32 )
294 if( WIN2K
) /* NT/Win2000/Whistler */
297 u8 buffer
[DVD_DISK_KEY_LENGTH
];
298 PDVD_COPY_PROTECT_KEY key
= (PDVD_COPY_PROTECT_KEY
) &buffer
;
300 memset( &buffer
, 0, sizeof( buffer
) );
302 key
->KeyLength
= DVD_DISK_KEY_LENGTH
;
303 key
->SessionId
= *pi_agid
;
304 key
->KeyType
= DvdDiskKey
;
307 i_ret
= DeviceIoControl( (HANDLE
) i_fd
, IOCTL_DVD_READ_KEY
, key
,
308 key
->KeyLength
, key
, key
->KeyLength
, &tmp
, NULL
) ? 0 : -1;
315 memcpy( p_key
, key
->KeyData
, 2048 );
319 INIT_SSC( GPCMD_READ_DVD_STRUCTURE
, 2048 + 4 );
321 ssc
.CDBByte
[ 7 ] = DVD_STRUCT_DISCKEY
;
322 ssc
.CDBByte
[ 10 ] = *pi_agid
<< 6;
324 i_ret
= WinSendSSC( i_fd
, &ssc
);
331 memcpy( p_key
, p_buffer
+ 4, 2048 );
335 /* DVD ioctls unavailable - do as if the ioctl failed */
342 /*****************************************************************************
343 * ioctl_ReportAgid: get AGID from the drive
344 *****************************************************************************/
345 int ioctl_ReportAgid( int i_fd
, int *pi_agid
)
349 #if defined( HAVE_LINUX_DVD_STRUCT )
350 dvd_authinfo auth_info
;
352 auth_info
.type
= DVD_LU_SEND_AGID
;
353 auth_info
.lsa
.agid
= *pi_agid
;
355 i_ret
= ioctl( i_fd
, DVD_AUTH
, &auth_info
);
357 *pi_agid
= auth_info
.lsa
.agid
;
359 #elif defined( HAVE_BSD_DVD_STRUCT )
360 struct dvd_authinfo auth_info
;
362 auth_info
.format
= DVD_REPORT_AGID
;
363 auth_info
.agid
= *pi_agid
;
365 i_ret
= ioctl( i_fd
, DVDIOCREPORTKEY
, &auth_info
);
367 *pi_agid
= auth_info
.agid
;
369 #elif defined( SYS_BEOS )
370 INIT_RDC( GPCMD_REPORT_KEY
, 8 );
372 rdc
.command
[ 10 ] = DVD_REPORT_AGID
| (*pi_agid
<< 6);
374 i_ret
= ioctl( i_fd
, B_RAW_DEVICE_COMMAND
, &rdc
, sizeof(rdc
) );
376 *pi_agid
= p_buffer
[ 7 ] >> 6;
378 #elif defined( SOLARIS_USCSI )
379 INIT_USCSI( GPCMD_REPORT_KEY
, 8 );
381 rs_cdb
.cdb_opaque
[ 10 ] = DVD_REPORT_AGID
| (*pi_agid
<< 6);
383 i_ret
= ioctl( i_fd
, USCSICMD
, &sc
);
385 if( i_ret
< 0 || sc
.uscsi_status
)
390 *pi_agid
= p_buffer
[ 7 ] >> 6;
392 #elif defined( SYS_DARWIN )
395 dvdioctl
.i_keyformat
= kCSSAGID
;
396 dvdioctl
.i_agid
= *pi_agid
;
399 i_ret
= ioctl( i_fd
, IODVD_REPORT_KEY
, &dvdioctl
);
401 *pi_agid
= p_buffer
[ 7 ] >> 6;
403 #elif defined( WIN32 )
404 if( WIN2K
) /* NT/Win2000/Whistler */
409 i_ret
= DeviceIoControl( (HANDLE
) i_fd
, IOCTL_DVD_START_SESSION
,
410 &tmp
, 4, &id
, sizeof( id
), &tmp
, NULL
) ? 0 : -1;
416 INIT_SSC( GPCMD_REPORT_KEY
, 8 );
418 ssc
.CDBByte
[ 10 ] = DVD_REPORT_AGID
| (*pi_agid
<< 6);
420 i_ret
= WinSendSSC( i_fd
, &ssc
);
422 *pi_agid
= p_buffer
[ 7 ] >> 6;
426 /* DVD ioctls unavailable - do as if the ioctl failed */
433 /*****************************************************************************
434 * ioctl_ReportChallenge: get challenge from the drive
435 *****************************************************************************/
436 int ioctl_ReportChallenge( int i_fd
, int *pi_agid
, u8
*p_challenge
)
440 #if defined( HAVE_LINUX_DVD_STRUCT )
441 dvd_authinfo auth_info
;
443 auth_info
.type
= DVD_LU_SEND_CHALLENGE
;
444 auth_info
.lsc
.agid
= *pi_agid
;
446 i_ret
= ioctl( i_fd
, DVD_AUTH
, &auth_info
);
448 memcpy( p_challenge
, auth_info
.lsc
.chal
, sizeof(dvd_challenge
) );
450 #elif defined( HAVE_BSD_DVD_STRUCT )
451 struct dvd_authinfo auth_info
;
453 auth_info
.format
= DVD_REPORT_CHALLENGE
;
454 auth_info
.agid
= *pi_agid
;
456 i_ret
= ioctl( i_fd
, DVDIOCREPORTKEY
, &auth_info
);
458 memcpy( p_challenge
, auth_info
.keychal
, 10 );
460 #elif defined( SYS_BEOS )
461 INIT_RDC( GPCMD_REPORT_KEY
, 16 );
463 rdc
.command
[ 10 ] = DVD_REPORT_CHALLENGE
| (*pi_agid
<< 6);
465 i_ret
= ioctl( i_fd
, B_RAW_DEVICE_COMMAND
, &rdc
, sizeof(rdc
) );
467 memcpy( p_challenge
, p_buffer
+ 4, 12 );
469 #elif defined( SOLARIS_USCSI )
470 INIT_USCSI( GPCMD_REPORT_KEY
, 16 );
472 rs_cdb
.cdb_opaque
[ 10 ] = DVD_REPORT_CHALLENGE
| (*pi_agid
<< 6);
474 i_ret
= ioctl( i_fd
, USCSICMD
, &sc
);
476 if( i_ret
< 0 || sc
.uscsi_status
)
481 memcpy( p_challenge
, p_buffer
+ 4, 12 );
483 #elif defined( SYS_DARWIN )
486 dvdioctl
.i_keyformat
= kChallengeKey
;
487 dvdioctl
.i_agid
= *pi_agid
;
490 i_ret
= ioctl( i_fd
, IODVD_REPORT_KEY
, &dvdioctl
);
492 memcpy( p_challenge
, p_buffer
+ 4, 12 );
494 #elif defined( WIN32 )
495 if( WIN2K
) /* NT/Win2000/Whistler */
498 u8 buffer
[DVD_CHALLENGE_KEY_LENGTH
];
499 PDVD_COPY_PROTECT_KEY key
= (PDVD_COPY_PROTECT_KEY
) &buffer
;
501 memset( &buffer
, 0, sizeof( buffer
) );
503 key
->KeyLength
= DVD_CHALLENGE_KEY_LENGTH
;
504 key
->SessionId
= *pi_agid
;
505 key
->KeyType
= DvdChallengeKey
;
508 i_ret
= DeviceIoControl( (HANDLE
) i_fd
, IOCTL_DVD_READ_KEY
, key
,
509 key
->KeyLength
, key
, key
->KeyLength
, &tmp
, NULL
) ? 0 : -1;
516 memcpy( p_challenge
, key
->KeyData
, 10 );
520 INIT_SSC( GPCMD_REPORT_KEY
, 16 );
522 ssc
.CDBByte
[ 10 ] = DVD_REPORT_CHALLENGE
| (*pi_agid
<< 6);
524 i_ret
= WinSendSSC( i_fd
, &ssc
);
526 memcpy( p_challenge
, p_buffer
+ 4, 12 );
530 /* DVD ioctls unavailable - do as if the ioctl failed */
537 /*****************************************************************************
538 * ioctl_ReportASF: get ASF from the drive
539 *****************************************************************************/
540 int ioctl_ReportASF( int i_fd
, int *pi_agid
, int *pi_asf
)
544 #if defined( HAVE_LINUX_DVD_STRUCT )
545 dvd_authinfo auth_info
;
547 auth_info
.type
= DVD_LU_SEND_ASF
;
548 auth_info
.lsasf
.agid
= *pi_agid
;
549 auth_info
.lsasf
.asf
= *pi_asf
;
551 i_ret
= ioctl( i_fd
, DVD_AUTH
, &auth_info
);
553 *pi_asf
= auth_info
.lsasf
.asf
;
555 #elif defined( HAVE_BSD_DVD_STRUCT )
556 struct dvd_authinfo auth_info
;
558 auth_info
.format
= DVD_REPORT_ASF
;
559 auth_info
.agid
= *pi_agid
;
560 auth_info
.asf
= *pi_asf
;
562 i_ret
= ioctl( i_fd
, DVDIOCREPORTKEY
, &auth_info
);
564 *pi_asf
= auth_info
.asf
;
566 #elif defined( SYS_BEOS )
567 INIT_RDC( GPCMD_REPORT_KEY
, 8 );
569 rdc
.command
[ 10 ] = DVD_REPORT_ASF
| (*pi_agid
<< 6);
571 i_ret
= ioctl( i_fd
, B_RAW_DEVICE_COMMAND
, &rdc
, sizeof(rdc
) );
573 *pi_asf
= p_buffer
[ 7 ] & 1;
575 #elif defined( SOLARIS_USCSI )
576 INIT_USCSI( GPCMD_REPORT_KEY
, 8 );
578 rs_cdb
.cdb_opaque
[ 10 ] = DVD_REPORT_ASF
| (*pi_agid
<< 6);
580 i_ret
= ioctl( i_fd
, USCSICMD
, &sc
);
582 if( i_ret
< 0 || sc
.uscsi_status
)
587 *pi_asf
= p_buffer
[ 7 ] & 1;
589 #elif defined( SYS_DARWIN )
592 dvdioctl
.i_keyformat
= kASF
;
593 dvdioctl
.i_agid
= *pi_agid
;
596 i_ret
= ioctl( i_fd
, IODVD_REPORT_KEY
, &dvdioctl
);
598 *pi_asf
= p_buffer
[ 7 ] & 1;
600 #elif defined( WIN32 )
601 if( WIN2K
) /* NT/Win2000/Whistler */
604 u8 buffer
[DVD_ASF_LENGTH
];
605 PDVD_COPY_PROTECT_KEY key
= (PDVD_COPY_PROTECT_KEY
) &buffer
;
607 memset( &buffer
, 0, sizeof( buffer
) );
609 key
->KeyLength
= DVD_ASF_LENGTH
;
610 key
->SessionId
= *pi_agid
;
611 key
->KeyType
= DvdAsf
;
614 ((PDVD_ASF
)key
->KeyData
)->SuccessFlag
= *pi_asf
;
616 i_ret
= DeviceIoControl( (HANDLE
) i_fd
, IOCTL_DVD_READ_KEY
, key
,
617 key
->KeyLength
, key
, key
->KeyLength
, &tmp
, NULL
) ? 0 : -1;
624 *pi_asf
= ((PDVD_ASF
)key
->KeyData
)->SuccessFlag
;
628 INIT_SSC( GPCMD_REPORT_KEY
, 8 );
630 ssc
.CDBByte
[ 10 ] = DVD_REPORT_ASF
| (*pi_agid
<< 6);
632 i_ret
= WinSendSSC( i_fd
, &ssc
);
634 *pi_asf
= p_buffer
[ 7 ] & 1;
638 /* DVD ioctls unavailable - do as if the ioctl failed */
645 /*****************************************************************************
646 * ioctl_ReportKey1: get the first key from the drive
647 *****************************************************************************/
648 int ioctl_ReportKey1( int i_fd
, int *pi_agid
, u8
*p_key
)
652 #if defined( HAVE_LINUX_DVD_STRUCT )
653 dvd_authinfo auth_info
;
655 auth_info
.type
= DVD_LU_SEND_KEY1
;
656 auth_info
.lsk
.agid
= *pi_agid
;
658 i_ret
= ioctl( i_fd
, DVD_AUTH
, &auth_info
);
660 memcpy( p_key
, auth_info
.lsk
.key
, sizeof(dvd_key
) );
662 #elif defined( HAVE_BSD_DVD_STRUCT )
663 struct dvd_authinfo auth_info
;
665 auth_info
.format
= DVD_REPORT_KEY1
;
666 auth_info
.agid
= *pi_agid
;
668 i_ret
= ioctl( i_fd
, DVDIOCREPORTKEY
, &auth_info
);
670 memcpy( p_key
, auth_info
.keychal
, 8 );
672 #elif defined( SYS_BEOS )
673 INIT_RDC( GPCMD_REPORT_KEY
, 12 );
675 rdc
.command
[ 10 ] = DVD_REPORT_KEY1
| (*pi_agid
<< 6);
677 i_ret
= ioctl( i_fd
, B_RAW_DEVICE_COMMAND
, &rdc
, sizeof(rdc
) );
679 memcpy( p_key
, p_buffer
+ 4, 8 );
681 #elif defined( SOLARIS_USCSI )
682 INIT_USCSI( GPCMD_REPORT_KEY
, 12 );
684 rs_cdb
.cdb_opaque
[ 10 ] = DVD_REPORT_KEY1
| (*pi_agid
<< 6);
686 i_ret
= ioctl( i_fd
, USCSICMD
, &sc
);
688 if( i_ret
< 0 || sc
.uscsi_status
)
693 memcpy( p_key
, p_buffer
+ 4, 8 );;
695 #elif defined( SYS_DARWIN )
698 dvdioctl
.i_keyformat
= kKey1
;
699 dvdioctl
.i_agid
= *pi_agid
;
701 i_ret
= ioctl( i_fd
, IODVD_SEND_KEY
, &dvdioctl
);
703 memcpy( p_key
, p_buffer
+ 4, 8 );
705 #elif defined( WIN32 )
706 if( WIN2K
) /* NT/Win2000/Whistler */
709 u8 buffer
[DVD_BUS_KEY_LENGTH
];
710 PDVD_COPY_PROTECT_KEY key
= (PDVD_COPY_PROTECT_KEY
) &buffer
;
712 memset( &buffer
, 0, sizeof( buffer
) );
714 key
->KeyLength
= DVD_BUS_KEY_LENGTH
;
715 key
->SessionId
= *pi_agid
;
716 key
->KeyType
= DvdBusKey1
;
719 i_ret
= DeviceIoControl( (HANDLE
) i_fd
, IOCTL_DVD_READ_KEY
, key
,
720 key
->KeyLength
, key
, key
->KeyLength
, &tmp
, NULL
) ? 0 : -1;
722 memcpy( p_key
, key
->KeyData
, 8 );
726 INIT_SSC( GPCMD_REPORT_KEY
, 12 );
728 ssc
.CDBByte
[ 10 ] = DVD_REPORT_KEY1
| (*pi_agid
<< 6);
730 i_ret
= WinSendSSC( i_fd
, &ssc
);
732 memcpy( p_key
, p_buffer
+ 4, 8 );
736 /* DVD ioctls unavailable - do as if the ioctl failed */
743 /*****************************************************************************
744 * ioctl_InvalidateAgid: invalidate the current AGID
745 *****************************************************************************/
746 int ioctl_InvalidateAgid( int i_fd
, int *pi_agid
)
750 #if defined( HAVE_LINUX_DVD_STRUCT )
751 dvd_authinfo auth_info
;
753 auth_info
.type
= DVD_INVALIDATE_AGID
;
754 auth_info
.lsa
.agid
= *pi_agid
;
756 i_ret
= ioctl( i_fd
, DVD_AUTH
, &auth_info
);
758 *pi_agid
= auth_info
.lsa
.agid
;
760 #elif defined( HAVE_BSD_DVD_STRUCT )
761 struct dvd_authinfo auth_info
;
763 auth_info
.format
= DVD_INVALIDATE_AGID
;
764 auth_info
.agid
= *pi_agid
;
766 i_ret
= ioctl( i_fd
, DVDIOCREPORTKEY
, &auth_info
);
768 *pi_agid
= auth_info
.agid
;
770 #elif defined( SYS_BEOS )
771 INIT_RDC( GPCMD_REPORT_KEY
, 0 );
773 rdc
.command
[ 10 ] = DVD_INVALIDATE_AGID
| (*pi_agid
<< 6);
775 i_ret
= ioctl( i_fd
, B_RAW_DEVICE_COMMAND
, &rdc
, sizeof(rdc
) );
777 #elif defined( SOLARIS_USCSI )
778 INIT_USCSI( GPCMD_REPORT_KEY
, 0 );
780 rs_cdb
.cdb_opaque
[ 10 ] = DVD_INVALIDATE_AGID
| (*pi_agid
<< 6);
782 i_ret
= ioctl( i_fd
, USCSICMD
, &sc
);
784 if( i_ret
< 0 || sc
.uscsi_status
)
789 #elif defined( SYS_DARWIN )
792 dvdioctl
.i_keyformat
= kInvalidateAGID
;
793 dvdioctl
.i_agid
= *pi_agid
;
795 i_ret
= ioctl( i_fd
, IODVD_SEND_KEY
, &dvdioctl
);
797 #elif defined( WIN32 )
798 if( WIN2K
) /* NT/Win2000/Whistler */
802 i_ret
= DeviceIoControl( (HANDLE
) i_fd
, IOCTL_DVD_END_SESSION
,
803 pi_agid
, sizeof( *pi_agid
), NULL
, 0, &tmp
, NULL
) ? 0 : -1;
807 #if defined( __MINGW32__ )
808 INIT_SSC( GPCMD_REPORT_KEY
, 0 );
810 INIT_SSC( GPCMD_REPORT_KEY
, 1 );
813 ssc
.CDBByte
[ 8 ] = 0;
814 ssc
.CDBByte
[ 9 ] = 0;
817 ssc
.CDBByte
[ 10 ] = DVD_INVALIDATE_AGID
| (*pi_agid
<< 6);
819 i_ret
= WinSendSSC( i_fd
, &ssc
);
823 /* DVD ioctls unavailable - do as if the ioctl failed */
830 /*****************************************************************************
831 * ioctl_SendChallenge: send challenge to the drive
832 *****************************************************************************/
833 int ioctl_SendChallenge( int i_fd
, int *pi_agid
, u8
*p_challenge
)
835 #if defined( HAVE_LINUX_DVD_STRUCT )
836 dvd_authinfo auth_info
;
838 auth_info
.type
= DVD_HOST_SEND_CHALLENGE
;
839 auth_info
.hsc
.agid
= *pi_agid
;
841 memcpy( auth_info
.hsc
.chal
, p_challenge
, sizeof(dvd_challenge
) );
843 return ioctl( i_fd
, DVD_AUTH
, &auth_info
);
845 #elif defined( HAVE_BSD_DVD_STRUCT )
846 struct dvd_authinfo auth_info
;
848 auth_info
.format
= DVD_SEND_CHALLENGE
;
849 auth_info
.agid
= *pi_agid
;
851 memcpy( auth_info
.keychal
, p_challenge
, 12 );
853 return ioctl( i_fd
, DVDIOCSENDKEY
, &auth_info
);
855 #elif defined( SYS_BEOS )
856 INIT_RDC( GPCMD_SEND_KEY
, 16 );
858 rdc
.command
[ 10 ] = DVD_SEND_CHALLENGE
| (*pi_agid
<< 6);
861 memcpy( p_buffer
+ 4, p_challenge
, 12 );
863 return ioctl( i_fd
, B_RAW_DEVICE_COMMAND
, &rdc
, sizeof(rdc
) );
865 #elif defined( SOLARIS_USCSI )
866 INIT_USCSI( GPCMD_SEND_KEY
, 16 );
868 rs_cdb
.cdb_opaque
[ 10 ] = DVD_SEND_CHALLENGE
| (*pi_agid
<< 6);
871 memcpy( p_buffer
+ 4, p_challenge
, 12 );
873 if( ioctl( i_fd
, USCSICMD
, &sc
) < 0 || sc
.uscsi_status
)
880 #elif defined( SYS_DARWIN )
883 dvdioctl
.i_keyformat
= kChallengeKey
;
884 dvdioctl
.i_agid
= *pi_agid
;
887 memcpy( p_buffer
+ 4, p_challenge
, 12 );
889 return ioctl( i_fd
, IODVD_SEND_KEY
, &dvdioctl
);
891 #elif defined( WIN32 )
892 if( WIN2K
) /* NT/Win2000/Whistler */
895 u8 buffer
[DVD_CHALLENGE_KEY_LENGTH
];
896 PDVD_COPY_PROTECT_KEY key
= (PDVD_COPY_PROTECT_KEY
) &buffer
;
898 memset( &buffer
, 0, sizeof( buffer
) );
900 key
->KeyLength
= DVD_CHALLENGE_KEY_LENGTH
;
901 key
->SessionId
= *pi_agid
;
902 key
->KeyType
= DvdChallengeKey
;
905 memcpy( key
->KeyData
, p_challenge
, 10 );
907 return DeviceIoControl( (HANDLE
) i_fd
, IOCTL_DVD_SEND_KEY
, key
,
908 key
->KeyLength
, key
, key
->KeyLength
, &tmp
, NULL
) ? 0 : -1;
912 INIT_SSC( GPCMD_SEND_KEY
, 16 );
914 ssc
.CDBByte
[ 10 ] = DVD_SEND_CHALLENGE
| (*pi_agid
<< 6);
917 memcpy( p_buffer
+ 4, p_challenge
, 12 );
919 return WinSendSSC( i_fd
, &ssc
);
923 /* DVD ioctls unavailable - do as if the ioctl failed */
929 /*****************************************************************************
930 * ioctl_SendKey2: send the second key to the drive
931 *****************************************************************************/
932 int ioctl_SendKey2( int i_fd
, int *pi_agid
, u8
*p_key
)
934 #if defined( HAVE_LINUX_DVD_STRUCT )
935 dvd_authinfo auth_info
;
937 auth_info
.type
= DVD_HOST_SEND_KEY2
;
938 auth_info
.hsk
.agid
= *pi_agid
;
940 memcpy( auth_info
.hsk
.key
, p_key
, sizeof(dvd_key
) );
942 return ioctl( i_fd
, DVD_AUTH
, &auth_info
);
944 #elif defined( HAVE_BSD_DVD_STRUCT )
945 struct dvd_authinfo auth_info
;
947 auth_info
.format
= DVD_SEND_KEY2
;
948 auth_info
.agid
= *pi_agid
;
950 memcpy( auth_info
.keychal
, p_key
, 8 );
952 return ioctl( i_fd
, DVDIOCSENDKEY
, &auth_info
);
954 #elif defined( SYS_BEOS )
955 INIT_RDC( GPCMD_SEND_KEY
, 12 );
957 rdc
.command
[ 10 ] = DVD_SEND_KEY2
| (*pi_agid
<< 6);
960 memcpy( p_buffer
+ 4, p_key
, 8 );
962 return ioctl( i_fd
, B_RAW_DEVICE_COMMAND
, &rdc
, sizeof(rdc
) );
964 #elif defined( SOLARIS_USCSI )
965 INIT_USCSI( GPCMD_SEND_KEY
, 12 );
967 rs_cdb
.cdb_opaque
[ 10 ] = DVD_SEND_KEY2
| (*pi_agid
<< 6);
970 memcpy( p_buffer
+ 4, p_key
, 8 );
972 if( ioctl( i_fd
, USCSICMD
, &sc
) < 0 || sc
.uscsi_status
)
979 #elif defined( WIN32 )
980 if( WIN2K
) /* NT/Win2000/Whistler */
983 u8 buffer
[DVD_BUS_KEY_LENGTH
];
984 PDVD_COPY_PROTECT_KEY key
= (PDVD_COPY_PROTECT_KEY
) &buffer
;
986 memset( &buffer
, 0, sizeof( buffer
) );
988 key
->KeyLength
= DVD_BUS_KEY_LENGTH
;
989 key
->SessionId
= *pi_agid
;
990 key
->KeyType
= DvdBusKey2
;
993 memcpy( key
->KeyData
, p_key
, 8 );
995 return DeviceIoControl( (HANDLE
) i_fd
, IOCTL_DVD_SEND_KEY
, key
,
996 key
->KeyLength
, key
, key
->KeyLength
, &tmp
, NULL
) ? 0 : -1;
1000 INIT_SSC( GPCMD_SEND_KEY
, 12 );
1002 ssc
.CDBByte
[ 10 ] = DVD_SEND_KEY2
| (*pi_agid
<< 6);
1004 p_buffer
[ 1 ] = 0xa;
1005 memcpy( p_buffer
+ 4, p_key
, 8 );
1007 return WinSendSSC( i_fd
, &ssc
);
1010 #elif defined( SYS_DARWIN )
1011 INIT_DVDIOCTL( 12 );
1013 dvdioctl
.i_keyformat
= kKey2
;
1014 dvdioctl
.i_agid
= *pi_agid
;
1016 p_buffer
[ 1 ] = 0xa;
1017 memcpy( p_buffer
+ 4, p_key
, 8 );
1019 return ioctl( i_fd
, IODVD_SEND_KEY
, &dvdioctl
);
1022 /* DVD ioctls unavailable - do as if the ioctl failed */
1028 /* Local prototypes */
1030 #if defined( SYS_BEOS )
1031 /*****************************************************************************
1032 * BeInitRDC: initialize a RDC structure for the BeOS kernel
1033 *****************************************************************************
1034 * This function initializes a BeOS raw device command structure for future
1035 * use, either a read command or a write command.
1036 *****************************************************************************/
1037 static void BeInitRDC( raw_device_command
*p_rdc
, int i_type
)
1039 memset( p_rdc
->data
, 0, p_rdc
->data_length
);
1043 case GPCMD_SEND_KEY
:
1044 /* leave the flags to 0 */
1047 case GPCMD_READ_DVD_STRUCTURE
:
1048 case GPCMD_REPORT_KEY
:
1049 p_rdc
->flags
= B_RAW_DEVICE_DATA_IN
;
1053 p_rdc
->command
[ 0 ] = i_type
;
1055 p_rdc
->command
[ 8 ] = (p_rdc
->data_length
>> 8) & 0xff;
1056 p_rdc
->command
[ 9 ] = p_rdc
->data_length
& 0xff;
1057 p_rdc
->command_length
= 12;
1059 p_rdc
->sense_data
= NULL
;
1060 p_rdc
->sense_data_length
= 0;
1062 p_rdc
->timeout
= 1000000;
1066 #if defined( SOLARIS_USCSI )
1067 /*****************************************************************************
1068 * SolarisInitUSCSI: initialize a USCSICMD structure for the Solaris kernel
1069 *****************************************************************************
1070 * This function initializes a Solaris userspace scsi command structure for
1071 * future use, either a read command or a write command.
1072 *****************************************************************************/
1073 static void SolarisInitUSCSI( struct uscsi_cmd
*p_sc
, int i_type
)
1075 union scsi_cdb
*rs_cdb
;
1076 memset( p_sc
->uscsi_cdb
, 0, sizeof( union scsi_cdb
) );
1077 memset( p_sc
->uscsi_bufaddr
, 0, p_sc
->uscsi_buflen
);
1081 case GPCMD_SEND_KEY
:
1082 p_sc
->uscsi_flags
= USCSI_ISOLATE
| USCSI_WRITE
;
1085 case GPCMD_READ_DVD_STRUCTURE
:
1086 case GPCMD_REPORT_KEY
:
1087 p_sc
->uscsi_flags
= USCSI_ISOLATE
| USCSI_READ
;
1091 rs_cdb
= (union scsi_cdb
*)p_sc
->uscsi_cdb
;
1093 rs_cdb
->scc_cmd
= i_type
;
1095 rs_cdb
->cdb_opaque
[ 8 ] = (p_sc
->uscsi_buflen
>> 8) & 0xff;
1096 rs_cdb
->cdb_opaque
[ 9 ] = p_sc
->uscsi_buflen
& 0xff;
1097 p_sc
->uscsi_cdblen
= 12;
1099 USCSI_TIMEOUT( p_sc
, 15 );
1103 #if defined( WIN32 )
1104 /*****************************************************************************
1105 * WinInitSSC: initialize a ssc structure for the win32 aspi layer
1106 *****************************************************************************
1107 * This function initializes a ssc raw device command structure for future
1108 * use, either a read command or a write command.
1109 *****************************************************************************/
1110 static void WinInitSSC( struct SRB_ExecSCSICmd
*p_ssc
, int i_type
)
1112 memset( p_ssc
->SRB_BufPointer
, 0, p_ssc
->SRB_BufLen
);
1116 case GPCMD_SEND_KEY
:
1117 p_ssc
->SRB_Flags
= SRB_DIR_OUT
;
1120 case GPCMD_READ_DVD_STRUCTURE
:
1121 case GPCMD_REPORT_KEY
:
1122 p_ssc
->SRB_Flags
= SRB_DIR_IN
;
1126 p_ssc
->SRB_Cmd
= SC_EXEC_SCSI_CMD
;
1127 p_ssc
->SRB_Flags
|= SRB_EVENT_NOTIFY
;
1129 p_ssc
->CDBByte
[ 0 ] = i_type
;
1131 p_ssc
->CDBByte
[ 8 ] = (u8
)(p_ssc
->SRB_BufLen
>> 8) & 0xff;
1132 p_ssc
->CDBByte
[ 9 ] = (u8
) p_ssc
->SRB_BufLen
& 0xff;
1133 p_ssc
->SRB_CDBLen
= 12;
1135 p_ssc
->SRB_SenseLen
= SENSE_LEN
;
1138 /*****************************************************************************
1139 * WinSendSSC: send a ssc structure to the aspi layer
1140 *****************************************************************************/
1141 static int WinSendSSC( int i_fd
, struct SRB_ExecSCSICmd
*p_ssc
)
1143 HANDLE hEvent
= NULL
;
1144 struct w32_aspidev
*fd
= (struct w32_aspidev
*) i_fd
;
1146 hEvent
= CreateEvent( NULL
, TRUE
, FALSE
, NULL
);
1147 if( hEvent
== NULL
)
1152 p_ssc
->SRB_PostProc
= hEvent
;
1153 p_ssc
->SRB_HaId
= LOBYTE( fd
->i_sid
);
1154 p_ssc
->SRB_Target
= HIBYTE( fd
->i_sid
);
1156 ResetEvent( hEvent
);
1157 if( fd
->lpSendCommand( (void*) p_ssc
) == SS_PENDING
)
1158 WaitForSingleObject( hEvent
, INFINITE
);
1160 CloseHandle( hEvent
);
1162 return p_ssc
->SRB_Status
== SS_COMP
? 0 : -1;