]> git.sesse.net Git - vlc/blob - plugins/dvd/dvd_ioctl.c
* Mandatory step for video output IV and the audio output quality
[vlc] / plugins / dvd / dvd_ioctl.c
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 $
6  *
7  * Authors: Markus Kuespert <ltlBeBoy@beosmail.com>
8  *          Samuel Hocevar <sam@zoy.org>
9  *
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.
14  *
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.
19  *
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  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #include "defs.h"
29
30 #include <string.h>                                    /* memcpy(), memset() */
31 #include <sys/types.h>
32 #include <netinet/in.h>
33
34 #ifdef HAVE_SYS_DVDIO_H
35 #   include <sys/ioctl.h>
36 #   include <sys/dvdio.h>
37 #endif
38 #ifdef LINUX_DVD
39 #   include <sys/ioctl.h>
40 #   include <linux/cdrom.h>
41 #endif
42 #ifdef SYS_BEOS
43 #   include <sys/ioctl.h>
44 #   include <malloc.h>
45 #   include <scsi.h>
46 #endif
47 #ifdef SYS_DARWIN1_3
48 #   include <sys/ioctl.h>
49 #endif
50
51 #include "common.h"
52
53 #include "intf_msg.h"
54
55 #ifdef SYS_DARWIN1_3
56 #   include "DVDioctl/DVDioctl.h"
57 #endif
58
59 #include "dvd_css.h"
60 #include "dvd_ioctl.h"
61
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) );
71 #endif
72
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 )
77 {
78     int i_ret;
79
80 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
81     dvd_struct dvd;
82
83     dvd.type = DVD_STRUCT_COPYRIGHT;
84     dvd.copyright.layer_num = i_layer;
85
86     i_ret = ioctl( i_fd, DVD_READ_STRUCT, &dvd );
87
88     *pi_copyright = dvd.copyright.cpst;
89
90 #elif defined( SYS_BEOS )
91     INIT_RDC( GPCMD_READ_DVD_STRUCTURE, 8 );
92
93     rdc.command[ 6 ] = i_layer;
94     rdc.command[ 7 ] = DVD_STRUCT_COPYRIGHT;
95
96     i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
97
98     *pi_copyright = p_buffer[ 4 ];
99
100 #elif defined( SYS_DARWIN1_3 )
101     intf_ErrMsg( "css error: DVD ioctls not fully functional yet" );
102
103     intf_ErrMsg( "css error: assuming disc is unencrypted" );
104     *pi_copyright = 0;
105
106     i_ret = 0;
107
108 #else
109     /* DVD ioctls unavailable - do as if the ioctl failed */
110     i_ret = -1;
111
112 #endif
113     return i_ret;
114 }
115
116 /*****************************************************************************
117  * ioctl_ReadKey: get the disc key
118  *****************************************************************************/
119 int ioctl_ReadKey( int i_fd, int *pi_agid, u8 *p_key )
120 {
121     int i_ret;
122
123 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
124     dvd_struct dvd;
125
126     dvd.type = DVD_STRUCT_DISCKEY;
127     dvd.disckey.agid = *pi_agid;
128
129     memset( dvd.disckey.value, 0, 2048 );
130
131     i_ret = ioctl( i_fd, DVD_READ_STRUCT, &dvd );
132
133     if( i_ret < 0 )
134     {
135         return i_ret;
136     }
137
138     memcpy( p_key, dvd.disckey.value, 2048 );
139
140 #elif defined( SYS_BEOS )
141     INIT_RDC( GPCMD_READ_DVD_STRUCTURE, 2048 + 4 );
142
143     rdc.command[ 7 ]  = DVD_STRUCT_DISCKEY;
144     rdc.command[ 10 ] = *pi_agid << 6;
145     
146     i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
147
148     if( i_ret < 0 )
149     {
150         return i_ret;
151     }
152
153     memcpy( p_key, p_buffer + 4, 2048 );
154
155 #else
156     /* DVD ioctls unavailable - do as if the ioctl failed */
157     i_ret = -1;
158
159 #endif
160     return i_ret;
161 }
162
163 /*****************************************************************************
164  * ioctl_LUSendAgid: get AGID from the drive
165  *****************************************************************************/
166 int ioctl_LUSendAgid( int i_fd, int *pi_agid )
167 {
168     int i_ret;
169
170 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
171     dvd_authinfo auth_info;
172
173     auth_info.type = DVD_LU_SEND_AGID;
174     auth_info.lsa.agid = *pi_agid;
175
176     i_ret = ioctl( i_fd, DVD_AUTH, &auth_info );
177
178     *pi_agid = auth_info.lsa.agid;
179
180 #elif defined( SYS_BEOS )
181     INIT_RDC( GPCMD_REPORT_KEY, 8 );
182
183     rdc.command[ 10 ] = 0x00 | (*pi_agid << 6);
184
185     i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
186
187     *pi_agid = p_buffer[ 7 ] >> 6;
188
189 #else
190     /* DVD ioctls unavailable - do as if the ioctl failed */
191     i_ret = -1;
192
193 #endif
194     return i_ret;
195 }
196
197 /*****************************************************************************
198  * ioctl_LUSendChallenge: get challenge from the drive
199  *****************************************************************************/
200 int ioctl_LUSendChallenge( int i_fd, int *pi_agid, u8 *p_challenge )
201 {
202     int i_ret;
203
204 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
205     dvd_authinfo auth_info;
206
207     auth_info.type = DVD_LU_SEND_CHALLENGE;
208     auth_info.lsc.agid = *pi_agid;
209
210     i_ret = ioctl( i_fd, DVD_AUTH, &auth_info );
211
212     memcpy( p_challenge, auth_info.lsc.chal, sizeof(dvd_challenge) );
213
214 #elif defined( SYS_BEOS )
215     INIT_RDC( GPCMD_REPORT_KEY, 16 );
216
217     rdc.command[ 10 ] = 0x01 | (*pi_agid << 6);
218
219     i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
220
221     memcpy( p_challenge, p_buffer + 4, 12 );
222
223 #else
224     /* DVD ioctls unavailable - do as if the ioctl failed */
225     i_ret = -1;
226
227 #endif
228     return i_ret;
229 }
230
231 /*****************************************************************************
232  * ioctl_LUSendASF: get ASF from the drive
233  *****************************************************************************/
234 int ioctl_LUSendASF( int i_fd, int *pi_agid, int *pi_asf )
235 {
236     int i_ret;
237
238 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
239     dvd_authinfo auth_info;
240
241     auth_info.type = DVD_LU_SEND_ASF;
242     auth_info.lsasf.agid = *pi_agid;
243     auth_info.lsasf.asf = *pi_asf;
244
245     i_ret = ioctl( i_fd, DVD_AUTH, &auth_info );
246
247     *pi_asf = auth_info.lsasf.asf;
248
249 #elif defined( SYS_BEOS )
250     INIT_RDC( GPCMD_REPORT_KEY, 8 );
251
252     rdc.command[ 10 ] = 0x05 | (*pi_agid << 6);
253
254     i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
255
256     *pi_asf = p_buffer[ 7 ] & 1;
257
258 #elif defined( SYS_DARWIN1_3 )
259     dvdioctl_data_t data;
260     u8 p_buffer[ 8 ];
261
262     data.p_buffer = p_buffer;
263     data.i_lba = 0;
264     data.i_agid = *pi_agid;
265     data.i_keyclass = kCSS_CSS2_CPRM;
266     data.i_keyformat = kASF;
267
268     i_ret = ioctl( i_fd, IODVD_REPORT_KEY, &data );
269
270     *pi_asf = p_buffer[ 7 ] & 1;
271
272 #else
273     /* DVD ioctls unavailable - do as if the ioctl failed */
274     i_ret = -1;
275
276 #endif
277     return i_ret;
278 }
279
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 )
284 {
285     int i_ret;
286
287 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
288     dvd_authinfo auth_info;
289
290     auth_info.type = DVD_LU_SEND_KEY1;
291     auth_info.lsk.agid = *pi_agid;
292
293     i_ret = ioctl( i_fd, DVD_AUTH, &auth_info );
294
295     memcpy( p_key, auth_info.lsk.key, sizeof(dvd_key) );
296
297 #elif defined( SYS_BEOS )
298     INIT_RDC( GPCMD_REPORT_KEY, 12 );
299
300     rdc.command[ 10 ] = 0x02 | (*pi_agid << 6);
301
302     i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
303
304     memcpy( p_key, p_buffer + 4, 8 );
305
306 #else
307     /* DVD ioctls unavailable - do as if the ioctl failed */
308     i_ret = -1;
309
310 #endif
311     return i_ret;
312 }
313
314 /*****************************************************************************
315  * ioctl_InvalidateAgid: invalidate the current AGID
316  *****************************************************************************/
317 int ioctl_InvalidateAgid( int i_fd, int *pi_agid )
318 {
319     int i_ret;
320
321 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
322     dvd_authinfo auth_info;
323
324     auth_info.type = DVD_INVALIDATE_AGID;
325     auth_info.lsa.agid = *pi_agid;
326
327     i_ret = ioctl( i_fd, DVD_AUTH, &auth_info );
328
329     *pi_agid = auth_info.lsa.agid;
330
331 #elif defined( SYS_BEOS )
332     INIT_RDC( GPCMD_REPORT_KEY, 0 );
333
334     rdc.command[ 10 ] = 0x3f | (*pi_agid << 6);
335
336     i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
337
338 #else
339     /* DVD ioctls unavailable - do as if the ioctl failed */
340     i_ret = -1;
341
342 #endif
343     return i_ret;
344 }
345
346 /*****************************************************************************
347  * ioctl_HostSendChallenge: send challenge to the drive
348  *****************************************************************************/
349 int ioctl_HostSendChallenge( int i_fd, int *pi_agid, u8 *p_challenge )
350 {
351 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
352     dvd_authinfo auth_info;
353
354     auth_info.type = DVD_HOST_SEND_CHALLENGE;
355     auth_info.hsc.agid = *pi_agid;
356
357     memcpy( auth_info.hsc.chal, p_challenge, sizeof(dvd_challenge) );
358
359     return ioctl( i_fd, DVD_AUTH, &auth_info );
360
361 #elif defined( SYS_BEOS )
362     INIT_RDC( GPCMD_SEND_KEY, 16 );
363
364     rdc.command[ 10 ] = 0x01 | (*pi_agid << 6);
365
366     p_buffer[ 1 ] = 0xe;
367     memcpy( p_buffer + 4, p_challenge, 12 );
368
369     return ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
370
371 #else
372     /* DVD ioctls unavailable - do as if the ioctl failed */
373     return -1;
374
375 #endif
376 }
377
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 )
382 {
383 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
384     dvd_authinfo auth_info;
385
386     auth_info.type = DVD_HOST_SEND_KEY2;
387     auth_info.hsk.agid = *pi_agid;
388
389     memcpy( auth_info.hsk.key, p_key, sizeof(dvd_key) );
390
391     return ioctl( i_fd, DVD_AUTH, &auth_info );
392
393 #elif defined( SYS_BEOS )
394     INIT_RDC( GPCMD_SEND_KEY, 12 );
395
396     rdc.command[ 10 ] = 0x3 | (*pi_agid << 6);
397
398     p_buffer[ 1 ] = 0xa;
399     memcpy( p_buffer + 4, p_key, 8 );
400
401     return ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
402
403 #else
404     /* DVD ioctls unavailable - do as if the ioctl failed */
405     return -1;
406
407 #endif
408 }
409
410 /* Local prototypes */
411
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 )
421 {
422     memset( p_rdc, 0, sizeof( raw_device_command ) );
423     memset( p_buffer, 0, i_len );
424
425     switch( i_type )
426     {
427         case GPCMD_SEND_KEY:
428             /* leave the flags to 0 */
429             break;
430
431         case GPCMD_READ_DVD_STRUCTURE:
432         case GPCMD_REPORT_KEY:
433             p_rdc->flags = B_RAW_DEVICE_DATA_IN;
434             break;
435     }
436
437     p_rdc->command[ 0 ]      = i_type;
438
439     p_rdc->command[ 8 ]      = (i_len >> 8) & 0xff;
440     p_rdc->command[ 9 ]      =  i_len       & 0xff;
441     p_rdc->command_length    = 12;
442
443     p_rdc->data              = (char *)p_buffer;
444     p_rdc->data_length       = i_len;
445
446     p_rdc->sense_data        = NULL;
447     p_rdc->sense_data_length = 0;
448
449     p_rdc->timeout           = 1000000;
450 }
451 #endif
452