1 /*****************************************************************************
2 * dvd_ioctl.c: DVD ioctl replacement function
3 *****************************************************************************
4 * Copyright (C) 1999-2001 VideoLAN
5 * $Id: dvd_ioctl.c,v 1.6 2001/04/04 16:33:07 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 <sys/types.h>
31 #include <netinet/in.h>
33 #ifdef HAVE_SYS_DVDIO_H
34 # include <sys/ioctl.h>
35 # include <sys/dvdio.h>
38 # include <sys/ioctl.h>
39 # include <linux/cdrom.h>
42 # include <sys/ioctl.h>
47 # include <sys/ioctl.h>
55 # include "DVDioctl/DVDioctl.h"
59 #include "dvd_ioctl.h"
61 /*****************************************************************************
62 * Local prototypes - BeOS specific
63 *****************************************************************************/
64 #if defined( SYS_BEOS )
65 static void BeInitRDC ( raw_device_command *, void *, int );
68 /*****************************************************************************
69 * ioctl_ReadCopyright: check whether the disc is encrypted or not
70 *****************************************************************************/
71 int ioctl_ReadCopyright( int i_fd, int i_layer, int *pi_copyright )
75 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
78 dvd.type = DVD_STRUCT_COPYRIGHT;
79 dvd.copyright.layer_num = i_layer;
81 i_ret = ioctl( i_fd, DVD_READ_STRUCT, &dvd );
83 *pi_copyright = dvd.copyright.cpst;
85 #elif defined( SYS_BEOS )
86 raw_device_command rdc;
89 BeInitRDC( &rdc, p_buffer, 8 );
91 rdc.flags = B_RAW_DEVICE_DATA_IN;
92 rdc.command[ 0 ] = GPCMD_READ_DVD_STRUCTURE;
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( css_t *p_css, u8 *p_key )
123 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
126 dvd.type = DVD_STRUCT_DISCKEY;
127 dvd.disckey.agid = p_css->i_agid;
129 memset( dvd.disckey.value, 0, 2048 );
131 i_ret = ioctl( p_css->i_fd, DVD_READ_STRUCT, &dvd );
138 memcpy( p_key, dvd.disckey.value, 2048 );
140 #elif defined( SYS_BEOS )
141 raw_device_command rdc;
142 u8 p_buffer[ 2048 + 4 ];
144 BeInitRDC( &rdc, p_buffer, 2048 + 4 );
146 rdc.flags = B_RAW_DEVICE_DATA_IN;
147 rdc.command[ 0 ] = GPCMD_READ_DVD_STRUCTURE;
148 rdc.command[ 7 ] = DVD_STRUCT_DISCKEY;
149 rdc.command[ 10 ] = p_css->i_agid << 6;
151 i_ret = ioctl( p_css->i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
158 memcpy( p_key, p_buffer + 4, 2048 );
161 /* DVD ioctls unavailable - do as if the ioctl failed */
168 /*****************************************************************************
169 * ioctl_LUSendAgid: get AGID from the drive
170 *****************************************************************************/
171 int ioctl_LUSendAgid( css_t *p_css )
175 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
176 dvd_authinfo auth_info;
178 auth_info.type = DVD_LU_SEND_AGID;
179 auth_info.lsa.agid = p_css->i_agid;
181 i_ret = ioctl( p_css->i_fd, DVD_AUTH, &auth_info );
183 p_css->i_agid = auth_info.lsa.agid;
185 #elif defined( SYS_BEOS )
186 raw_device_command rdc;
189 BeInitRDC( &rdc, p_buffer, 8 );
191 rdc.flags = B_RAW_DEVICE_DATA_IN;
192 rdc.command[ 0 ] = GPCMD_REPORT_KEY;
193 rdc.command[ 10 ] = 0x00 | (p_css->i_agid << 6);
195 i_ret = ioctl( p_css->i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
197 p_css->i_agid = p_buffer[ 7 ] >> 6;
200 /* DVD ioctls unavailable - do as if the ioctl failed */
207 /*****************************************************************************
208 * ioctl_LUSendChallenge: get challenge from the drive
209 *****************************************************************************/
210 int ioctl_LUSendChallenge( css_t *p_css, u8 *p_challenge )
214 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
215 dvd_authinfo auth_info;
217 auth_info.type = DVD_LU_SEND_CHALLENGE;
219 i_ret = ioctl( p_css->i_fd, DVD_AUTH, &auth_info );
221 memcpy( p_challenge, auth_info.lsc.chal, sizeof(dvd_challenge) );
223 #elif defined( SYS_BEOS )
224 raw_device_command rdc;
227 BeInitRDC( &rdc, p_buffer, 16 );
229 rdc.flags = B_RAW_DEVICE_DATA_IN;
230 rdc.command[ 0 ] = GPCMD_REPORT_KEY;
231 rdc.command[ 10 ] = 0x01 | (p_css->i_agid << 6);
233 i_ret = ioctl( p_css->i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
235 memcpy( p_challenge, p_buffer + 4, 12 );
238 /* DVD ioctls unavailable - do as if the ioctl failed */
245 /*****************************************************************************
246 * ioctl_LUSendASF: get ASF from the drive
247 *****************************************************************************/
248 int ioctl_LUSendASF( css_t *p_css, int *pi_asf )
252 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
253 dvd_authinfo auth_info;
255 auth_info.type = DVD_LU_SEND_ASF;
256 auth_info.lsasf.agid = p_css->i_agid;
257 auth_info.lsasf.asf = *pi_asf;
259 i_ret = ioctl( p_css->i_fd, DVD_AUTH, &auth_info );
261 *pi_asf = auth_info.lsasf.asf;
263 #elif defined( SYS_BEOS )
264 raw_device_command rdc;
267 BeInitRDC( &rdc, p_buffer, 8 );
269 rdc.flags = B_RAW_DEVICE_DATA_IN;
270 rdc.command[ 0 ] = GPCMD_REPORT_KEY;
271 rdc.command[ 10 ] = 0x05 | (p_css->i_agid << 6);
273 i_ret = ioctl( p_css->i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
275 *pi_asf = p_buffer[ 7 ] & 1;
277 #elif defined( SYS_DARWIN1_3 )
278 dvdioctl_data_t data;
281 data.p_buffer = p_buffer;
283 data.i_agid = p_css->i_agid;
284 data.i_keyclass = kCSS_CSS2_CPRM;
285 data.i_keyformat = kASF;
287 i_ret = ioctl( p_css->i_fd, IODVD_REPORT_KEY, &data );
289 *pi_asf = p_buffer[ 7 ] & 1;
292 /* DVD ioctls unavailable - do as if the ioctl failed */
299 /*****************************************************************************
300 * ioctl_LUSendKey1: get the first key from the drive
301 *****************************************************************************/
302 int ioctl_LUSendKey1( css_t *p_css, u8 *p_key )
306 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
307 dvd_authinfo auth_info;
309 auth_info.type = DVD_LU_SEND_KEY1;
310 auth_info.lsk.agid = p_css->i_agid;
312 i_ret = ioctl( p_css->i_fd, DVD_AUTH, &auth_info );
314 memcpy( p_key, auth_info.lsk.key, sizeof(dvd_key) );
316 #elif defined( SYS_BEOS )
317 raw_device_command rdc;
320 BeInitRDC( &rdc, p_buffer, 12 );
322 rdc.flags = B_RAW_DEVICE_DATA_IN;
323 rdc.command[ 0 ] = GPCMD_REPORT_KEY;
324 rdc.command[ 10 ] = 0x02 | (p_css->i_agid << 6);
326 i_ret = ioctl( p_css->i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
328 memcpy( p_key, p_buffer + 4, 8 );
331 /* DVD ioctls unavailable - do as if the ioctl failed */
338 /*****************************************************************************
339 * ioctl_InvalidateAgid: invalidate the current AGID
340 *****************************************************************************/
341 int ioctl_InvalidateAgid( css_t *p_css )
345 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
346 dvd_authinfo auth_info;
348 auth_info.type = DVD_INVALIDATE_AGID;
349 auth_info.lsa.agid = p_css->i_agid;
351 i_ret = ioctl( p_css->i_fd, DVD_AUTH, &auth_info );
353 p_css->i_agid = auth_info.lsa.agid;
355 #elif defined( SYS_BEOS )
356 raw_device_command rdc;
359 BeInitRDC( &rdc, p_buffer, 0 );
361 rdc.flags = B_RAW_DEVICE_DATA_IN;
362 rdc.command[ 0 ] = GPCMD_REPORT_KEY;
363 rdc.command[ 10 ] = 0x3f | (p_css->i_agid << 6);
365 i_ret = ioctl( p_css->i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
368 /* DVD ioctls unavailable - do as if the ioctl failed */
375 /*****************************************************************************
376 * ioctl_HostSendChallenge: send challenge to the drive
377 *****************************************************************************/
378 int ioctl_HostSendChallenge( css_t *p_css, u8 *p_challenge )
380 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
381 dvd_authinfo auth_info;
383 auth_info.type = DVD_HOST_SEND_CHALLENGE;
385 memcpy( auth_info.hsc.chal, p_challenge, sizeof(dvd_challenge) );
387 return ioctl( p_css->i_fd, DVD_AUTH, &auth_info );
389 #elif defined( SYS_BEOS )
390 raw_device_command rdc;
393 BeInitRDC( &rdc, p_buffer, 16 );
395 rdc.command[ 0 ] = GPCMD_SEND_KEY;
396 rdc.command[ 10 ] = 0x01 | (p_css->i_agid << 6);
399 memcpy( p_buffer + 4, p_challenge, 12 );
401 return ioctl( p_css->i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
404 /* DVD ioctls unavailable - do as if the ioctl failed */
410 /*****************************************************************************
411 * ioctl_HostSendKey2: send the second key to the drive
412 *****************************************************************************/
413 int ioctl_HostSendKey2( css_t *p_css, u8 *p_key )
415 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
416 dvd_authinfo auth_info;
418 auth_info.type = DVD_HOST_SEND_KEY2;
419 auth_info.hsk.agid = p_css->i_agid;
421 memcpy( auth_info.hsk.key, p_key, sizeof(dvd_key) );
423 return ioctl( p_css->i_fd, DVD_AUTH, &auth_info );
425 #elif defined( SYS_BEOS )
426 raw_device_command rdc;
429 BeInitRDC( &rdc, p_buffer, 12 );
431 rdc.command[ 0 ] = GPCMD_REPORT_KEY;
432 rdc.command[ 10 ] = 0x3 | (p_css->i_agid << 6);
435 memcpy( p_buffer + 4, p_key, 8 );
437 return ioctl( p_css->i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
440 /* DVD ioctls unavailable - do as if the ioctl failed */
446 /* Local prototypes */
448 #if defined( SYS_BEOS )
449 /*****************************************************************************
450 * BeInitRDC: initialize a RDC structure for the BeOS kernel
451 *****************************************************************************
452 * This function initializes a BeOS raw device command structure for future
453 * use, either a read command or a write command.
454 *****************************************************************************/
455 static void BeInitRDC( raw_device_command *p_rdc, void *p_buffer, int i_len )
457 memset( p_rdc, 0, sizeof( raw_device_command ) );
458 memset( p_buffer, 0, i_len );
460 p_rdc->command[ 8 ] = (i_len >> 8) & 0xff;
461 p_rdc->command[ 9 ] = i_len & 0xff;
462 p_rdc->command_length = 12;
464 p_rdc->data = (char *)p_buffer;
465 p_rdc->data_length = i_len;
467 p_rdc->sense_data = NULL;
468 p_rdc->sense_data_length = 0;
470 p_rdc->timeout = 1000000;