]> git.sesse.net Git - vlc/blob - plugins/dvd/dvd_ioctl.c
* fixes for the Qt plugin compilation under Debian
[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.4 2001/04/02 23:30:41 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 <sys/types.h>
31 #include <netinet/in.h>
32 #ifdef HAVE_SYS_DVDIO_H
33 #   include <sys/ioctl.h>
34 #   include <sys/dvdio.h>
35 #endif
36 #ifdef LINUX_DVD
37 #   include <sys/ioctl.h>
38 #   include <linux/cdrom.h>
39 #endif
40 #ifdef SYS_BEOS
41 #   include <sys/ioctl.h>
42 #   include <malloc.h>
43 #   include <scsi.h>
44 #endif
45 #ifdef SYS_DARWIN1_3
46 #   include <sys/ioctl.h>
47 #   include <DVDioctl/DVDioctl.h>
48 #endif
49
50 #include "common.h"
51 #include "intf_msg.h"
52
53 #include "dvd_css.h"
54 #include "dvd_ioctl.h"
55
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 );
63 #endif
64
65 /*****************************************************************************
66  * dvd_ReadKey: 
67  *****************************************************************************
68  * 
69  *****************************************************************************/
70 int dvd_ReadKey( css_t *p_css, u8 *p_key )
71 {
72 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
73     int i_ret;
74     dvd_struct dvd;
75
76     dvd.type = DVD_STRUCT_DISCKEY;
77     dvd.disckey.agid = p_css->i_agid;
78
79     memset( dvd.disckey.value, 0, 2048 );
80
81     i_ret = ioctl( p_css->i_fd, DVD_READ_STRUCT, &dvd );
82
83     if( i_ret < 0 )
84     {
85         return i_ret;
86     }
87
88     memcpy( p_key, dvd.disckey.value, 2048 );
89     return i_ret;
90
91 #elif defined( SYS_BEOS )
92     int i_ret, size;
93     u8 p_buf[ 2048 + 4];
94     struct cdrom_generic_command cgc;
95
96     size = 2048 + 4;
97
98     InitCommand( &cgc, p_buf, size, CGC_DATA_READ );
99
100     cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;
101
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;
106
107     i_ret = SendCommand( p_css->i_fd, &cgc );
108
109     if( i_ret < 0 )
110     {
111         return i_ret;
112     }
113
114     memcpy( p_key, p_buf + 4, 2048 );
115     return i_ret;
116
117 #else
118     return -1;
119
120 #endif
121 }
122
123 /*****************************************************************************
124  * dvd_ReadCopyright: 
125  *****************************************************************************
126  * 
127  *****************************************************************************/
128 int dvd_ReadCopyright( int i_fd, int i_layer, int *pi_copyright )
129 {
130 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
131     int i_ret;
132     dvd_struct dvd;
133
134     dvd.type = DVD_STRUCT_COPYRIGHT;
135     dvd.copyright.layer_num = i_layer;
136
137     i_ret = ioctl( i_fd, DVD_READ_STRUCT, &dvd );
138
139     *pi_copyright = dvd.copyright.cpst;
140     return i_ret;
141
142 #elif defined( SYS_BEOS )
143     int i_ret;
144     u8 p_buf[8];
145     struct cdrom_generic_command cgc;
146
147     InitCommand( &cgc, p_buf, sizeof(p_buf), CGC_DATA_READ );
148
149     cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;
150
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;
155
156     i_ret = SendCommand( i_fd, &cgc );
157
158     *pi_copyright = p_buf[4];
159     return i_ret;
160
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" );
164
165     *pi_copyright = 0;
166     return 0;
167
168 #else
169     return -1;
170
171 #endif
172 }
173
174 /*****************************************************************************
175  * dvd_LUSendAgid: 
176  *****************************************************************************
177  * 
178  *****************************************************************************/
179 int dvd_LUSendAgid( css_t *p_css )
180 {
181 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
182     int i_ret;
183     dvd_authinfo auth_info;
184
185     auth_info.type = DVD_LU_SEND_AGID;
186     auth_info.lsa.agid = p_css->i_agid;
187
188     i_ret = ioctl( p_css->i_fd, DVD_AUTH, &auth_info );
189
190     p_css->i_agid = auth_info.lsa.agid;
191     return i_ret;
192
193 #elif defined( SYS_BEOS )
194     u8 p_buf[8];
195     int i_ret;
196     struct cdrom_generic_command cgc;
197
198     //memset( p_buf, 0, sizeof( p_buf ) );
199
200     InitCommand( &cgc, p_buf, 0, CGC_DATA_READ );
201
202     cgc.cmd[0] = GPCMD_REPORT_KEY;
203     cgc.cmd[10] = 0x00 | (p_css->i_agid << 6);
204     cgc.buflen = 8;
205     cgc.cmd[9] = cgc.buflen;
206     cgc.data_direction = CGC_DATA_READ;
207
208     i_ret = SendCommand( p_css->i_fd, &cgc );
209
210     p_css->i_agid = p_buf[7] >> 6;
211     return i_ret;
212
213 #else
214     return -1;
215
216 #endif
217 }
218
219 /*****************************************************************************
220  * dvd_InvalidateAgid: 
221  *****************************************************************************
222  * 
223  *****************************************************************************/
224 int dvd_InvalidateAgid( css_t *p_css )
225 {
226 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
227     int i_ret;
228     dvd_authinfo auth_info;
229
230     auth_info.type = DVD_INVALIDATE_AGID;
231     auth_info.lsa.agid = p_css->i_agid;
232
233     i_ret = ioctl( p_css->i_fd, DVD_AUTH, &auth_info );
234
235     p_css->i_agid = auth_info.lsa.agid;
236     return i_ret;
237
238 #elif defined( SYS_BEOS )
239     u8 p_buf[0];
240     struct cdrom_generic_command cgc;
241
242     //memset( p_buf, 0, sizeof( p_buf ) );
243
244     InitCommand( &cgc, p_buf, 0, CGC_DATA_READ );
245
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;
250
251     return SendCommand( p_css->i_fd, &cgc );
252
253 #else
254     return -1;
255
256 #endif
257 }
258
259 /*****************************************************************************
260  * dvd_HostSendChallenge: 
261  *****************************************************************************
262  * 
263  *****************************************************************************/
264 int dvd_HostSendChallenge( css_t *p_css, u8 *p_challenge )
265 {
266 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
267     dvd_authinfo auth_info;
268
269     auth_info.type = DVD_HOST_SEND_CHALLENGE;
270
271     memcpy( auth_info.hsc.chal, p_challenge, sizeof(dvd_challenge) );
272
273     return ioctl( p_css->i_fd, DVD_AUTH, &auth_info );
274
275 #elif defined( SYS_BEOS )
276     u8 p_buf[16];
277     struct cdrom_generic_command cgc;
278
279     //memset( p_buf, 0, sizeof( p_buf ) );
280
281     InitCommand( &cgc, p_buf, 0, CGC_DATA_READ );
282
283     cgc.cmd[0] = GPCMD_SEND_KEY;
284     cgc.cmd[10] = 0x01 | (p_css->i_agid << 6);
285     cgc.buflen = 16;
286     cgc.cmd[9] = cgc.buflen;
287     cgc.data_direction = CGC_DATA_WRITE;
288
289     p_buf[1] = 0xe;
290     memcpy( p_buf + 4, p_challenge, sizeof(dvd_challenge) );
291
292     return SendCommand( p_css->i_fd, &cgc );
293
294 #else
295     return -1;
296
297 #endif
298 }
299
300 /*****************************************************************************
301  * dvd_LUSendASF: 
302  *****************************************************************************
303  * 
304  *****************************************************************************/
305 int dvd_LUSendASF( css_t *p_css, int *pi_asf )
306 {
307 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
308     int i_ret;
309     dvd_authinfo auth_info;
310
311     auth_info.type = DVD_LU_SEND_ASF;
312     auth_info.lsasf.agid = p_css->i_agid;
313     auth_info.lsasf.asf = *pi_asf;
314
315     i_ret = ioctl( p_css->i_fd, DVD_AUTH, &auth_info );
316
317     *pi_asf = auth_info.lsasf.asf;
318     return i_ret;
319
320 #elif defined( SYS_BEOS )
321     int i_ret;
322     u8 p_buf[8];
323     struct cdrom_generic_command cgc;
324
325     //memset( p_buf, 0, sizeof( p_buf ) );
326
327     InitCommand( &cgc, p_buf, 0, CGC_DATA_READ );
328
329     cgc.cmd[0] = GPCMD_REPORT_KEY;
330     cgc.cmd[10] = 0x05 | (p_css->i_agid << 6);
331     cgc.buflen = 8;
332     cgc.cmd[9] = cgc.buflen;
333     cgc.data_direction = CGC_DATA_READ;
334
335     i_ret = SendCommand( p_css->i_fd, &cgc );
336
337     *pi_asf = p_buf[7] & 1;
338     return i_ret;
339
340 #else
341     return -1;
342
343 #endif
344 }
345
346 /*****************************************************************************
347  * dvd_LUSendChallenge: 
348  *****************************************************************************
349  * 
350  *****************************************************************************/
351 int dvd_LUSendChallenge( css_t *p_css, u8 *p_challenge )
352 {
353 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
354     int i_ret;
355     dvd_authinfo auth_info;
356
357     auth_info.type = DVD_LU_SEND_CHALLENGE;
358
359     i_ret = ioctl( p_css->i_fd, DVD_AUTH, &auth_info );
360
361     memcpy( p_challenge, auth_info.lsc.chal, sizeof(dvd_challenge) );
362     return i_ret;
363
364 #elif defined( SYS_BEOS )
365     int i_ret;
366     u8 p_buf[16];
367     struct cdrom_generic_command cgc;
368
369     //memset( p_buf, 0, sizeof( p_buf ) );
370
371     InitCommand( &cgc, p_buf, 0, CGC_DATA_READ );
372
373     cgc.cmd[0] = GPCMD_REPORT_KEY;
374     cgc.cmd[10] = 0x01 | (p_css->i_agid << 6);
375     cgc.buflen = 16;
376     cgc.cmd[9] = cgc.buflen;
377     cgc.data_direction = CGC_DATA_READ;
378
379     i_ret = SendCommand( p_css->i_fd, &cgc );
380
381     memcpy( p_challenge, p_buf + 4, sizeof(dvd_challenge) );
382     return i_ret;
383
384 #else
385     return -1;
386
387 #endif
388 }
389
390 /*****************************************************************************
391  * dvd_LUSendKey1: 
392  *****************************************************************************
393  * 
394  *****************************************************************************/
395 int dvd_LUSendKey1( css_t *p_css, u8 *p_key )
396 {
397 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
398     int i_ret;
399     dvd_authinfo auth_info;
400
401     auth_info.type = DVD_LU_SEND_KEY1;
402     auth_info.lsk.agid = p_css->i_agid;
403
404     i_ret = ioctl( p_css->i_fd, DVD_AUTH, &auth_info );
405
406     memcpy( p_key, auth_info.lsk.key, sizeof(dvd_key) );
407     return i_ret;
408
409 #elif defined( SYS_BEOS )
410     int i_ret;
411     u8 p_buf[12];
412     struct cdrom_generic_command cgc;
413
414     //memset( p_buf, 0, sizeof( p_buf ) );
415
416     InitCommand( &cgc, p_buf, 0, CGC_DATA_READ );
417
418     cgc.cmd[0] = GPCMD_REPORT_KEY;
419     cgc.cmd[10] = 0x02 | (p_css->i_agid << 6);
420     cgc.buflen = 12;
421     cgc.cmd[9] = cgc.buflen;
422     cgc.data_direction = CGC_DATA_READ;
423
424     i_ret = SendCommand( p_css->i_fd, &cgc );
425
426     memcpy( p_key, p_buf + 4, sizeof(dvd_key) );
427     return i_ret;
428
429 #else
430     return -1;
431
432 #endif
433 }
434
435 /*****************************************************************************
436  * dvd_HostSendKey2: 
437  *****************************************************************************
438  * 
439  *****************************************************************************/
440 int dvd_HostSendKey2( css_t *p_css, u8 *p_key )
441 {
442 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
443     dvd_authinfo auth_info;
444
445     auth_info.type = DVD_HOST_SEND_KEY2;
446     auth_info.hsk.agid = p_css->i_agid;
447
448     memcpy( auth_info.hsk.key, p_key, sizeof(dvd_key) );
449
450     return ioctl( p_css->i_fd, DVD_AUTH, &auth_info );
451
452 #elif defined( SYS_BEOS )
453     u8 p_buf[12];
454     struct cdrom_generic_command cgc;
455
456     //memset( p_buf, 0, sizeof( p_buf ) );
457
458     InitCommand( &cgc, p_buf, 0, CGC_DATA_READ );
459
460     cgc.cmd[0] = GPCMD_SEND_KEY;
461     cgc.cmd[10] = 0x3 | (p_css->i_agid << 6);
462     cgc.buflen = 12;
463     cgc.cmd[9] = cgc.buflen;
464     cgc.data_direction = CGC_DATA_WRITE;
465
466     p_buf[1] = 0xa;
467     memcpy( p_buf + 4, p_key, sizeof(dvd_key) );
468
469     return SendCommand( p_css->i_fd, &cgc );
470
471 #else
472     return -1;
473
474 #endif
475 }
476
477 /* Local prototypes */
478
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 )
488 {
489     memset( p_cgc, 0, sizeof( struct cdrom_generic_command ) );
490
491     if( p_buf != NULL )
492     {
493         memset( p_buf, 0, i_len );
494     }
495
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;
500 }
501
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 )
509 {
510     int i;
511
512     raw_device_command rdc;
513     memset( &rdc, 0, sizeof( rdc ) );
514
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;
521
522     if( p_cgc->data_direction == CGC_DATA_READ )
523     {
524         intf_WarnMsg( 2, "css: data_direction == CGC_DATA_READ" );
525         rdc.flags = B_RAW_DEVICE_DATA_IN;
526     }
527
528     rdc.command_length = 12;
529
530     /* FIXME: check if this _really_ should go up to [12] */
531     for( i = 0 ; i < 13 ; i++ )
532     {
533         rdc.command[i] = p_cgc->cmd[i];
534     }
535
536     return ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
537 }
538 #endif
539