1 /*****************************************************************************
2 * dvd_ioctl.c: DVD ioctl replacement function
3 *****************************************************************************
4 * Copyright (C) 1999-2001 VideoLAN
5 * $Id: dvd_ioctl.c,v 1.4 2001/04/02 23:30:41 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>
32 #ifdef HAVE_SYS_DVDIO_H
33 # include <sys/ioctl.h>
34 # include <sys/dvdio.h>
37 # include <sys/ioctl.h>
38 # include <linux/cdrom.h>
41 # include <sys/ioctl.h>
46 # include <sys/ioctl.h>
47 # include <DVDioctl/DVDioctl.h>
54 #include "dvd_ioctl.h"
56 /*****************************************************************************
57 * Local prototypes - BeOS specific
58 *****************************************************************************/
59 #if defined( SYS_BEOS )
60 static void InitCommand ( struct cdrom_generic_command *p_cgc,
61 void *buf, int i_len, int i_type );
62 static int SendCommand ( int i_fd, struct cdrom_generic_command *p_cgc );
65 /*****************************************************************************
67 *****************************************************************************
69 *****************************************************************************/
70 int dvd_ReadKey( css_t *p_css, u8 *p_key )
72 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
76 dvd.type = DVD_STRUCT_DISCKEY;
77 dvd.disckey.agid = p_css->i_agid;
79 memset( dvd.disckey.value, 0, 2048 );
81 i_ret = ioctl( p_css->i_fd, DVD_READ_STRUCT, &dvd );
88 memcpy( p_key, dvd.disckey.value, 2048 );
91 #elif defined( SYS_BEOS )
94 struct cdrom_generic_command cgc;
98 InitCommand( &cgc, p_buf, size, CGC_DATA_READ );
100 cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;
102 cgc.cmd[7] = DVD_STRUCT_DISCKEY;
103 cgc.cmd[8] = size >> 8;
104 cgc.cmd[9] = size & 0xff;
105 cgc.cmd[10] = p_css->i_agid << 6;
107 i_ret = SendCommand( p_css->i_fd, &cgc );
114 memcpy( p_key, p_buf + 4, 2048 );
123 /*****************************************************************************
125 *****************************************************************************
127 *****************************************************************************/
128 int dvd_ReadCopyright( int i_fd, int i_layer, int *pi_copyright )
130 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
134 dvd.type = DVD_STRUCT_COPYRIGHT;
135 dvd.copyright.layer_num = i_layer;
137 i_ret = ioctl( i_fd, DVD_READ_STRUCT, &dvd );
139 *pi_copyright = dvd.copyright.cpst;
142 #elif defined( SYS_BEOS )
145 struct cdrom_generic_command cgc;
147 InitCommand( &cgc, p_buf, sizeof(p_buf), CGC_DATA_READ );
149 cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;
151 cgc.cmd[6] = i_layer;
152 cgc.cmd[7] = DVD_STRUCT_COPYRIGHT;
153 cgc.cmd[8] = cgc.buflen >> 8;
154 cgc.cmd[9] = cgc.buflen & 0xff;
156 i_ret = SendCommand( i_fd, &cgc );
158 *pi_copyright = p_buf[4];
161 #elif defined( SYS_DARWIN1_3 )
162 intf_ErrMsg( "css error: DVD ioctls not fully functional yet" );
163 intf_ErrMsg( "css error: assuming disc is unencrypted" );
174 /*****************************************************************************
176 *****************************************************************************
178 *****************************************************************************/
179 int dvd_LUSendAgid( css_t *p_css )
181 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
183 dvd_authinfo auth_info;
185 auth_info.type = DVD_LU_SEND_AGID;
186 auth_info.lsa.agid = p_css->i_agid;
188 i_ret = ioctl( p_css->i_fd, DVD_AUTH, &auth_info );
190 p_css->i_agid = auth_info.lsa.agid;
193 #elif defined( SYS_BEOS )
196 struct cdrom_generic_command cgc;
198 //memset( p_buf, 0, sizeof( p_buf ) );
200 InitCommand( &cgc, p_buf, 0, CGC_DATA_READ );
202 cgc.cmd[0] = GPCMD_REPORT_KEY;
203 cgc.cmd[10] = 0x00 | (p_css->i_agid << 6);
205 cgc.cmd[9] = cgc.buflen;
206 cgc.data_direction = CGC_DATA_READ;
208 i_ret = SendCommand( p_css->i_fd, &cgc );
210 p_css->i_agid = p_buf[7] >> 6;
219 /*****************************************************************************
220 * dvd_InvalidateAgid:
221 *****************************************************************************
223 *****************************************************************************/
224 int dvd_InvalidateAgid( css_t *p_css )
226 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
228 dvd_authinfo auth_info;
230 auth_info.type = DVD_INVALIDATE_AGID;
231 auth_info.lsa.agid = p_css->i_agid;
233 i_ret = ioctl( p_css->i_fd, DVD_AUTH, &auth_info );
235 p_css->i_agid = auth_info.lsa.agid;
238 #elif defined( SYS_BEOS )
240 struct cdrom_generic_command cgc;
242 //memset( p_buf, 0, sizeof( p_buf ) );
244 InitCommand( &cgc, p_buf, 0, CGC_DATA_READ );
246 cgc.cmd[0] = GPCMD_REPORT_KEY;
247 cgc.cmd[10] = 0x3f | (p_css->i_agid << 6);
248 cgc.cmd[9] = cgc.buflen = 0;
249 cgc.data_direction = CGC_DATA_READ;
251 return SendCommand( p_css->i_fd, &cgc );
259 /*****************************************************************************
260 * dvd_HostSendChallenge:
261 *****************************************************************************
263 *****************************************************************************/
264 int dvd_HostSendChallenge( css_t *p_css, u8 *p_challenge )
266 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
267 dvd_authinfo auth_info;
269 auth_info.type = DVD_HOST_SEND_CHALLENGE;
271 memcpy( auth_info.hsc.chal, p_challenge, sizeof(dvd_challenge) );
273 return ioctl( p_css->i_fd, DVD_AUTH, &auth_info );
275 #elif defined( SYS_BEOS )
277 struct cdrom_generic_command cgc;
279 //memset( p_buf, 0, sizeof( p_buf ) );
281 InitCommand( &cgc, p_buf, 0, CGC_DATA_READ );
283 cgc.cmd[0] = GPCMD_SEND_KEY;
284 cgc.cmd[10] = 0x01 | (p_css->i_agid << 6);
286 cgc.cmd[9] = cgc.buflen;
287 cgc.data_direction = CGC_DATA_WRITE;
290 memcpy( p_buf + 4, p_challenge, sizeof(dvd_challenge) );
292 return SendCommand( p_css->i_fd, &cgc );
300 /*****************************************************************************
302 *****************************************************************************
304 *****************************************************************************/
305 int dvd_LUSendASF( css_t *p_css, int *pi_asf )
307 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
309 dvd_authinfo auth_info;
311 auth_info.type = DVD_LU_SEND_ASF;
312 auth_info.lsasf.agid = p_css->i_agid;
313 auth_info.lsasf.asf = *pi_asf;
315 i_ret = ioctl( p_css->i_fd, DVD_AUTH, &auth_info );
317 *pi_asf = auth_info.lsasf.asf;
320 #elif defined( SYS_BEOS )
323 struct cdrom_generic_command cgc;
325 //memset( p_buf, 0, sizeof( p_buf ) );
327 InitCommand( &cgc, p_buf, 0, CGC_DATA_READ );
329 cgc.cmd[0] = GPCMD_REPORT_KEY;
330 cgc.cmd[10] = 0x05 | (p_css->i_agid << 6);
332 cgc.cmd[9] = cgc.buflen;
333 cgc.data_direction = CGC_DATA_READ;
335 i_ret = SendCommand( p_css->i_fd, &cgc );
337 *pi_asf = p_buf[7] & 1;
346 /*****************************************************************************
347 * dvd_LUSendChallenge:
348 *****************************************************************************
350 *****************************************************************************/
351 int dvd_LUSendChallenge( css_t *p_css, u8 *p_challenge )
353 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
355 dvd_authinfo auth_info;
357 auth_info.type = DVD_LU_SEND_CHALLENGE;
359 i_ret = ioctl( p_css->i_fd, DVD_AUTH, &auth_info );
361 memcpy( p_challenge, auth_info.lsc.chal, sizeof(dvd_challenge) );
364 #elif defined( SYS_BEOS )
367 struct cdrom_generic_command cgc;
369 //memset( p_buf, 0, sizeof( p_buf ) );
371 InitCommand( &cgc, p_buf, 0, CGC_DATA_READ );
373 cgc.cmd[0] = GPCMD_REPORT_KEY;
374 cgc.cmd[10] = 0x01 | (p_css->i_agid << 6);
376 cgc.cmd[9] = cgc.buflen;
377 cgc.data_direction = CGC_DATA_READ;
379 i_ret = SendCommand( p_css->i_fd, &cgc );
381 memcpy( p_challenge, p_buf + 4, sizeof(dvd_challenge) );
390 /*****************************************************************************
392 *****************************************************************************
394 *****************************************************************************/
395 int dvd_LUSendKey1( css_t *p_css, u8 *p_key )
397 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
399 dvd_authinfo auth_info;
401 auth_info.type = DVD_LU_SEND_KEY1;
402 auth_info.lsk.agid = p_css->i_agid;
404 i_ret = ioctl( p_css->i_fd, DVD_AUTH, &auth_info );
406 memcpy( p_key, auth_info.lsk.key, sizeof(dvd_key) );
409 #elif defined( SYS_BEOS )
412 struct cdrom_generic_command cgc;
414 //memset( p_buf, 0, sizeof( p_buf ) );
416 InitCommand( &cgc, p_buf, 0, CGC_DATA_READ );
418 cgc.cmd[0] = GPCMD_REPORT_KEY;
419 cgc.cmd[10] = 0x02 | (p_css->i_agid << 6);
421 cgc.cmd[9] = cgc.buflen;
422 cgc.data_direction = CGC_DATA_READ;
424 i_ret = SendCommand( p_css->i_fd, &cgc );
426 memcpy( p_key, p_buf + 4, sizeof(dvd_key) );
435 /*****************************************************************************
437 *****************************************************************************
439 *****************************************************************************/
440 int dvd_HostSendKey2( css_t *p_css, u8 *p_key )
442 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
443 dvd_authinfo auth_info;
445 auth_info.type = DVD_HOST_SEND_KEY2;
446 auth_info.hsk.agid = p_css->i_agid;
448 memcpy( auth_info.hsk.key, p_key, sizeof(dvd_key) );
450 return ioctl( p_css->i_fd, DVD_AUTH, &auth_info );
452 #elif defined( SYS_BEOS )
454 struct cdrom_generic_command cgc;
456 //memset( p_buf, 0, sizeof( p_buf ) );
458 InitCommand( &cgc, p_buf, 0, CGC_DATA_READ );
460 cgc.cmd[0] = GPCMD_SEND_KEY;
461 cgc.cmd[10] = 0x3 | (p_css->i_agid << 6);
463 cgc.cmd[9] = cgc.buflen;
464 cgc.data_direction = CGC_DATA_WRITE;
467 memcpy( p_buf + 4, p_key, sizeof(dvd_key) );
469 return SendCommand( p_css->i_fd, &cgc );
477 /* Local prototypes */
479 #if defined( SYS_BEOS )
480 /*****************************************************************************
481 * InitCommand: initialize a CGC structure
482 *****************************************************************************
483 * This function initializes a CDRom Generic Command structure for
484 * future use, either a read command or a write command.
485 *****************************************************************************/
486 static void InitCommand( struct cdrom_generic_command *p_cgc,
487 void *p_buf, int i_len, int i_type )
489 memset( p_cgc, 0, sizeof( struct cdrom_generic_command ) );
493 memset( p_buf, 0, i_len );
496 p_cgc->buffer = ( char * )p_buf;
497 p_cgc->buflen = i_len;
498 p_cgc->data_direction = i_type;
499 p_cgc->timeout = 255;
502 /*****************************************************************************
503 * SendCommand: send a raw device command to the DVD drive.
504 *****************************************************************************
505 * This is the most important part of the ioctl emulation, the place where
506 * data is really sent to the DVD.
507 *****************************************************************************/
508 static int SendCommand( int i_fd, struct cdrom_generic_command *p_cgc )
512 raw_device_command rdc;
513 memset( &rdc, 0, sizeof( rdc ) );
515 /* fill out our raw device command data */
516 rdc.data = p_cgc->buffer;
517 rdc.data_length = p_cgc->buflen;
518 rdc.sense_data = p_cgc->sense;
519 rdc.sense_data_length = 0;
520 rdc.timeout = 1000000;
522 if( p_cgc->data_direction == CGC_DATA_READ )
524 intf_WarnMsg( 2, "css: data_direction == CGC_DATA_READ" );
525 rdc.flags = B_RAW_DEVICE_DATA_IN;
528 rdc.command_length = 12;
530 /* FIXME: check if this _really_ should go up to [12] */
531 for( i = 0 ; i < 13 ; i++ )
533 rdc.command[i] = p_cgc->cmd[i];
536 return ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );