1 /*****************************************************************************
2 * dvd_ioctl.c: DVD ioctl replacement function
3 *****************************************************************************
4 * Copyright (C) 1999-2001 VideoLAN
5 * $Id: dvd_ioctl.c,v 1.8 2001/04/08 09:04:33 stef 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 );
69 /*****************************************************************************
70 * ioctl_ReadCopyright: check whether the disc is encrypted or not
71 *****************************************************************************/
72 int ioctl_ReadCopyright( int i_fd, int i_layer, int *pi_copyright )
76 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
79 dvd.type = DVD_STRUCT_COPYRIGHT;
80 dvd.copyright.layer_num = i_layer;
82 i_ret = ioctl( i_fd, DVD_READ_STRUCT, &dvd );
84 *pi_copyright = dvd.copyright.cpst;
86 #elif defined( SYS_BEOS )
87 raw_device_command rdc;
90 BeInitRDC( &rdc, p_buffer, 8 );
92 rdc.flags = B_RAW_DEVICE_DATA_IN;
93 rdc.command[ 0 ] = GPCMD_READ_DVD_STRUCTURE;
94 rdc.command[ 6 ] = i_layer;
95 rdc.command[ 7 ] = DVD_STRUCT_COPYRIGHT;
97 i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
99 *pi_copyright = p_buffer[ 4 ];
101 #elif defined( SYS_DARWIN1_3 )
102 intf_ErrMsg( "css error: DVD ioctls not fully functional yet" );
104 intf_ErrMsg( "css error: assuming disc is unencrypted" );
110 /* DVD ioctls unavailable - do as if the ioctl failed */
117 /*****************************************************************************
118 * ioctl_ReadKey: get the disc key
119 *****************************************************************************/
120 int ioctl_ReadKey( css_t *p_css, u8 *p_key )
124 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
127 dvd.type = DVD_STRUCT_DISCKEY;
128 dvd.disckey.agid = p_css->i_agid;
130 memset( dvd.disckey.value, 0, 2048 );
132 i_ret = ioctl( p_css->i_fd, DVD_READ_STRUCT, &dvd );
139 memcpy( p_key, dvd.disckey.value, 2048 );
141 #elif defined( SYS_BEOS )
142 raw_device_command rdc;
143 u8 p_buffer[ 2048 + 4 ];
145 BeInitRDC( &rdc, p_buffer, 2048 + 4 );
147 rdc.flags = B_RAW_DEVICE_DATA_IN;
148 rdc.command[ 0 ] = GPCMD_READ_DVD_STRUCTURE;
149 rdc.command[ 7 ] = DVD_STRUCT_DISCKEY;
150 rdc.command[ 10 ] = p_css->i_agid << 6;
152 i_ret = ioctl( p_css->i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
159 memcpy( p_key, p_buffer + 4, 2048 );
162 /* DVD ioctls unavailable - do as if the ioctl failed */
169 /*****************************************************************************
170 * ioctl_LUSendAgid: get AGID from the drive
171 *****************************************************************************/
172 int ioctl_LUSendAgid( css_t *p_css )
176 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
177 dvd_authinfo auth_info;
179 auth_info.type = DVD_LU_SEND_AGID;
180 auth_info.lsa.agid = p_css->i_agid;
182 i_ret = ioctl( p_css->i_fd, DVD_AUTH, &auth_info );
184 p_css->i_agid = auth_info.lsa.agid;
186 #elif defined( SYS_BEOS )
187 raw_device_command rdc;
190 BeInitRDC( &rdc, p_buffer, 8 );
192 rdc.flags = B_RAW_DEVICE_DATA_IN;
193 rdc.command[ 0 ] = GPCMD_REPORT_KEY;
194 rdc.command[ 10 ] = 0x00 | (p_css->i_agid << 6);
196 i_ret = ioctl( p_css->i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
198 p_css->i_agid = p_buffer[ 7 ] >> 6;
201 /* DVD ioctls unavailable - do as if the ioctl failed */
208 /*****************************************************************************
209 * ioctl_LUSendChallenge: get challenge from the drive
210 *****************************************************************************/
211 int ioctl_LUSendChallenge( css_t *p_css, u8 *p_challenge )
215 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
216 dvd_authinfo auth_info;
218 auth_info.type = DVD_LU_SEND_CHALLENGE;
219 auth_info.lsa.agid = p_css->i_agid;
221 i_ret = ioctl( p_css->i_fd, DVD_AUTH, &auth_info );
223 memcpy( p_challenge, auth_info.lsc.chal, sizeof(dvd_challenge) );
225 #elif defined( SYS_BEOS )
226 raw_device_command rdc;
229 BeInitRDC( &rdc, p_buffer, 16 );
231 rdc.flags = B_RAW_DEVICE_DATA_IN;
232 rdc.command[ 0 ] = GPCMD_REPORT_KEY;
233 rdc.command[ 10 ] = 0x01 | (p_css->i_agid << 6);
235 i_ret = ioctl( p_css->i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
237 memcpy( p_challenge, p_buffer + 4, 12 );
240 /* DVD ioctls unavailable - do as if the ioctl failed */
247 /*****************************************************************************
248 * ioctl_LUSendASF: get ASF from the drive
249 *****************************************************************************/
250 int ioctl_LUSendASF( css_t *p_css, int *pi_asf )
254 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
255 dvd_authinfo auth_info;
257 auth_info.type = DVD_LU_SEND_ASF;
258 auth_info.lsasf.agid = p_css->i_agid;
259 auth_info.lsasf.asf = *pi_asf;
261 i_ret = ioctl( p_css->i_fd, DVD_AUTH, &auth_info );
263 *pi_asf = auth_info.lsasf.asf;
265 #elif defined( SYS_BEOS )
266 raw_device_command rdc;
269 BeInitRDC( &rdc, p_buffer, 8 );
271 rdc.flags = B_RAW_DEVICE_DATA_IN;
272 rdc.command[ 0 ] = GPCMD_REPORT_KEY;
273 rdc.command[ 10 ] = 0x05 | (p_css->i_agid << 6);
275 i_ret = ioctl( p_css->i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
277 *pi_asf = p_buffer[ 7 ] & 1;
279 #elif defined( SYS_DARWIN1_3 )
280 dvdioctl_data_t data;
283 data.p_buffer = p_buffer;
285 data.i_agid = p_css->i_agid;
286 data.i_keyclass = kCSS_CSS2_CPRM;
287 data.i_keyformat = kASF;
289 i_ret = ioctl( p_css->i_fd, IODVD_REPORT_KEY, &data );
291 *pi_asf = p_buffer[ 7 ] & 1;
294 /* DVD ioctls unavailable - do as if the ioctl failed */
301 /*****************************************************************************
302 * ioctl_LUSendKey1: get the first key from the drive
303 *****************************************************************************/
304 int ioctl_LUSendKey1( css_t *p_css, u8 *p_key )
308 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
309 dvd_authinfo auth_info;
311 auth_info.type = DVD_LU_SEND_KEY1;
312 auth_info.lsk.agid = p_css->i_agid;
314 i_ret = ioctl( p_css->i_fd, DVD_AUTH, &auth_info );
316 memcpy( p_key, auth_info.lsk.key, sizeof(dvd_key) );
318 #elif defined( SYS_BEOS )
319 raw_device_command rdc;
322 BeInitRDC( &rdc, p_buffer, 12 );
324 rdc.flags = B_RAW_DEVICE_DATA_IN;
325 rdc.command[ 0 ] = GPCMD_REPORT_KEY;
326 rdc.command[ 10 ] = 0x02 | (p_css->i_agid << 6);
328 i_ret = ioctl( p_css->i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
330 memcpy( p_key, p_buffer + 4, 8 );
333 /* DVD ioctls unavailable - do as if the ioctl failed */
340 /*****************************************************************************
341 * ioctl_InvalidateAgid: invalidate the current AGID
342 *****************************************************************************/
343 int ioctl_InvalidateAgid( css_t *p_css )
347 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
348 dvd_authinfo auth_info;
350 auth_info.type = DVD_INVALIDATE_AGID;
351 auth_info.lsa.agid = p_css->i_agid;
353 i_ret = ioctl( p_css->i_fd, DVD_AUTH, &auth_info );
355 p_css->i_agid = auth_info.lsa.agid;
357 #elif defined( SYS_BEOS )
358 raw_device_command rdc;
361 BeInitRDC( &rdc, p_buffer, 0 );
363 rdc.flags = B_RAW_DEVICE_DATA_IN;
364 rdc.command[ 0 ] = GPCMD_REPORT_KEY;
365 rdc.command[ 10 ] = 0x3f | (p_css->i_agid << 6);
367 i_ret = ioctl( p_css->i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
370 /* DVD ioctls unavailable - do as if the ioctl failed */
377 /*****************************************************************************
378 * ioctl_HostSendChallenge: send challenge to the drive
379 *****************************************************************************/
380 int ioctl_HostSendChallenge( css_t *p_css, u8 *p_challenge )
382 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
383 dvd_authinfo auth_info;
385 auth_info.type = DVD_HOST_SEND_CHALLENGE;
386 auth_info.lsa.agid = p_css->i_agid;
388 memcpy( auth_info.hsc.chal, p_challenge, sizeof(dvd_challenge) );
390 return ioctl( p_css->i_fd, DVD_AUTH, &auth_info );
392 #elif defined( SYS_BEOS )
393 raw_device_command rdc;
396 BeInitRDC( &rdc, p_buffer, 16 );
398 rdc.command[ 0 ] = GPCMD_SEND_KEY;
399 rdc.command[ 10 ] = 0x01 | (p_css->i_agid << 6);
402 memcpy( p_buffer + 4, p_challenge, 12 );
404 return ioctl( p_css->i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
407 /* DVD ioctls unavailable - do as if the ioctl failed */
413 /*****************************************************************************
414 * ioctl_HostSendKey2: send the second key to the drive
415 *****************************************************************************/
416 int ioctl_HostSendKey2( css_t *p_css, u8 *p_key )
418 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
419 dvd_authinfo auth_info;
421 auth_info.type = DVD_HOST_SEND_KEY2;
422 auth_info.hsk.agid = p_css->i_agid;
424 memcpy( auth_info.hsk.key, p_key, sizeof(dvd_key) );
426 return ioctl( p_css->i_fd, DVD_AUTH, &auth_info );
428 #elif defined( SYS_BEOS )
429 raw_device_command rdc;
432 BeInitRDC( &rdc, p_buffer, 12 );
434 rdc.command[ 0 ] = GPCMD_REPORT_KEY;
435 rdc.command[ 10 ] = 0x3 | (p_css->i_agid << 6);
438 memcpy( p_buffer + 4, p_key, 8 );
440 return ioctl( p_css->i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
443 /* DVD ioctls unavailable - do as if the ioctl failed */
449 /* Local prototypes */
451 #if defined( SYS_BEOS )
452 /*****************************************************************************
453 * BeInitRDC: initialize a RDC structure for the BeOS kernel
454 *****************************************************************************
455 * This function initializes a BeOS raw device command structure for future
456 * use, either a read command or a write command.
457 *****************************************************************************/
458 static void BeInitRDC( raw_device_command *p_rdc, void *p_buffer, int i_len )
460 memset( p_rdc, 0, sizeof( raw_device_command ) );
461 memset( p_buffer, 0, i_len );
463 p_rdc->command[ 8 ] = (i_len >> 8) & 0xff;
464 p_rdc->command[ 9 ] = i_len & 0xff;
465 p_rdc->command_length = 12;
467 p_rdc->data = (char *)p_buffer;
468 p_rdc->data_length = i_len;
470 p_rdc->sense_data = NULL;
471 p_rdc->sense_data_length = 0;
473 p_rdc->timeout = 1000000;