📄 loader_app.c
字号:
/*****************************************************************************
******************************************************************************
** **
** Copyright (c) 2002 Videon Central, Inc. **
** All rights reserved. **
** **
** The computer program contained herein contains proprietary information **
** which is the property of Videon Central, Inc. The program may be used **
** and/or copied only with the written permission of Videon Central, Inc. **
** or in accordance with the terms and conditions stipulated in the **
** agreement/contract under which the programs have been supplied. **
** **
******************************************************************************
*****************************************************************************/
/**
* @file loader_app.c
*
* $Revision: 1.67 $
*
* DVD disc access module.
*
*/
#include "vdvd_types.h"
#include <stdio.h>
#include <stdlib.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/mount.h>
#include <fcntl.h>
#include <linux/cdrom.h>
#include <linux/hdreg.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include "osapi.h"
#include "loader_app.h"
#include "dbgprint.h"
#include "css.h"
#ifdef DMALLOC
#include "dmalloc.h"
#endif
#define DEBUG_CDROM 0
#if 1
#define CDROM_DEVICE_NAME "/dev/cdrom"
#define CDROM_MOUNT_DIRECTORY "/mnt/cdrom"
#else
#define CDROM_DEVICE_NAME "/dev/cdroms/cdrom0"
#define CDROM_MOUNT_DIRECTORY "/hd0/mnt/cdrom"
#endif
/* MACROS AND DEFINITIONS */
#define DEBUG_LOADER DBG_ERROR
#define DBG_ON(x) (DEBUG_LOADER >= x)
#define LOADER_DIRECT_IO_ON TRUE
#define LOADER_DIRECT_IO_OFF FALSE
#define LDR_BUF_SIZE 2052
/*
** Globals
*/
BYTE loaderBuf[LDR_BUF_SIZE];
/* used to spoof the player */
int PLAY_FROM_HD = 0;
/* Tracing counters */
static int ldr_read10_cnt = 0;
static int ldr_read12_strm_cnt = 0;
/*
* Private Data Types
*****************************************************************************/
typedef struct _tagLoaderHandle
{
LONG lFileHandle; /**< File handle returned from open */
ULONG ulLastErr;
LOADER_TYPE LoaderType; /**< Type of media currently in the tray */
ULONG ulLastLBA;
ULONG ulBlockLength;
BYTE bRegionMask; /**< region code mask */
BYTE bFlags;
BYTE bDiscType;
BYTE bNumLayers;
LOADER_TYPE ptLayerFormatType[LOADER_SUPPORTED_NUMBER_OF_LAYERS];
} LOADERHANDLE;
static ULONG LoaderRead10Enable = 0;
/*
** Flags definitions
*/
#define LOADER_STREAMING_SUPPORT 0x01
#define LOADER_TIMEOUT_SUPPORT 0x02
#define LOADER_RW_ERR_RECOVERY_SUPPORT 0x04
#define LOADER_READ_12_ILLEGAL 0x08
#define LOADER_AACS_CAPABLE 0x10
#define LOADER_READ_NUMLAYERS_FAILS 0x20
/*
** Loader Eject support
*/
typedef enum _loejStart {
LOADER_EJECT_DISC = 0x02,
LOADER_LOAD_DISC = 0x00
} LOEJSTARTBITS;
/*
* Local Fuction Prototypes
*****************************************************************************/
static void loaderSetError(LOADER_HANDLE tLoader, ULONG ulErr);
static void loaderGetRPC_local(LOADER_HANDLE tLoader);
static void loaderGetType_local(LOADER_HANDLE tLoader);
static int test_unit_ready(int fd, int *s);
static LOADER_ERR loaderTestUnitReady_local(LOADER_HANDLE tLoader);
static LOADER_ERR LoaderSendKey(LOADER_HANDLE tLoader, BYTE bAgid, BYTE key_class, BYTE key_format, USHORT param_length, BYTE *pData);
static LOADER_ERR LoaderReportKey(LOADER_HANDLE tLoader, BYTE pAgid, ULONG address, BYTE blk_cnt, BYTE key_class, BYTE key_format, USHORT buf_length, BYTE *pData);
static LOADER_ERR LoaderReadDiscStruct(LOADER_HANDLE tLoader, BYTE bAgid, BYTE sub_cmd, ULONG address, BYTE format_code, BYTE *pBuf, USHORT len);
static LOADER_ERR LoaderInitGetAgid(LOADER_HANDLE tLoader, BYTE key_class);
static LOADER_ERR loaderGetConfiguration(int fd, char RT, int bufSize, char *bufPtr, struct request_sense *sense);
static LOADER_ERR loaderGetCapacity(int fd, int bufSize, char *bufPtr, struct request_sense *sense);
static LOADER_ERR loaderSetStreaming(int fd, int bufSize, char *bufPtr, struct request_sense *sense);
static LOADER_ERR loaderModeSense(LOADER_HANDLE tLoader, char page_code, int bufSize, char *bufPtr, struct request_sense *sense);
static LOADER_ERR loaderModeSelect(LOADER_HANDLE tLoader, int bufSize, char *bufPtr, struct request_sense *sense);
static LOADER_ERR loaderFileOpen(LOADER_HANDLE tLoader, const char *pcFileName, LOADER_FILE_HANDLE *hFileHandle, BOOLEAN fDirectIO);
static LOADER_TYPE loaderTranslateHybridLayerFormatType(USHORT usLayerFormatType);
/**
* Creates a handle to a loader device, initializes any global variables,
* allocates any required memory, and returns a pointer to the device handle.
*
* @param eBusType - NOT USED FOR THIS IMPLEMENTATION
* @param ulDeviceNum - NOT USED FOR THIS IMPLEMENTATION
*/
LOADER_HANDLE LoaderCreate(LOADER_BUS_TYPE eBusType, ULONG ulDeviceNum)
{
LOADERHANDLE *tLoader = NULL;
LONG lFileHandle;
(void)eBusType;
(void)ulDeviceNum;
lFileHandle = open(CDROM_DEVICE_NAME, O_RDONLY | O_NONBLOCK);
if (lFileHandle < 0)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("LoaderCreate() --FAILED (%s)\n", strerror(errno)));
}
else
{
tLoader = (LOADERHANDLE*)OS_MemAlloc(sizeof(LOADERHANDLE));
if ( tLoader == NULL )
{
/* Out of memory, close device */
close(lFileHandle);
}
else
{
/* set initial state */
memset( tLoader, 0, sizeof(LOADERHANDLE) );
tLoader->lFileHandle = lFileHandle;
tLoader->LoaderType = LOADER_TYPE_UNKNOWN;
}
}
DBGPRINT(DBG_ON(DBG_ERROR),("LoaderCreate() -- r10_ok fallback enabled\n"));
LoaderRead10Enable = 1;
return ((LOADER_HANDLE)tLoader);
}
/**
* Stops the storage media if necessary, closes the current session and frees
* any memory allocated during the LoaderCreate() call.
*
* @param tLoader - The loader handle.
*/
LOADER_ERR LoaderDestroy(LOADER_HANDLE tLoader)
{
if (tLoader == NULL)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("LoaderDestroy() --LOADER_NULL_PTR\n"));
return (LOADER_NULL_PTR);
}
if (((LOADERHANDLE*)tLoader)->lFileHandle != 0)
{
/* close the drive */
close(((LOADERHANDLE*)tLoader)->lFileHandle);
}
/* free the memory */
OS_MemFree(tLoader);
return (LOADER_SUCCESS);
}
/**
* Loads/Eject a disc into the device with Immediate bit set
* This function is critical for emergency exit.
*
* @param tLoader - The loader handle.
*/
static LOADER_ERR LoaderStartStopUnit(LOADER_HANDLE tLoader, LOEJSTARTBITS loejStartBits)
{
int cdrom;
struct cdrom_generic_command cgc;
struct request_sense sense;
LOADER_ERR ldrSts = LOADER_SUCCESS;
cdrom = ((LOADERHANDLE*)tLoader)->lFileHandle;
memset(&cgc, 0, sizeof(cgc));
memset(&sense, 0, sizeof(sense));
/* fill in required info for GPCMD_REPORT_KEY RPC State request */
cgc.sense = &sense;
cgc.data_direction = CGC_DATA_NONE;
cgc.timeout = 20000;
cgc.cmd[ 0] = GPCMD_START_STOP_UNIT;
cgc.cmd[ 1] = 0x01;
cgc.cmd[ 4] = loejStartBits;
/* send command to driver */
if (ioctl(cdrom, CDROM_SEND_PACKET, &cgc) < 0)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("LoaderStartStopUnit() --FAILED (%s), loejStartBits 0x%x\n", strerror(errno), loejStartBits));
ldrSts = LOADER_FAILURE;
}
return ldrSts;
}
/**
* Stops the disc if necessary, closes the session, and opens the tray holding
* the disc.
*
* @param tLoader - The loader handle.
*/
LOADER_ERR LoaderOpenTray(LOADER_HANDLE tLoader)
{
LOADER_ERR err = LOADER_SUCCESS;
LOADERHANDLE* ldr = (LOADERHANDLE*)tLoader;
if (tLoader == NULL)
{
return (LOADER_NULL_PTR);
}
err = LoaderStartStopUnit(tLoader, LOADER_EJECT_DISC);
if (err == LOADER_SUCCESS)
{
/* Reset the loader type */
ldr->LoaderType = LOADER_TYPE_UNKNOWN;
}
/*
** Clear flags that change with media.
*/
ldr->bFlags = 0;
return (err);
}
/**
* Loads a disc into the device, and prepares everything needed to start the
* disc.
*
* @param tLoader - The loader handle.
*/
LOADER_ERR LoaderCloseTray(LOADER_HANDLE tLoader)
{
LOADER_ERR err = LOADER_SUCCESS;
LOADERHANDLE* ldr = (LOADERHANDLE*)tLoader;
if (tLoader == NULL)
{
return (LOADER_NULL_PTR);
}
err = LoaderStartStopUnit(tLoader, LOADER_LOAD_DISC);
if (err == LOADER_SUCCESS)
{
/* Reset the loader type */
ldr->LoaderType = LOADER_TYPE_UNKNOWN;
}
/*
** Clear flags that change with media.
*/
ldr->bFlags = 0;
return (err);
}
/**
* Starts the spinning of the disc, as well as detection of the disc type,
* sector size, and encryption. This also begins the disc authentication
* process.
*
* @param tLoader - The loader handle.
*/
LOADER_ERR LoaderStart(LOADER_HANDLE tLoader)
{
if (tLoader == NULL)
{
return (LOADER_NULL_PTR);
}
/*DBGPRINT(DBG_ON(DBG_TRACE), ("LoaderStart() --Entry LoaderType %d\n", ldr->LoaderType));*/
/* check the "spoof" environment setting */
if ( getenv( "PLAY_FROM_HD" ) )
{
PLAY_FROM_HD = 1;
printf("\nENABLE PLAY FROM HD\n");
}
else
{
PLAY_FROM_HD = 0;
}
/* start the drive */
if (LoaderStartStopUnit(tLoader, LOADER_LOAD_DISC) != LOADER_SUCCESS)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("LoaderStart: LOADER FAILED TO START UNIT!!!\n"));
return (LOADER_FAILURE);
}
return (LOADER_SUCCESS);
}
/**
* Checks if the unit is ready. If the unit is not ready, fReady is set to
* false and the function returns. If the unit is ready, fReady is set to
* true and the loader startup is completed.
*
* @param tLoader - The loader handle.
* @param fReady - gets set to true if unit is ready, false otherwise
*/
LOADER_ERR LoaderTestUnitReady(LOADER_HANDLE tLoader, BOOLEAN *fReady)
{
LOADERHANDLE* ldr = (LOADERHANDLE*)tLoader;
LOADER_ERR err = LOADER_SUCCESS;
if (tLoader == NULL)
{
return (LOADER_NULL_PTR);
}
if (fReady == NULL)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("LoaderTestUnitReady: NULL pointer!\n"));
return (LOADER_NULL_PTR);
}
DBGPRINT(DBG_ON(DBG_TRACE), ("LoaderTestUnitReady()\n"));
/* test for unit ready */
if (loaderTestUnitReady_local(tLoader) != LOADER_SUCCESS)
{
DBGPRINT(DBG_ON(DBG_TRACE), ("LoaderTestUnitReady: LOADER FAILED TO BECOME READY!!!\n"));
*fReady = FALSE;
/* unit not ready, so just return */
return (LOADER_SUCCESS);
}
/* unit is ready */
*fReady = TRUE;
DBGPRINT(DBG_ON(DBG_TRACE), ("LoaderTestUnitReady: READY!\n"));
if (ldr->LoaderType == LOADER_TYPE_NODISK)
{
DBGPRINT(DBG_ON(DBG_TRACE), ("LoaderTestUnitReady: No disc!\n"));
/* no disc, so just return */
return (LOADER_SUCCESS);
}
/* medium loaded so get type */
loaderGetType_local(tLoader);
if (ldr->LoaderType == LOADER_TYPE_UNKNOWN)
{
DBGPRINT(DBG_ON(DBG_TRACE), ("LoaderTestUnitReady: Unknown disc type!\n"));
/* unknown disc type, so just return */
return (LOADER_SUCCESS);
}
DBGPRINT(DBG_ON(DBG_TRACE), ("Loader: LOADER_TYPE %d, Media Type 0x%x, Num Layers %d\n", ldr->LoaderType, ldr->bDiscType, ldr->bNumLayers));
/* get the region of the drive */
loaderGetRPC_local(tLoader);
/*
** Perform a read to LBA 0x10 to absorb drive head recalibration.
** Read status is unimportant.
** Note that this operation placed here helps to avoid errors during mount.
*/
LoaderSectorRead(tLoader, 0x10, loaderBuf, 1);
/*
* If loader type is known and there is a disc in the tray, then
* mount the drive. Otherwise, just lock the drive.
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -