comparison libdvdcss/device.c @ 35952:691431d2289e

Update internal libdvdcss to Git revision 39e0e2b.
author diego
date Sat, 23 Mar 2013 14:32:26 +0000
parents 3c0cf739f1e1
children
comparison
equal deleted inserted replaced
35951:9b4ba0fb999b 35952:691431d2289e
1 /***************************************************************************** 1 /*****************************************************************************
2 * device.h: DVD device access 2 * device.h: DVD device access
3 ***************************************************************************** 3 *****************************************************************************
4 * Copyright (C) 1998-2006 VideoLAN 4 * Copyright (C) 1998-2006 VideoLAN
5 * $Id$
6 * 5 *
7 * Authors: Stéphane Borel <stef@via.ecp.fr> 6 * Authors: Stéphane Borel <stef@via.ecp.fr>
8 * Sam Hocevar <sam@zoy.org> 7 * Sam Hocevar <sam@zoy.org>
9 * Håkan Hjort <d95hjort@dtek.chalmers.se> 8 * Håkan Hjort <d95hjort@dtek.chalmers.se>
10 * 9 *
47 46
48 #ifdef HAVE_LIMITS_H 47 #ifdef HAVE_LIMITS_H
49 # include <limits.h> 48 # include <limits.h>
50 #endif 49 #endif
51 50
52 #if defined( WIN32 ) && !defined( SYS_CYGWIN )
53 # include <io.h> /* read() */
54 #else
55 # include <sys/uio.h> /* struct iovec */
56 #endif
57
58 #ifdef DARWIN_DVD_IOCTL 51 #ifdef DARWIN_DVD_IOCTL
59 # include <paths.h> 52 # include <paths.h>
60 # include <CoreFoundation/CoreFoundation.h> 53 # include <CoreFoundation/CoreFoundation.h>
61 # include <IOKit/IOKitLib.h> 54 # include <IOKit/IOKitLib.h>
62 # include <IOKit/IOBSD.h> 55 # include <IOKit/IOBSD.h>
63 # include <IOKit/storage/IOMedia.h> 56 # include <IOKit/storage/IOMedia.h>
64 # include <IOKit/storage/IOCDMedia.h> 57 # include <IOKit/storage/IOCDMedia.h>
65 # include <IOKit/storage/IODVDMedia.h> 58 # include <IOKit/storage/IODVDMedia.h>
66 #endif 59 #endif
67 60
68 #ifdef SYS_OS2 61 #ifdef __OS2__
69 # define INCL_DOS 62 # define INCL_DOS
70 # define INCL_DOSDEVIOCTL 63 # define INCL_DOSDEVIOCTL
71 # include <os2.h> 64 # include <os2.h>
72 # include <io.h> /* setmode() */ 65 # include <io.h> /* setmode() */
73 # include <fcntl.h> /* O_BINARY */ 66 # include <fcntl.h> /* O_BINARY */
97 static int win2k_read ( dvdcss_t, void *, int ); 90 static int win2k_read ( dvdcss_t, void *, int );
98 static int aspi_read ( dvdcss_t, void *, int ); 91 static int aspi_read ( dvdcss_t, void *, int );
99 static int win_readv ( dvdcss_t, struct iovec *, int ); 92 static int win_readv ( dvdcss_t, struct iovec *, int );
100 93
101 static int aspi_read_internal ( int, void *, int ); 94 static int aspi_read_internal ( int, void *, int );
102 #elif defined( SYS_OS2 ) 95 #elif defined( __OS2__ )
103 static int os2_open ( dvdcss_t, char const * ); 96 static int os2_open ( dvdcss_t, char const * );
104 /* just use macros for libc */ 97 /* just use macros for libc */
105 # define os2_seek libc_seek 98 # define os2_seek libc_seek
106 # define os2_read libc_read 99 # define os2_read libc_read
107 # define os2_readv libc_readv 100 # define os2_readv libc_readv
122 } 115 }
123 else 116 else
124 { 117 {
125 return 1; 118 return 1;
126 } 119 }
127 #elif defined( SYS_OS2 ) 120 #elif defined( __OS2__ )
128 ULONG ulMode; 121 ULONG ulMode;
129 122
130 if( DosQueryFHState( dvdcss->i_fd, &ulMode ) != 0 ) 123 if( DosQueryFHState( dvdcss->i_fd, &ulMode ) != 0 )
131 return 1; /* What to do? Be conservative and try to use the ioctls */ 124 return 1; /* What to do? Be conservative and try to use the ioctls */
132 125
152 * Solaris needs a char device 145 * Solaris needs a char device
153 * Darwin needs a char device 146 * Darwin needs a char device
154 * OpenBSD needs a char device 147 * OpenBSD needs a char device
155 * NetBSD needs a char device 148 * NetBSD needs a char device
156 * FreeBSD can use either the block or the char device 149 * FreeBSD can use either the block or the char device
157 * BSD/OS can use either the block or the char device
158 */ 150 */
159 151
160 /* Check if this is a block/char device */ 152 /* Check if this is a block/char device */
161 if( S_ISBLK( fileinfo.st_mode ) || 153 if( S_ISBLK( fileinfo.st_mode ) ||
162 S_ISCHR( fileinfo.st_mode ) ) 154 S_ISCHR( fileinfo.st_mode ) )
179 io_object_t next_media; 171 io_object_t next_media;
180 mach_port_t master_port; 172 mach_port_t master_port;
181 kern_return_t kern_result; 173 kern_return_t kern_result;
182 io_iterator_t media_iterator; 174 io_iterator_t media_iterator;
183 CFMutableDictionaryRef classes_to_match; 175 CFMutableDictionaryRef classes_to_match;
184 #elif defined( SYS_OS2 ) 176 #elif defined( __OS2__ )
185 #pragma pack( 1 ) 177 #pragma pack( 1 )
186 struct 178 struct
187 { 179 {
188 BYTE bCmdInfo; 180 BYTE bCmdInfo;
189 BYTE bDrive; 181 BYTE bDrive;
237 } 229 }
238 230
239 /* Remove trailing backslash */ 231 /* Remove trailing backslash */
240 psz_device[2] = '\0'; 232 psz_device[2] = '\0';
241 233
242 /* FIXME: we want to differenciate between CD and DVD drives 234 /* FIXME: we want to differentiate between CD and DVD drives
243 * using DeviceIoControl() */ 235 * using DeviceIoControl() */
244 print_debug( dvdcss, "defaulting to drive `%s'", psz_device ); 236 print_debug( dvdcss, "defaulting to drive `%s'", psz_device );
245 free( dvdcss->psz_device ); 237 free( dvdcss->psz_device );
246 dvdcss->psz_device = strdup( psz_device ); 238 dvdcss->psz_device = strdup( psz_device );
247 return; 239 return;
314 306
315 IOObjectRelease( next_media ); 307 IOObjectRelease( next_media );
316 } 308 }
317 309
318 IOObjectRelease( media_iterator ); 310 IOObjectRelease( media_iterator );
319 #elif defined( SYS_OS2 ) 311 #elif defined( __OS2__ )
320 for( i = 0; i < 26; i++ ) 312 for( i = 0; i < 26; i++ )
321 { 313 {
322 param.bCmdInfo = 0; 314 param.bCmdInfo = 0;
323 param.bDrive = i; 315 param.bDrive = i;
324 316
392 dvdcss->pf_read = aspi_read; 384 dvdcss->pf_read = aspi_read;
393 dvdcss->pf_readv = win_readv; 385 dvdcss->pf_readv = win_readv;
394 return aspi_open( dvdcss, psz_device ); 386 return aspi_open( dvdcss, psz_device );
395 } 387 }
396 else 388 else
397 #elif defined( SYS_OS2 ) 389 #elif defined( __OS2__ )
398 /* If device is "X:" or "X:\", we are not actually opening a file. */ 390 /* If device is "X:" or "X:\", we are not actually opening a file. */
399 if( psz_device[0] && psz_device[1] == ':' && 391 if( psz_device[0] && psz_device[1] == ':' &&
400 ( !psz_device[2] || ( psz_device[2] == '\\' && !psz_device[3] ) ) ) 392 ( !psz_device[2] || ( psz_device[2] == '\\' && !psz_device[3] ) ) )
401 { 393 {
402 print_debug( dvdcss, "using OS2 API for access" ); 394 print_debug( dvdcss, "using OS2 API for access" );
414 dvdcss->pf_readv = libc_readv; 406 dvdcss->pf_readv = libc_readv;
415 return libc_open( dvdcss, psz_device ); 407 return libc_open( dvdcss, psz_device );
416 } 408 }
417 } 409 }
418 410
419 #if !defined(WIN32) && !defined(SYS_OS2) 411 #ifdef DVDCSS_RAW_OPEN
420 int _dvdcss_raw_open ( dvdcss_t dvdcss, char const *psz_device ) 412 int _dvdcss_raw_open ( dvdcss_t dvdcss, char const *psz_device )
421 { 413 {
422 dvdcss->i_raw_fd = open( psz_device, 0 ); 414 dvdcss->i_raw_fd = open( psz_device, 0 );
423 415
424 if( dvdcss->i_raw_fd == -1 ) 416 if( dvdcss->i_raw_fd == -1 )
450 } 442 }
451 else /* ASPI */ 443 else /* ASPI */
452 { 444 {
453 struct w32_aspidev *fd = (struct w32_aspidev *) dvdcss->i_fd; 445 struct w32_aspidev *fd = (struct w32_aspidev *) dvdcss->i_fd;
454 446
455 /* Unload aspi and free w32_aspidev structure */ 447 /* Unload ASPI and free w32_aspidev structure */
456 FreeLibrary( (HMODULE) fd->hASPI ); 448 FreeLibrary( (HMODULE) fd->hASPI );
457 free( (void*) dvdcss->i_fd ); 449 free( (void*) dvdcss->i_fd );
458 } 450 }
459 451
460 /* Free readv temporary buffer */ 452 /* Free readv temporary buffer */
467 459
468 return 0; 460 return 0;
469 #else 461 #else
470 close( dvdcss->i_fd ); 462 close( dvdcss->i_fd );
471 463
472 #ifndef SYS_OS2 464 #ifdef DVDCSS_RAW_OPEN
473 if( dvdcss->i_raw_fd >= 0 ) 465 if( dvdcss->i_raw_fd >= 0 )
474 { 466 {
475 close( dvdcss->i_raw_fd ); 467 close( dvdcss->i_raw_fd );
476 dvdcss->i_raw_fd = -1; 468 dvdcss->i_raw_fd = -1;
477 } 469 }
486 /***************************************************************************** 478 /*****************************************************************************
487 * Open commands. 479 * Open commands.
488 *****************************************************************************/ 480 *****************************************************************************/
489 static int libc_open ( dvdcss_t dvdcss, char const *psz_device ) 481 static int libc_open ( dvdcss_t dvdcss, char const *psz_device )
490 { 482 {
491 #if !defined( WIN32 ) && !defined( SYS_OS2 )
492 dvdcss->i_fd = dvdcss->i_read_fd = open( psz_device, 0 );
493 #else
494 dvdcss->i_fd = dvdcss->i_read_fd = open( psz_device, O_BINARY ); 483 dvdcss->i_fd = dvdcss->i_read_fd = open( psz_device, O_BINARY );
495 #endif
496 484
497 if( dvdcss->i_fd == -1 ) 485 if( dvdcss->i_fd == -1 )
498 { 486 {
499 print_debug( dvdcss, "cannot open %s (%s)", 487 print_debug( dvdcss, "cannot open %s (%s)",
500 psz_device, strerror(errno) ); 488 psz_device, strerror(errno) );
514 snprintf( psz_dvd, 7, "\\\\.\\%c:", psz_device[0] ); 502 snprintf( psz_dvd, 7, "\\\\.\\%c:", psz_device[0] );
515 503
516 /* To work around an M$ bug in IOCTL_DVD_READ_STRUCTURE, we need read 504 /* To work around an M$ bug in IOCTL_DVD_READ_STRUCTURE, we need read
517 * _and_ write access to the device (so we can make SCSI Pass Through 505 * _and_ write access to the device (so we can make SCSI Pass Through
518 * Requests). Unfortunately this is only allowed if you have 506 * Requests). Unfortunately this is only allowed if you have
519 * administrator priviledges so we allow for a fallback method with 507 * administrator privileges so we allow for a fallback method with
520 * only read access to the device (in this case ioctl_ReadCopyright() 508 * only read access to the device (in this case ioctl_ReadCopyright()
521 * won't send back the right result). 509 * won't send back the right result).
522 * (See Microsoft Q241374: Read and Write Access Required for SCSI 510 * (See Microsoft Q241374: Read and Write Access Required for SCSI
523 * Pass Through Requests) */ 511 * Pass Through Requests) */
524 dvdcss->i_fd = (int) 512 dvdcss->i_fd = (int)
552 int i, j, i_hostadapters; 540 int i, j, i_hostadapters;
553 GETASPI32SUPPORTINFO lpGetSupport; 541 GETASPI32SUPPORTINFO lpGetSupport;
554 SENDASPI32COMMAND lpSendCommand; 542 SENDASPI32COMMAND lpSendCommand;
555 char c_drive = psz_device[0]; 543 char c_drive = psz_device[0];
556 544
557 /* load aspi and init w32_aspidev structure */ 545 /* load ASPI and init w32_aspidev structure */
558 hASPI = LoadLibrary( "wnaspi32.dll" ); 546 hASPI = LoadLibrary( "wnaspi32.dll" );
559 if( hASPI == NULL ) 547 if( hASPI == NULL )
560 { 548 {
561 print_error( dvdcss, "unable to load wnaspi32.dll" ); 549 print_error( dvdcss, "unable to load wnaspi32.dll" );
562 return -1; 550 return -1;
565 lpGetSupport = (GETASPI32SUPPORTINFO) GetProcAddress( hASPI, "GetASPI32SupportInfo" ); 553 lpGetSupport = (GETASPI32SUPPORTINFO) GetProcAddress( hASPI, "GetASPI32SupportInfo" );
566 lpSendCommand = (SENDASPI32COMMAND) GetProcAddress( hASPI, "SendASPI32Command" ); 554 lpSendCommand = (SENDASPI32COMMAND) GetProcAddress( hASPI, "SendASPI32Command" );
567 555
568 if(lpGetSupport == NULL || lpSendCommand == NULL ) 556 if(lpGetSupport == NULL || lpSendCommand == NULL )
569 { 557 {
570 print_error( dvdcss, "unable to get aspi function pointers" ); 558 print_error( dvdcss, "unable to get ASPI function pointers" );
571 FreeLibrary( hASPI ); 559 FreeLibrary( hASPI );
572 return -1; 560 return -1;
573 } 561 }
574 562
575 dwSupportInfo = lpGetSupport(); 563 dwSupportInfo = lpGetSupport();
581 return -1; 569 return -1;
582 } 570 }
583 571
584 if( HIBYTE( LOWORD ( dwSupportInfo ) ) != SS_COMP ) 572 if( HIBYTE( LOWORD ( dwSupportInfo ) ) != SS_COMP )
585 { 573 {
586 print_error( dvdcss, "unable to initalize aspi layer" ); 574 print_error( dvdcss, "unable to initialize ASPI layer" );
587 FreeLibrary( hASPI ); 575 FreeLibrary( hASPI );
588 return -1; 576 return -1;
589 } 577 }
590 578
591 i_hostadapters = LOBYTE( LOWORD( dwSupportInfo ) ); 579 i_hostadapters = LOBYTE( LOWORD( dwSupportInfo ) );
626 lpSendCommand( (void*) &srbDiskInfo ); 614 lpSendCommand( (void*) &srbDiskInfo );
627 615
628 if( (srbDiskInfo.SRB_Status == SS_COMP) && 616 if( (srbDiskInfo.SRB_Status == SS_COMP) &&
629 (srbDiskInfo.SRB_Int13HDriveInfo == c_drive) ) 617 (srbDiskInfo.SRB_Int13HDriveInfo == c_drive) )
630 { 618 {
631 /* Make sure this is a cdrom device */ 619 /* Make sure this is a CD-ROM device */
632 struct SRB_GDEVBlock srbGDEVBlock; 620 struct SRB_GDEVBlock srbGDEVBlock = { 0 };
633 621
634 memset( &srbGDEVBlock, 0, sizeof(struct SRB_GDEVBlock) );
635 srbGDEVBlock.SRB_Cmd = SC_GET_DEV_TYPE; 622 srbGDEVBlock.SRB_Cmd = SC_GET_DEV_TYPE;
636 srbGDEVBlock.SRB_HaId = i; 623 srbGDEVBlock.SRB_HaId = i;
637 srbGDEVBlock.SRB_Target = j; 624 srbGDEVBlock.SRB_Target = j;
638 625
639 lpSendCommand( (void*) &srbGDEVBlock ); 626 lpSendCommand( (void*) &srbGDEVBlock );
648 } 635 }
649 else 636 else
650 { 637 {
651 free( (void*) fd ); 638 free( (void*) fd );
652 FreeLibrary( hASPI ); 639 FreeLibrary( hASPI );
653 print_error( dvdcss,"this is not a cdrom drive" ); 640 print_error( dvdcss,"this is not a CD-ROM drive" );
654 return -1; 641 return -1;
655 } 642 }
656 } 643 }
657 } 644 }
658 } 645 }
659 646
660 free( (void*) fd ); 647 free( (void*) fd );
661 FreeLibrary( hASPI ); 648 FreeLibrary( hASPI );
662 print_error( dvdcss, "unable to get haid and target (aspi)" ); 649 print_error( dvdcss, "unable to get haid and target (ASPI)" );
663 return -1; 650 return -1;
664 } 651 }
665 #endif 652 #endif
666 653
667 #ifdef SYS_OS2 654 #ifdef __OS2__
668 static int os2_open ( dvdcss_t dvdcss, char const *psz_device ) 655 static int os2_open ( dvdcss_t dvdcss, char const *psz_device )
669 { 656 {
670 char psz_dvd[] = "X:"; 657 char psz_dvd[] = "X:";
671 HFILE hfile; 658 HFILE hfile;
672 ULONG ulAction; 659 ULONG ulAction;
879 i_bytes = read( dvdcss->i_fd, p_base, i_len ); 866 i_bytes = read( dvdcss->i_fd, p_base, i_len );
880 867
881 if( i_bytes < 0 ) 868 if( i_bytes < 0 )
882 { 869 {
883 /* One of the reads failed, too bad. 870 /* One of the reads failed, too bad.
884 * We won't even bother returning the reads that went ok, 871 * We won't even bother returning the reads that went OK,
885 * and as in the posix spec the file postition is left 872 * and as in the POSIX spec the file position is left
886 * unspecified after a failure */ 873 * unspecified after a failure */
887 dvdcss->i_pos = -1; 874 dvdcss->i_pos = -1;
888 return -1; 875 return -1;
889 } 876 }
890 877
966 unsigned long int i_bytes; 953 unsigned long int i_bytes;
967 if( !ReadFile( (HANDLE)dvdcss->i_fd, dvdcss->p_readv_buffer, 954 if( !ReadFile( (HANDLE)dvdcss->i_fd, dvdcss->p_readv_buffer,
968 i_blocks_total * DVDCSS_BLOCK_SIZE, &i_bytes, NULL ) ) 955 i_blocks_total * DVDCSS_BLOCK_SIZE, &i_bytes, NULL ) )
969 { 956 {
970 /* The read failed... too bad. 957 /* The read failed... too bad.
971 * As in the posix spec the file postition is left 958 * As in the POSIX spec the file position is left
972 * unspecified after a failure */ 959 * unspecified after a failure */
973 dvdcss->i_pos = -1; 960 dvdcss->i_pos = -1;
974 return -1; 961 return -1;
975 } 962 }
976 i_blocks_read = i_bytes / DVDCSS_BLOCK_SIZE; 963 i_blocks_read = i_bytes / DVDCSS_BLOCK_SIZE;
1008 } 995 }
1009 996
1010 static int aspi_read_internal( int i_fd, void *p_data, int i_blocks ) 997 static int aspi_read_internal( int i_fd, void *p_data, int i_blocks )
1011 { 998 {
1012 HANDLE hEvent; 999 HANDLE hEvent;
1013 struct SRB_ExecSCSICmd ssc; 1000 struct SRB_ExecSCSICmd ssc = { 0 };
1014 struct w32_aspidev *fd = (struct w32_aspidev *) i_fd; 1001 struct w32_aspidev *fd = (struct w32_aspidev *) i_fd;
1015 1002
1016 /* Create the transfer completion event */ 1003 /* Create the transfer completion event */
1017 hEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); 1004 hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
1018 if( hEvent == NULL ) 1005 if( hEvent == NULL )
1019 { 1006 {
1020 return -1; 1007 return -1;
1021 } 1008 }
1022
1023 memset( &ssc, 0, sizeof( ssc ) );
1024 1009
1025 ssc.SRB_Cmd = SC_EXEC_SCSI_CMD; 1010 ssc.SRB_Cmd = SC_EXEC_SCSI_CMD;
1026 ssc.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; 1011 ssc.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
1027 ssc.SRB_HaId = LOBYTE( fd->i_sid ); 1012 ssc.SRB_HaId = LOBYTE( fd->i_sid );
1028 ssc.SRB_Target = HIBYTE( fd->i_sid ); 1013 ssc.SRB_Target = HIBYTE( fd->i_sid );
1036 ssc.CDBByte[2] = (UCHAR) (fd->i_blocks >> 24); 1021 ssc.CDBByte[2] = (UCHAR) (fd->i_blocks >> 24);
1037 ssc.CDBByte[3] = (UCHAR) (fd->i_blocks >> 16) & 0xff; 1022 ssc.CDBByte[3] = (UCHAR) (fd->i_blocks >> 16) & 0xff;
1038 ssc.CDBByte[4] = (UCHAR) (fd->i_blocks >> 8) & 0xff; 1023 ssc.CDBByte[4] = (UCHAR) (fd->i_blocks >> 8) & 0xff;
1039 ssc.CDBByte[5] = (UCHAR) (fd->i_blocks) & 0xff; 1024 ssc.CDBByte[5] = (UCHAR) (fd->i_blocks) & 0xff;
1040 1025
1041 /* We have to break down the reads into 64kb pieces (ASPI restriction) */ 1026 /* We have to break down the reads into 64KB pieces (ASPI restriction) */
1042 if( i_blocks > 32 ) 1027 if( i_blocks > 32 )
1043 { 1028 {
1044 ssc.SRB_BufLen = 32 * DVDCSS_BLOCK_SIZE; 1029 ssc.SRB_BufLen = 32 * DVDCSS_BLOCK_SIZE;
1045 ssc.CDBByte[9] = 32; 1030 ssc.CDBByte[9] = 32;
1046 fd->i_blocks += 32; 1031 fd->i_blocks += 32;
1047 1032
1048 /* Initiate transfer */ 1033 /* Initiate transfer */
1049 ResetEvent( hEvent ); 1034 ResetEvent( hEvent );
1050 fd->lpSendCommand( (void*) &ssc ); 1035 fd->lpSendCommand( (void*) &ssc );
1051 1036
1052 /* transfer the next 64kb (aspi_read_internal is called recursively) 1037 /* transfer the next 64KB (aspi_read_internal is called recursively)
1053 * We need to check the status of the read on return */ 1038 * We need to check the status of the read on return */
1054 if( aspi_read_internal( i_fd, 1039 if( aspi_read_internal( i_fd,
1055 (uint8_t*) p_data + 32 * DVDCSS_BLOCK_SIZE, 1040 (uint8_t*) p_data + 32 * DVDCSS_BLOCK_SIZE,
1056 i_blocks - 32) < 0 ) 1041 i_blocks - 32) < 0 )
1057 { 1042 {