]> git.sesse.net Git - vlc/blob - plugins/dvd/dvd_ioctl.c
OS X fixes:
[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.12 2001/05/25 04:23:37 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 #include <sys/ioctl.h>
35
36 #ifdef DVD_STRUCT_IN_SYS_CDIO_H
37 #   include <sys/cdio.h>
38 #endif
39 #ifdef DVD_STRUCT_IN_SYS_DVDIO_H
40 #   include <sys/dvdio.h>
41 #endif
42 #ifdef DVD_STRUCT_IN_LINUX_CDROM_H
43 #   include <linux/cdrom.h>
44 #endif
45 #ifdef SYS_BEOS
46 #   include <malloc.h>
47 #   include <scsi.h>
48 #endif
49
50 #include "common.h"
51
52 #include "intf_msg.h"
53
54 #ifdef SYS_DARWIN1_3
55 #   include "DVDioctl/DVDioctl.h"
56 #endif
57
58 #include "dvd_css.h"
59 #include "dvd_ioctl.h"
60
61 /*****************************************************************************
62  * Local prototypes, BeOS specific
63  *****************************************************************************/
64 #if defined( SYS_BEOS )
65 static void BeInitRDC ( raw_device_command *, int );
66 #define INIT_RDC( TYPE, SIZE ) \
67     raw_device_command rdc; \
68     u8 p_buffer[ (SIZE) ]; \
69     rdc.data = (char *)p_buffer; \
70     rdc.data_length = (SIZE); \
71     BeInitRDC( &rdc, (TYPE) );
72 #endif
73
74 /*****************************************************************************
75  * Local prototypes, Darwin specific
76  *****************************************************************************/
77 #if defined( SYS_DARWIN1_3 )
78 #define INIT_DVDIOCTL( SIZE ) \
79     dvdioctl_data_t dvdioctl; \
80     u8 p_buffer[ (SIZE) ]; \
81     dvdioctl.p_buffer = p_buffer; \
82     dvdioctl.i_size = (SIZE); \
83     dvdioctl.i_keyclass = kCSS_CSS2_CPRM; \
84     memset( p_buffer, 0, (SIZE) );
85 #endif
86
87 /*****************************************************************************
88  * ioctl_ReadCopyright: check whether the disc is encrypted or not
89  *****************************************************************************/
90 int ioctl_ReadCopyright( int i_fd, int i_layer, int *pi_copyright )
91 {
92     int i_ret;
93
94 #if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
95     dvd_struct dvd;
96
97     dvd.type = DVD_STRUCT_COPYRIGHT;
98     dvd.copyright.layer_num = i_layer;
99
100     i_ret = ioctl( i_fd, DVD_READ_STRUCT, &dvd );
101
102     *pi_copyright = dvd.copyright.cpst;
103
104 #elif defined( HAVE_BSD_DVD_STRUCT )
105     struct dvd_struct dvd;
106
107     dvd.format = DVD_STRUCT_COPYRIGHT;
108     dvd.layer_num = i_layer;
109
110     i_ret = ioctl( i_fd, DVDIOCREADSTRUCTURE, &dvd );
111
112     *pi_copyright = dvd.cpst;
113
114 #elif defined( SYS_BEOS )
115     INIT_RDC( GPCMD_READ_DVD_STRUCTURE, 8 );
116
117     rdc.command[ 6 ] = i_layer;
118     rdc.command[ 7 ] = DVD_STRUCT_COPYRIGHT;
119
120     i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
121
122     *pi_copyright = p_buffer[ 4 ];
123
124 #elif defined( SYS_DARWIN1_3 )
125     intf_ErrMsg( "css error: DVD ioctls not fully functional yet" );
126     intf_ErrMsg( "css error: assuming disc is encrypted" );
127
128     *pi_copyright = 1;
129
130     i_ret = 0;
131
132 #else
133     /* DVD ioctls unavailable - do as if the ioctl failed */
134     i_ret = -1;
135
136 #endif
137     return i_ret;
138 }
139
140 /*****************************************************************************
141  * ioctl_ReadKey: get the disc key
142  *****************************************************************************/
143 int ioctl_ReadKey( int i_fd, int *pi_agid, u8 *p_key )
144 {
145     int i_ret;
146
147 #if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
148     dvd_struct dvd;
149
150     dvd.type = DVD_STRUCT_DISCKEY;
151     dvd.disckey.agid = *pi_agid;
152     memset( dvd.disckey.value, 0, 2048 );
153
154     i_ret = ioctl( i_fd, DVD_READ_STRUCT, &dvd );
155
156     if( i_ret < 0 )
157     {
158         return i_ret;
159     }
160
161     memcpy( p_key, dvd.disckey.value, 2048 );
162
163 #elif defined( HAVE_BSD_DVD_STRUCT )
164     struct dvd_struct dvd;
165
166     dvd.format = DVD_STRUCT_DISCKEY;
167     dvd.agid = *pi_agid;
168     memset( dvd.data, 0, 2048 );
169
170     i_ret = ioctl( i_fd, DVDIOCREADSTRUCTURE, &dvd );
171
172     if( i_ret < 0 )
173     {
174         return i_ret;
175     }
176
177     memcpy( p_key, dvd.data, 2048 );
178
179 #elif defined( SYS_BEOS )
180     INIT_RDC( GPCMD_READ_DVD_STRUCTURE, 2048 + 4 );
181
182     rdc.command[ 7 ]  = DVD_STRUCT_DISCKEY;
183     rdc.command[ 10 ] = *pi_agid << 6;
184     
185     i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
186
187     if( i_ret < 0 )
188     {
189         return i_ret;
190     }
191
192     memcpy( p_key, p_buffer + 4, 2048 );
193
194 #elif defined( SYS_DARWIN1_3 )
195     intf_ErrMsg( "css error: DVD ioctls not fully functional yet" );
196     intf_ErrMsg( "css error: sending an empty key" );
197
198     i_ret = 0;
199
200     memset( p_key, 0x00, 2048 );
201
202 #else
203     /* DVD ioctls unavailable - do as if the ioctl failed */
204     i_ret = -1;
205
206 #endif
207     return i_ret;
208 }
209
210 /*****************************************************************************
211  * ioctl_ReportAgid: get AGID from the drive
212  *****************************************************************************/
213 int ioctl_ReportAgid( int i_fd, int *pi_agid )
214 {
215     int i_ret;
216
217 #if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
218     dvd_authinfo auth_info;
219
220     auth_info.type = DVD_LU_SEND_AGID;
221     auth_info.lsa.agid = *pi_agid;
222
223     i_ret = ioctl( i_fd, DVD_AUTH, &auth_info );
224
225     *pi_agid = auth_info.lsa.agid;
226
227 #elif defined( HAVE_BSD_DVD_STRUCT )
228     struct dvd_authinfo auth_info;
229
230     auth_info.format = DVD_REPORT_AGID;
231     auth_info.agid = *pi_agid;
232
233     i_ret = ioctl( i_fd, DVDIOCREPORTKEY, &auth_info );
234
235     *pi_agid = auth_info.agid;
236
237 #elif defined( SYS_BEOS )
238     INIT_RDC( GPCMD_REPORT_KEY, 8 );
239
240     rdc.command[ 10 ] = DVD_REPORT_AGID | (*pi_agid << 6);
241
242     i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
243
244     *pi_agid = p_buffer[ 7 ] >> 6;
245
246 #elif defined( SYS_DARWIN1_3 )
247     INIT_DVDIOCTL( 8 );
248
249     dvdioctl.i_keyformat = kCSSAGID;
250     dvdioctl.i_agid = *pi_agid;
251     dvdioctl.i_lba = 0;
252
253     i_ret = ioctl( i_fd, IODVD_REPORT_KEY, &dvdioctl );
254
255     *pi_asf = p_buffer[ 7 ] >> 6;
256
257 #else
258     /* DVD ioctls unavailable - do as if the ioctl failed */
259     i_ret = -1;
260
261 #endif
262     return i_ret;
263 }
264
265 /*****************************************************************************
266  * ioctl_ReportChallenge: get challenge from the drive
267  *****************************************************************************/
268 int ioctl_ReportChallenge( int i_fd, int *pi_agid, u8 *p_challenge )
269 {
270     int i_ret;
271
272 #if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
273     dvd_authinfo auth_info;
274
275     auth_info.type = DVD_LU_SEND_CHALLENGE;
276     auth_info.lsc.agid = *pi_agid;
277
278     i_ret = ioctl( i_fd, DVD_AUTH, &auth_info );
279
280     memcpy( p_challenge, auth_info.lsc.chal, sizeof(dvd_challenge) );
281
282 #elif defined( HAVE_BSD_DVD_STRUCT )
283     struct dvd_authinfo auth_info;
284
285     auth_info.format = DVD_REPORT_CHALLENGE;
286     auth_info.agid = *pi_agid;
287
288     i_ret = ioctl( i_fd, DVDIOCREPORTKEY, &auth_info );
289
290     memcpy( p_challenge, auth_info.keychal, 10 );
291
292 #elif defined( SYS_BEOS )
293     INIT_RDC( GPCMD_REPORT_KEY, 16 );
294
295     rdc.command[ 10 ] = DVD_REPORT_CHALLENGE | (*pi_agid << 6);
296
297     i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
298
299     memcpy( p_challenge, p_buffer + 4, 12 );
300
301 #elif defined( SYS_DARWIN1_3 )
302     INIT_DVDIOCTL( 16 );
303
304     dvdioctl.i_keyformat = kChallengeKey;
305     dvdioctl.i_agid = *pi_agid;
306     dvdioctl.i_lba = 0;
307
308     i_ret = ioctl( i_fd, IODVD_REPORT_KEY, &dvdioctl );
309
310     memcpy( p_challenge, p_buffer + 4, 12 );
311
312 #else
313     /* DVD ioctls unavailable - do as if the ioctl failed */
314     i_ret = -1;
315
316 #endif
317     return i_ret;
318 }
319
320 /*****************************************************************************
321  * ioctl_ReportASF: get ASF from the drive
322  *****************************************************************************/
323 int ioctl_ReportASF( int i_fd, int *pi_agid, int *pi_asf )
324 {
325     int i_ret;
326
327 #if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
328     dvd_authinfo auth_info;
329
330     auth_info.type = DVD_LU_SEND_ASF;
331     auth_info.lsasf.agid = *pi_agid;
332     auth_info.lsasf.asf = *pi_asf;
333
334     i_ret = ioctl( i_fd, DVD_AUTH, &auth_info );
335
336     *pi_asf = auth_info.lsasf.asf;
337
338 #elif defined( HAVE_BSD_DVD_STRUCT )
339     struct dvd_authinfo auth_info;
340
341     auth_info.format = DVD_REPORT_ASF;
342     auth_info.agid = *pi_agid;
343     auth_info.asf = *pi_asf;
344
345     i_ret = ioctl( i_fd, DVDIOCREPORTKEY, &auth_info );
346
347     *pi_asf = auth_info.asf;
348
349 #elif defined( SYS_BEOS )
350     INIT_RDC( GPCMD_REPORT_KEY, 8 );
351
352     rdc.command[ 10 ] = DVD_REPORT_ASF | (*pi_agid << 6);
353
354     i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
355
356     *pi_asf = p_buffer[ 7 ] & 1;
357
358 #elif defined( SYS_DARWIN1_3 )
359     INIT_DVDIOCTL( 8 );
360
361     dvdioctl.i_keyformat = kASF;
362     dvdioctl.i_agid = *pi_agid;
363     dvdioctl.i_lba = 0;
364
365     i_ret = ioctl( i_fd, IODVD_REPORT_KEY, &dvdioctl );
366
367     *pi_asf = p_buffer[ 7 ] & 1;
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_ReportKey1: get the first key from the drive
379  *****************************************************************************/
380 int ioctl_ReportKey1( int i_fd, int *pi_agid, u8 *p_key )
381 {
382     int i_ret;
383
384 #if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
385     dvd_authinfo auth_info;
386
387     auth_info.type = DVD_LU_SEND_KEY1;
388     auth_info.lsk.agid = *pi_agid;
389
390     i_ret = ioctl( i_fd, DVD_AUTH, &auth_info );
391
392     memcpy( p_key, auth_info.lsk.key, sizeof(dvd_key) );
393
394 #elif defined( HAVE_BSD_DVD_STRUCT )
395     struct dvd_authinfo auth_info;
396
397     auth_info.format = DVD_REPORT_KEY1;
398     auth_info.agid = *pi_agid;
399
400     i_ret = ioctl( i_fd, DVDIOCREPORTKEY, &auth_info );
401
402     memcpy( p_key, auth_info.keychal, 8 );
403
404 #elif defined( SYS_BEOS )
405     INIT_RDC( GPCMD_REPORT_KEY, 12 );
406
407     rdc.command[ 10 ] = DVD_REPORT_KEY1 | (*pi_agid << 6);
408
409     i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
410
411     memcpy( p_key, p_buffer + 4, 8 );
412
413 #elif defined( SYS_DARWIN1_3 )
414     INIT_DVDIOCTL( 12 );
415
416     dvdioctl.i_keyformat = kKey1;
417     dvdioctl.i_agid = *pi_agid;
418
419     i_ret = ioctl( i_fd, IODVD_SEND_KEY, &dvdioctl );
420
421     memcpy( p_key, p_buffer + 4, 8 );
422
423 #else
424     /* DVD ioctls unavailable - do as if the ioctl failed */
425     i_ret = -1;
426
427 #endif
428     return i_ret;
429 }
430
431 /*****************************************************************************
432  * ioctl_InvalidateAgid: invalidate the current AGID
433  *****************************************************************************/
434 int ioctl_InvalidateAgid( int i_fd, int *pi_agid )
435 {
436     int i_ret;
437
438 #if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
439     dvd_authinfo auth_info;
440
441     auth_info.type = DVD_INVALIDATE_AGID;
442     auth_info.lsa.agid = *pi_agid;
443
444     i_ret = ioctl( i_fd, DVD_AUTH, &auth_info );
445
446     *pi_agid = auth_info.lsa.agid;
447
448 #elif defined( HAVE_BSD_DVD_STRUCT )
449     struct dvd_authinfo auth_info;
450
451     auth_info.format = DVD_INVALIDATE_AGID;
452     auth_info.agid = *pi_agid;
453
454     i_ret = ioctl( i_fd, DVDIOCREPORTKEY, &auth_info );
455
456     *pi_agid = auth_info.agid;
457
458 #elif defined( SYS_BEOS )
459     INIT_RDC( GPCMD_REPORT_KEY, 0 );
460
461     rdc.command[ 10 ] = DVD_INVALIDATE_AGID | (*pi_agid << 6);
462
463     i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
464
465 #elif defined( SYS_DARWIN1_3 )
466     INIT_DVDIOCTL( 0 );
467
468     dvdioctl.i_keyformat = kInvalidateAGID;
469     dvdioctl.i_agid = *pi_agid;
470
471     i_ret = ioctl( i_fd, IODVD_SEND_KEY, &dvdioctl );
472
473 #else
474     /* DVD ioctls unavailable - do as if the ioctl failed */
475     i_ret = -1;
476
477 #endif
478     return i_ret;
479 }
480
481 /*****************************************************************************
482  * ioctl_SendChallenge: send challenge to the drive
483  *****************************************************************************/
484 int ioctl_SendChallenge( int i_fd, int *pi_agid, u8 *p_challenge )
485 {
486 #if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
487     dvd_authinfo auth_info;
488
489     auth_info.type = DVD_HOST_SEND_CHALLENGE;
490     auth_info.hsc.agid = *pi_agid;
491
492     memcpy( auth_info.hsc.chal, p_challenge, sizeof(dvd_challenge) );
493
494     return ioctl( i_fd, DVD_AUTH, &auth_info );
495
496 #elif defined( HAVE_BSD_DVD_STRUCT )
497     struct dvd_authinfo auth_info;
498
499     auth_info.format = DVD_SEND_CHALLENGE;
500     auth_info.agid = *pi_agid;
501
502     memcpy( auth_info.keychal, p_challenge, 12 );
503
504     return ioctl( i_fd, DVDIOCSENDKEY, &auth_info );
505
506 #elif defined( SYS_BEOS )
507     INIT_RDC( GPCMD_SEND_KEY, 16 );
508
509     rdc.command[ 10 ] = DVD_SEND_CHALLENGE | (*pi_agid << 6);
510
511     p_buffer[ 1 ] = 0xe;
512     memcpy( p_buffer + 4, p_challenge, 12 );
513
514     return ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
515
516 #elif defined( SYS_DARWIN1_3 )
517     INIT_DVDIOCTL( 16 );
518
519     dvdioctl.i_keyformat = kChallengeKey;
520     dvdioctl.i_agid = *pi_agid;
521
522     p_buffer[ 1 ] = 0xe;
523     memcpy( p_buffer + 4, p_challenge, 12 );
524
525     return ioctl( i_fd, IODVD_SEND_KEY, &dvdioctl );
526
527 #else
528     /* DVD ioctls unavailable - do as if the ioctl failed */
529     return -1;
530
531 #endif
532 }
533
534 /*****************************************************************************
535  * ioctl_SendKey2: send the second key to the drive
536  *****************************************************************************/
537 int ioctl_SendKey2( int i_fd, int *pi_agid, u8 *p_key )
538 {
539 #if defined( DVD_STRUCT_IN_LINUX_CDROM_H )
540     dvd_authinfo auth_info;
541
542     auth_info.type = DVD_HOST_SEND_KEY2;
543     auth_info.hsk.agid = *pi_agid;
544
545     memcpy( auth_info.hsk.key, p_key, sizeof(dvd_key) );
546
547     return ioctl( i_fd, DVD_AUTH, &auth_info );
548
549 #elif defined( HAVE_BSD_DVD_STRUCT )
550     struct dvd_authinfo auth_info;
551
552     auth_info.format = DVD_SEND_KEY2;
553     auth_info.agid = *pi_agid;
554
555     memcpy( auth_info.keychal, p_key, 8 );
556
557     return ioctl( i_fd, DVDIOCSENDKEY, &auth_info );
558
559 #elif defined( SYS_BEOS )
560     INIT_RDC( GPCMD_SEND_KEY, 12 );
561
562     rdc.command[ 10 ] = DVD_SEND_KEY2 | (*pi_agid << 6);
563
564     p_buffer[ 1 ] = 0xa;
565     memcpy( p_buffer + 4, p_key, 8 );
566
567     return ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
568
569 #elif defined( SYS_DARWIN1_3 )
570     INIT_DVDIOCTL( 12 );
571
572     dvdioctl.i_keyformat = kKey2;
573     dvdioctl.i_agid = *pi_agid;
574
575     p_buffer[ 1 ] = 0xa;
576     memcpy( p_buffer + 4, p_key, 8 );
577
578     return ioctl( i_fd, IODVD_SEND_KEY, &dvdioctl );
579
580 #else
581     /* DVD ioctls unavailable - do as if the ioctl failed */
582     return -1;
583
584 #endif
585 }
586
587 /* Local prototypes */
588
589 #if defined( SYS_BEOS )
590 /*****************************************************************************
591  * BeInitRDC: initialize a RDC structure for the BeOS kernel
592  *****************************************************************************
593  * This function initializes a BeOS raw device command structure for future
594  * use, either a read command or a write command.
595  *****************************************************************************/
596 static void BeInitRDC( raw_device_command *p_rdc, int i_type )
597 {
598     memset( p_rdc, 0, sizeof( raw_device_command ) );
599     memset( p_rdc->data, 0, p_rdc->data_length );
600
601     switch( i_type )
602     {
603         case GPCMD_SEND_KEY:
604             /* leave the flags to 0 */
605             break;
606
607         case GPCMD_READ_DVD_STRUCTURE:
608         case GPCMD_REPORT_KEY:
609             p_rdc->flags = B_RAW_DEVICE_DATA_IN;
610             break;
611     }
612
613     p_rdc->command[ 0 ]      = i_type;
614
615     p_rdc->command[ 8 ]      = (p_rdc->data_length >> 8) & 0xff;
616     p_rdc->command[ 9 ]      =  p_rdc->data_length       & 0xff;
617     p_rdc->command_length    = 12;
618
619     p_rdc->sense_data        = NULL;
620     p_rdc->sense_data_length = 0;
621
622     p_rdc->timeout           = 1000000;
623 }
624 #endif
625