]> git.sesse.net Git - vlc/blob - plugins/dvd/dvd_ioctl.c
ba99236274862e1bb36b0e2ecae786563d438255
[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.8 2001/04/08 09:04:33 stef 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 );
67 #endif
68
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 )
73 {
74     int i_ret;
75
76 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
77     dvd_struct dvd;
78
79     dvd.type = DVD_STRUCT_COPYRIGHT;
80     dvd.copyright.layer_num = i_layer;
81
82     i_ret = ioctl( i_fd, DVD_READ_STRUCT, &dvd );
83
84     *pi_copyright = dvd.copyright.cpst;
85
86 #elif defined( SYS_BEOS )
87     raw_device_command rdc;
88     u8 p_buffer[ 8 ];
89
90     BeInitRDC( &rdc, p_buffer, 8 );
91
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;
96
97     i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
98
99     *pi_copyright = p_buffer[ 4 ];
100
101 #elif defined( SYS_DARWIN1_3 )
102     intf_ErrMsg( "css error: DVD ioctls not fully functional yet" );
103
104     intf_ErrMsg( "css error: assuming disc is unencrypted" );
105     *pi_copyright = 0;
106
107     i_ret = 0;
108
109 #else
110     /* DVD ioctls unavailable - do as if the ioctl failed */
111     i_ret = -1;
112
113 #endif
114     return i_ret;
115 }
116
117 /*****************************************************************************
118  * ioctl_ReadKey: get the disc key
119  *****************************************************************************/
120 int ioctl_ReadKey( css_t *p_css, u8 *p_key )
121 {
122     int i_ret;
123
124 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
125     dvd_struct dvd;
126
127     dvd.type = DVD_STRUCT_DISCKEY;
128     dvd.disckey.agid = p_css->i_agid;
129
130     memset( dvd.disckey.value, 0, 2048 );
131
132     i_ret = ioctl( p_css->i_fd, DVD_READ_STRUCT, &dvd );
133
134     if( i_ret < 0 )
135     {
136         return i_ret;
137     }
138
139     memcpy( p_key, dvd.disckey.value, 2048 );
140
141 #elif defined( SYS_BEOS )
142     raw_device_command rdc;
143     u8 p_buffer[ 2048 + 4 ];
144
145     BeInitRDC( &rdc, p_buffer, 2048 + 4 );
146
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;
151     
152     i_ret = ioctl( p_css->i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
153
154     if( i_ret < 0 )
155     {
156         return i_ret;
157     }
158
159     memcpy( p_key, p_buffer + 4, 2048 );
160
161 #else
162     /* DVD ioctls unavailable - do as if the ioctl failed */
163     i_ret = -1;
164
165 #endif
166     return i_ret;
167 }
168
169 /*****************************************************************************
170  * ioctl_LUSendAgid: get AGID from the drive
171  *****************************************************************************/
172 int ioctl_LUSendAgid( css_t *p_css )
173 {
174     int i_ret;
175
176 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
177     dvd_authinfo auth_info;
178
179     auth_info.type = DVD_LU_SEND_AGID;
180     auth_info.lsa.agid = p_css->i_agid;
181
182     i_ret = ioctl( p_css->i_fd, DVD_AUTH, &auth_info );
183
184     p_css->i_agid = auth_info.lsa.agid;
185
186 #elif defined( SYS_BEOS )
187     raw_device_command rdc;
188     u8 p_buffer[ 8 ];
189
190     BeInitRDC( &rdc, p_buffer, 8 );
191
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);
195
196     i_ret = ioctl( p_css->i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
197
198     p_css->i_agid = p_buffer[ 7 ] >> 6;
199
200 #else
201     /* DVD ioctls unavailable - do as if the ioctl failed */
202     i_ret = -1;
203
204 #endif
205     return i_ret;
206 }
207
208 /*****************************************************************************
209  * ioctl_LUSendChallenge: get challenge from the drive
210  *****************************************************************************/
211 int ioctl_LUSendChallenge( css_t *p_css, u8 *p_challenge )
212 {
213     int i_ret;
214
215 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
216     dvd_authinfo auth_info;
217
218     auth_info.type = DVD_LU_SEND_CHALLENGE;
219     auth_info.lsa.agid = p_css->i_agid;
220
221     i_ret = ioctl( p_css->i_fd, DVD_AUTH, &auth_info );
222
223     memcpy( p_challenge, auth_info.lsc.chal, sizeof(dvd_challenge) );
224
225 #elif defined( SYS_BEOS )
226     raw_device_command rdc;
227     u8 p_buffer[ 16 ];
228
229     BeInitRDC( &rdc, p_buffer, 16 );
230
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);
234
235     i_ret = ioctl( p_css->i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
236
237     memcpy( p_challenge, p_buffer + 4, 12 );
238
239 #else
240     /* DVD ioctls unavailable - do as if the ioctl failed */
241     i_ret = -1;
242
243 #endif
244     return i_ret;
245 }
246
247 /*****************************************************************************
248  * ioctl_LUSendASF: get ASF from the drive
249  *****************************************************************************/
250 int ioctl_LUSendASF( css_t *p_css, int *pi_asf )
251 {
252     int i_ret;
253
254 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
255     dvd_authinfo auth_info;
256
257     auth_info.type = DVD_LU_SEND_ASF;
258     auth_info.lsasf.agid = p_css->i_agid;
259     auth_info.lsasf.asf = *pi_asf;
260
261     i_ret = ioctl( p_css->i_fd, DVD_AUTH, &auth_info );
262
263     *pi_asf = auth_info.lsasf.asf;
264
265 #elif defined( SYS_BEOS )
266     raw_device_command rdc;
267     u8 p_buffer[ 8 ];
268
269     BeInitRDC( &rdc, p_buffer, 8 );
270
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);
274
275     i_ret = ioctl( p_css->i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
276
277     *pi_asf = p_buffer[ 7 ] & 1;
278
279 #elif defined( SYS_DARWIN1_3 )
280     dvdioctl_data_t data;
281     u8 p_buffer[ 8 ];
282
283     data.p_buffer = p_buffer;
284     data.i_lba = 0;
285     data.i_agid = p_css->i_agid;
286     data.i_keyclass = kCSS_CSS2_CPRM;
287     data.i_keyformat = kASF;
288
289     i_ret = ioctl( p_css->i_fd, IODVD_REPORT_KEY, &data );
290
291     *pi_asf = p_buffer[ 7 ] & 1;
292
293 #else
294     /* DVD ioctls unavailable - do as if the ioctl failed */
295     i_ret = -1;
296
297 #endif
298     return i_ret;
299 }
300
301 /*****************************************************************************
302  * ioctl_LUSendKey1: get the first key from the drive
303  *****************************************************************************/
304 int ioctl_LUSendKey1( css_t *p_css, u8 *p_key )
305 {
306     int i_ret;
307
308 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
309     dvd_authinfo auth_info;
310
311     auth_info.type = DVD_LU_SEND_KEY1;
312     auth_info.lsk.agid = p_css->i_agid;
313
314     i_ret = ioctl( p_css->i_fd, DVD_AUTH, &auth_info );
315
316     memcpy( p_key, auth_info.lsk.key, sizeof(dvd_key) );
317
318 #elif defined( SYS_BEOS )
319     raw_device_command rdc;
320     u8 p_buffer[ 12 ];
321
322     BeInitRDC( &rdc, p_buffer, 12 );
323
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);
327
328     i_ret = ioctl( p_css->i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
329
330     memcpy( p_key, p_buffer + 4, 8 );
331
332 #else
333     /* DVD ioctls unavailable - do as if the ioctl failed */
334     i_ret = -1;
335
336 #endif
337     return i_ret;
338 }
339
340 /*****************************************************************************
341  * ioctl_InvalidateAgid: invalidate the current AGID
342  *****************************************************************************/
343 int ioctl_InvalidateAgid( css_t *p_css )
344 {
345     int i_ret;
346
347 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
348     dvd_authinfo auth_info;
349
350     auth_info.type = DVD_INVALIDATE_AGID;
351     auth_info.lsa.agid = p_css->i_agid;
352
353     i_ret = ioctl( p_css->i_fd, DVD_AUTH, &auth_info );
354
355     p_css->i_agid = auth_info.lsa.agid;
356
357 #elif defined( SYS_BEOS )
358     raw_device_command rdc;
359     u8 p_buffer[ 0 ];
360
361     BeInitRDC( &rdc, p_buffer, 0 );
362
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);
366
367     i_ret = ioctl( p_css->i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
368
369 #else
370     /* DVD ioctls unavailable - do as if the ioctl failed */
371     i_ret = -1;
372
373 #endif
374     return i_ret;
375 }
376
377 /*****************************************************************************
378  * ioctl_HostSendChallenge: send challenge to the drive
379  *****************************************************************************/
380 int ioctl_HostSendChallenge( css_t *p_css, u8 *p_challenge )
381 {
382 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
383     dvd_authinfo auth_info;
384
385     auth_info.type = DVD_HOST_SEND_CHALLENGE;
386     auth_info.lsa.agid = p_css->i_agid;
387
388     memcpy( auth_info.hsc.chal, p_challenge, sizeof(dvd_challenge) );
389
390     return ioctl( p_css->i_fd, DVD_AUTH, &auth_info );
391
392 #elif defined( SYS_BEOS )
393     raw_device_command rdc;
394     u8 p_buffer[ 16 ];
395
396     BeInitRDC( &rdc, p_buffer, 16 );
397
398     rdc.command[ 0 ]  = GPCMD_SEND_KEY;
399     rdc.command[ 10 ] = 0x01 | (p_css->i_agid << 6);
400
401     p_buffer[ 1 ] = 0xe;
402     memcpy( p_buffer + 4, p_challenge, 12 );
403
404     return ioctl( p_css->i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
405
406 #else
407     /* DVD ioctls unavailable - do as if the ioctl failed */
408     return -1;
409
410 #endif
411 }
412
413 /*****************************************************************************
414  * ioctl_HostSendKey2: send the second key to the drive
415  *****************************************************************************/
416 int ioctl_HostSendKey2( css_t *p_css, u8 *p_key )
417 {
418 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
419     dvd_authinfo auth_info;
420
421     auth_info.type = DVD_HOST_SEND_KEY2;
422     auth_info.hsk.agid = p_css->i_agid;
423
424     memcpy( auth_info.hsk.key, p_key, sizeof(dvd_key) );
425
426     return ioctl( p_css->i_fd, DVD_AUTH, &auth_info );
427
428 #elif defined( SYS_BEOS )
429     raw_device_command rdc;
430     u8 p_buffer[ 12 ];
431
432     BeInitRDC( &rdc, p_buffer, 12 );
433
434     rdc.command[ 0 ]  = GPCMD_REPORT_KEY;
435     rdc.command[ 10 ] = 0x3 | (p_css->i_agid << 6);
436
437     p_buffer[ 1 ] = 0xa;
438     memcpy( p_buffer + 4, p_key, 8 );
439
440     return ioctl( p_css->i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
441
442 #else
443     /* DVD ioctls unavailable - do as if the ioctl failed */
444     return -1;
445
446 #endif
447 }
448
449 /* Local prototypes */
450
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 )
459 {
460     memset( p_rdc, 0, sizeof( raw_device_command ) );
461     memset( p_buffer, 0, i_len );
462
463     p_rdc->command[ 8 ]      = (i_len >> 8) & 0xff;
464     p_rdc->command[ 9 ]      =  i_len       & 0xff;
465     p_rdc->command_length    = 12;
466
467     p_rdc->data              = (char *)p_buffer;
468     p_rdc->data_length       = i_len;
469
470     p_rdc->sense_data        = NULL;
471     p_rdc->sense_data_length = 0;
472
473     p_rdc->timeout           = 1000000;
474 }
475
476 #endif
477