1 /*****************************************************************************
2 * dvd_ioctl.c: DVD ioctl replacement function
3 *****************************************************************************
4 * Copyright (C) 1999-2001 VideoLAN
5 * $Id: dvd_ioctl.c,v 1.10 2001/04/11 04:46:18 sam Exp $
7 * Authors: Markus Kuespert <ltlBeBoy@beosmail.com>
8 * Samuel Hocevar <sam@zoy.org>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
23 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
30 #include <string.h> /* memcpy(), memset() */
31 #include <sys/types.h>
32 #include <netinet/in.h>
34 #ifdef HAVE_SYS_DVDIO_H
35 # include <sys/ioctl.h>
36 # include <sys/dvdio.h>
39 # include <sys/ioctl.h>
40 # include <linux/cdrom.h>
43 # include <sys/ioctl.h>
48 # include <sys/ioctl.h>
56 # include "DVDioctl/DVDioctl.h"
60 #include "dvd_ioctl.h"
62 /*****************************************************************************
63 * Local prototypes - BeOS specific
64 *****************************************************************************/
65 #if defined( SYS_BEOS )
66 static void BeInitRDC ( raw_device_command *, void *, int, int );
67 #define INIT_RDC( TYPE, SIZE ) \
68 raw_device_command rdc; \
69 u8 p_buffer[ (SIZE) ]; \
70 BeInitRDC( &rdc, p_buffer, (TYPE), (SIZE) );
73 /*****************************************************************************
74 * ioctl_ReadCopyright: check whether the disc is encrypted or not
75 *****************************************************************************/
76 int ioctl_ReadCopyright( int i_fd, int i_layer, int *pi_copyright )
80 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
83 dvd.type = DVD_STRUCT_COPYRIGHT;
84 dvd.copyright.layer_num = i_layer;
86 i_ret = ioctl( i_fd, DVD_READ_STRUCT, &dvd );
88 *pi_copyright = dvd.copyright.cpst;
90 #elif defined( SYS_BEOS )
91 INIT_RDC( GPCMD_READ_DVD_STRUCTURE, 8 );
93 rdc.command[ 6 ] = i_layer;
94 rdc.command[ 7 ] = DVD_STRUCT_COPYRIGHT;
96 i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
98 *pi_copyright = p_buffer[ 4 ];
100 #elif defined( SYS_DARWIN1_3 )
101 intf_ErrMsg( "css error: DVD ioctls not fully functional yet" );
103 intf_ErrMsg( "css error: assuming disc is unencrypted" );
109 /* DVD ioctls unavailable - do as if the ioctl failed */
116 /*****************************************************************************
117 * ioctl_ReadKey: get the disc key
118 *****************************************************************************/
119 int ioctl_ReadKey( int i_fd, int *pi_agid, u8 *p_key )
123 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
126 dvd.type = DVD_STRUCT_DISCKEY;
127 dvd.disckey.agid = *pi_agid;
129 memset( dvd.disckey.value, 0, 2048 );
131 i_ret = ioctl( i_fd, DVD_READ_STRUCT, &dvd );
138 memcpy( p_key, dvd.disckey.value, 2048 );
140 #elif defined( SYS_BEOS )
141 INIT_RDC( GPCMD_READ_DVD_STRUCTURE, 2048 + 4 );
143 rdc.command[ 7 ] = DVD_STRUCT_DISCKEY;
144 rdc.command[ 10 ] = *pi_agid << 6;
146 i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
153 memcpy( p_key, p_buffer + 4, 2048 );
156 /* DVD ioctls unavailable - do as if the ioctl failed */
163 /*****************************************************************************
164 * ioctl_LUSendAgid: get AGID from the drive
165 *****************************************************************************/
166 int ioctl_LUSendAgid( int i_fd, int *pi_agid )
170 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
171 dvd_authinfo auth_info;
173 auth_info.type = DVD_LU_SEND_AGID;
174 auth_info.lsa.agid = *pi_agid;
176 i_ret = ioctl( i_fd, DVD_AUTH, &auth_info );
178 *pi_agid = auth_info.lsa.agid;
180 #elif defined( SYS_BEOS )
181 INIT_RDC( GPCMD_REPORT_KEY, 8 );
183 rdc.command[ 10 ] = 0x00 | (*pi_agid << 6);
185 i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
187 *pi_agid = p_buffer[ 7 ] >> 6;
190 /* DVD ioctls unavailable - do as if the ioctl failed */
197 /*****************************************************************************
198 * ioctl_LUSendChallenge: get challenge from the drive
199 *****************************************************************************/
200 int ioctl_LUSendChallenge( int i_fd, int *pi_agid, u8 *p_challenge )
204 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
205 dvd_authinfo auth_info;
207 auth_info.type = DVD_LU_SEND_CHALLENGE;
208 auth_info.lsc.agid = *pi_agid;
210 i_ret = ioctl( i_fd, DVD_AUTH, &auth_info );
212 memcpy( p_challenge, auth_info.lsc.chal, sizeof(dvd_challenge) );
214 #elif defined( SYS_BEOS )
215 INIT_RDC( GPCMD_REPORT_KEY, 16 );
217 rdc.command[ 10 ] = 0x01 | (*pi_agid << 6);
219 i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
221 memcpy( p_challenge, p_buffer + 4, 12 );
224 /* DVD ioctls unavailable - do as if the ioctl failed */
231 /*****************************************************************************
232 * ioctl_LUSendASF: get ASF from the drive
233 *****************************************************************************/
234 int ioctl_LUSendASF( int i_fd, int *pi_agid, int *pi_asf )
238 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
239 dvd_authinfo auth_info;
241 auth_info.type = DVD_LU_SEND_ASF;
242 auth_info.lsasf.agid = *pi_agid;
243 auth_info.lsasf.asf = *pi_asf;
245 i_ret = ioctl( i_fd, DVD_AUTH, &auth_info );
247 *pi_asf = auth_info.lsasf.asf;
249 #elif defined( SYS_BEOS )
250 INIT_RDC( GPCMD_REPORT_KEY, 8 );
252 rdc.command[ 10 ] = 0x05 | (*pi_agid << 6);
254 i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
256 *pi_asf = p_buffer[ 7 ] & 1;
258 #elif defined( SYS_DARWIN1_3 )
259 dvdioctl_data_t data;
262 data.p_buffer = p_buffer;
264 data.i_agid = *pi_agid;
265 data.i_keyclass = kCSS_CSS2_CPRM;
266 data.i_keyformat = kASF;
268 i_ret = ioctl( i_fd, IODVD_REPORT_KEY, &data );
270 *pi_asf = p_buffer[ 7 ] & 1;
273 /* DVD ioctls unavailable - do as if the ioctl failed */
280 /*****************************************************************************
281 * ioctl_LUSendKey1: get the first key from the drive
282 *****************************************************************************/
283 int ioctl_LUSendKey1( int i_fd, int *pi_agid, u8 *p_key )
287 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
288 dvd_authinfo auth_info;
290 auth_info.type = DVD_LU_SEND_KEY1;
291 auth_info.lsk.agid = *pi_agid;
293 i_ret = ioctl( i_fd, DVD_AUTH, &auth_info );
295 memcpy( p_key, auth_info.lsk.key, sizeof(dvd_key) );
297 #elif defined( SYS_BEOS )
298 INIT_RDC( GPCMD_REPORT_KEY, 12 );
300 rdc.command[ 10 ] = 0x02 | (*pi_agid << 6);
302 i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
304 memcpy( p_key, p_buffer + 4, 8 );
307 /* DVD ioctls unavailable - do as if the ioctl failed */
314 /*****************************************************************************
315 * ioctl_InvalidateAgid: invalidate the current AGID
316 *****************************************************************************/
317 int ioctl_InvalidateAgid( int i_fd, int *pi_agid )
321 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
322 dvd_authinfo auth_info;
324 auth_info.type = DVD_INVALIDATE_AGID;
325 auth_info.lsa.agid = *pi_agid;
327 i_ret = ioctl( i_fd, DVD_AUTH, &auth_info );
329 *pi_agid = auth_info.lsa.agid;
331 #elif defined( SYS_BEOS )
332 INIT_RDC( GPCMD_REPORT_KEY, 0 );
334 rdc.command[ 10 ] = 0x3f | (*pi_agid << 6);
336 i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
339 /* DVD ioctls unavailable - do as if the ioctl failed */
346 /*****************************************************************************
347 * ioctl_HostSendChallenge: send challenge to the drive
348 *****************************************************************************/
349 int ioctl_HostSendChallenge( int i_fd, int *pi_agid, u8 *p_challenge )
351 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
352 dvd_authinfo auth_info;
354 auth_info.type = DVD_HOST_SEND_CHALLENGE;
355 auth_info.hsc.agid = *pi_agid;
357 memcpy( auth_info.hsc.chal, p_challenge, sizeof(dvd_challenge) );
359 return ioctl( i_fd, DVD_AUTH, &auth_info );
361 #elif defined( SYS_BEOS )
362 INIT_RDC( GPCMD_SEND_KEY, 16 );
364 rdc.command[ 10 ] = 0x01 | (*pi_agid << 6);
367 memcpy( p_buffer + 4, p_challenge, 12 );
369 return ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
372 /* DVD ioctls unavailable - do as if the ioctl failed */
378 /*****************************************************************************
379 * ioctl_HostSendKey2: send the second key to the drive
380 *****************************************************************************/
381 int ioctl_HostSendKey2( int i_fd, int *pi_agid, u8 *p_key )
383 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
384 dvd_authinfo auth_info;
386 auth_info.type = DVD_HOST_SEND_KEY2;
387 auth_info.hsk.agid = *pi_agid;
389 memcpy( auth_info.hsk.key, p_key, sizeof(dvd_key) );
391 return ioctl( i_fd, DVD_AUTH, &auth_info );
393 #elif defined( SYS_BEOS )
394 INIT_RDC( GPCMD_SEND_KEY, 12 );
396 rdc.command[ 10 ] = 0x3 | (*pi_agid << 6);
399 memcpy( p_buffer + 4, p_key, 8 );
401 return ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
404 /* DVD ioctls unavailable - do as if the ioctl failed */
410 /* Local prototypes */
412 #if defined( SYS_BEOS )
413 /*****************************************************************************
414 * BeInitRDC: initialize a RDC structure for the BeOS kernel
415 *****************************************************************************
416 * This function initializes a BeOS raw device command structure for future
417 * use, either a read command or a write command.
418 *****************************************************************************/
419 static void BeInitRDC( raw_device_command *p_rdc,
420 void *p_buffer, int i_type, int i_len )
422 memset( p_rdc, 0, sizeof( raw_device_command ) );
423 memset( p_buffer, 0, i_len );
428 /* leave the flags to 0 */
431 case GPCMD_READ_DVD_STRUCTURE:
432 case GPCMD_REPORT_KEY:
433 p_rdc->flags = B_RAW_DEVICE_DATA_IN;
437 p_rdc->command[ 0 ] = i_type;
439 p_rdc->command[ 8 ] = (i_len >> 8) & 0xff;
440 p_rdc->command[ 9 ] = i_len & 0xff;
441 p_rdc->command_length = 12;
443 p_rdc->data = (char *)p_buffer;
444 p_rdc->data_length = i_len;
446 p_rdc->sense_data = NULL;
447 p_rdc->sense_data_length = 0;
449 p_rdc->timeout = 1000000;