www.pudn.com > DMBDRV.rar > SmsGenDrv.c


 
#include "SmsGenDrv.h" 
#include  
#include "BusDrvIf.h" 
 
 
 
/////////////////////////////////////////////////////////////////////////////// 
 
#define ENABLED_DEBUG_ZONE   ZONE_ERROR_SET | ZONE_WARNING_SET | ZONE_INIT_SET | ZONE_INFO_SET 
 
 DBGPARAM dpCurSettings = 
 { 
   TEXT("Siano Generic Driver"), 
   {	/* Note: the order of the following must */ 
		/* match the definitions in debug.h:     */ 
     TEXT("Errors"),    TEXT("Warnings"),   TEXT("Init"),             
     TEXT("Info"), TEXT("Undefined"),  TEXT("Undefined"), 
     TEXT("Undefined"), TEXT("Temporary"),  TEXT("Undefined"), 
     TEXT("Undefined"), TEXT("Undefined"),  TEXT("Undefined"), 
     TEXT("Undefined"), TEXT("Undefined"),  TEXT("Undefined"), 
     TEXT("Undefined") 
   }, 
   ENABLED_DEBUG_ZONE 
  }; 
 
 
/////////////////////////////////////////////////////////////////////////////// 
 
// Sms Message Header Structure 
typedef struct SmsMsgHdr_S 
{ 
	UINT16	msgType; 
	UINT8	msgSrcId; 
	UINT8	msgDstId; 
	UINT16	msgLength;	// Length is of the entire message, including header 
	UINT16	msgFlags; 
 
} SmsMsgHdr_ST; 
 
// Sms Messages 
#define MSG_SMS_NON_IP_MSG			607 
#define MSG_SMS_IP_MSG				699 
 
#define MSG_SMS_RF_TUNE_REQ 561	// A request to tune to a new frequency 
#define MSG_SMS_RF_TUNE_RES 562	// A request to tune to a new frequency 
/////////////////////////////////////////////////////////////////////////////// 
 
typedef struct AppNameTransltTable_S 
{ 
    TCHAR*                  AppName; 
    SIANO_APPLICATION_TYPE_E      AppType; 
}AppNameTransltTable_ST; 
                                     
const TCHAR* FwRegistryEntry[] = {   
                    /*DVBH       , DVBT         , TDMB          , ISDBT         , CMMB*/ 
/*SDIO Stellar*/    L"DvbhSdioFw", L"DvbtSdioFw", L"TdmbSdioFw" , L"None"	    , L"None"		,  
/*SPI Stellar*/     L"DvbhSpiFw" , L"DvbtSpiFw" , L"TdmbSpiFw"  , L"None"	    , L"None"		,  
/*HIF Stellar*/	    L"DvbhHifFw" , L"DvbtHifFw" , L"TdmbHifFw"  , L"None"	    , L"None"		,  
/*USB Stellar*/	    L"DvbhUsbFw" , L"DvbtUsbFw" , L"TdmbUsbFw"  , L"None"	    , L"None"		,  
/*NoLoad */         L"None"		 , L"None"	    , L"None"		, L"None"	    , L"None"		,  
/*SDIO Nova*/	    L"DvbNovaFw" , L"DvbNovaFw" , L"TdmbNovaFw" , L"IsdbtNovaFw", L"None"		,  
/*SPI Nova*/	    L"DvbNovaFw" , L"DvbNovaFw" , L"TdmbNovaFw" , L"IsdbtNovaFw", L"None"		,  
/*HIF Nova*/	    L"DvbNovaFw" , L"DvbNovaFw" , L"TdmbNovaFw" , L"IsdbtNovaFw", L"None"		,  
/*USB Nova*/    	L"DvbNovaFw" , L"DvbNovaFw" , L"TdmbNovaFw" , L"IsdbtNovaFw", L"None"		,  
					NULL}; 
 
const AppNameTransltTable_ST AppNameToAppEnumTable[] = {{L"DVBH", SIANO_DVBH}, 
                                                        {L"DVBT", SIANO_DVBT}, 
                                                        {L"TDMB", SIANO_TDMB}, 
                                                        {L"ISDBT", SIANO_ISDBT}, 
                                                        {L"CMMB", SIANO_CMMB}, 
                                                        {NULL, 0}}; 
 
/* Supported applications are DVBH, DVBT and TDBM*/      
#define NUM_OF_SUPPORTED_APPLICATIONS 5 
 
 
typedef struct 
{ 
    HANDLE userHandle; 
	BOOL   cancelIo; 
	HANDLE hReadEvent; 
	PUCHAR pFileBuffer; 
	ULONG  fileBuffSize; 
	ULONG  fileWrIdx; 
	ULONG  fileRdIdx; 
	ULONG  count; 
	HANDLE semRdWr; 
	UINT32 readTimeOut; 
 
} FILE_STREAM_PARAMS, *PFILE_STREAM_PARAMS; 
 
 
/*****************************************************************************/ 
/* The generic device structure                                              */ 
/*****************************************************************************/ 
typedef struct SMS_GEN_DEVICE_S 
{ 
    HANDLE				hBdDevice; 
	HANDLE				OpenCommThread; 
    HANDLE              hTuneEvent; 
	BD_TYPE_E			BdType; 
	FILE_STREAM_PARAMS	fStreams[SIANO_NUM_OF_FILE_STREAMS]; 
	ULONG				fStreamHandleCnt; 
	SmsMsgHdr_ST		SmsMsgHdr; 
	BOOL				MsgHdrReceived; 
	HINSTANCE			hNdisDLL; 
	GEN_ReadIpCBFunc	pReadIpCBFunc; 
	DWORD				hRdIpContext; 
    TCHAR               FwFileName[200]; 
    TCHAR               activeReg[40]; 
    SIANO_APPLICATION_TYPE_E AppType; 
    BOOL                blockIncommingDataPackets; 
} SMS_GEN_DEVICE_ST, *PSMS_GEN_DEVICE_ST; 
 
/* Global pointer to the only gen driver instance */ 
PSMS_GEN_DEVICE_ST g_pGenDrvInst = NULL; 
 
 
/////////////////////////////////////////////////////////////////////////////// 
 
BOOL SGD_Close(DWORD hOpenContext); 
 
PFILE_STREAM_PARAMS HandleToFS(PSMS_GEN_DEVICE_ST pGenDrv,HANDLE Handle); 
 
void FileBuffAppend(PSMS_GEN_DEVICE_ST pGenDev,SIANO_FILE_STREAM_TYPE_E fsType,PBYTE dataPtr,ULONG len); 
 
void BD_ReadCB(DWORD hContext, void* pBuffer, UINT32 BufSize); 
 
DWORD OpenCommToBD_Thread(LPVOID lpParam); 
 
void LoadMiniport(PSMS_GEN_DEVICE_ST pGenDev); 
 
void UnloadMiniport(PSMS_GEN_DEVICE_ST pGenDev); 
 
BOOL ChangeApplication(PSMS_GEN_DEVICE_ST pGenDev, SIANO_APPLICATION_TYPE_E AppType); 
 
#ifdef DVBT_CHECK_TS_SEQ_NUM 
UINT16 PidList[100]; 
UINT8 SeqNumList[100]; 
UINT8 seq_err_cnt[100]; 
UINT32 checked_pid_err_cnt = 0; 
UINT32  dvbt_ts_pkt_cnt = 0; 
void CheckTSSeqNum(PBYTE pBuff,DWORD buffSize); 
#endif 
 
/////////////////////////////////////////////////////////////////////////////// 
//define LOG_TO_FILE 
#define LOG_FILE TEXT("\\GenDrvLog.txt") 
#define MAX_REG_KEY_SIZE 100 
 
HANDLE hLogFile = INVALID_HANDLE_VALUE; 
 
 
#ifdef LOG_TO_FILE 
 
CRITICAL_SECTION    g_CriticalSection; 
 
VOID LogStrToFile(TCHAR *pLogStr,...) 
{ 
	va_list		argumentList; 
	int			length; 
	CHAR		charBuffer[500]; 
	TCHAR		tcharBuffer[500]; 
	DWORD		written; 
	INT			i; 
 
	EnterCriticalSection(&g_CriticalSection); 
 
	va_start(argumentList, pLogStr); 
 
	do { 
 
		length = _vsntprintf(tcharBuffer, 
			(500 - 1), 
			pLogStr, 
			argumentList); 
 
		if (length < 0) { 
			break; 
		} 
 
		if (hLogFile == INVALID_HANDLE_VALUE) { 
			break; 
		} 
 
		for (i = 0; i < length; i++) { 
			if ((CHAR)tcharBuffer != '\n') { 
				charBuffer[i] = (CHAR)tcharBuffer[i]; 
			} else { 
				charBuffer[i] = ' '; 
			} 
		} 
 
		WriteFile(hLogFile,charBuffer,length,&written,NULL); 
 
	} while (FALSE); 
 
	va_end(argumentList); 
 
	LeaveCriticalSection(&g_CriticalSection); 
} 
#endif 
 
 
void FlushAllFileBuf(PSMS_GEN_DEVICE_ST pGenDev) 
{ 
    int i; 
 
    for (i = 1;i < SIANO_NUM_OF_FILE_STREAMS;i++) 
    { 
        WaitForSingleObject(pGenDev->fStreams[i].semRdWr, INFINITE); 
        if (pGenDev->fStreams[i].userHandle != NULL && i != SIANO_CTRL_FILE_STREAM) 
        { 
            pGenDev->fStreams[i].fileWrIdx = 0; 
            pGenDev->fStreams[i].fileRdIdx = 0; 
            pGenDev->fStreams[i].count = 0; 
        } 
        ReleaseSemaphore(pGenDev->fStreams[i].semRdWr,1,NULL); 
    } 
 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
 
BOOL WINAPI DllMain( 
   HANDLE hDllHandle, 
   DWORD  dwReason, 
   LPVOID lpreserved 
   ) 
{ 
    BOOL bRc = TRUE; 
    
    UNREFERENCED_PARAMETER(hDllHandle); 
    UNREFERENCED_PARAMETER(lpreserved); 
 
	switch (dwReason) 
	{ 
		case DLL_PROCESS_ATTACH: 
			REGISTERZONES(hDllHandle); 
 
			// keep file handle open to indicate that the driver is loaded. 
			// on failure, continue without that indication 
#ifdef LOG_TO_FILE 
			hLogFile = CreateFile(LOG_FILE, 
                                  GENERIC_WRITE, 
                                  FILE_SHARE_READ | FILE_SHARE_WRITE, 
                                  NULL, 
                                  CREATE_ALWAYS, 
                                  0, 
                                  NULL); 
			 
 
 
			InitializeCriticalSection(&g_CriticalSection); 
#endif 
		//	RETAILMSG(1, (TEXT("SmsGenDrv: DLL_PROCESS_ATTACH\r\n"))); 
			break; 
 
		case DLL_PROCESS_DETACH: 
			RETAILMSG(1, (TEXT("SmsGenDrv: DLL_PROCESS_DETACH\r\n"))); 
			if (hLogFile != INVALID_HANDLE_VALUE) 
			{ 
				CloseHandle(hLogFile); 
			} 
#ifdef LOG_TO_FILE 
			DeleteCriticalSection(&g_CriticalSection); 
#endif 
			break; 
 
		default: 
			break; 
	} 
 
    return bRc; 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
//  SGD_Init - the init entry point 
//  Input:  dwContext - the context for this init 
//  Output: 
//  Return: returns a non-zero context 
//  Notes:  
/////////////////////////////////////////////////////////////////////////////// 
DWORD SGD_Init(DWORD dwContext) 
{ 
	PSMS_GEN_DEVICE_ST pGenDev; 
	PWCHAR		activeKeyPath = (PWCHAR)dwContext; 
	HKEY		regKey; 
	DWORD		keyType = 0; 
	DWORD		keyDataSize; 
	int i; 
 
 
	DBGMSG(ZONE_INFO, (TEXT("SmsGenDrv: +SGD_Init\r\n"))); 
 
#ifdef DVBT_CHECK_TS_SEQ_NUM 
	for (i = 0;i < 100;i++) 
	{ 
		PidList[i] = 0xFFFF; 
		SeqNumList[i] = 0xF; 
		seq_err_cnt[i] = 0; 
	} 
#endif 
 
	if (g_pGenDrvInst != NULL) 
	{ 
		DBGMSG(ZONE_ERROR, (TEXT("SmsGenDrv: Currently, SmsGenDrv support only one instance\r\n"))); 
		return 0; 
	} 
 
	/* Allocate the Gen Device */ 
	pGenDev = (PSMS_GEN_DEVICE_ST)LocalAlloc(LPTR, sizeof(SMS_GEN_DEVICE_ST)); 
	if (pGenDev == NULL) 
	{ 
		DBGMSG(ZONE_ERROR, (TEXT("SmsGenDrv: Failed to allocate SMS_GEN_DEVICE_ST\r\n"))); 
		return 0; 
	} 
 
       wcscpy(pGenDev->activeReg, activeKeyPath); 
 
	pGenDev->hBdDevice = INVALID_HANDLE_VALUE; 
 
	/* Read ClientInfo key to detect bus driver type */ 
	if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,pGenDev->activeReg,0,KEY_READ,®Key) != ERROR_SUCCESS) 
	{ 
		DBGMSG(ZONE_ERROR, (TEXT("SmsGenDrv: Failed to open registry for read\r\n"))); 
	    LocalFree(pGenDev); 
		return 0; 
	} 
 
	keyDataSize = sizeof(BD_TYPE_E); 
	if (RegQueryValueEx(regKey,TEXT("ClientInfo"),NULL,&keyType,(LPBYTE)&pGenDev->BdType,&keyDataSize) 
						!= ERROR_SUCCESS) 
	{ 
		DBGMSG(ZONE_ERROR, (TEXT("SmsGenDrv: Failed to read ClientInfo\r\n"))); 
	    LocalFree(pGenDev); 
		return 0; 
	} 
 
	if (RegCloseKey(regKey) != ERROR_SUCCESS) 
	{ 
		DBGMSG(ZONE_ERROR, (TEXT("SmsGenDrv: Failed to close registry\r\n"))); 
	    LocalFree(pGenDev); 
		return 0; 
	} 
 
	switch(pGenDev->BdType) 
	{ 
		case BD_TYPE_SDIO_STELLAR: 
		case BD_TYPE_SPI_STELLAR: 
		case BD_TYPE_HIF_STELLAR: 
		case BD_TYPE_SDIO_NOVA: 
		case BD_TYPE_SPI_NOVA: 
		case BD_TYPE_HIF_NOVA: 
			break; 
		case BD_TYPE_USB_STELLAR: 
		case BD_TYPE_USB_FW: 
		case BD_TYPE_USB_NOVA: 
		default: 
			DBGMSG(ZONE_ERROR, (TEXT("SmsGenDrv: Bus driver type not supported\r\n"))); 
			LocalFree(pGenDev); 
			return 0; 
	} 
 
	for (i = 0; i < SIANO_NUM_OF_FILE_STREAMS; i++) 
	{ 
		PFILE_STREAM_PARAMS pfStream = pGenDev->fStreams + i; 
		pfStream->userHandle = NULL; 
		pfStream->cancelIo = FALSE; 
		pfStream->hReadEvent = CreateEvent(NULL, FALSE, FALSE, NULL); 
		pfStream->fileBuffSize = (i == SIANO_CTRL_FILE_STREAM) ? CTRL_FILE_BUFF_SIZE : DATA_FILE_BUFF_SIZE; 
		pfStream->pFileBuffer = NULL; 
		pfStream->semRdWr = CreateSemaphore(NULL,1,1,NULL); 
	} 
 
	g_pGenDrvInst = pGenDev; 
 
    pGenDev->hTuneEvent = CreateEvent(NULL, FALSE, FALSE, NULL); 
    if (pGenDev->hTuneEvent == NULL) 
    { 
        DBGMSG(ZONE_ERROR, (TEXT("SmsGenDrv: Failed to create tune event.\r\n"))); 
        LocalFree(pGenDev); 
        return 0; 
    } 
	pGenDev->OpenCommThread = CreateThread(NULL,0,OpenCommToBD_Thread,(LPVOID)pGenDev,0,NULL); 
   	 
	DBGMSG(ZONE_INFO, (TEXT("SmsGenDrv: -SGD_Init\r\n"))); 
	return (DWORD)pGenDev; 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
//  SGD_Deinit - the deinit entry point for this driver 
//  Input:  hDeviceContext - the context returned from XXX_Init 
//  Output: 
//  Returns: Succeed or Failed 
//  Notes:  
/////////////////////////////////////////////////////////////////////////////// 
BOOL SGD_Deinit(DWORD hDeviceContext) 
{ 
	PSMS_GEN_DEVICE_ST pGenDev = (PSMS_GEN_DEVICE_ST)hDeviceContext; 
	int i; 
 
	DBGMSG(ZONE_INFO, (TEXT("SmsGenDrv: +SGD_Deinit\r\n"))); 
 
#ifdef DVBT_CHECK_TS_SEQ_NUM 
	for (i = 0;i < 100;i++) 
	{ 
		if (PidList[i] == 0xFFFF) 
			break; 
		DBGMSG(ZONE_ERROR, (TEXT("SmsGenDrv: Pid %d Seq %d Errs %d\r\n"),PidList[i],SeqNumList[i],seq_err_cnt[i]));		 
	} 
	DBGMSG(ZONE_ERROR, (TEXT("SmsGenDrv: Seq Errors %d from %d\r\n"),checked_pid_err_cnt,dvbt_ts_pkt_cnt)); 
#endif 
 
	for (i = 0;i < SIANO_NUM_OF_FILE_STREAMS;i++) 
	{ 
		if (pGenDev->fStreams[i].userHandle != NULL) 
		{ 
			SGD_Close((DWORD)pGenDev->fStreams[i].userHandle); 
			pGenDev->fStreams[i].userHandle = NULL; 
		} 
		CloseHandle(pGenDev->fStreams[i].hReadEvent); 
		pGenDev->fStreams[i].hReadEvent = NULL; 
		CloseHandle(pGenDev->fStreams[i].semRdWr); 
		pGenDev->fStreams[i].semRdWr = NULL; 
	} 
 
	if (pGenDev->hBdDevice != INVALID_HANDLE_VALUE) 
	{ 
		CloseHandle(pGenDev->hBdDevice); 
		pGenDev->hBdDevice = INVALID_HANDLE_VALUE; 
	} 
 
	// for protection, if the card was removed before the thread finished 
	if (pGenDev->OpenCommThread != NULL) 
	{ 
		WaitForSingleObject(pGenDev->OpenCommThread,2000); 
	} 
 
    if (pGenDev->hTuneEvent != NULL) 
    { 
        CloseHandle(pGenDev->hTuneEvent); 
    } 
	UnloadMiniport(pGenDev); 
 
    LocalFree(pGenDev); 
	pGenDev = NULL; 
 
	g_pGenDrvInst = NULL; 
 
	DBGMSG(ZONE_INFO, (TEXT("SmsGenDrv: -SGD_Deinit\r\n"))); 
	return TRUE; 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
//  SGD_Open - the open entry point 
//  Input:  hDeviceContext - the device context from XXX_Init 
//          AccessCode - the desired access 
//          ShareMode - the desired share mode 
//  Output: 
//  Return: returns an open context 
//  Notes: 
/////////////////////////////////////////////////////////////////////////////// 
DWORD SGD_Open(DWORD    hDeviceContext, 
               DWORD    AccessCode, 
               DWORD    ShareMode) 
{ 
	PSMS_GEN_DEVICE_ST pGenDev = (PSMS_GEN_DEVICE_ST)hDeviceContext; 
 
	DBGMSG(ZONE_INFO, (TEXT("SmsGenDrv: +SGD_Open\r\n"))); 
 
	if (pGenDev->hBdDevice == INVALID_HANDLE_VALUE) 
	{ 
	    // cummunication with bus briver is not ready yet 
	    DBGMSG(ZONE_INFO, (TEXT("SmsGenDrv: -SGD_Open cummunication with bus briver is not ready yet\r\n"))); 
		return 0; 
	} 
 
	pGenDev->fStreamHandleCnt++; 
 
    DBGMSG(ZONE_INFO, (TEXT("SmsGenDrv: -SGD_Open fStreamHandleCnt 0x%X\r\n"),pGenDev->fStreamHandleCnt)); 
 
	return pGenDev->fStreamHandleCnt; 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
//  SGD_Close - the close entry point 
//  Input:  hOpenContext - the context returned from XXX_Open 
//  Output: 
//  Return: Succeed or Failed 
//  Notes: 
/////////////////////////////////////////////////////////////////////////////// 
BOOL SGD_Close(DWORD hOpenContext) 
{ 
	PSMS_GEN_DEVICE_ST pGenDev = g_pGenDrvInst; 
	PFILE_STREAM_PARAMS fStream = HandleToFS(pGenDev,(HANDLE)hOpenContext); 
 
	DBGMSG(ZONE_INFO, (TEXT("SmsGenDrv: +SGD_Close\r\n"))); 
 
        pGenDev->fStreamHandleCnt--; 
	if (fStream == NULL) 
	{ 
	    DBGMSG(1,(TEXT("SmsGenDrv: SGD_Close failed to get fStream\r\n"))); 
		return FALSE; 
	} 
 
	WaitForSingleObject(fStream->semRdWr, INFINITE); 
	fStream->userHandle = NULL; 
	fStream->fileWrIdx = 0; 
	fStream->fileRdIdx = 0; 
	LocalFree(fStream->pFileBuffer); 
	fStream->pFileBuffer = NULL; 
	fStream->cancelIo = TRUE; 
	SetEvent(fStream->hReadEvent); 
	ReleaseSemaphore(fStream->semRdWr,1,NULL); 
 
	DBGMSG(ZONE_INFO, (TEXT("SmsGenDrv: -SGD_Close\r\n"))); 
	return TRUE; 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
//  SGD_IOControl - the I/O control entry point 
//  Input:  Handle - the context returned from XXX_Open 
//          IoctlCode - the ioctl code 
//          pInBuf - the input buffer from the user 
//          InBufSize - the length of the input buffer 
//          pOutBuf - the output buffer from the user 
//          InBufSize - the length of the output buffer 
//          pBytesReturned - the size of the transfer 
//  Output: 
//  Return: Succeed or Failed 
//  Notes: 
/////////////////////////////////////////////////////////////////////////////// 
BOOL SGD_IOControl(DWORD   Handle, 
                   DWORD   IoctlCode, 
                   PBYTE   pInBuf, 
                   DWORD   InBufSize, 
                   PBYTE   pOutBuf, 
                   DWORD   OutBufSize, 
                   PDWORD  pBytesReturned) 
{ 
	PSMS_GEN_DEVICE_ST pGenDev = g_pGenDrvInst; 
    	BOOL retVal = FALSE; 
	PFILE_STREAM_PARAMS fStream = NULL; 
	SIANO_FILE_STREAM_TYPE_E fsType; 
 
	DBGMSG(ZONE_INFO, (TEXT("SmsGenDrv: +SGD_IOControl IoctlCode=0x%x\r\n"), IoctlCode)); 
 
   	 switch (IoctlCode) 
	{ 
		case SIANO_GEN_IOCTL_SET_FILE_STREAM_TYPE: 
			/* input format : UINT32 - requested file stream type */ 
			DBGMSG(ZONE_INFO, (TEXT("SmsGenDrv: SIANO_GEN_IOCTL_SET_FILE_STREAM_TYPE\r\n"))); 
                        if ((NULL == pInBuf) || 
			     (InBufSize < sizeof(UINT32)) || 
			     ((UINT32*)pInBuf)[0] >= SIANO_NUM_OF_FILE_STREAMS || // is valid type 
				pGenDev->fStreams[((UINT32 *)pInBuf)[0]].userHandle != NULL) // is occupied 
			{ 
				 RETAILMSG(1, (TEXT("SmsGenDrv: SGD_IOControl SET_FILE_STREAM_TYPE failed %d\r\n"),Handle)); 
		                break; 
		         } 
			fsType = ((UINT32 *)pInBuf)[0]; 
			pGenDev->fStreams[fsType].userHandle = (HANDLE)Handle; 
			pGenDev->fStreams[fsType].pFileBuffer = (PUCHAR) 
			LocalAlloc(LPTR, pGenDev->fStreams[fsType].fileBuffSize); 
			ResetEvent(pGenDev->fStreams[fsType].hReadEvent); 
			pGenDev->fStreams[fsType].cancelIo = FALSE; 
			pGenDev->fStreams[fsType].fileWrIdx = 0; 
			pGenDev->fStreams[fsType].fileRdIdx = 0; 
			pGenDev->fStreams[fsType].count = 0; 
			pGenDev->fStreams[fsType].readTimeOut = INFINITE; 
			retVal = TRUE; 
			break; 
        	case SIANO_GEN_IOCTL_SET_READ_TIMEOUT: 
			DBGMSG(ZONE_INFO, (TEXT("SmsGenDrv: SIANO_GEN_IOCTL_SET_READ_TIMEOUT\r\n"))); 
			fStream = HandleToFS(pGenDev,(HANDLE)Handle); 
			if (fStream == NULL) 
			{ 
			    DBGMSG(ZONE_ERROR, (TEXT("SmsGenDrv: SGD_IOControl SIANO_GEN_IOCTL_SET_READ_TIMEOUT failed %d\r\n"),Handle)); 
               		    break; 
           		 } 
			fStream->readTimeOut = ((UINT32 *)pInBuf)[0]; 
			retVal = TRUE; 
			break; 
        	case SIANO_GEN_IOCTL_CANCEL_IO: 
			/* input format : None */ 
			DBGMSG(ZONE_INFO, (TEXT("SmsGenDrv: SIANO_GEN_IOCTL_CANCEL_IO\r\n"))); 
			fStream = HandleToFS(pGenDev,(HANDLE)Handle); 
			if (fStream == NULL) 
			{ 
			    DBGMSG(ZONE_ERROR, (TEXT("SmsGenDrv: SGD_IOControl IOCTL_CANCEL_IO failed %d\r\n"),Handle)); 
                	   break; 
           		} 
			WaitForSingleObject(fStream->semRdWr, INFINITE); 
			fStream->cancelIo = TRUE; 
			SetEvent(fStream->hReadEvent); 
			ReleaseSemaphore(fStream->semRdWr,1,NULL); 
           		RETAILMSG(1, (TEXT("SmsGenDrv: SGD_IOControl user cancel IO\r\n"))); 
			retVal = TRUE; 
            		break; 
		case SIANO_GEN_IOCTL_REGISTER_READ_IP_CB: 
			DBGMSG(1, (TEXT("SmsGenDrv: SIANO_GEN_IOCTL_REGISTER_READ_IP_CB\r\n"))); 
			pGenDev->pReadIpCBFunc = ((PGEN_IOCTL_REGISTER_READ_IP_PARAMS_ST)pInBuf)->pReadIpCBFunc; 
			pGenDev->hRdIpContext = ((PGEN_IOCTL_REGISTER_READ_IP_PARAMS_ST)pInBuf)->hContext; 
			retVal = TRUE; 
           		 break; 
        	case SIANO_IOCTL_CHANGE_APPLICATION: 
     	                if (pGenDev->AppType != *((SIANO_APPLICATION_TYPE_E*)pInBuf)) 
     	                { 
     	                    retVal = ChangeApplication(pGenDev, *((SIANO_APPLICATION_TYPE_E*)pInBuf)); 
     	                } 
     	                 else 
     	                    retVal = TRUE; 
     	                 break; 
       		 case SIANO_GEN_IOCTL_GET_APP_TYPE: 
		            DBGMSG(1, (TEXT("SmsGenDrv: SIANO_GEN_IOCTL_GET_APP_TYPE.\r\n"))); 
		            if (pOutBuf && OutBufSize >= sizeof(SIANO_APPLICATION_TYPE_E)) 
		            { 
		                *((SIANO_APPLICATION_TYPE_E*)pOutBuf) = pGenDev->AppType; 
		                if (pBytesReturned) 
		                    *pBytesReturned = sizeof(SIANO_APPLICATION_TYPE_E); 
		                retVal = TRUE; 
		            } 
		            else 
		            { 
		                if (pBytesReturned) 
		                    *pBytesReturned = 0; 
		                retVal = FALSE; 
		            } 
		            break; 
		        default: 
			DBGMSG(1, (TEXT("SmsGenDrv: Unknown IOCTL 0x%X 0x%X\r\n"),IoctlCode)); 
            break; 
	} 
 
	DBGMSG(1, (TEXT("SmsGenDrv: -SGD_IOControl. ret %d\r\n"),retVal)); 
	return retVal; 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
//  SGD_Read - the read entry point 
//  Input:  hOpenContext - the context from XXX_Open 
//          pBuffer - the user's buffer 
//          Count - the size of the transfer 
//  Output: 
//  Return: (-1) OS will return FALSE in ReadFile 
//  Notes:  Not used 
/////////////////////////////////////////////////////////////////////////////// 
DWORD SGD_Read(DWORD    hOpenContext, 
               LPVOID   pBuffer, 
               DWORD    Count) 
{ 
	PSMS_GEN_DEVICE_ST pGenDev = g_pGenDrvInst; 
	PFILE_STREAM_PARAMS fStream = HandleToFS(pGenDev,(HANDLE)hOpenContext); 
	DWORD bytesRead = 0; 
 
	DBGMSG(ZONE_INFO, (TEXT("SmsGenDrv: +SGD_Read\r\n"))); 
 
	if (fStream == NULL) 
	{ 
	    RETAILMSG(1,(TEXT("SmsGenDrv: SGD_Read failed to get fStream\r\n"))); 
		return (DWORD)(-1); 
	} 
 
	if ((pBuffer == NULL) || (Count == 0)) 
	{ 
		return (DWORD)(-1); 
	} 
 
	WaitForSingleObject(fStream->semRdWr, INFINITE); 
      
	while (fStream->count == 0) 
	{ 
		ReleaseSemaphore(fStream->semRdWr,1,NULL); 
 
		if (WaitForSingleObject(fStream->hReadEvent,fStream->readTimeOut) != WAIT_OBJECT_0) 
			return 0; //No data, timeout on read. 
           
 
		WaitForSingleObject(fStream->semRdWr, INFINITE); 
		 
		// check if cancel was request 
		if (fStream->cancelIo == TRUE) 
		{ 
			ReleaseSemaphore(fStream->semRdWr,1,NULL); 
			return (DWORD)(-1); // ReadFile will return FALSE 
		} 
	} 
	// limit the read to the bytes in the buffer 
	if (Count > fStream->count) 
		Count = fStream->count; 
 
	if (Count > (fStream->fileBuffSize - fStream->fileRdIdx)) 
	{ 
		bytesRead = (fStream->fileBuffSize - fStream->fileRdIdx); 
		memcpy(pBuffer,fStream->pFileBuffer + fStream->fileRdIdx,bytesRead); 
		memcpy(((LPBYTE)pBuffer) + bytesRead,fStream->pFileBuffer,Count - bytesRead);		 
	} 
	else 
	{ 
		memcpy(pBuffer,fStream->pFileBuffer + fStream->fileRdIdx,Count); 
	} 
	bytesRead = Count; 
 
	fStream->count -= Count; 
 
	fStream->fileRdIdx += bytesRead; 
	if (fStream->fileRdIdx >= fStream->fileBuffSize) 
		fStream->fileRdIdx -= fStream->fileBuffSize; 
 
	ReleaseSemaphore(fStream->semRdWr,1,NULL); 
 
	DBGMSG(ZONE_INFO, (TEXT("SmsGenDrv: -SGD_Read bytesRead %d\r\n"),bytesRead)); 
	return bytesRead; 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
//  SGD_Write - the write entry point 
//  Input:  hOpenContext - the context from XXX_Open 
//          pBuffer - the user's buffer 
//          Count - the size of the transfer 
//  Output: 
//  Return: Number of bytes written. ? indicates failure 
//  Notes: 
/////////////////////////////////////////////////////////////////////////////// 
DWORD SGD_Write(DWORD   hOpenContext, 
                LPCVOID pBuffer, 
                DWORD   Count) 
{ 
	SmsMsgHdr_ST* pMsgHdr = (SmsMsgHdr_ST*)pBuffer; 
	PSMS_GEN_DEVICE_ST pGenDev = g_pGenDrvInst; 
	PFILE_STREAM_PARAMS fStream = HandleToFS(pGenDev,(HANDLE)hOpenContext); 
	DWORD bytesWr = 0; 
 
	DBGMSG(ZONE_INFO, (TEXT("SmsGenDrv: +SGD_Write. Count %d\r\n"),Count)); 
 
	if (pGenDev->hBdDevice == INVALID_HANDLE_VALUE) 
	{ 
		RETAILMSG(1,(TEXT("SmsGenDrv: SGD_Write failed. hBdDevice is invalid\r\n"))); 
		return (DWORD)(-1); 
	} 
 
	if (fStream == NULL) 
	{ 
	        RETAILMSG(1,(TEXT("SmsGenDrv: SGD_Write failed to get fStream\r\n"))); 
		return (DWORD)(-1); 
	} 
 
  // RETAILMSG(1, (TEXT("SmsGenDrv: +SGD_Write. msgtype  %d\r\n"),pMsgHdr->msgType));@@@@@@@@@ 
    if (pMsgHdr->msgType == MSG_SMS_RF_TUNE_REQ) 
    { //Tuning SMS freq, so SDIO clk need to avoid harmonics on tunes freq. 
		pGenDev->blockIncommingDataPackets = TRUE; 
		FlushAllFileBuf(pGenDev); 
    } 
	if (WriteFile(pGenDev->hBdDevice,pBuffer,Count,&bytesWr,NULL) == FALSE) 
	{ 
	    RETAILMSG(1,(TEXT("SmsGenDrv: SGD_Write failed to write buffer\r\n"))); 
	    return (DWORD)(-1); 
	} 
 
    if (pMsgHdr->msgType == MSG_SMS_RF_TUNE_REQ) 
    { //Tuning SMS freq, so SDIO clk need to avoid harmonics on tunes freq. 
        WaitForSingleObject(pGenDev->hTuneEvent, 500); 
        pGenDev->blockIncommingDataPackets = FALSE; 
    } 
	if (bytesWr != Count) 
	{ 
	    RETAILMSG(1, (TEXT("SmsGenDrv: SGD_Write failed to write all bytes. %d != %d\r\n"),Count,bytesWr)); 
	    return (DWORD)(-1); 
	} 
 
	DBGMSG(ZONE_INFO, (TEXT("SmsGenDrv: -SGD_Write\r\n"))); 
	return bytesWr; 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
//  SGD_PowerDown - the power down entry point event from the OS 
//  Input:  hDeviceContext - the device context from XXX_Init 
//  Output: 
//  Return: 
//  Notes: 
/////////////////////////////////////////////////////////////////////////////// 
void SGD_PowerDown(DWORD    hDeviceContext) 
{ 
    return; 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
//  SGD_PowerUp - the power up entry point event from the OS 
//  Input:  hDeviceContext - the device context from XXX_Init 
//  Output: 
//  Return: 
//  Notes: 
/////////////////////////////////////////////////////////////////////////////// 
void SGD_PowerUp(DWORD  hDeviceContext) 
{ 
    return; 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
//  SGD_Seek - the seek entry point 
//  Input:  hOpenContext - the context from XXX_Open 
//          Amount - the amount to seek 
//          Type - the type of seek 
//  Output: 
//  Return: (-1) indicates failure 
//  Notes:  Not used 
/////////////////////////////////////////////////////////////////////////////// 
DWORD SGD_Seek(DWORD    hOpenContext, 
               long     Amount, 
               DWORD    Type) 
{ 
	return (DWORD)(-1); 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
 
PFILE_STREAM_PARAMS HandleToFS(PSMS_GEN_DEVICE_ST pGenDrv,HANDLE Handle) 
{ 
	int i; 
 
	for (i = 0;i < SIANO_NUM_OF_FILE_STREAMS;i++) 
	{ 
		if (pGenDrv->fStreams[i].userHandle == Handle) 
		{ 
			return &pGenDrv->fStreams[i]; 
		} 
	} 
	return NULL; 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
 
void FileBuffAppend(PSMS_GEN_DEVICE_ST pGenDev,SIANO_FILE_STREAM_TYPE_E fsType,PBYTE dataPtr,ULONG len) 
{ 
	ULONG sizeToWr; 
	PFILE_STREAM_PARAMS fStream = &pGenDev->fStreams[fsType]; 
 
	if (len == 0) 
	{ 
		RETAILMSG(1, (TEXT("SmsGenDrv: File stream error: request to append 0 %d\r\n"),fsType)); 
		return; 
	} 
 
	WaitForSingleObject(fStream->semRdWr, INFINITE); 
 
	if (fStream->userHandle == NULL) 
	{ 
		ReleaseSemaphore(fStream->semRdWr,1,NULL); 
		return; 
	} 
 
	if (len > (fStream->fileBuffSize - fStream->count)) 
	{ 
		RETAILMSG(1, (TEXT("SmsGenDrv: FileBuffAppend - buffer %d is full\r\n"),fsType)); 
		ReleaseSemaphore(fStream->semRdWr,1,NULL); 
		return; 
	} 
 
	sizeToWr = len; 
	if ((fStream->fileWrIdx + len) > fStream->fileBuffSize) 
		sizeToWr = fStream->fileBuffSize - fStream->fileWrIdx; 
 
	memcpy(fStream->pFileBuffer + fStream->fileWrIdx,dataPtr,sizeToWr); 
 
	fStream->fileWrIdx += len; 
	if (fStream->fileWrIdx >= fStream->fileBuffSize) 
		fStream->fileWrIdx -= fStream->fileBuffSize; 
 
	dataPtr += sizeToWr; 
	sizeToWr = len - sizeToWr; 
 
	// copy the residual to the start of the buffer 
	if (sizeToWr > 0) 
	{ 
		memcpy(fStream->pFileBuffer,dataPtr,sizeToWr); 
	} 
 
	fStream->count += len; 
 
	SetEvent(fStream->hReadEvent); 
 
	ReleaseSemaphore(fStream->semRdWr,1,NULL); 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
 
void BD_ReadCB(DWORD hContext, void* pBuffer, UINT32 BufSize) 
{ 
	PSMS_GEN_DEVICE_ST pGenDev = (PSMS_GEN_DEVICE_ST)hContext; 
	SmsMsgHdr_ST* SmsMsgHdrPtr; 
	PBYTE pMsgData; 
	UINT32 msgDataLen; 
 
	//RETAILMSG(1,(TEXT("SmsGenDrv: +BD_ReadCB\r\n"))); 
 
	if (pGenDev->MsgHdrReceived == FALSE) 
	{ 
		SmsMsgHdrPtr = (SmsMsgHdr_ST*)pBuffer; 
		if (SmsMsgHdrPtr->msgLength > BufSize) 
		{ 
			// message is split. NOTE: support only split of header from message data. 
			if (BufSize < sizeof(SmsMsgHdr_ST)) 
			{ 
				RETAILMSG(1, (TEXT("SmsGenDrv: Received len less than msg header size %d\r\n"),BufSize)); 
				return; 
			} 
 
			// keep the header 
			memcpy(&pGenDev->SmsMsgHdr,SmsMsgHdrPtr,sizeof(SmsMsgHdr_ST)); 
			// Exit. The msg data will should be received in the next call to the function 
			pGenDev->MsgHdrReceived = TRUE; 
			return; 
		} 
		else 
		{ 
			pMsgData = (PBYTE)(SmsMsgHdrPtr + 1); 
		} 
	} 
	else 
	{ 
		SmsMsgHdrPtr = &pGenDev->SmsMsgHdr; 
		pMsgData = pBuffer; 
	} 
 
	// check msg total length 
	if (pGenDev->MsgHdrReceived) // split 
	{ 
		if (SmsMsgHdrPtr->msgLength > (BufSize + sizeof(SmsMsgHdr_ST))) 
		{ 
			RETAILMSG(1, (TEXT("SmsGenDrv: Received less than msg len %d > %d (split)\r\n"), 
						SmsMsgHdrPtr->msgLength,(BufSize + sizeof(SmsMsgHdr_ST)))); 
			pGenDev->MsgHdrReceived = FALSE; 
			return; 
		} 
	} 
	else // not split 
	{ 
		if (SmsMsgHdrPtr->msgLength > BufSize) 
		{ 
			RETAILMSG(1,(TEXT("SmsGenDrv: Received less than msg len %d > %d\r\n"), 
						SmsMsgHdrPtr->msgLength,BufSize)); 
			return; 
		} 
	} 
 
	msgDataLen = SmsMsgHdrPtr->msgLength - sizeof(SmsMsgHdr_ST); 
 
	//RETAILMSG(1,(TEXT("SmsGenDrv: Received msg - MsgType %d SrcId %X DstId %X Len %d Flags %X Size %d bufSize %d\r\n"), 
	//	SmsMsgHdrPtr->msgType,SmsMsgHdrPtr->msgSrcId,SmsMsgHdrPtr->msgDstId, 
	//	SmsMsgHdrPtr->msgLength,SmsMsgHdrPtr->msgFlags,msgDataLen,BufSize)); 
 
	switch (SmsMsgHdrPtr->msgType) 
	{ 
		case MSG_SMS_IP_MSG: 
			if (pGenDev->pReadIpCBFunc) 
			{ 
                if (!pGenDev->blockIncommingDataPackets) 
                { 
                    pGenDev->pReadIpCBFunc(pGenDev->hRdIpContext,pMsgData,msgDataLen); 
                } 
			} 
			else 
			{ 
				RETAILMSG(1, (TEXT("SmsGenDrv: No ReadIpCB to accept IP msg\r\n"))); 
			} 
			break; 
		case MSG_SMS_NON_IP_MSG: 
        case 729: 
			if (SmsMsgHdrPtr->msgDstId >= SIANO_MIN_DATA_FILE_STREAM && SmsMsgHdrPtr->msgDstId <= SIANO_MAX_DATA_FILE_STREAM) 
			{ 
				if (!pGenDev->blockIncommingDataPackets) 
				{ 
#ifdef DVBT_CHECK_TS_SEQ_NUM 
				CheckTSSeqNum(pMsgData,msgDataLen); 
#endif 
				FileBuffAppend(pGenDev,(SIANO_FILE_STREAM_TYPE_E)SmsMsgHdrPtr->msgDstId,pMsgData,msgDataLen); 
                } 
			} 
			else 
			{ 
				RETAILMSG(1,(TEXT("SmsGenDrv: FileBuffAppend : request to append to unknow file stream %d\r\n"), 
							SmsMsgHdrPtr->msgDstId)); 
			} 
			break; 
		case MSG_SMS_RF_TUNE_RES: 
            SetEvent(pGenDev->hTuneEvent);				 
		default:  // control message 
			if (pGenDev->MsgHdrReceived) // split 
			{ 
				FileBuffAppend(pGenDev,SIANO_CTRL_FILE_STREAM,(PBYTE)SmsMsgHdrPtr,sizeof(SmsMsgHdr_ST)); 
				FileBuffAppend(pGenDev,SIANO_CTRL_FILE_STREAM,pMsgData,msgDataLen); 
				//RETAILMSG(1,(TEXT("SmsGenDrv: -BD_ReadCB:control message split\r\n")));@@@@@@@@@ 
			} 
			else // non split 
			{ 
				FileBuffAppend(pGenDev,SIANO_CTRL_FILE_STREAM,(PBYTE)SmsMsgHdrPtr,SmsMsgHdrPtr->msgLength); 
				//RETAILMSG(1,(TEXT("SmsGenDrv: -BD_ReadCB:control message non split\r\n")));@@@@@@@@@@@ 
			} 
			break; 
	} 
 
	pGenDev->MsgHdrReceived = FALSE; // turn off the flag for next message 
 
//	RETAILMSG(1,(TEXT("SmsGenDrv: -BD_ReadCB\r\n")));@@@@@@@@@@@ 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
 
static BOOL genGetRegistrySettings(PSMS_GEN_DEVICE_ST pGenDev) 
{ 
    TCHAR*	regKey; 
    BOOL	st; 
    HKEY	hKey; 
    DWORD	dataSize, type, idx; 
    TCHAR   AppName[10]; 
    SIANO_APPLICATION_TYPE_E    AppType; 
 
    RETAILMSG(1, (TEXT("SmsGenDrv: +genGetRegistrySettings.\r\n"))); 
    regKey = (TCHAR *)LocalAlloc (LPTR, MAX_REG_KEY_SIZE); 
    if (regKey == NULL) 
    { 
        RETAILMSG(1, (TEXT("SmsGenDrv: Allocating memory for registry reading failed.\r\n"))); 
        return FALSE; 
    } 
 
 
    st = RegOpenKeyEx(HKEY_LOCAL_MACHINE, pGenDev->activeReg, 0, 0, &hKey);						 
    if(st != ERROR_SUCCESS) 
    { 
        RETAILMSG(1, (TEXT("SmsGenDrv: Could not open active registry key.\r\n"))); 
        LocalFree(regKey); 
        return (FALSE); 
    } 
 
    dataSize=MAX_REG_KEY_SIZE; 
    st = RegQueryValueEx(	hKey,  
        TEXT("Key"),  
        NULL, 
        &type,  
        (LPBYTE)regKey,  
        &dataSize); 
 
    RegCloseKey(hKey); 
    if(st!=ERROR_SUCCESS)	 
    { 
        RETAILMSG(1, (TEXT("SmsGenDrv: Could not get registry key name.\r\n"))); 
        LocalFree(regKey); 
        return (FALSE); 
    } 
 
    // Now - read all the needed parameters for the driver from the registry. 
    st = RegOpenKeyEx(HKEY_LOCAL_MACHINE, regKey, 0, 0, &hKey); 
    if(st != ERROR_SUCCESS) 
    { 
        RETAILMSG(1, (TEXT("SmsGenDrv: Could not open registry key.\r\n"))); 
        LocalFree(regKey); 
        return (FALSE); 
    } 
 
 
    // Read the current mdtv application. 
   /* 
    dataSize=sizeof(AppName); 
    st = RegQueryValueEx(   hKey,  
                            L"Application",  
                            0,  
                            &type,  
                            (LPBYTE)&AppName, 
                            &dataSize);                      
  */ 
   
   wcscpy(AppName,AppNameToAppEnumTable[2].AppName); 
    for (idx = 0; AppName[idx] != 0 && idx < sizeof(AppName)/2; idx++) 
        AppName[idx] = towupper(AppName[idx]); 
 
    //Translate the application string into Enum 
    for (idx = 0; AppNameToAppEnumTable[idx].AppName != NULL; idx++) 
    {         
        if (wcscmp(AppName, AppNameToAppEnumTable[idx].AppName) == 0) 
        { 
            AppType = AppNameToAppEnumTable[idx].AppType; 
            break; 
        } 
    } 
 
    pGenDev->AppType = AppType; 
 
    // According to Enum and Application - find the Fw file name. 
    idx = pGenDev->BdType * NUM_OF_SUPPORTED_APPLICATIONS + AppType; 
    RETAILMSG(1, (TEXT("SmsGenDrv: Chosen application is %s, RegistryIdx=%d.\r\n"), AppName, idx)); 
 
    // Read Fw fileName from registry. 
    dataSize=sizeof(pGenDev->FwFileName); 
    st = RegQueryValueEx(   hKey,  
                            FwRegistryEntry[idx],  
                            0,  
                            &type,  
                            (LPBYTE)&pGenDev->FwFileName, 
                            &dataSize); 
     
    RETAILMSG(1, (TEXT("SmsGenDrv: Firmware file name is :%s.\r\n"), pGenDev->FwFileName)); 
    LocalFree(regKey); 
    return (TRUE); 
 
} 
 
 
/////////////////////////////////////////////////////////////////////////////// 
 
BOOL DownloadCardFw(PSMS_GEN_DEVICE_ST pGenDev) 
{ 
	FILE* pf; 
	BOOL found; 
	DWORD fileSize; 
	PBYTE pBuff; 
 
 
    found = FALSE; 
 
    /* Read the registry again to make sure we download the current required FW */ 
    genGetRegistrySettings(pGenDev); 
 
	/* read inp to memory */ 
 
	if (pGenDev->FwFileName[0] == 0) 
	{ 
		RETAILMSG(1, (TEXT("SmsGenDrv: FW Download failed since FW filename is unknown.\r\n"))); 
		return FALSE; 
	} 
	 
	DBGMSG(1, (TEXT("SmsGenDrv: download FW :%s\r\n"),pGenDev->FwFileName)); 
 
	pf = _wfopen(pGenDev->FwFileName,TEXT("rb")); 
	if (pf == NULL) 
	{ 
		// error open file 
	//	MessageBox(NULL,TEXT("Error reading inp file!"),TEXT("Siano Error"),MB_OK); 
		RETAILMSG(1, (TEXT("Error reading inp file!\r\n"))); 
		return FALSE; 
	} 
 
	fseek(pf,0,SEEK_END); 
	fileSize = ftell(pf); 
	fseek(pf,0,SEEK_SET); 
	 
	pBuff = (PBYTE)LocalAlloc(LPTR, fileSize); 
	if (fread(pBuff,1,fileSize,pf) == fileSize) 
		DBGMSG(1,(TEXT("SmsGenDrv: download file size: %d\r\n"),fileSize)); 
	else 
		DBGMSG(1,(TEXT("SmsGenDrv: fread faild. err %d\r\n"),GetLastError())); 
 
	fclose(pf); 
 
	/* write FW buffer to the card */ 
 
	if (DeviceIoControl(pGenDev->hBdDevice ,SIANO_BD_IOCTL_WRITE_FW_BUFF_TO_DEVICE,pBuff,fileSize, 
					NULL,0,NULL,NULL) == FALSE) 
	{ 
		RETAILMSG(1,(TEXT("SmsGenDrv: Failed to download FW. Error %d\r\n"), 
							GetLastError())); 
		return FALSE; 
	} 
     LocalFree(pBuff);  
	 
	   
	return TRUE; 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
BOOL ChangeApplication(PSMS_GEN_DEVICE_ST pGenDev, SIANO_APPLICATION_TYPE_E AppType) 
{ 
 
    TCHAR*	regKey; 
    BOOL	st; 
    HKEY	hKey; 
    DWORD	dataSize, type; 
    char msg[] = {0xb9, 0x02, 0x96, 0x0b, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 
 
    RETAILMSG(1,(TEXT("SmsGenDrv: +genGetRegistrySettings.\r\n"))); 
    regKey = (TCHAR *)LocalAlloc (LPTR, MAX_REG_KEY_SIZE); 
    if (regKey == NULL) 
    { 
        RETAILMSG(1,(TEXT("SmsGenDrv: Allocating memory for registry reading failed.\r\n"))); 
        return FALSE; 
    } 
 
 
    st = RegOpenKeyEx(HKEY_LOCAL_MACHINE, pGenDev->activeReg, 0, 0, &hKey);						 
    if(st != ERROR_SUCCESS) 
    { 
        RETAILMSG(1,(TEXT("SmsGenDrv: Could not open active registry key.\r\n"))); 
        LocalFree(regKey); 
        return (FALSE); 
    } 
 
    dataSize=MAX_REG_KEY_SIZE; 
    st = RegQueryValueEx(hKey,  
        TEXT("Key"),  
        NULL, 
        &type,  
        (LPBYTE)regKey,  
        &dataSize); 
 
    RegCloseKey(hKey); 
    if(st!=ERROR_SUCCESS)	 
    { 
        RETAILMSG(1,(TEXT("SmsGenDrv: Could not get registry key name.\r\n"))); 
        LocalFree(regKey); 
        return (FALSE); 
    } 
 
    // Now - read all the needed parameters for the driver from the registry. 
    st = RegOpenKeyEx(HKEY_LOCAL_MACHINE, regKey, 0, 0, &hKey); 
    if(st != ERROR_SUCCESS) 
    { 
        RETAILMSG(1,(TEXT("SmsGenDrv: Could not open registry key.\r\n"))); 
        LocalFree(regKey); 
        return (FALSE); 
    } 
 
    st = RegSetValueEx(  hKey, 
                    L"Application", 
                    0, 
                    REG_SZ, 
                    (LPBYTE)AppNameToAppEnumTable[AppType].AppName, 
                    sizeof(AppNameToAppEnumTable[AppType].AppName) * 2); 
    if(st != ERROR_SUCCESS) 
    { 
       RETAILMSG(1,(TEXT("SmsGenDrv: Could not Change registry key.\r\n"))); 
        LocalFree(regKey); 
        RegCloseKey(hKey); 
        return (FALSE); 
    } 
    st = RegFlushKey(hKey); 
    if(st != ERROR_SUCCESS) 
    { 
        RETAILMSG(1,(TEXT("SmsGenDrv: Could not Change registry key.\r\n"))); 
        LocalFree(regKey); 
        RegCloseKey(hKey); 
        return (FALSE); 
    } 
    RegCloseKey(hKey); 
 
    /*Reset the device in order to return it to the ROM*/ 
    if (WriteFile(pGenDev->hBdDevice,msg,sizeof(msg),&dataSize,NULL) == FALSE) 
    { 
        DBGMSG(ZONE_ERROR, (TEXT("SmsGenDrv: ChangeApplication failed to send reset.\r\n"))); 
        return (DWORD)(-1); 
    } 
    Sleep (3000); 
    /* Re-Download The FW*/ 
    st = DownloadCardFw(pGenDev); 
    Sleep (100); 
    return st; 
 
 
 
} 
 
 
/////////////////////////////////////////////////////////////////////////////// 
DWORD OpenCommToBD_Thread(LPVOID lpParam) 
{ 
	HANDLE hBdFile; 
	BD_IOCTL_REGISTER_READ_PARAMS_ST readParams; 
	PSMS_GEN_DEVICE_ST pGenDev = (PSMS_GEN_DEVICE_ST)lpParam; 
	UINT32 retryCnt = 0; 
	_TCHAR	bdName[10]; 
 
	 
	RETAILMSG(1, (TEXT("SmsGenDrv: +OpenCommToBD_Thread\r\n"))); 
 
	switch(pGenDev->BdType) 
	{ 
		case BD_TYPE_SDIO_STELLAR: 
		case BD_TYPE_SDIO_NOVA: 
			wcscpy(bdName,SIANO_SDIO_PREFIX); 
			break; 
		case BD_TYPE_SPI_STELLAR: 
		case BD_TYPE_SPI_NOVA: 
			wcscpy(bdName,SIANO_SPI_PREFIX); 
			break; 
		case BD_TYPE_HIF_STELLAR: 
		case BD_TYPE_HIF_NOVA: 
			wcscpy(bdName,SIANO_HIF_PREFIX); 
			break; 
	} 
	wcscat(bdName,TEXT("1:")); // for now, support only one device 
 
	/* open communication to bus driver. try up to three times to assure that the bus driver finish its XXX_Init */ 
	RETAILMSG(1, (TEXT("SmsGenDrv: open communication to %s\r\n"),bdName)); 
	do { 
		retryCnt++; 
		hBdFile = CreateFile(bdName,GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL); 
		if (hBdFile == INVALID_HANDLE_VALUE) 
		{ 
			RETAILMSG(1, (TEXT("SmsGenDrv: Failed to open connection to the bus driver. Try % d Error %d\r\n"), 
								retryCnt,GetLastError())); 
			if (retryCnt == 3) 
			{ 
				RETAILMSG(1, (TEXT("SmsGenDrv: Stop trying to open connection to the bus driver.\r\n"))); 
				return 1; 
			} 
			Sleep(100); 
			continue; 
		} 
		break; 
	} while (TRUE); 
 
 
	readParams.pBD_ReadCBFunc = BD_ReadCB; 
	readParams.hContext = (DWORD)pGenDev; 
	if (DeviceIoControl(hBdFile,SIANO_BD_IOCTL_REGISTER_READ_CB,&readParams,sizeof(readParams), 
						  NULL,0,NULL,NULL) == FALSE) 
	{ 
		RETAILMSG(1, (TEXT("SmsGenDrv: Failed to register read callback in the bus driver. Error %d\r\n"), 
							GetLastError())); 
		CloseHandle(hBdFile); 
		return 1; 
	} 
 
 
	 pGenDev->hBdDevice = hBdFile; /////////////////// 
 
	if (DownloadCardFw(pGenDev) == FALSE) 
	{ 
		pGenDev->hBdDevice = NULL; 
		CloseHandle(hBdFile); 
		return 1; 
	} 
 
	pGenDev->OpenCommThread = NULL; 
 
	LoadMiniport(pGenDev); 
      
 
	RETAILMSG(1, (TEXT("SmsGenDrv: -OpenCommToBD_Thread\r\n"))); 
	return 0; 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
 
void LoadMiniport(PSMS_GEN_DEVICE_ST pGenDev) 
{ 
	NDIS_STATUS ndisStatus; 
	VOID (*pNdisRegisterAdapter)(PNDIS_STATUS, PWSTR,PWSTR); 
 
	pGenDev->hNdisDLL = LoadLibrary(TEXT("Ndis.dll")); 
	if (pGenDev->hNdisDLL == NULL) 
	{ 
		return; 
	} 
 
	pNdisRegisterAdapter = (VOID (*)(PNDIS_STATUS, PWSTR,PWSTR))GetProcAddress( 
									pGenDev->hNdisDLL,TEXT("NdisRegisterAdapter"));  
	if (pNdisRegisterAdapter == NULL) 
	{ 
		RETAILMSG(1, (TEXT("SmsGenDrv: Failed to get NdisRegisterAdapter proc address\r\n"))); 
		FreeLibrary(pGenDev->hNdisDLL); 
		pGenDev->hNdisDLL = NULL; 
		return; 
	} 
 
	pNdisRegisterAdapter(&ndisStatus,TEXT("SmsNdis"),TEXT("SmsNdis1")); 
	if(ndisStatus != STATUS_SUCCESS) 
	{ 
		RETAILMSG(1, (TEXT("SmsGenDrv: Failed to register miniport adapter. status 0x%X\r\n"),ndisStatus)); 
		FreeLibrary(pGenDev->hNdisDLL); 
		pGenDev->hNdisDLL = NULL; 
		return; 
	} 
	RETAILMSG(1, (TEXT("SmsGenDrv: Miniport loaded successfully\r\n"))); 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
 
void UnloadMiniport(PSMS_GEN_DEVICE_ST pGenDev) 
{ 
	NDIS_STATUS ndisStatus; 
	VOID (*pNdisDeregisterAdapter)(PNDIS_STATUS, PWSTR); 
 
	if (pGenDev->hNdisDLL) 
	{ 
		pNdisDeregisterAdapter = (VOID (*)(PNDIS_STATUS, PWSTR))GetProcAddress(pGenDev->hNdisDLL,TEXT("NdisDeregisterAdapter")); 
		if (pNdisDeregisterAdapter) 
		{ 
			pNdisDeregisterAdapter(&ndisStatus,TEXT("SmsNdis1")); 
			if(ndisStatus != STATUS_SUCCESS) 
			{ 
				RETAILMSG(1,(TEXT("SmsGenDrv: Failed to deregister miniport adapter. status %d\r\n"),ndisStatus)); 
			} 
		} 
		else 
		{ 
			RETAILMSG(1,(TEXT("SmsGenDrv: Failed to get NdisDeregisterAdapter proc address\r\n"))); 
		} 
 
		FreeLibrary(pGenDev->hNdisDLL); 
		pGenDev->hNdisDLL = NULL; 
		RETAILMSG(1,(TEXT("SmsGenDrv: Miniport unloaded successfully\r\n"))); 
	} 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
 
#ifdef DVBT_CHECK_TS_SEQ_NUM 
void CheckTSSeqNum(PBYTE pBuff,DWORD buffSize) 
{ 
	int i; 
	UINT16 pid; 
	UINT8 seq_num; 
 
	PBYTE pTS = pBuff; 
 
	while (pTS < (pBuff + buffSize)) 
	{ 
		dvbt_ts_pkt_cnt++; 
 
		if (pTS[0] != 0x47) 
		{ 
			checked_pid_err_cnt+=1000; 
			pTS += 188; 
			continue; 
		} 
 
		pid = ((pTS[1] << 8) + pTS[2]) & 0x1FFF; 
		seq_num = pTS[3] & 0xF; 
 
		if (pid == 0x1FFF) 
		{ 
			// skip null packets 
			pTS += 188; 
			continue; 
		} 
 
		// search if pid exist 
		for (i = 0;i < 100;i++) 
		{ 
			if (PidList[i] == 0xFFFF || pid == PidList[i]) 
			{ 
				break; 
			} 
		} 
 
		if (i == 100) 
		{ 
			// more than 100 pids 
			pTS += 188; 
			continue; 
		} 
 
		if (PidList[i] == 0xFFFF) 
		{ 
			// pid not exist in the list, add it 
			PidList[i] = pid; 
			SeqNumList[i] = seq_num; 
			seq_err_cnt[i] = 0; 
		} 
		else 
		{ 
			// check seq num 
			if (((SeqNumList[i] + 1) & 0xF) != seq_num) 
			{ 
				// error 
				checked_pid_err_cnt++; 
				seq_err_cnt[i]++; 
				DBGMSG(ZONE_ERROR, (TEXT("SmsGenDrv: TS Seq Err. %d Prev %d Cur %d\r\n") 
						,pid,SeqNumList[i],seq_num)); 
				//MessageBeep(0xFFFFFFFF); 
			} 
 
			SeqNumList[i] = seq_num; 
		} 
 
		pTS += 188; 
	} 
} 
#endif