1 /*****************************************************************************
2 * ioctl.c: DVD ioctl replacement function
3 *****************************************************************************
4 * Copyright (C) 1999-2001 VideoLAN
6 * Modified for use with MPlayer, changes contained in libdvdcss_changes.diff.
7 * detailed CVS changelog at http://www.mplayerhq.hu/cgi-bin/cvsweb.cgi/main/
10 * Authors: Markus Kuespert <ltlBeBoy@beosmail.com>
11 * Samuel Hocevar <sam@zoy.org>
12 * Jon Lech Johansen <jon-vl@nanocrew.net>
13 * Håkan Hjort <d95hjort@dtek.chalmers.se>
14 * Eugenio Jarosiewicz <ej0@cise.ufl.edu>
15 * David Siebörger <drs-videolan@rucus.ru.ac.za>
16 * Alex Strelnikov <lelik@os2.ru>
17 * Gildas Bazin <gbazin@netcourrier.com>
19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation; either version 2 of the License, or
22 * (at your option) any later version.
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
29 * You should have received a copy of the GNU General Public License
30 * along with this program; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
32 *****************************************************************************/
34 /*****************************************************************************
36 *****************************************************************************/
41 #include <string.h> /* memcpy(), memset() */
42 #include <sys/types.h>
46 # include <winioctl.h>
47 #elif defined ( SYS_OS2 )
48 # define INCL_DOSFILEMGR
49 # define INCL_DOSDEVICES
50 # define INCL_DOSDEVIOCTL
51 # define INCL_DOSERRORS
53 # include <sys/ioctl.h>
55 # include <netinet/in.h>
56 # include <sys/ioctl.h>
59 #ifdef DVD_STRUCT_IN_SYS_CDIO_H
60 # include <sys/cdio.h>
62 #ifdef DVD_STRUCT_IN_SYS_DVDIO_H
63 # include <sys/dvdio.h>
65 #ifdef DVD_STRUCT_IN_LINUX_CDROM_H
66 # include <linux/cdrom.h>
68 #ifdef DVD_STRUCT_IN_DVD_H
71 #ifdef DVD_STRUCT_IN_BSDI_DVDIOCTL_DVD_H
72 # include "bsdi_dvd.h"
79 # include <sys/scsi.h>
85 # include <sys/scsi/scsi_types.h>
86 # include <sys/scsi/impl/uscsi.h>
88 #ifdef DARWIN_DVD_IOCTL
89 # include <IOKit/storage/IODVDMediaBSDClient.h>
92 # include <sys/mman.h>
93 # include <sys/dcmd_cam.h>
100 /*****************************************************************************
101 * Local prototypes, BeOS specific
102 *****************************************************************************/
103 #if defined( SYS_BEOS )
104 static void BeInitRDC ( raw_device_command
*, int );
107 /*****************************************************************************
108 * Local prototypes, HP-UX specific
109 *****************************************************************************/
110 #if defined( HPUX_SCTL_IO )
111 static void HPUXInitSCTL ( struct sctl_io
*sctl_io
, int i_type
);
114 /*****************************************************************************
115 * Local prototypes, Solaris specific
116 *****************************************************************************/
117 #if defined( SOLARIS_USCSI )
118 static void SolarisInitUSCSI( struct uscsi_cmd
*p_sc
, int i_type
);
119 static int SolarisSendUSCSI( int fd
, struct uscsi_cmd
*p_sc
);
122 /*****************************************************************************
123 * Local prototypes, win32 (aspi) specific
124 *****************************************************************************/
126 static void WinInitSPTD ( SCSI_PASS_THROUGH_DIRECT
*, int );
127 static void WinInitSSC ( struct SRB_ExecSCSICmd
*, int );
128 static int WinSendSSC ( int, struct SRB_ExecSCSICmd
* );
131 /*****************************************************************************
132 * Local prototypes, QNX specific
133 *****************************************************************************/
134 #if defined( __QNXNTO__ )
135 static void QNXInitCPT ( CAM_PASS_THRU
*, int );
138 /*****************************************************************************
139 * Local prototypes, OS2 specific
140 *****************************************************************************/
141 #if defined( SYS_OS2 )
142 static void OS2InitSDC( struct OS2_ExecSCSICmd
*, int );
145 /*****************************************************************************
146 * ioctl_ReadCopyright: check whether the disc is encrypted or not
147 *****************************************************************************/
148 int ioctl_ReadCopyright( int i_fd
, int i_layer
, int *pi_copyright
)
152 #if defined( HAVE_LINUX_DVD_STRUCT )
155 memset( &dvd
, 0, sizeof( dvd
) );
156 dvd
.type
= DVD_STRUCT_COPYRIGHT
;
157 dvd
.copyright
.layer_num
= i_layer
;
159 i_ret
= ioctl( i_fd
, DVD_READ_STRUCT
, &dvd
);
161 *pi_copyright
= dvd
.copyright
.cpst
;
163 #elif defined( HAVE_BSD_DVD_STRUCT )
164 struct dvd_struct dvd
;
166 memset( &dvd
, 0, sizeof( dvd
) );
167 dvd
.format
= DVD_STRUCT_COPYRIGHT
;
168 dvd
.layer_num
= i_layer
;
170 i_ret
= ioctl( i_fd
, DVDIOCREADSTRUCTURE
, &dvd
);
172 *pi_copyright
= dvd
.cpst
;
174 #elif defined( SYS_BEOS )
175 INIT_RDC( GPCMD_READ_DVD_STRUCTURE
, 8 );
177 rdc
.command
[ 6 ] = i_layer
;
178 rdc
.command
[ 7 ] = DVD_STRUCT_COPYRIGHT
;
180 i_ret
= ioctl( i_fd
, B_RAW_DEVICE_COMMAND
, &rdc
, sizeof(rdc
) );
182 *pi_copyright
= p_buffer
[ 4 ];
184 #elif defined( HPUX_SCTL_IO )
185 INIT_SCTL_IO( GPCMD_READ_DVD_STRUCTURE
, 8 );
187 sctl_io
.cdb
[ 6 ] = i_layer
;
188 sctl_io
.cdb
[ 7 ] = DVD_STRUCT_COPYRIGHT
;
190 i_ret
= ioctl( i_fd
, SIOC_IO
, &sctl_io
);
192 *pi_copyright
= p_buffer
[ 4 ];
194 #elif defined( SOLARIS_USCSI )
195 INIT_USCSI( GPCMD_READ_DVD_STRUCTURE
, 8 );
197 rs_cdb
.cdb_opaque
[ 6 ] = i_layer
;
198 rs_cdb
.cdb_opaque
[ 7 ] = DVD_STRUCT_COPYRIGHT
;
200 i_ret
= SolarisSendUSCSI(i_fd
, &sc
);
202 if( i_ret
< 0 || sc
.uscsi_status
) {
206 *pi_copyright
= p_buffer
[ 4 ];
207 /* s->copyright.rmi = p_buffer[ 5 ]; */
209 #elif defined( DARWIN_DVD_IOCTL )
210 INIT_DVDIOCTL( dk_dvd_read_structure_t
, DVDCopyrightInfo
,
211 kDVDStructureFormatCopyrightInfo
);
215 i_ret
= ioctl( i_fd
, DKIOCDVDREADSTRUCTURE
, &dvd
);
217 *pi_copyright
= dvdbs
.copyrightProtectionSystemType
;
219 #elif defined( WIN32 )
220 if( WIN2K
) /* NT/2k/XP */
222 INIT_SPTD( GPCMD_READ_DVD_STRUCTURE
, 8 );
224 /* When using IOCTL_DVD_READ_STRUCTURE and
225 DVD_COPYRIGHT_DESCRIPTOR, CopyrightProtectionType
226 seems to be always 6 ???
227 To work around this MS bug we try to send a raw scsi command
228 instead (if we've got enough privileges to do so). */
230 sptd
.Cdb
[ 6 ] = i_layer
;
231 sptd
.Cdb
[ 7 ] = DVD_STRUCT_COPYRIGHT
;
233 i_ret
= SEND_SPTD( i_fd
, &sptd
, &tmp
);
237 *pi_copyright
= p_buffer
[ 4 ];
242 INIT_SSC( GPCMD_READ_DVD_STRUCTURE
, 8 );
244 ssc
.CDBByte
[ 6 ] = i_layer
;
245 ssc
.CDBByte
[ 7 ] = DVD_STRUCT_COPYRIGHT
;
247 i_ret
= WinSendSSC( i_fd
, &ssc
);
249 *pi_copyright
= p_buffer
[ 4 ];
252 #elif defined( __QNXNTO__ )
254 INIT_CPT( GPCMD_READ_DVD_STRUCTURE
, 8 );
256 p_cpt
->cam_cdb
[ 6 ] = i_layer
;
257 p_cpt
->cam_cdb
[ 7 ] = DVD_STRUCT_COPYRIGHT
;
259 i_ret
= devctl(i_fd
, DCMD_CAM_PASS_THRU
, p_cpt
, structSize
, NULL
);
261 *pi_copyright
= p_buffer
[4];
263 #elif defined( SYS_OS2 )
264 INIT_SSC( GPCMD_READ_DVD_STRUCTURE
, 8 );
266 sdc
.command
[ 6 ] = i_layer
;
267 sdc
.command
[ 7 ] = DVD_STRUCT_COPYRIGHT
;
269 i_ret
= DosDevIOCtl(i_fd
, IOCTL_CDROMDISK
, CDROMDISK_EXECMD
,
270 &sdc
, sizeof(sdc
), &ulParamLen
,
271 p_buffer
, sizeof(p_buffer
), &ulDataLen
);
273 *pi_copyright
= p_buffer
[ 4 ];
276 # error "DVD ioctls are unavailable on this system"
282 /*****************************************************************************
283 * ioctl_ReadDiscKey: get the disc key
284 *****************************************************************************/
285 int ioctl_ReadDiscKey( int i_fd
, int *pi_agid
, uint8_t *p_key
)
289 #if defined( HAVE_LINUX_DVD_STRUCT )
292 memset( &dvd
, 0, sizeof( dvd
) );
293 dvd
.type
= DVD_STRUCT_DISCKEY
;
294 dvd
.disckey
.agid
= *pi_agid
;
295 memset( dvd
.disckey
.value
, 0, DVD_DISCKEY_SIZE
);
297 i_ret
= ioctl( i_fd
, DVD_READ_STRUCT
, &dvd
);
304 memcpy( p_key
, dvd
.disckey
.value
, DVD_DISCKEY_SIZE
);
306 #elif defined( HAVE_BSD_DVD_STRUCT )
307 struct dvd_struct dvd
;
309 memset( &dvd
, 0, sizeof( dvd
) );
310 dvd
.format
= DVD_STRUCT_DISCKEY
;
312 memset( dvd
.data
, 0, DVD_DISCKEY_SIZE
);
314 i_ret
= ioctl( i_fd
, DVDIOCREADSTRUCTURE
, &dvd
);
321 memcpy( p_key
, dvd
.data
, DVD_DISCKEY_SIZE
);
323 #elif defined( SYS_BEOS )
324 INIT_RDC( GPCMD_READ_DVD_STRUCTURE
, DVD_DISCKEY_SIZE
+ 4 );
326 rdc
.command
[ 7 ] = DVD_STRUCT_DISCKEY
;
327 rdc
.command
[ 10 ] = *pi_agid
<< 6;
329 i_ret
= ioctl( i_fd
, B_RAW_DEVICE_COMMAND
, &rdc
, sizeof(rdc
) );
336 memcpy( p_key
, p_buffer
+ 4, DVD_DISCKEY_SIZE
);
338 #elif defined( HPUX_SCTL_IO )
339 INIT_SCTL_IO( GPCMD_READ_DVD_STRUCTURE
, DVD_DISCKEY_SIZE
+ 4 );
341 sctl_io
.cdb
[ 7 ] = DVD_STRUCT_DISCKEY
;
342 sctl_io
.cdb
[ 10 ] = *pi_agid
<< 6;
344 i_ret
= ioctl( i_fd
, SIOC_IO
, &sctl_io
);
351 memcpy( p_key
, p_buffer
+ 4, DVD_DISCKEY_SIZE
);
353 #elif defined( SOLARIS_USCSI )
354 INIT_USCSI( GPCMD_READ_DVD_STRUCTURE
, DVD_DISCKEY_SIZE
+ 4 );
356 rs_cdb
.cdb_opaque
[ 7 ] = DVD_STRUCT_DISCKEY
;
357 rs_cdb
.cdb_opaque
[ 10 ] = *pi_agid
<< 6;
359 i_ret
= SolarisSendUSCSI( i_fd
, &sc
);
361 if( i_ret
< 0 || sc
.uscsi_status
)
367 memcpy( p_key
, p_buffer
+ 4, DVD_DISCKEY_SIZE
);
369 #elif defined( DARWIN_DVD_IOCTL )
370 INIT_DVDIOCTL( dk_dvd_read_structure_t
, DVDDiscKeyInfo
,
371 kDVDStructureFormatDiscKeyInfo
);
373 dvd
.grantID
= *pi_agid
;
375 i_ret
= ioctl( i_fd
, DKIOCDVDREADSTRUCTURE
, &dvd
);
377 memcpy( p_key
, dvdbs
.discKeyStructures
, DVD_DISCKEY_SIZE
);
379 #elif defined( WIN32 )
380 if( WIN2K
) /* NT/2k/XP */
383 uint8_t buffer
[DVD_DISK_KEY_LENGTH
];
384 PDVD_COPY_PROTECT_KEY key
= (PDVD_COPY_PROTECT_KEY
) &buffer
;
386 memset( &buffer
, 0, sizeof( buffer
) );
388 key
->KeyLength
= DVD_DISK_KEY_LENGTH
;
389 key
->SessionId
= *pi_agid
;
390 key
->KeyType
= DvdDiskKey
;
393 i_ret
= DeviceIoControl( (HANDLE
) i_fd
, IOCTL_DVD_READ_KEY
, key
,
394 key
->KeyLength
, key
, key
->KeyLength
, &tmp
, NULL
) ? 0 : -1;
401 memcpy( p_key
, key
->KeyData
, DVD_DISCKEY_SIZE
);
405 INIT_SSC( GPCMD_READ_DVD_STRUCTURE
, DVD_DISCKEY_SIZE
+ 4 );
407 ssc
.CDBByte
[ 7 ] = DVD_STRUCT_DISCKEY
;
408 ssc
.CDBByte
[ 10 ] = *pi_agid
<< 6;
410 i_ret
= WinSendSSC( i_fd
, &ssc
);
417 memcpy( p_key
, p_buffer
+ 4, DVD_DISCKEY_SIZE
);
420 #elif defined( __QNXNTO__ )
422 INIT_CPT( GPCMD_READ_DVD_STRUCTURE
, DVD_DISCKEY_SIZE
+ 4 );
424 p_cpt
->cam_cdb
[ 7 ] = DVD_STRUCT_DISCKEY
;
425 p_cpt
->cam_cdb
[ 10 ] = *pi_agid
<< 6;
427 i_ret
= devctl(i_fd
, DCMD_CAM_PASS_THRU
, p_cpt
, structSize
, NULL
);
429 memcpy( p_key
, p_buffer
+ 4, DVD_DISCKEY_SIZE
);
431 #elif defined ( SYS_OS2 )
432 INIT_SSC( GPCMD_READ_DVD_STRUCTURE
, DVD_DISCKEY_SIZE
+ 4 );
434 sdc
.command
[ 7 ] = DVD_STRUCT_DISCKEY
;
435 sdc
.command
[ 10 ] = *pi_agid
<< 6;
437 i_ret
= DosDevIOCtl(i_fd
, IOCTL_CDROMDISK
, CDROMDISK_EXECMD
,
438 &sdc
, sizeof(sdc
), &ulParamLen
,
439 p_buffer
, sizeof(p_buffer
), &ulDataLen
);
446 memcpy( p_key
, p_buffer
+ 4, DVD_DISCKEY_SIZE
);
449 # error "DVD ioctls are unavailable on this system"
455 /*****************************************************************************
456 * ioctl_ReadTitleKey: get the title key
457 *****************************************************************************/
458 int ioctl_ReadTitleKey( int i_fd
, int *pi_agid
, int i_pos
, uint8_t *p_key
)
462 #if defined( HAVE_LINUX_DVD_STRUCT )
463 dvd_authinfo auth_info
;
465 memset( &auth_info
, 0, sizeof( auth_info
) );
466 auth_info
.type
= DVD_LU_SEND_TITLE_KEY
;
467 auth_info
.lstk
.agid
= *pi_agid
;
468 auth_info
.lstk
.lba
= i_pos
;
470 i_ret
= ioctl( i_fd
, DVD_AUTH
, &auth_info
);
472 memcpy( p_key
, auth_info
.lstk
.title_key
, DVD_KEY_SIZE
);
474 #elif defined( HAVE_BSD_DVD_STRUCT )
475 struct dvd_authinfo auth_info
;
477 memset( &auth_info
, 0, sizeof( auth_info
) );
478 auth_info
.format
= DVD_REPORT_TITLE_KEY
;
479 auth_info
.agid
= *pi_agid
;
480 auth_info
.lba
= i_pos
;
482 i_ret
= ioctl( i_fd
, DVDIOCREPORTKEY
, &auth_info
);
484 memcpy( p_key
, auth_info
.keychal
, DVD_KEY_SIZE
);
486 #elif defined( SYS_BEOS )
487 INIT_RDC( GPCMD_REPORT_KEY
, 12 );
489 rdc
.command
[ 2 ] = ( i_pos
>> 24 ) & 0xff;
490 rdc
.command
[ 3 ] = ( i_pos
>> 16 ) & 0xff;
491 rdc
.command
[ 4 ] = ( i_pos
>> 8 ) & 0xff;
492 rdc
.command
[ 5 ] = ( i_pos
) & 0xff;
493 rdc
.command
[ 10 ] = DVD_REPORT_TITLE_KEY
| (*pi_agid
<< 6);
495 i_ret
= ioctl( i_fd
, B_RAW_DEVICE_COMMAND
, &rdc
, sizeof(rdc
) );
497 memcpy( p_key
, p_buffer
+ 5, DVD_KEY_SIZE
);
499 #elif defined( HPUX_SCTL_IO )
500 INIT_SCTL_IO( GPCMD_REPORT_KEY
, 12 );
502 sctl_io
.cdb
[ 2 ] = ( i_pos
>> 24 ) & 0xff;
503 sctl_io
.cdb
[ 3 ] = ( i_pos
>> 16 ) & 0xff;
504 sctl_io
.cdb
[ 4 ] = ( i_pos
>> 8 ) & 0xff;
505 sctl_io
.cdb
[ 5 ] = ( i_pos
) & 0xff;
506 sctl_io
.cdb
[ 10 ] = DVD_REPORT_TITLE_KEY
| (*pi_agid
<< 6);
508 i_ret
= ioctl( i_fd
, SIOC_IO
, &sctl_io
);
510 memcpy( p_key
, p_buffer
+ 5, DVD_KEY_SIZE
);
512 #elif defined( SOLARIS_USCSI )
513 INIT_USCSI( GPCMD_REPORT_KEY
, 12 );
515 rs_cdb
.cdb_opaque
[ 2 ] = ( i_pos
>> 24 ) & 0xff;
516 rs_cdb
.cdb_opaque
[ 3 ] = ( i_pos
>> 16 ) & 0xff;
517 rs_cdb
.cdb_opaque
[ 4 ] = ( i_pos
>> 8 ) & 0xff;
518 rs_cdb
.cdb_opaque
[ 5 ] = ( i_pos
) & 0xff;
519 rs_cdb
.cdb_opaque
[ 10 ] = DVD_REPORT_TITLE_KEY
| (*pi_agid
<< 6);
521 i_ret
= SolarisSendUSCSI( i_fd
, &sc
);
523 if( i_ret
< 0 || sc
.uscsi_status
)
528 /* Do we want to return the cp_sec flag perhaps? */
529 /* a->lstk.cpm = (buf[ 4 ] >> 7) & 1; */
530 /* a->lstk.cp_sec = (buf[ 4 ] >> 6) & 1; */
531 /* a->lstk.cgms = (buf[ 4 ] >> 4) & 3; */
533 memcpy( p_key
, p_buffer
+ 5, DVD_KEY_SIZE
);
535 #elif defined( DARWIN_DVD_IOCTL )
536 INIT_DVDIOCTL( dk_dvd_report_key_t
, DVDTitleKeyInfo
,
537 kDVDKeyFormatTitleKey
);
540 dvd
.grantID
= *pi_agid
;
541 dvd
.keyClass
= kDVDKeyClassCSS_CPPM_CPRM
;
543 i_ret
= ioctl( i_fd
, DKIOCDVDREPORTKEY
, &dvd
);
545 memcpy( p_key
, dvdbs
.titleKeyValue
, DVD_KEY_SIZE
);
547 #elif defined( WIN32 )
548 if( WIN2K
) /* NT/2k/XP */
551 uint8_t buffer
[DVD_TITLE_KEY_LENGTH
];
552 PDVD_COPY_PROTECT_KEY key
= (PDVD_COPY_PROTECT_KEY
) &buffer
;
554 memset( &buffer
, 0, sizeof( buffer
) );
556 key
->KeyLength
= DVD_TITLE_KEY_LENGTH
;
557 key
->SessionId
= *pi_agid
;
558 key
->KeyType
= DvdTitleKey
;
560 key
->Parameters
.TitleOffset
.QuadPart
= (LONGLONG
) i_pos
*
561 2048 /*DVDCSS_BLOCK_SIZE*/;
563 i_ret
= DeviceIoControl( (HANDLE
) i_fd
, IOCTL_DVD_READ_KEY
, key
,
564 key
->KeyLength
, key
, key
->KeyLength
, &tmp
, NULL
) ? 0 : -1;
566 memcpy( p_key
, key
->KeyData
, DVD_KEY_SIZE
);
570 INIT_SSC( GPCMD_REPORT_KEY
, 12 );
572 ssc
.CDBByte
[ 2 ] = ( i_pos
>> 24 ) & 0xff;
573 ssc
.CDBByte
[ 3 ] = ( i_pos
>> 16 ) & 0xff;
574 ssc
.CDBByte
[ 4 ] = ( i_pos
>> 8 ) & 0xff;
575 ssc
.CDBByte
[ 5 ] = ( i_pos
) & 0xff;
576 ssc
.CDBByte
[ 10 ] = DVD_REPORT_TITLE_KEY
| (*pi_agid
<< 6);
578 i_ret
= WinSendSSC( i_fd
, &ssc
);
580 memcpy( p_key
, p_buffer
+ 5, DVD_KEY_SIZE
);
583 #elif defined( __QNXNTO__ )
585 INIT_CPT( GPCMD_REPORT_KEY
, 12 );
587 p_cpt
->cam_cdb
[ 2 ] = ( i_pos
>> 24 ) & 0xff;
588 p_cpt
->cam_cdb
[ 3 ] = ( i_pos
>> 16 ) & 0xff;
589 p_cpt
->cam_cdb
[ 4 ] = ( i_pos
>> 8 ) & 0xff;
590 p_cpt
->cam_cdb
[ 5 ] = ( i_pos
) & 0xff;
591 p_cpt
->cam_cdb
[ 10 ] = DVD_REPORT_TITLE_KEY
| (*pi_agid
<< 6);
593 i_ret
= devctl(i_fd
, DCMD_CAM_PASS_THRU
, p_cpt
, structSize
, NULL
);
595 memcpy( p_key
, p_buffer
+ 5, DVD_KEY_SIZE
);
597 #elif defined( SYS_OS2 )
598 INIT_SSC( GPCMD_REPORT_KEY
, 12 );
600 sdc
.command
[ 2 ] = ( i_pos
>> 24 ) & 0xff;
601 sdc
.command
[ 3 ] = ( i_pos
>> 16 ) & 0xff;
602 sdc
.command
[ 4 ] = ( i_pos
>> 8 ) & 0xff;
603 sdc
.command
[ 5 ] = ( i_pos
) & 0xff;
604 sdc
.command
[ 10 ] = DVD_REPORT_TITLE_KEY
| (*pi_agid
<< 6);
606 i_ret
= DosDevIOCtl(i_fd
, IOCTL_CDROMDISK
, CDROMDISK_EXECMD
,
607 &sdc
, sizeof(sdc
), &ulParamLen
,
608 p_buffer
, sizeof(p_buffer
), &ulDataLen
);
610 memcpy( p_key
, p_buffer
+ 5, DVD_KEY_SIZE
);
613 # error "DVD ioctls are unavailable on this system"
621 /*****************************************************************************
622 * ioctl_ReportAgid: get AGID from the drive
623 *****************************************************************************/
624 int ioctl_ReportAgid( int i_fd
, int *pi_agid
)
628 #if defined( HAVE_LINUX_DVD_STRUCT )
629 dvd_authinfo auth_info
;
631 memset( &auth_info
, 0, sizeof( auth_info
) );
632 auth_info
.type
= DVD_LU_SEND_AGID
;
633 auth_info
.lsa
.agid
= *pi_agid
;
635 i_ret
= ioctl( i_fd
, DVD_AUTH
, &auth_info
);
637 *pi_agid
= auth_info
.lsa
.agid
;
639 #elif defined( HAVE_BSD_DVD_STRUCT )
640 struct dvd_authinfo auth_info
;
642 memset( &auth_info
, 0, sizeof( auth_info
) );
643 auth_info
.format
= DVD_REPORT_AGID
;
644 auth_info
.agid
= *pi_agid
;
646 i_ret
= ioctl( i_fd
, DVDIOCREPORTKEY
, &auth_info
);
648 *pi_agid
= auth_info
.agid
;
650 #elif defined( SYS_BEOS )
651 INIT_RDC( GPCMD_REPORT_KEY
, 8 );
653 rdc
.command
[ 10 ] = DVD_REPORT_AGID
| (*pi_agid
<< 6);
655 i_ret
= ioctl( i_fd
, B_RAW_DEVICE_COMMAND
, &rdc
, sizeof(rdc
) );
657 *pi_agid
= p_buffer
[ 7 ] >> 6;
659 #elif defined( HPUX_SCTL_IO )
660 INIT_SCTL_IO( GPCMD_REPORT_KEY
, 8 );
662 sctl_io
.cdb
[ 10 ] = DVD_REPORT_AGID
| (*pi_agid
<< 6);
664 i_ret
= ioctl( i_fd
, SIOC_IO
, &sctl_io
);
666 *pi_agid
= p_buffer
[ 7 ] >> 6;
668 #elif defined( SOLARIS_USCSI )
669 INIT_USCSI( GPCMD_REPORT_KEY
, 8 );
671 rs_cdb
.cdb_opaque
[ 10 ] = DVD_REPORT_AGID
| (*pi_agid
<< 6);
673 i_ret
= SolarisSendUSCSI( i_fd
, &sc
);
675 if( i_ret
< 0 || sc
.uscsi_status
)
680 *pi_agid
= p_buffer
[ 7 ] >> 6;
682 #elif defined( DARWIN_DVD_IOCTL )
683 INIT_DVDIOCTL( dk_dvd_report_key_t
, DVDAuthenticationGrantIDInfo
,
684 kDVDKeyFormatAGID_CSS
);
686 dvd
.grantID
= *pi_agid
;
687 dvd
.keyClass
= kDVDKeyClassCSS_CPPM_CPRM
;
689 i_ret
= ioctl( i_fd
, DKIOCDVDREPORTKEY
, &dvd
);
691 *pi_agid
= dvdbs
.grantID
;
693 #elif defined( WIN32 )
694 if( WIN2K
) /* NT/2k/XP */
699 i_ret
= DeviceIoControl( (HANDLE
) i_fd
, IOCTL_DVD_START_SESSION
,
700 &tmp
, 4, &id
, sizeof( id
), &tmp
, NULL
) ? 0 : -1;
706 INIT_SSC( GPCMD_REPORT_KEY
, 8 );
708 ssc
.CDBByte
[ 10 ] = DVD_REPORT_AGID
| (*pi_agid
<< 6);
710 i_ret
= WinSendSSC( i_fd
, &ssc
);
712 *pi_agid
= p_buffer
[ 7 ] >> 6;
715 #elif defined( __QNXNTO__ )
717 INIT_CPT( GPCMD_REPORT_KEY
, 8 );
719 p_cpt
->cam_cdb
[ 10 ] = DVD_REPORT_AGID
| (*pi_agid
<< 6);
721 i_ret
= devctl(i_fd
, DCMD_CAM_PASS_THRU
, p_cpt
, structSize
, NULL
);
723 *pi_agid
= p_buffer
[ 7 ] >> 6;
725 #elif defined( SYS_OS2 )
726 INIT_SSC( GPCMD_REPORT_KEY
, 8 );
728 sdc
.command
[ 10 ] = DVD_REPORT_AGID
| (*pi_agid
<< 6);
730 i_ret
= DosDevIOCtl(i_fd
, IOCTL_CDROMDISK
, CDROMDISK_EXECMD
,
731 &sdc
, sizeof(sdc
), &ulParamLen
,
732 p_buffer
, sizeof(p_buffer
), &ulDataLen
);
734 *pi_agid
= p_buffer
[ 7 ] >> 6;
737 # error "DVD ioctls are unavailable on this system"
743 /*****************************************************************************
744 * ioctl_ReportChallenge: get challenge from the drive
745 *****************************************************************************/
746 int ioctl_ReportChallenge( int i_fd
, int *pi_agid
, uint8_t *p_challenge
)
750 #if defined( HAVE_LINUX_DVD_STRUCT )
751 dvd_authinfo auth_info
;
753 memset( &auth_info
, 0, sizeof( auth_info
) );
754 auth_info
.type
= DVD_LU_SEND_CHALLENGE
;
755 auth_info
.lsc
.agid
= *pi_agid
;
757 i_ret
= ioctl( i_fd
, DVD_AUTH
, &auth_info
);
759 memcpy( p_challenge
, auth_info
.lsc
.chal
, DVD_CHALLENGE_SIZE
);
761 #elif defined( HAVE_BSD_DVD_STRUCT )
762 struct dvd_authinfo auth_info
;
764 memset( &auth_info
, 0, sizeof( auth_info
) );
765 auth_info
.format
= DVD_REPORT_CHALLENGE
;
766 auth_info
.agid
= *pi_agid
;
768 i_ret
= ioctl( i_fd
, DVDIOCREPORTKEY
, &auth_info
);
770 memcpy( p_challenge
, auth_info
.keychal
, DVD_CHALLENGE_SIZE
);
772 #elif defined( SYS_BEOS )
773 INIT_RDC( GPCMD_REPORT_KEY
, 16 );
775 rdc
.command
[ 10 ] = DVD_REPORT_CHALLENGE
| (*pi_agid
<< 6);
777 i_ret
= ioctl( i_fd
, B_RAW_DEVICE_COMMAND
, &rdc
, sizeof(rdc
) );
779 memcpy( p_challenge
, p_buffer
+ 4, DVD_CHALLENGE_SIZE
);
781 #elif defined( HPUX_SCTL_IO )
782 INIT_SCTL_IO( GPCMD_REPORT_KEY
, 16 );
784 sctl_io
.cdb
[ 10 ] = DVD_REPORT_CHALLENGE
| (*pi_agid
<< 6);
786 i_ret
= ioctl( i_fd
, SIOC_IO
, &sctl_io
);
788 memcpy( p_challenge
, p_buffer
+ 4, DVD_CHALLENGE_SIZE
);
790 #elif defined( SOLARIS_USCSI )
791 INIT_USCSI( GPCMD_REPORT_KEY
, 16 );
793 rs_cdb
.cdb_opaque
[ 10 ] = DVD_REPORT_CHALLENGE
| (*pi_agid
<< 6);
795 i_ret
= SolarisSendUSCSI( i_fd
, &sc
);
797 if( i_ret
< 0 || sc
.uscsi_status
)
802 memcpy( p_challenge
, p_buffer
+ 4, DVD_CHALLENGE_SIZE
);
804 #elif defined( DARWIN_DVD_IOCTL )
805 INIT_DVDIOCTL( dk_dvd_report_key_t
, DVDChallengeKeyInfo
,
806 kDVDKeyFormatChallengeKey
);
808 dvd
.grantID
= *pi_agid
;
810 i_ret
= ioctl( i_fd
, DKIOCDVDREPORTKEY
, &dvd
);
812 memcpy( p_challenge
, dvdbs
.challengeKeyValue
, DVD_CHALLENGE_SIZE
);
814 #elif defined( WIN32 )
815 if( WIN2K
) /* NT/2k/XP */
818 uint8_t buffer
[DVD_CHALLENGE_KEY_LENGTH
];
819 PDVD_COPY_PROTECT_KEY key
= (PDVD_COPY_PROTECT_KEY
) &buffer
;
821 memset( &buffer
, 0, sizeof( buffer
) );
823 key
->KeyLength
= DVD_CHALLENGE_KEY_LENGTH
;
824 key
->SessionId
= *pi_agid
;
825 key
->KeyType
= DvdChallengeKey
;
828 i_ret
= DeviceIoControl( (HANDLE
) i_fd
, IOCTL_DVD_READ_KEY
, key
,
829 key
->KeyLength
, key
, key
->KeyLength
, &tmp
, NULL
) ? 0 : -1;
836 memcpy( p_challenge
, key
->KeyData
, DVD_CHALLENGE_SIZE
);
840 INIT_SSC( GPCMD_REPORT_KEY
, 16 );
842 ssc
.CDBByte
[ 10 ] = DVD_REPORT_CHALLENGE
| (*pi_agid
<< 6);
844 i_ret
= WinSendSSC( i_fd
, &ssc
);
846 memcpy( p_challenge
, p_buffer
+ 4, DVD_CHALLENGE_SIZE
);
849 #elif defined( __QNXNTO__ )
851 INIT_CPT( GPCMD_REPORT_KEY
, 16 );
853 p_cpt
->cam_cdb
[ 10 ] = DVD_REPORT_CHALLENGE
| (*pi_agid
<< 6);
855 i_ret
= devctl(i_fd
, DCMD_CAM_PASS_THRU
, p_cpt
, structSize
, NULL
);
857 memcpy( p_challenge
, p_buffer
+ 4, DVD_CHALLENGE_SIZE
);
859 #elif defined( SYS_OS2 )
860 INIT_SSC( GPCMD_REPORT_KEY
, 16 );
862 sdc
.command
[ 10 ] = DVD_REPORT_CHALLENGE
| (*pi_agid
<< 6);
864 i_ret
= DosDevIOCtl(i_fd
, IOCTL_CDROMDISK
, CDROMDISK_EXECMD
,
865 &sdc
, sizeof(sdc
), &ulParamLen
,
866 p_buffer
, sizeof(p_buffer
), &ulDataLen
);
868 memcpy( p_challenge
, p_buffer
+ 4, DVD_CHALLENGE_SIZE
);
871 # error "DVD ioctls are unavailable on this system"
877 /*****************************************************************************
878 * ioctl_ReportASF: get ASF from the drive
879 *****************************************************************************/
880 int ioctl_ReportASF( int i_fd
, int *pi_remove_me
, int *pi_asf
)
884 #if defined( HAVE_LINUX_DVD_STRUCT )
885 dvd_authinfo auth_info
;
887 memset( &auth_info
, 0, sizeof( auth_info
) );
888 auth_info
.type
= DVD_LU_SEND_ASF
;
889 auth_info
.lsasf
.asf
= *pi_asf
;
891 i_ret
= ioctl( i_fd
, DVD_AUTH
, &auth_info
);
893 *pi_asf
= auth_info
.lsasf
.asf
;
895 #elif defined( HAVE_BSD_DVD_STRUCT )
896 struct dvd_authinfo auth_info
;
898 memset( &auth_info
, 0, sizeof( auth_info
) );
899 auth_info
.format
= DVD_REPORT_ASF
;
900 auth_info
.asf
= *pi_asf
;
902 i_ret
= ioctl( i_fd
, DVDIOCREPORTKEY
, &auth_info
);
904 *pi_asf
= auth_info
.asf
;
906 #elif defined( SYS_BEOS )
907 INIT_RDC( GPCMD_REPORT_KEY
, 8 );
909 rdc
.command
[ 10 ] = DVD_REPORT_ASF
;
911 i_ret
= ioctl( i_fd
, B_RAW_DEVICE_COMMAND
, &rdc
, sizeof(rdc
) );
913 *pi_asf
= p_buffer
[ 7 ] & 1;
915 #elif defined( HPUX_SCTL_IO )
916 INIT_SCTL_IO( GPCMD_REPORT_KEY
, 8 );
918 sctl_io
.cdb
[ 10 ] = DVD_REPORT_ASF
;
920 i_ret
= ioctl( i_fd
, SIOC_IO
, &sctl_io
);
922 *pi_asf
= p_buffer
[ 7 ] & 1;
924 #elif defined( SOLARIS_USCSI )
925 INIT_USCSI( GPCMD_REPORT_KEY
, 8 );
927 rs_cdb
.cdb_opaque
[ 10 ] = DVD_REPORT_ASF
;
929 i_ret
= SolarisSendUSCSI( i_fd
, &sc
);
931 if( i_ret
< 0 || sc
.uscsi_status
)
936 *pi_asf
= p_buffer
[ 7 ] & 1;
938 #elif defined( DARWIN_DVD_IOCTL )
939 INIT_DVDIOCTL( dk_dvd_report_key_t
, DVDAuthenticationSuccessFlagInfo
,
942 i_ret
= ioctl( i_fd
, DKIOCDVDREPORTKEY
, &dvd
);
944 *pi_asf
= dvdbs
.successFlag
;
946 #elif defined( WIN32 )
947 if( WIN2K
) /* NT/2k/XP */
950 uint8_t buffer
[DVD_ASF_LENGTH
];
951 PDVD_COPY_PROTECT_KEY key
= (PDVD_COPY_PROTECT_KEY
) &buffer
;
953 memset( &buffer
, 0, sizeof( buffer
) );
955 key
->KeyLength
= DVD_ASF_LENGTH
;
956 key
->KeyType
= DvdAsf
;
959 ((PDVD_ASF
)key
->KeyData
)->SuccessFlag
= *pi_asf
;
961 i_ret
= DeviceIoControl( (HANDLE
) i_fd
, IOCTL_DVD_READ_KEY
, key
,
962 key
->KeyLength
, key
, key
->KeyLength
, &tmp
, NULL
) ? 0 : -1;
969 *pi_asf
= ((PDVD_ASF
)key
->KeyData
)->SuccessFlag
;
973 INIT_SSC( GPCMD_REPORT_KEY
, 8 );
975 ssc
.CDBByte
[ 10 ] = DVD_REPORT_ASF
;
977 i_ret
= WinSendSSC( i_fd
, &ssc
);
979 *pi_asf
= p_buffer
[ 7 ] & 1;
982 #elif defined( __QNXNTO__ )
984 INIT_CPT( GPCMD_REPORT_KEY
, 8 );
986 p_cpt
->cam_cdb
[ 10 ] = DVD_REPORT_ASF
;
988 i_ret
= devctl(i_fd
, DCMD_CAM_PASS_THRU
, p_cpt
, structSize
, NULL
);
990 *pi_asf
= p_buffer
[ 7 ] & 1;
992 #elif defined( SYS_OS2 )
993 INIT_SSC( GPCMD_REPORT_KEY
, 8 );
995 sdc
.command
[ 10 ] = DVD_REPORT_ASF
;
997 i_ret
= DosDevIOCtl(i_fd
, IOCTL_CDROMDISK
, CDROMDISK_EXECMD
,
998 &sdc
, sizeof(sdc
), &ulParamLen
,
999 p_buffer
, sizeof(p_buffer
), &ulDataLen
);
1001 *pi_asf
= p_buffer
[ 7 ] & 1;
1004 # error "DVD ioctls are unavailable on this system"
1010 /*****************************************************************************
1011 * ioctl_ReportKey1: get the first key from the drive
1012 *****************************************************************************/
1013 int ioctl_ReportKey1( int i_fd
, int *pi_agid
, uint8_t *p_key
)
1017 #if defined( HAVE_LINUX_DVD_STRUCT )
1018 dvd_authinfo auth_info
;
1020 memset( &auth_info
, 0, sizeof( auth_info
) );
1021 auth_info
.type
= DVD_LU_SEND_KEY1
;
1022 auth_info
.lsk
.agid
= *pi_agid
;
1024 i_ret
= ioctl( i_fd
, DVD_AUTH
, &auth_info
);
1026 memcpy( p_key
, auth_info
.lsk
.key
, DVD_KEY_SIZE
);
1028 #elif defined( HAVE_BSD_DVD_STRUCT )
1029 struct dvd_authinfo auth_info
;
1031 memset( &auth_info
, 0, sizeof( auth_info
) );
1032 auth_info
.format
= DVD_REPORT_KEY1
;
1033 auth_info
.agid
= *pi_agid
;
1035 i_ret
= ioctl( i_fd
, DVDIOCREPORTKEY
, &auth_info
);
1037 memcpy( p_key
, auth_info
.keychal
, DVD_KEY_SIZE
);
1039 #elif defined( SYS_BEOS )
1040 INIT_RDC( GPCMD_REPORT_KEY
, 12 );
1042 rdc
.command
[ 10 ] = DVD_REPORT_KEY1
| (*pi_agid
<< 6);
1044 i_ret
= ioctl( i_fd
, B_RAW_DEVICE_COMMAND
, &rdc
, sizeof(rdc
) );
1046 memcpy( p_key
, p_buffer
+ 4, DVD_KEY_SIZE
);
1048 #elif defined( HPUX_SCTL_IO )
1049 INIT_SCTL_IO( GPCMD_REPORT_KEY
, 12 );
1051 sctl_io
.cdb
[ 10 ] = DVD_REPORT_KEY1
| (*pi_agid
<< 6);
1053 i_ret
= ioctl( i_fd
, SIOC_IO
, &sctl_io
);
1055 memcpy( p_key
, p_buffer
+ 4, DVD_KEY_SIZE
);
1057 #elif defined( SOLARIS_USCSI )
1058 INIT_USCSI( GPCMD_REPORT_KEY
, 12 );
1060 rs_cdb
.cdb_opaque
[ 10 ] = DVD_REPORT_KEY1
| (*pi_agid
<< 6);
1062 i_ret
= SolarisSendUSCSI( i_fd
, &sc
);
1064 if( i_ret
< 0 || sc
.uscsi_status
)
1069 memcpy( p_key
, p_buffer
+ 4, DVD_KEY_SIZE
);
1071 #elif defined( DARWIN_DVD_IOCTL )
1072 INIT_DVDIOCTL( dk_dvd_report_key_t
, DVDKey1Info
,
1073 kDVDKeyFormatKey1
);
1075 dvd
.grantID
= *pi_agid
;
1077 i_ret
= ioctl( i_fd
, DKIOCDVDREPORTKEY
, &dvd
);
1079 memcpy( p_key
, dvdbs
.key1Value
, DVD_KEY_SIZE
);
1081 #elif defined( WIN32 )
1082 if( WIN2K
) /* NT/2k/XP */
1085 uint8_t buffer
[DVD_BUS_KEY_LENGTH
];
1086 PDVD_COPY_PROTECT_KEY key
= (PDVD_COPY_PROTECT_KEY
) &buffer
;
1088 memset( &buffer
, 0, sizeof( buffer
) );
1090 key
->KeyLength
= DVD_BUS_KEY_LENGTH
;
1091 key
->SessionId
= *pi_agid
;
1092 key
->KeyType
= DvdBusKey1
;
1095 i_ret
= DeviceIoControl( (HANDLE
) i_fd
, IOCTL_DVD_READ_KEY
, key
,
1096 key
->KeyLength
, key
, key
->KeyLength
, &tmp
, NULL
) ? 0 : -1;
1098 memcpy( p_key
, key
->KeyData
, DVD_KEY_SIZE
);
1102 INIT_SSC( GPCMD_REPORT_KEY
, 12 );
1104 ssc
.CDBByte
[ 10 ] = DVD_REPORT_KEY1
| (*pi_agid
<< 6);
1106 i_ret
= WinSendSSC( i_fd
, &ssc
);
1108 memcpy( p_key
, p_buffer
+ 4, DVD_KEY_SIZE
);
1111 #elif defined( __QNXNTO__ )
1113 INIT_CPT( GPCMD_REPORT_KEY
, 12 );
1115 p_cpt
->cam_cdb
[ 10 ] = DVD_REPORT_KEY1
| (*pi_agid
<< 6);
1117 i_ret
= devctl(i_fd
, DCMD_CAM_PASS_THRU
, p_cpt
, structSize
, NULL
);
1119 memcpy( p_key
, p_buffer
+ 4, DVD_KEY_SIZE
);
1121 #elif defined( SYS_OS2 )
1122 INIT_SSC( GPCMD_REPORT_KEY
, 12 );
1124 sdc
.command
[ 10 ] = DVD_REPORT_KEY1
| (*pi_agid
<< 6);
1126 i_ret
= DosDevIOCtl(i_fd
, IOCTL_CDROMDISK
, CDROMDISK_EXECMD
,
1127 &sdc
, sizeof(sdc
), &ulParamLen
,
1128 p_buffer
, sizeof(p_buffer
), &ulDataLen
);
1130 memcpy( p_key
, p_buffer
+ 4, DVD_KEY_SIZE
);
1133 # error "DVD ioctls are unavailable on this system"
1139 /*****************************************************************************
1140 * ioctl_InvalidateAgid: invalidate the current AGID
1141 *****************************************************************************/
1142 int ioctl_InvalidateAgid( int i_fd
, int *pi_agid
)
1146 #if defined( HAVE_LINUX_DVD_STRUCT )
1147 dvd_authinfo auth_info
;
1149 memset( &auth_info
, 0, sizeof( auth_info
) );
1150 auth_info
.type
= DVD_INVALIDATE_AGID
;
1151 auth_info
.lsa
.agid
= *pi_agid
;
1153 i_ret
= ioctl( i_fd
, DVD_AUTH
, &auth_info
);
1155 #elif defined( HAVE_BSD_DVD_STRUCT )
1156 struct dvd_authinfo auth_info
;
1158 memset( &auth_info
, 0, sizeof( auth_info
) );
1159 auth_info
.format
= DVD_INVALIDATE_AGID
;
1160 auth_info
.agid
= *pi_agid
;
1162 i_ret
= ioctl( i_fd
, DVDIOCREPORTKEY
, &auth_info
);
1164 #elif defined( SYS_BEOS )
1165 INIT_RDC( GPCMD_REPORT_KEY
, 0 );
1167 rdc
.command
[ 10 ] = DVD_INVALIDATE_AGID
| (*pi_agid
<< 6);
1169 i_ret
= ioctl( i_fd
, B_RAW_DEVICE_COMMAND
, &rdc
, sizeof(rdc
) );
1171 #elif defined( HPUX_SCTL_IO )
1172 INIT_SCTL_IO( GPCMD_REPORT_KEY
, 0 );
1174 sctl_io
.cdb
[ 10 ] = DVD_INVALIDATE_AGID
| (*pi_agid
<< 6);
1176 i_ret
= ioctl( i_fd
, SIOC_IO
, &sctl_io
);
1178 #elif defined( SOLARIS_USCSI )
1179 INIT_USCSI( GPCMD_REPORT_KEY
, 0 );
1181 rs_cdb
.cdb_opaque
[ 10 ] = DVD_INVALIDATE_AGID
| (*pi_agid
<< 6);
1183 i_ret
= SolarisSendUSCSI( i_fd
, &sc
);
1185 if( i_ret
< 0 || sc
.uscsi_status
)
1190 #elif defined( DARWIN_DVD_IOCTL )
1191 INIT_DVDIOCTL( dk_dvd_send_key_t
, DVDAuthenticationGrantIDInfo
,
1192 kDVDKeyFormatAGID_Invalidate
);
1194 dvd
.grantID
= *pi_agid
;
1196 i_ret
= ioctl( i_fd
, DKIOCDVDSENDKEY
, &dvd
);
1198 #elif defined( WIN32 )
1199 if( WIN2K
) /* NT/2k/XP */
1203 i_ret
= DeviceIoControl( (HANDLE
) i_fd
, IOCTL_DVD_END_SESSION
,
1204 pi_agid
, sizeof( *pi_agid
), NULL
, 0, &tmp
, NULL
) ? 0 : -1;
1208 #if defined( __MINGW32__ )
1209 INIT_SSC( GPCMD_REPORT_KEY
, 0 );
1211 INIT_SSC( GPCMD_REPORT_KEY
, 1 );
1214 ssc
.CDBByte
[ 8 ] = 0;
1215 ssc
.CDBByte
[ 9 ] = 0;
1218 ssc
.CDBByte
[ 10 ] = DVD_INVALIDATE_AGID
| (*pi_agid
<< 6);
1220 i_ret
= WinSendSSC( i_fd
, &ssc
);
1223 #elif defined( __QNXNTO__ )
1225 INIT_CPT( GPCMD_REPORT_KEY
, 0 );
1227 p_cpt
->cam_cdb
[ 10 ] = DVD_INVALIDATE_AGID
| (*pi_agid
<< 6);
1229 i_ret
= devctl(i_fd
, DCMD_CAM_PASS_THRU
, p_cpt
, structSize
, NULL
);
1231 #elif defined( SYS_OS2 )
1232 INIT_SSC( GPCMD_REPORT_KEY
, 1 );
1234 sdc
.data_length
= 0;
1235 sdc
.command
[ 8 ] = 0;
1236 sdc
.command
[ 9 ] = 0;
1238 sdc
.command
[ 10 ] = DVD_INVALIDATE_AGID
| (*pi_agid
<< 6);
1240 i_ret
= DosDevIOCtl(i_fd
, IOCTL_CDROMDISK
, CDROMDISK_EXECMD
,
1241 &sdc
, sizeof(sdc
), &ulParamLen
,
1242 NULL
, 0, &ulDataLen
);
1244 # error "DVD ioctls are unavailable on this system"
1250 /*****************************************************************************
1251 * ioctl_SendChallenge: send challenge to the drive
1252 *****************************************************************************/
1253 int ioctl_SendChallenge( int i_fd
, int *pi_agid
, uint8_t *p_challenge
)
1257 #if defined( HAVE_LINUX_DVD_STRUCT )
1258 dvd_authinfo auth_info
;
1260 memset( &auth_info
, 0, sizeof( auth_info
) );
1261 auth_info
.type
= DVD_HOST_SEND_CHALLENGE
;
1262 auth_info
.hsc
.agid
= *pi_agid
;
1264 memcpy( auth_info
.hsc
.chal
, p_challenge
, DVD_CHALLENGE_SIZE
);
1266 i_ret
= ioctl( i_fd
, DVD_AUTH
, &auth_info
);
1268 #elif defined( HAVE_BSD_DVD_STRUCT )
1269 struct dvd_authinfo auth_info
;
1271 memset( &auth_info
, 0, sizeof( auth_info
) );
1272 auth_info
.format
= DVD_SEND_CHALLENGE
;
1273 auth_info
.agid
= *pi_agid
;
1275 memcpy( auth_info
.keychal
, p_challenge
, DVD_CHALLENGE_SIZE
);
1277 i_ret
= ioctl( i_fd
, DVDIOCSENDKEY
, &auth_info
);
1279 #elif defined( SYS_BEOS )
1280 INIT_RDC( GPCMD_SEND_KEY
, 16 );
1282 rdc
.command
[ 10 ] = DVD_SEND_CHALLENGE
| (*pi_agid
<< 6);
1284 p_buffer
[ 1 ] = 0xe;
1285 memcpy( p_buffer
+ 4, p_challenge
, DVD_CHALLENGE_SIZE
);
1287 i_ret
= ioctl( i_fd
, B_RAW_DEVICE_COMMAND
, &rdc
, sizeof(rdc
) );
1289 #elif defined( HPUX_SCTL_IO )
1290 INIT_SCTL_IO( GPCMD_SEND_KEY
, 16 );
1292 sctl_io
.cdb
[ 10 ] = DVD_SEND_CHALLENGE
| (*pi_agid
<< 6);
1294 p_buffer
[ 1 ] = 0xe;
1295 memcpy( p_buffer
+ 4, p_challenge
, DVD_CHALLENGE_SIZE
);
1297 i_ret
= ioctl( i_fd
, SIOC_IO
, &sctl_io
);
1299 #elif defined( SOLARIS_USCSI )
1300 INIT_USCSI( GPCMD_SEND_KEY
, 16 );
1302 rs_cdb
.cdb_opaque
[ 10 ] = DVD_SEND_CHALLENGE
| (*pi_agid
<< 6);
1304 p_buffer
[ 1 ] = 0xe;
1305 memcpy( p_buffer
+ 4, p_challenge
, DVD_CHALLENGE_SIZE
);
1307 if( SolarisSendUSCSI( i_fd
, &sc
) < 0 || sc
.uscsi_status
)
1314 #elif defined( DARWIN_DVD_IOCTL )
1315 INIT_DVDIOCTL( dk_dvd_send_key_t
, DVDChallengeKeyInfo
,
1316 kDVDKeyFormatChallengeKey
);
1318 dvd
.grantID
= *pi_agid
;
1319 dvd
.keyClass
= kDVDKeyClassCSS_CPPM_CPRM
;
1321 dvdbs
.dataLength
[ 1 ] = 0xe;
1322 memcpy( dvdbs
.challengeKeyValue
, p_challenge
, DVD_CHALLENGE_SIZE
);
1324 i_ret
= ioctl( i_fd
, DKIOCDVDSENDKEY
, &dvd
);
1326 #elif defined( WIN32 )
1327 if( WIN2K
) /* NT/2k/XP */
1330 uint8_t buffer
[DVD_CHALLENGE_KEY_LENGTH
];
1331 PDVD_COPY_PROTECT_KEY key
= (PDVD_COPY_PROTECT_KEY
) &buffer
;
1333 memset( &buffer
, 0, sizeof( buffer
) );
1335 key
->KeyLength
= DVD_CHALLENGE_KEY_LENGTH
;
1336 key
->SessionId
= *pi_agid
;
1337 key
->KeyType
= DvdChallengeKey
;
1340 memcpy( key
->KeyData
, p_challenge
, DVD_CHALLENGE_SIZE
);
1342 i_ret
= DeviceIoControl( (HANDLE
) i_fd
, IOCTL_DVD_SEND_KEY
, key
,
1343 key
->KeyLength
, key
, key
->KeyLength
, &tmp
, NULL
) ? 0 : -1;
1347 INIT_SSC( GPCMD_SEND_KEY
, 16 );
1349 ssc
.CDBByte
[ 10 ] = DVD_SEND_CHALLENGE
| (*pi_agid
<< 6);
1351 p_buffer
[ 1 ] = 0xe;
1352 memcpy( p_buffer
+ 4, p_challenge
, DVD_CHALLENGE_SIZE
);
1354 i_ret
= WinSendSSC( i_fd
, &ssc
);
1357 #elif defined( __QNXNTO__ )
1359 INIT_CPT( GPCMD_SEND_KEY
, 16 );
1361 p_cpt
->cam_cdb
[ 10 ] = DVD_SEND_CHALLENGE
| (*pi_agid
<< 6);
1363 p_buffer
[ 1 ] = 0xe;
1364 memcpy( p_buffer
+ 4, p_challenge
, DVD_CHALLENGE_SIZE
);
1366 i_ret
= devctl(i_fd
, DCMD_CAM_PASS_THRU
, p_cpt
, structSize
, NULL
);
1368 #elif defined( SYS_OS2 )
1369 INIT_SSC( GPCMD_SEND_KEY
, 16 );
1371 sdc
.command
[ 10 ] = DVD_SEND_CHALLENGE
| (*pi_agid
<< 6);
1373 p_buffer
[ 1 ] = 0xe;
1374 memcpy( p_buffer
+ 4, p_challenge
, DVD_CHALLENGE_SIZE
);
1376 i_ret
= DosDevIOCtl( i_fd
, IOCTL_CDROMDISK
, CDROMDISK_EXECMD
,
1377 &sdc
, sizeof(sdc
), &ulParamLen
,
1378 p_buffer
, sizeof(p_buffer
), &ulDataLen
);
1381 # error "DVD ioctls are unavailable on this system"
1387 /*****************************************************************************
1388 * ioctl_SendKey2: send the second key to the drive
1389 *****************************************************************************/
1390 int ioctl_SendKey2( int i_fd
, int *pi_agid
, uint8_t *p_key
)
1394 #if defined( HAVE_LINUX_DVD_STRUCT )
1395 dvd_authinfo auth_info
;
1397 memset( &auth_info
, 0, sizeof( auth_info
) );
1398 auth_info
.type
= DVD_HOST_SEND_KEY2
;
1399 auth_info
.hsk
.agid
= *pi_agid
;
1401 memcpy( auth_info
.hsk
.key
, p_key
, DVD_KEY_SIZE
);
1403 i_ret
= ioctl( i_fd
, DVD_AUTH
, &auth_info
);
1405 #elif defined( HAVE_BSD_DVD_STRUCT )
1406 struct dvd_authinfo auth_info
;
1408 memset( &auth_info
, 0, sizeof( auth_info
) );
1409 auth_info
.format
= DVD_SEND_KEY2
;
1410 auth_info
.agid
= *pi_agid
;
1412 memcpy( auth_info
.keychal
, p_key
, DVD_KEY_SIZE
);
1414 i_ret
= ioctl( i_fd
, DVDIOCSENDKEY
, &auth_info
);
1416 #elif defined( SYS_BEOS )
1417 INIT_RDC( GPCMD_SEND_KEY
, 12 );
1419 rdc
.command
[ 10 ] = DVD_SEND_KEY2
| (*pi_agid
<< 6);
1421 p_buffer
[ 1 ] = 0xa;
1422 memcpy( p_buffer
+ 4, p_key
, DVD_KEY_SIZE
);
1424 i_ret
= ioctl( i_fd
, B_RAW_DEVICE_COMMAND
, &rdc
, sizeof(rdc
) );
1426 #elif defined( HPUX_SCTL_IO )
1427 INIT_SCTL_IO( GPCMD_SEND_KEY
, 12 );
1429 sctl_io
.cdb
[ 10 ] = DVD_SEND_KEY2
| (*pi_agid
<< 6);
1431 p_buffer
[ 1 ] = 0xa;
1432 memcpy( p_buffer
+ 4, p_key
, DVD_KEY_SIZE
);
1434 i_ret
= ioctl( i_fd
, SIOC_IO
, &sctl_io
);
1436 #elif defined( SOLARIS_USCSI )
1437 INIT_USCSI( GPCMD_SEND_KEY
, 12 );
1439 rs_cdb
.cdb_opaque
[ 10 ] = DVD_SEND_KEY2
| (*pi_agid
<< 6);
1441 p_buffer
[ 1 ] = 0xa;
1442 memcpy( p_buffer
+ 4, p_key
, DVD_KEY_SIZE
);
1444 if( SolarisSendUSCSI( i_fd
, &sc
) < 0 || sc
.uscsi_status
)
1451 #elif defined( DARWIN_DVD_IOCTL )
1452 INIT_DVDIOCTL( dk_dvd_send_key_t
, DVDKey2Info
,
1453 kDVDKeyFormatKey2
);
1455 dvd
.grantID
= *pi_agid
;
1456 dvd
.keyClass
= kDVDKeyClassCSS_CPPM_CPRM
;
1458 dvdbs
.dataLength
[ 1 ] = 0xa;
1459 memcpy( dvdbs
.key2Value
, p_key
, DVD_KEY_SIZE
);
1461 i_ret
= ioctl( i_fd
, DKIOCDVDSENDKEY
, &dvd
);
1463 #elif defined( WIN32 )
1464 if( WIN2K
) /* NT/2k/XP */
1467 uint8_t buffer
[DVD_BUS_KEY_LENGTH
];
1468 PDVD_COPY_PROTECT_KEY key
= (PDVD_COPY_PROTECT_KEY
) &buffer
;
1470 memset( &buffer
, 0, sizeof( buffer
) );
1472 key
->KeyLength
= DVD_BUS_KEY_LENGTH
;
1473 key
->SessionId
= *pi_agid
;
1474 key
->KeyType
= DvdBusKey2
;
1477 memcpy( key
->KeyData
, p_key
, DVD_KEY_SIZE
);
1479 i_ret
= DeviceIoControl( (HANDLE
) i_fd
, IOCTL_DVD_SEND_KEY
, key
,
1480 key
->KeyLength
, key
, key
->KeyLength
, &tmp
, NULL
) ? 0 : -1;
1484 INIT_SSC( GPCMD_SEND_KEY
, 12 );
1486 ssc
.CDBByte
[ 10 ] = DVD_SEND_KEY2
| (*pi_agid
<< 6);
1488 p_buffer
[ 1 ] = 0xa;
1489 memcpy( p_buffer
+ 4, p_key
, DVD_KEY_SIZE
);
1491 i_ret
= WinSendSSC( i_fd
, &ssc
);
1494 #elif defined( __QNXNTO__ )
1496 INIT_CPT( GPCMD_SEND_KEY
, 12 );
1498 p_cpt
->cam_cdb
[ 10 ] = DVD_SEND_KEY2
| (*pi_agid
<< 6);
1500 p_buffer
[ 1 ] = 0xa;
1501 memcpy( p_buffer
+ 4, p_key
, DVD_KEY_SIZE
);
1503 i_ret
= devctl(i_fd
, DCMD_CAM_PASS_THRU
, p_cpt
, structSize
, NULL
);
1505 #elif defined( SYS_OS2 )
1506 INIT_SSC( GPCMD_SEND_KEY
, 12 );
1508 sdc
.command
[ 10 ] = DVD_SEND_KEY2
| (*pi_agid
<< 6);
1510 p_buffer
[ 1 ] = 0xa;
1511 memcpy( p_buffer
+ 4, p_key
, DVD_KEY_SIZE
);
1513 i_ret
= DosDevIOCtl( i_fd
, IOCTL_CDROMDISK
, CDROMDISK_EXECMD
,
1514 &sdc
, sizeof(sdc
), &ulParamLen
,
1515 p_buffer
, sizeof(p_buffer
), &ulDataLen
);
1518 # error "DVD ioctls are unavailable on this system"
1524 /*****************************************************************************
1525 * ioctl_ReportRPC: get RPC status for the drive
1526 *****************************************************************************/
1527 int ioctl_ReportRPC( int i_fd
, int *p_type
, int *p_mask
, int *p_scheme
)
1531 #if defined( HAVE_LINUX_DVD_STRUCT ) && defined( DVD_LU_SEND_RPC_STATE )
1532 dvd_authinfo auth_info
;
1534 memset( &auth_info
, 0, sizeof( auth_info
) );
1535 auth_info
.type
= DVD_LU_SEND_RPC_STATE
;
1537 i_ret
= ioctl( i_fd
, DVD_AUTH
, &auth_info
);
1539 *p_type
= auth_info
.lrpcs
.type
;
1540 *p_mask
= auth_info
.lrpcs
.region_mask
;
1541 *p_scheme
= auth_info
.lrpcs
.rpc_scheme
;
1543 #elif defined( HAVE_LINUX_DVD_STRUCT )
1544 /* FIXME: OpenBSD doesn't know this */
1547 #elif defined( HAVE_BSD_DVD_STRUCT )
1548 struct dvd_authinfo auth_info
;
1550 memset( &auth_info
, 0, sizeof( auth_info
) );
1551 auth_info
.format
= DVD_REPORT_RPC
;
1553 i_ret
= ioctl( i_fd
, DVDIOCREPORTKEY
, &auth_info
);
1555 *p_type
= auth_info
.reg_type
;
1556 *p_mask
= auth_info
.region
; // ??
1557 *p_scheme
= auth_info
.rpc_scheme
;
1559 #elif defined( SYS_BEOS )
1560 INIT_RDC( GPCMD_REPORT_KEY
, 8 );
1562 rdc
.command
[ 10 ] = DVD_REPORT_RPC
;
1564 i_ret
= ioctl( i_fd
, B_RAW_DEVICE_COMMAND
, &rdc
, sizeof(rdc
) );
1566 *p_type
= p_buffer
[ 4 ] >> 6;
1567 *p_mask
= p_buffer
[ 5 ];
1568 *p_scheme
= p_buffer
[ 6 ];
1570 #elif defined( HPUX_SCTL_IO )
1571 INIT_SCTL_IO( GPCMD_REPORT_KEY
, 8 );
1573 sctl_io
.cdb
[ 10 ] = DVD_REPORT_RPC
;
1575 i_ret
= ioctl( i_fd
, SIOC_IO
, &sctl_io
);
1577 *p_type
= p_buffer
[ 4 ] >> 6;
1578 *p_mask
= p_buffer
[ 5 ];
1579 *p_scheme
= p_buffer
[ 6 ];
1581 #elif defined( SOLARIS_USCSI )
1582 INIT_USCSI( GPCMD_REPORT_KEY
, 8 );
1584 rs_cdb
.cdb_opaque
[ 10 ] = DVD_REPORT_RPC
;
1586 i_ret
= SolarisSendUSCSI( i_fd
, &sc
);
1588 if( i_ret
< 0 || sc
.uscsi_status
)
1593 *p_type
= p_buffer
[ 4 ] >> 6;
1594 *p_mask
= p_buffer
[ 5 ];
1595 *p_scheme
= p_buffer
[ 6 ];
1597 #elif defined( DARWIN_DVD_IOCTL )
1598 INIT_DVDIOCTL( dk_dvd_report_key_t
, DVDRegionPlaybackControlInfo
,
1599 kDVDKeyFormatRegionState
);
1601 dvd
.keyClass
= kDVDKeyClassCSS_CPPM_CPRM
;
1603 i_ret
= ioctl( i_fd
, DKIOCDVDREPORTKEY
, &dvd
);
1605 *p_type
= dvdbs
.typeCode
;
1606 *p_mask
= dvdbs
.driveRegion
;
1607 *p_scheme
= dvdbs
.rpcScheme
;
1609 #elif defined( WIN32 )
1610 if( WIN2K
) /* NT/2k/XP */
1613 uint8_t buffer
[DVD_RPC_KEY_LENGTH
];
1614 PDVD_COPY_PROTECT_KEY key
= (PDVD_COPY_PROTECT_KEY
) &buffer
;
1616 memset( &buffer
, 0, sizeof( buffer
) );
1618 key
->KeyLength
= DVD_RPC_KEY_LENGTH
;
1619 key
->KeyType
= DvdGetRpcKey
;
1622 i_ret
= DeviceIoControl( (HANDLE
) i_fd
, IOCTL_DVD_READ_KEY
, key
,
1623 key
->KeyLength
, key
, key
->KeyLength
, &tmp
, NULL
) ? 0 : -1;
1630 *p_type
= ((PDVD_RPC_KEY
)key
->KeyData
)->TypeCode
;
1631 *p_mask
= ((PDVD_RPC_KEY
)key
->KeyData
)->RegionMask
;
1632 *p_scheme
= ((PDVD_RPC_KEY
)key
->KeyData
)->RpcScheme
;
1636 INIT_SSC( GPCMD_REPORT_KEY
, 8 );
1638 ssc
.CDBByte
[ 10 ] = DVD_REPORT_RPC
;
1640 i_ret
= WinSendSSC( i_fd
, &ssc
);
1642 *p_type
= p_buffer
[ 4 ] >> 6;
1643 *p_mask
= p_buffer
[ 5 ];
1644 *p_scheme
= p_buffer
[ 6 ];
1647 #elif defined( __QNXNTO__ )
1649 INIT_CPT( GPCMD_REPORT_KEY
, 8 );
1651 p_cpt
->cam_cdb
[ 10 ] = DVD_REPORT_RPC
;
1653 i_ret
= devctl(i_fd
, DCMD_CAM_PASS_THRU
, p_cpt
, structSize
, NULL
);
1655 *p_type
= p_buffer
[ 4 ] >> 6;
1656 *p_mask
= p_buffer
[ 5 ];
1657 *p_scheme
= p_buffer
[ 6 ];
1659 #elif defined( SYS_OS2 )
1660 INIT_SSC( GPCMD_REPORT_KEY
, 8 );
1662 sdc
.command
[ 10 ] = DVD_REPORT_RPC
;
1664 i_ret
= DosDevIOCtl(i_fd
, IOCTL_CDROMDISK
, CDROMDISK_EXECMD
,
1665 &sdc
, sizeof(sdc
), &ulParamLen
,
1666 p_buffer
, sizeof(p_buffer
), &ulDataLen
);
1668 *p_type
= p_buffer
[ 4 ] >> 6;
1669 *p_mask
= p_buffer
[ 5 ];
1670 *p_scheme
= p_buffer
[ 6 ];
1673 # error "DVD ioctls are unavailable on this system"
1679 /*****************************************************************************
1680 * ioctl_SendRPC: set RPC status for the drive
1681 *****************************************************************************/
1682 int ioctl_SendRPC( int i_fd
, int i_pdrc
)
1686 #if defined( HAVE_LINUX_DVD_STRUCT ) && defined( DVD_HOST_SEND_RPC_STATE )
1687 dvd_authinfo auth_info
;
1689 memset( &auth_info
, 0, sizeof( auth_info
) );
1690 auth_info
.type
= DVD_HOST_SEND_RPC_STATE
;
1691 auth_info
.hrpcs
.pdrc
= i_pdrc
;
1693 i_ret
= ioctl( i_fd
, DVD_AUTH
, &auth_info
);
1695 #elif defined( HAVE_LINUX_DVD_STRUCT )
1696 /* FIXME: OpenBSD doesn't know this */
1699 #elif defined( HAVE_BSD_DVD_STRUCT )
1700 struct dvd_authinfo auth_info
;
1702 memset( &auth_info
, 0, sizeof( auth_info
) );
1703 auth_info
.format
= DVD_SEND_RPC
;
1704 auth_info
.region
= i_pdrc
;
1706 i_ret
= ioctl( i_fd
, DVDIOCSENDKEY
, &auth_info
);
1708 #elif defined( SYS_BEOS )
1709 INIT_RDC( GPCMD_SEND_KEY
, 8 );
1711 rdc
.command
[ 10 ] = DVD_SEND_RPC
;
1714 p_buffer
[ 4 ] = i_pdrc
;
1716 i_ret
= ioctl( i_fd
, B_RAW_DEVICE_COMMAND
, &rdc
, sizeof(rdc
) );
1718 #elif defined( HPUX_SCTL_IO )
1719 INIT_SCTL_IO( GPCMD_SEND_KEY
, 8 );
1721 sctl_io
.cdb
[ 10 ] = DVD_SEND_RPC
;
1724 p_buffer
[ 4 ] = i_pdrc
;
1726 i_ret
= ioctl( i_fd
, SIOC_IO
, &sctl_io
);
1728 #elif defined( SOLARIS_USCSI )
1729 INIT_USCSI( GPCMD_SEND_KEY
, 8 );
1731 rs_cdb
.cdb_opaque
[ 10 ] = DVD_SEND_RPC
;
1734 p_buffer
[ 4 ] = i_pdrc
;
1736 i_ret
= SolarisSendUSCSI( i_fd
, &sc
);
1738 if( i_ret
< 0 || sc
.uscsi_status
)
1743 #elif defined( DARWIN_DVD_IOCTL )
1744 INIT_DVDIOCTL( dk_dvd_send_key_t
, DVDRegionPlaybackControlInfo
,
1745 kDVDKeyFormatSetRegion
);
1747 dvd
.keyClass
= kDVDKeyClassCSS_CPPM_CPRM
;
1748 dvdbs
.driveRegion
= i_pdrc
;
1750 i_ret
= ioctl( i_fd
, DKIOCDVDSENDKEY
, &dvd
);
1752 #elif defined( WIN32 )
1753 if( WIN2K
) /* NT/2k/XP */
1755 INIT_SPTD( GPCMD_SEND_KEY
, 8 );
1757 sptd
.Cdb
[ 10 ] = DVD_SEND_RPC
;
1760 p_buffer
[ 4 ] = i_pdrc
;
1762 i_ret
= SEND_SPTD( i_fd
, &sptd
, &tmp
);
1766 INIT_SSC( GPCMD_SEND_KEY
, 8 );
1768 ssc
.CDBByte
[ 10 ] = DVD_SEND_RPC
;
1771 p_buffer
[ 4 ] = i_pdrc
;
1773 i_ret
= WinSendSSC( i_fd
, &ssc
);
1776 #elif defined( __QNXNTO__ )
1778 INIT_CPT( GPCMD_SEND_KEY
, 8 );
1780 p_cpt
->cam_cdb
[ 10 ] = DVD_SEND_RPC
;
1783 p_buffer
[ 4 ] = i_pdrc
;
1785 i_ret
= devctl(i_fd
, DCMD_CAM_PASS_THRU
, p_cpt
, structSize
, NULL
);
1787 #elif defined( SYS_OS2 )
1788 INIT_SSC( GPCMD_SEND_KEY
, 8 );
1790 sdc
.command
[ 10 ] = DVD_SEND_RPC
;
1793 p_buffer
[ 4 ] = i_pdrc
;
1795 i_ret
= DosDevIOCtl( i_fd
, IOCTL_CDROMDISK
, CDROMDISK_EXECMD
,
1796 &sdc
, sizeof(sdc
), &ulParamLen
,
1797 p_buffer
, sizeof(p_buffer
), &ulDataLen
);
1800 # error "DVD ioctls are unavailable on this system"
1806 /* Local prototypes */
1808 #if defined( SYS_BEOS )
1809 /*****************************************************************************
1810 * BeInitRDC: initialize a RDC structure for the BeOS kernel
1811 *****************************************************************************
1812 * This function initializes a BeOS raw device command structure for future
1813 * use, either a read command or a write command.
1814 *****************************************************************************/
1815 static void BeInitRDC( raw_device_command
*p_rdc
, int i_type
)
1817 memset( p_rdc
->data
, 0, p_rdc
->data_length
);
1821 case GPCMD_SEND_KEY
:
1822 /* leave the flags to 0 */
1825 case GPCMD_READ_DVD_STRUCTURE
: case GPCMD_REPORT_KEY
:
1826 p_rdc
->flags
= B_RAW_DEVICE_DATA_IN
; break; }
1828 p_rdc
->command
[ 0 ] = i_type
;
1830 p_rdc
->command
[ 8 ] = (p_rdc
->data_length
>> 8) & 0xff;
1831 p_rdc
->command
[ 9 ] = p_rdc
->data_length
& 0xff;
1832 p_rdc
->command_length
= 12;
1834 p_rdc
->sense_data
= NULL
;
1835 p_rdc
->sense_data_length
= 0;
1837 p_rdc
->timeout
= 1000000;
1841 #if defined( HPUX_SCTL_IO )
1842 /*****************************************************************************
1843 * HPUXInitSCTL: initialize a sctl_io structure for the HP-UX kernel
1844 *****************************************************************************
1845 * This function initializes a HP-UX command structure for future
1846 * use, either a read command or a write command.
1847 *****************************************************************************/
1848 static void HPUXInitSCTL( struct sctl_io
*sctl_io
, int i_type
)
1850 memset( sctl_io
->data
, 0, sctl_io
->data_length
);
1854 case GPCMD_SEND_KEY
:
1855 /* leave the flags to 0 */
1858 case GPCMD_READ_DVD_STRUCTURE
:
1859 case GPCMD_REPORT_KEY
:
1860 sctl_io
->flags
= SCTL_READ
;
1864 sctl_io
->cdb
[ 0 ] = i_type
;
1866 sctl_io
->cdb
[ 8 ] = (sctl_io
->data_length
>> 8) & 0xff;
1867 sctl_io
->cdb
[ 9 ] = sctl_io
->data_length
& 0xff;
1868 sctl_io
->cdb_length
= 12;
1870 sctl_io
->max_msecs
= 1000000;
1874 #if defined( SOLARIS_USCSI )
1875 /*****************************************************************************
1876 * SolarisInitUSCSI: initialize a USCSICMD structure for the Solaris kernel
1877 *****************************************************************************
1878 * This function initializes a Solaris userspace scsi command structure for
1879 * future use, either a read command or a write command.
1880 *****************************************************************************/
1881 static void SolarisInitUSCSI( struct uscsi_cmd
*p_sc
, int i_type
)
1883 union scsi_cdb
*rs_cdb
;
1884 memset( p_sc
->uscsi_cdb
, 0, sizeof( union scsi_cdb
) );
1885 memset( p_sc
->uscsi_bufaddr
, 0, p_sc
->uscsi_buflen
);
1889 case GPCMD_SEND_KEY
:
1890 p_sc
->uscsi_flags
= USCSI_ISOLATE
| USCSI_WRITE
;
1893 case GPCMD_READ_DVD_STRUCTURE
:
1894 case GPCMD_REPORT_KEY
:
1895 p_sc
->uscsi_flags
= USCSI_ISOLATE
| USCSI_READ
;
1899 rs_cdb
= (union scsi_cdb
*)p_sc
->uscsi_cdb
;
1901 rs_cdb
->scc_cmd
= i_type
;
1903 rs_cdb
->cdb_opaque
[ 8 ] = (p_sc
->uscsi_buflen
>> 8) & 0xff;
1904 rs_cdb
->cdb_opaque
[ 9 ] = p_sc
->uscsi_buflen
& 0xff;
1905 p_sc
->uscsi_cdblen
= 12;
1907 USCSI_TIMEOUT( p_sc
, 15 );
1910 /*****************************************************************************
1911 * SolarisSendUSCSI: send a USCSICMD structure to the Solaris kernel
1913 *****************************************************************************
1914 * When available, this function uses the function smedia_uscsi_cmd()
1915 * from solaris' libsmedia library (solaris 9 or newer) to execute the
1916 * USCSI command. smedia_uscsi_cmd() allows USCSI commands for
1917 * non-root users on removable media devices on solaris 9; sending the
1918 * USCSI command directly to the device using the USCSICMD ioctl fails
1919 * with an EPERM error on solaris 9.
1921 * The code will fall back to the USCSICMD ioctl method, when
1922 * libsmedia.so is not available or does not export the
1923 * smedia_uscsi_cmd() function (on solaris releases upto and including
1924 * solaris 8). Fortunatelly, on these old releases non-root users are
1925 * allowed to perform USCSICMD ioctls on removable media devices.
1926 *****************************************************************************/
1927 static int SolarisSendUSCSI( int i_fd
, struct uscsi_cmd
*p_sc
) {
1929 static int initialized
;
1930 static void* (*sm_get_handle
)(int32_t);
1931 static int (*sm_release_handle
)(void*);
1932 static int (*sm_uscsi_cmd
)(void*, struct uscsi_cmd
*);
1938 smedia_lib
= dlopen("libsmedia.so", RTLD_NOW
);
1940 sm_get_handle
= dlsym(smedia_lib
, "smedia_get_handle");
1941 sm_release_handle
= dlsym(smedia_lib
, "smedia_release_handle");
1942 sm_uscsi_cmd
= dlsym(smedia_lib
, "smedia_uscsi_cmd");
1947 if (sm_get_handle
&& sm_uscsi_cmd
&& sm_release_handle
1948 && (sm_hdl
= sm_get_handle(i_fd
)))
1950 int i_ret
= sm_uscsi_cmd(sm_hdl
, p_sc
);
1951 sm_release_handle(sm_hdl
);
1955 return ioctl( i_fd
, USCSICMD
, p_sc
);
1959 #if defined( WIN32 )
1960 /*****************************************************************************
1961 * WinInitSPTD: initialize a sptd structure
1962 *****************************************************************************
1963 * This function initializes a SCSI pass through command structure for future
1964 * use, either a read command or a write command.
1965 *****************************************************************************/
1966 static void WinInitSPTD( SCSI_PASS_THROUGH_DIRECT
*p_sptd
, int i_type
)
1968 memset( p_sptd
->DataBuffer
, 0, p_sptd
->DataTransferLength
);
1972 case GPCMD_SEND_KEY
:
1973 p_sptd
->DataIn
= SCSI_IOCTL_DATA_OUT
;
1976 case GPCMD_READ_DVD_STRUCTURE
:
1977 case GPCMD_REPORT_KEY
:
1978 p_sptd
->DataIn
= SCSI_IOCTL_DATA_IN
;
1982 p_sptd
->Cdb
[ 0 ] = i_type
;
1983 p_sptd
->Cdb
[ 8 ] = (uint8_t)(p_sptd
->DataTransferLength
>> 8) & 0xff;
1984 p_sptd
->Cdb
[ 9 ] = (uint8_t) p_sptd
->DataTransferLength
& 0xff;
1985 p_sptd
->CdbLength
= 12;
1987 p_sptd
->TimeOutValue
= 2;
1990 /*****************************************************************************
1991 * WinInitSSC: initialize a ssc structure for the win32 aspi layer
1992 *****************************************************************************
1993 * This function initializes a ssc raw device command structure for future
1994 * use, either a read command or a write command.
1995 *****************************************************************************/
1996 static void WinInitSSC( struct SRB_ExecSCSICmd
*p_ssc
, int i_type
)
1998 memset( p_ssc
->SRB_BufPointer
, 0, p_ssc
->SRB_BufLen
);
2002 case GPCMD_SEND_KEY
:
2003 p_ssc
->SRB_Flags
= SRB_DIR_OUT
;
2006 case GPCMD_READ_DVD_STRUCTURE
:
2007 case GPCMD_REPORT_KEY
:
2008 p_ssc
->SRB_Flags
= SRB_DIR_IN
;
2012 p_ssc
->SRB_Cmd
= SC_EXEC_SCSI_CMD
;
2013 p_ssc
->SRB_Flags
|= SRB_EVENT_NOTIFY
;
2015 p_ssc
->CDBByte
[ 0 ] = i_type
;
2017 p_ssc
->CDBByte
[ 8 ] = (uint8_t)(p_ssc
->SRB_BufLen
>> 8) & 0xff;
2018 p_ssc
->CDBByte
[ 9 ] = (uint8_t) p_ssc
->SRB_BufLen
& 0xff;
2019 p_ssc
->SRB_CDBLen
= 12;
2021 p_ssc
->SRB_SenseLen
= SENSE_LEN
;
2024 /*****************************************************************************
2025 * WinSendSSC: send a ssc structure to the aspi layer
2026 *****************************************************************************/
2027 static int WinSendSSC( int i_fd
, struct SRB_ExecSCSICmd
*p_ssc
)
2029 HANDLE hEvent
= NULL
;
2030 struct w32_aspidev
*fd
= (struct w32_aspidev
*) i_fd
;
2032 hEvent
= CreateEvent( NULL
, TRUE
, FALSE
, NULL
);
2033 if( hEvent
== NULL
)
2038 p_ssc
->SRB_PostProc
= hEvent
;
2039 p_ssc
->SRB_HaId
= LOBYTE( fd
->i_sid
);
2040 p_ssc
->SRB_Target
= HIBYTE( fd
->i_sid
);
2042 ResetEvent( hEvent
);
2043 if( fd
->lpSendCommand( (void*) p_ssc
) == SS_PENDING
)
2044 WaitForSingleObject( hEvent
, INFINITE
);
2046 CloseHandle( hEvent
);
2048 return p_ssc
->SRB_Status
== SS_COMP
? 0 : -1;
2052 #if defined( __QNXNTO__ )
2053 /*****************************************************************************
2054 * QNXInitCPT: initialize a CPT structure for QNX Neutrino
2055 *****************************************************************************
2056 * This function initializes a cpt command structure for future use,
2057 * either a read command or a write command.
2058 *****************************************************************************/
2059 static void QNXInitCPT( CAM_PASS_THRU
* p_cpt
, int i_type
)
2063 case GPCMD_SEND_KEY
:
2064 p_cpt
->cam_flags
= CAM_DIR_OUT
;
2067 case GPCMD_READ_DVD_STRUCTURE
:
2068 case GPCMD_REPORT_KEY
:
2069 p_cpt
->cam_flags
= CAM_DIR_IN
;
2073 p_cpt
->cam_cdb
[0] = i_type
;
2075 p_cpt
->cam_cdb
[ 8 ] = (p_cpt
->cam_dxfer_len
>> 8) & 0xff;
2076 p_cpt
->cam_cdb
[ 9 ] = p_cpt
->cam_dxfer_len
& 0xff;
2077 p_cpt
->cam_cdb_len
= 12;
2079 p_cpt
->cam_timeout
= CAM_TIME_DEFAULT
;
2083 #if defined( SYS_OS2 )
2084 /*****************************************************************************
2085 * OS2InitSDC: initialize a SDC structure for the Execute SCSI-command
2086 *****************************************************************************
2087 * This function initializes a OS2 'execute SCSI command' structure for
2088 * future use, either a read command or a write command.
2089 *****************************************************************************/
2090 static void OS2InitSDC( struct OS2_ExecSCSICmd
*p_sdc
, int i_type
)
2094 case GPCMD_SEND_KEY
:
2098 case GPCMD_READ_DVD_STRUCTURE
:
2099 case GPCMD_REPORT_KEY
:
2100 p_sdc
->flags
= EX_DIRECTION_IN
;
2104 p_sdc
->command
[ 0 ] = i_type
;
2105 p_sdc
->command
[ 8 ] = (p_sdc
->data_length
>> 8) & 0xff;
2106 p_sdc
->command
[ 9 ] = p_sdc
->data_length
& 0xff;
2107 p_sdc
->id_code
= 0x31304443; // 'CD01'
2108 p_sdc
->cmd_length
= 12;