?? device.c
字號:
/***************************************************************************** * device.h: DVD device access ***************************************************************************** * Copyright (C) 1998-2006 VideoLAN * $Id: device.c,v 1.3 2008/04/12 07:14:44 dsqiu Exp $ * * Authors: St閜hane Borel <stef@via.ecp.fr> * Sam Hocevar <sam@zoy.org> * H錵an Hjort <d95hjort@dtek.chalmers.se> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. *****************************************************************************//***************************************************************************** * Preamble *****************************************************************************/#include "config.h"#include <mplaylib.h>#include <mplaylib.h>#include <mplaylib.h>#ifdef HAVE_ERRNO_H# include <errno.h>#endif#include <sys/types.h>#include <sys/stat.h>#ifdef HAVE_SYS_PARAM_H# include <sys/param.h>#endif#include <fcntl.h>#ifdef HAVE_UNISTD_H# include <unistd.h>#endif#ifdef HAVE_LIMITS_H# include <limits.h>#endif#if defined( WIN32 ) && !defined( SYS_CYGWIN )# include <io.h> /* read() */#else# include <sys/uio.h> /* struct iovec */#endif#ifdef DARWIN_DVD_IOCTL# include <paths.h># include <CoreFoundation/CoreFoundation.h># include <IOKit/IOKitLib.h># include <IOKit/IOBSD.h># include <IOKit/storage/IOMedia.h># include <IOKit/storage/IOCDMedia.h># include <IOKit/storage/IODVDMedia.h>#endif#include "dvdcss/dvdcss.h"#include "common.h"#include "css.h"#include "libdvdcss.h"#include "ioctl.h"#include "device.h"#undef memcpy#define memcpy uc_memcpy/***************************************************************************** * Device reading prototypes *****************************************************************************/static int libc_open ( dvdcss_t, char const * );static int libc_seek ( dvdcss_t, int );static int libc_read ( dvdcss_t, void *, int );static int libc_readv ( dvdcss_t, struct iovec *, int );#ifdef WIN32static int win2k_open ( dvdcss_t, char const * );static int aspi_open ( dvdcss_t, char const * );static int win2k_seek ( dvdcss_t, int );static int aspi_seek ( dvdcss_t, int );static int win2k_read ( dvdcss_t, void *, int );static int aspi_read ( dvdcss_t, void *, int );static int win_readv ( dvdcss_t, struct iovec *, int );static int aspi_read_internal ( int, void *, int );#endifint _dvdcss_use_ioctls( dvdcss_t dvdcss ){#if defined( WIN32 ) if( dvdcss->b_file ) { return 0; } /* FIXME: implement this for Windows */ if( WIN2K ) { return 1; } else { return 1; }#else struct stat fileinfo; int ret; ret = fstat( dvdcss->i_fd, &fileinfo ); if( ret < 0 ) { return 1; /* What to do? Be conservative and try to use the ioctls */ } /* Complete this list and check that we test for the right things * (I've assumed for all OSs that 'r', (raw) device, are char devices * and those that don't contain/use an 'r' in the name are block devices) * * Linux needs a block device * Solaris needs a char device * Darwin needs a char device * OpenBSD needs a char device * NetBSD needs a char device * FreeBSD can use either the block or the char device * BSD/OS can use either the block or the char device */ /* Check if this is a block/char device */ if( S_ISBLK( fileinfo.st_mode ) || S_ISCHR( fileinfo.st_mode ) ) { return 1; } else { return 0; }#endif}void _dvdcss_check ( dvdcss_t dvdcss ){#if defined( WIN32 ) DWORD drives; int i;#elif defined( DARWIN_DVD_IOCTL ) io_object_t next_media; mach_port_t master_port; kern_return_t kern_result; io_iterator_t media_iterator; CFMutableDictionaryRef classes_to_match;#else char *ppsz_devices[] = { "/dev/dvd", "/dev/cdrom", "/dev/hdc", NULL }; int i, i_fd;#endif /* If the device name is non-null, return */ if( dvdcss->psz_device[0] ) { return; }#if defined( WIN32 ) drives = GetLogicalDrives(); for( i = 0; drives; i++ ) { char psz_device[5]; DWORD cur = 1 << i; UINT i_ret; if( (drives & cur) == 0 ) { continue; } drives &= ~cur; sprintf( psz_device, "%c:\\", 'A' + i ); i_ret = GetDriveType( psz_device ); if( i_ret != DRIVE_CDROM ) { continue; } /* Remove trailing backslash */ psz_device[2] = '\0'; /* FIXME: we want to differenciate between CD and DVD drives * using DeviceIoControl() */ print_debug( dvdcss, "defaulting to drive `%s'", psz_device ); free( dvdcss->psz_device ); dvdcss->psz_device = strdup( psz_device ); return; }#elif defined( DARWIN_DVD_IOCTL ) kern_result = IOMasterPort( MACH_PORT_NULL, &master_port ); if( kern_result != KERN_SUCCESS ) { return; } classes_to_match = IOServiceMatching( kIODVDMediaClass ); if( classes_to_match == NULL ) { return; } CFDictionarySetValue( classes_to_match, CFSTR( kIOMediaEjectableKey ), kCFBooleanTrue ); kern_result = IOServiceGetMatchingServices( master_port, classes_to_match, &media_iterator ); if( kern_result != KERN_SUCCESS ) { return; } next_media = IOIteratorNext( media_iterator ); for( ; ; ) { char psz_buf[0x32]; size_t i_pathlen; CFTypeRef psz_path; next_media = IOIteratorNext( media_iterator ); if( next_media == 0 ) { break; } psz_path = IORegistryEntryCreateCFProperty( next_media, CFSTR( kIOBSDNameKey ), kCFAllocatorDefault, 0 ); if( psz_path == NULL ) { IOObjectRelease( next_media ); continue; } snprintf( psz_buf, sizeof(psz_buf), "%s%c", _PATH_DEV, 'r' ); i_pathlen = strlen( psz_buf ); if( CFStringGetCString( psz_path, (char*)&psz_buf + i_pathlen, sizeof(psz_buf) - i_pathlen, kCFStringEncodingASCII ) ) { print_debug( dvdcss, "defaulting to drive `%s'", psz_buf ); CFRelease( psz_path ); IOObjectRelease( next_media ); IOObjectRelease( media_iterator ); free( dvdcss->psz_device ); dvdcss->psz_device = strdup( psz_buf ); return; } CFRelease( psz_path ); IOObjectRelease( next_media ); } IOObjectRelease( media_iterator );#else for( i = 0; ppsz_devices[i]; i++ ) { i_fd = open( ppsz_devices[i], 0 ); if( i_fd != -1 ) { print_debug( dvdcss, "defaulting to drive `%s'", ppsz_devices[i] ); close( i_fd ); free( dvdcss->psz_device ); dvdcss->psz_device = strdup( ppsz_devices[i] ); return; } }#endif print_error( dvdcss, "could not find a suitable default drive" );}int _dvdcss_open ( dvdcss_t dvdcss ){ char const *psz_device = dvdcss->psz_device; print_debug( dvdcss, "opening target `%s'", psz_device );#if defined( WIN32 ) dvdcss->b_file = 1; /* If device is "X:" or "X:\", we are not actually opening a file. */ if (psz_device[0] && psz_device[1] == ':' && (!psz_device[2] || (psz_device[2] == '\\' && !psz_device[3]))) dvdcss->b_file = 0; /* Initialize readv temporary buffer */ dvdcss->p_readv_buffer = NULL; dvdcss->i_readv_buf_size = 0; if( !dvdcss->b_file && WIN2K ) { print_debug( dvdcss, "using Win2K API for access" ); dvdcss->pf_seek = win2k_seek; dvdcss->pf_read = win2k_read; dvdcss->pf_readv = win_readv; return win2k_open( dvdcss, psz_device ); } else if( !dvdcss->b_file ) { print_debug( dvdcss, "using ASPI for access" ); dvdcss->pf_seek = aspi_seek; dvdcss->pf_read = aspi_read; dvdcss->pf_readv = win_readv; return aspi_open( dvdcss, psz_device ); } else#endif { print_debug( dvdcss, "using libc for access" ); dvdcss->pf_seek = libc_seek; dvdcss->pf_read = libc_read; dvdcss->pf_readv = libc_readv; return libc_open( dvdcss, psz_device ); }}#ifndef WIN32int _dvdcss_raw_open ( dvdcss_t dvdcss, char const *psz_device ){ dvdcss->i_raw_fd = open( psz_device, 0 ); if( dvdcss->i_raw_fd == -1 ) { print_debug( dvdcss, "cannot open %s (%s)", psz_device, strerror(errno) ); print_error( dvdcss, "failed to open raw device, but continuing" ); return -1; } else { dvdcss->i_read_fd = dvdcss->i_raw_fd; } return 0;}#endifint _dvdcss_close ( dvdcss_t dvdcss ){#if defined( WIN32 ) if( dvdcss->b_file ) { close( dvdcss->i_fd ); } else if( WIN2K ) { CloseHandle( (HANDLE) dvdcss->i_fd ); } else /* ASPI */ { struct w32_aspidev *fd = (struct w32_aspidev *) dvdcss->i_fd; /* Unload aspi and free w32_aspidev structure */ FreeLibrary( (HMODULE) fd->hASPI ); free( (void*) dvdcss->i_fd ); } /* Free readv temporary buffer */ if( dvdcss->p_readv_buffer ) { free( dvdcss->p_readv_buffer ); dvdcss->p_readv_buffer = NULL; dvdcss->i_readv_buf_size = 0; } return 0;#else close( dvdcss->i_fd ); if( dvdcss->i_raw_fd >= 0 ) { close( dvdcss->i_raw_fd ); dvdcss->i_raw_fd = -1; } return 0;#endif}/* Following functions are local *//***************************************************************************** * Open commands. *****************************************************************************/static int libc_open ( dvdcss_t dvdcss, char const *psz_device ){#if !defined( WIN32 ) dvdcss->i_fd = dvdcss->i_read_fd = open( psz_device, 0 );#else dvdcss->i_fd = dvdcss->i_read_fd = open( psz_device, O_BINARY );#endif if( dvdcss->i_fd == -1 ) { print_debug( dvdcss, "cannot open %s (%s)", psz_device, strerror(errno) ); print_error( dvdcss, "failed to open device" ); return -1; } dvdcss->i_pos = 0; return 0;}#if defined( WIN32 )static int win2k_open ( dvdcss_t dvdcss, char const *psz_device ){ char psz_dvd[7]; _snprintf( psz_dvd, 7, "\\\\.\\%c:", psz_device[0] ); /* To work around an M$ bug in IOCTL_DVD_READ_STRUCTURE, we need read * _and_ write access to the device (so we can make SCSI Pass Through * Requests). Unfortunately this is only allowed if you have * administrator priviledges so we allow for a fallback method with * only read access to the device (in this case ioctl_ReadCopyright() * won't send back the right result). * (See Microsoft Q241374: Read and Write Access Required for SCSI * Pass Through Requests) */ dvdcss->i_fd = (int) CreateFile( psz_dvd, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, NULL ); if( (HANDLE) dvdcss->i_fd == INVALID_HANDLE_VALUE ) dvdcss->i_fd = (int) CreateFile( psz_dvd, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, NULL ); if( (HANDLE) dvdcss->i_fd == INVALID_HANDLE_VALUE ) { print_error( dvdcss, "failed opening device" ); return -1; } dvdcss->i_pos = 0; return 0;}static int aspi_open( dvdcss_t dvdcss, char const * psz_device ){ HMODULE hASPI; DWORD dwSupportInfo; struct w32_aspidev *fd; int i, j, i_hostadapters; GETASPI32SUPPORTINFO lpGetSupport; SENDASPI32COMMAND lpSendCommand; char c_drive = psz_device[0]; /* load aspi and init w32_aspidev structure */ hASPI = LoadLibrary( "wnaspi32.dll" ); if( hASPI == NULL ) { print_error( dvdcss, "unable to load wnaspi32.dll" ); return -1; } lpGetSupport = (GETASPI32SUPPORTINFO) GetProcAddress( hASPI, "GetASPI32SupportInfo" ); lpSendCommand = (SENDASPI32COMMAND) GetProcAddress( hASPI, "SendASPI32Command" ); if(lpGetSupport == NULL || lpSendCommand == NULL ) { print_error( dvdcss, "unable to get aspi function pointers" ); FreeLibrary( hASPI ); return -1; }
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -