/*===========================================================================
                              OEMConfig.c

  OEM REFERENCE APPLICATION CONTROL ROUTINES
  
  This file contains a reference implementation of a standard AEE application
  control interfaces.
    
        Copyright © 1999-2002 QUALCOMM Incorporated.
               All Rights Reserved.
            QUALCOMM Proprietary/GTDR
============================================================================*/

#include "OEMFeatures.h"
#include "comdef.h"

#include "target.h"
#include "customer.h"
#include "OEMDisp.h"
#include "OEMFS.h"

#include "voc.h"
#if defined(FEATURE_WCDMA) || defined(FEATURE_GSM)
#include "ghdi_exp.h"
#endif

#if defined(OEMCONFIG)

#include "OEMConfig.h"
#include "bridle_oemsvc.h"
#include "AEE_OEM.h"
#include "AEEShell.h"
#include "AEEStdLib.h"
#include "AEEFile.h"
#include "AEEDownload.h"


static uint32 GetLngCode(void);

extern boolean OEMSound_IsVibratorON(void);

// color table, returned from OEM_GetDeviceInfoEx (AEE_DEVICEITEM_SYS_COLORS_DISP1)
#define RGB_LIGHT_GREY  (MAKE_RGB(0xC0, 0xC0, 0xC0))
#define RGB_DARK_GREY   (MAKE_RGB(0x80, 0x80, 0x80))
static const RGBVAL gSysRGBs[CLR_SYS_LAST] = {
   0,
   RGB_BLACK,     // CLR_USER_TEXT
   RGB_WHITE,     // CLR_USER_BACKGROUND
   RGB_BLACK,     // CLR_USER_LINE
   RGB_WHITE,     // CLR_SYS_TITLE
   RGB_BLACK,     // CLR_SYS_TITLE_TEXT
   RGB_LIGHT_GREY,// CLR_SYS_ITEM
   RGB_BLACK,     // CLR_SYS_ITEM_TEXT
   RGB_LIGHT_GREY,// CLR_SYS_ITEM_SEL
   RGB_BLACK,     // CLR_SYS_ITEM_SEL_TEXT
   RGB_WHITE,     // CLR_SYS_WIN
   RGB_WHITE,     // CLR_SYS_FRAME_HI
   RGB_BLACK,     // CLR_SYS_FRAME_LO
   RGB_LIGHT_GREY,// CLR_SYS_LT_SHADOW
   RGB_DARK_GREY, // CLR_SYS_DK_SHADOW 
   RGB_WHITE,     // CLR_SYS_SCROLLBAR
   RGB_BLACK      // CLR_SYS_SCROLLBAR_FILL
};


/*==================================================================
Function: OEM_GetConfig

Description: Retrieves configuration information from the OEM

Prototype:
   int  OEM_GetConfig(AEEConfigItem i, void * pBuff, int nSize)

Parameter(s):

Return Value:  None
Comments:      None
Side Effects:  None
See Also:      None

==================================================================*/
int OEM_GetConfig(AEEConfigItem i, void * pBuff, int nSize)
{
   return packbridle_OEM_SVCGetConfig(i, pBuff, nSize);
}

/*==================================================================
Function: OEM_SetConfig

Description: Sets configuration information from the OEM

Prototype:
   int  OEM_GetConfig(AEEConfigItem i, void * pBuff, int nSize)

Parameter(s):

Return Value:  None
Comments:      None
Side Effects:  None
See Also:      None

==================================================================*/
int OEM_SetConfig(AEEConfigItem i, void * pBuff, int nSize)
{
   return packbridle_OEM_SVCSetConfig(i, pBuff, nSize);
}

/*==================================================================
Function: OEM_GetDeviceInfo

Description: Retrieves the device information from the OEM

Prototype:
   void  OEM_GetDeviceInfo(AEEDeviceInfo * pi, RGBVAL * pSysColors, int nRGB);

Parameter(s):

Return Value:  None
Comments:      None
Side Effects:  None
See Also:      None

==================================================================*/
void  OEM_GetDeviceInfo(AEEDeviceInfo * pi)
{
   if(pi){
      MEMSET(pi,0, sizeof(AEEDeviceInfo));

#error OEM must fill in values for cxScreen, cyScreen, and nColorDepth
      pi->cxScreen         = 0;
      pi->cyScreen         = 0;
      pi->nColorDepth      = 0;

      pi->cxScrollBar      = 3;
      pi->dwPromptProps    = CP_3D_BORDER|ST_MIDDLETEXT|ST_UNDERLINE;
      pi->bAltDisplay      = FALSE;
      pi->cxAltScreen      = 0;
      pi->cyAltScreen      = 0;
      pi->wKeyCloseApp     = AVK_CLR;
      pi->wKeyCloseAllApps = AVK_END;

#if defined(AEE_SIMULATOR)
      pi->dwPlatformID     = DEFAULT_PLATFORM_ID;
#else
      pi->wStructSize = sizeof(AEEDeviceInfo);
      pi->dwPlatformID = 500;
      pi->wEncoding = AEE_ENC_UNICODE;
      pi->dwSleepDefer = 30000;
#endif 
      // Set Language Support...
      pi->dwLang = GetLngCode();
      pi->wMaxPath = (uint16)OEMFS_GetMaxPathLength();

#ifdef FEATURE_DYNAMIC_OEM_HEAP
      pi->dwRAM = guHeapBytesLen;
#else
      pi->dwRAM = OEM_STATIC_HEAP_SIZE;
#endif

#if defined(FEATURE_AUDIO_FORMAT)
      pi->bMIDI = TRUE;
#endif

#if defined(FEATURE_CMX)
      pi->bCMX = TRUE;
#endif

#if defined(FEATURE_GPSONE) || defined(FEATURE_PDAPI)
      pi->bPosLoc = TRUE;
#endif

#if defined(FEATURE_VIBRATOR)
      pi->bVibrator = TRUE;
#endif

#if defined(FEATURE_SPEAKER_PHONE)
      pi->bExtSpeaker = TRUE;
#endif

#if defined(FEATURE_PHONE_VR)
      pi->bVR = TRUE;
#endif
   }
}

#if defined(FEATURE_WCDMA) || defined (FEATURE_GSM)
static int OEM_ReadIMEI(byte *  imei_ptr)
{
	ghdi_status_T status;
	byte imei_bcd_len = 0;
	int bcd_index = 0;
	int ascii_index = 0;
	byte asc_1 = 0;
	byte asc_2 = 0;
	byte imei[NV_UE_IMEI_SIZE*2];

  /* This is a valid IMEI */
  memset(imei, 0, NV_UE_IMEI_SIZE*2);

	status = ghdi_read_imei(imei_ptr);
	if (status != GHDI_SUCCESS)
		return 0;
	
	/* The first byte of NV ue_imei is the length of IMEI BCDs */
  imei_bcd_len = imei_ptr[0];

  if (imei_bcd_len == 0)
  {
    memcpy((byte *) imei_ptr, (byte *) " NOT SET", 8);
    return (int) strlen(" NOT SET");
  }

  if( imei_bcd_len < NV_UE_IMEI_SIZE )
  {
    /*
    ** THIS IS A VALID IMEI, SO CONVERT IT TO ASCII
    */
    for( bcd_index = 1; bcd_index <= (int) imei_bcd_len; bcd_index++ )
    {
      asc_1 = (imei_ptr[bcd_index] & 0x0F);
      asc_2 = (imei_ptr[bcd_index] & 0xF0) >> 4;
      imei[ascii_index++] = (asc_1 <= 9)?asc_1+'0'
                                              :asc_1-10+'A';
      imei[ascii_index++] = (asc_2 <= 9)?asc_2+'0'
                                              :asc_2-10+'A';
    }

    if(ascii_index > 2)
    {
      memcpy( imei_ptr, imei + 1, (uint32) (ascii_index - 1) );
    }

    return (ascii_index - 1);
  } //  if( imei_bcd_len < NV_UE_IME...
  else
  {
    return 0;
  }
} //uiutils_get_imei(byte imei_asc...
#endif


/*===========================================================================

===========================================================================*/
static boolean OEM_CompressNumber(char * pszSrc)
{
   char *   pszDest;
   char     ch;
   int      i;

   // Compress out any garbage...

   for(i = 0, pszDest = pszSrc; (ch = *pszSrc) != 0; pszSrc++){
      if((ch == '*' || ch == '#') || (ch >= '0' && ch <= '9')){
         *(pszDest++) = ch;
         i++;
      }
   }
   *pszDest = 0;

   return (boolean)(i > 0);
}

/*======================================================================= 
Function: OEM_GetDeviceInfoEx()

Description: 
   This method is used to get specific information about the device. This function takes
   an ID that specifies what information is needed. The buffer contains the corresponding
   information on return.

Prototype:

   int   OEM_GetDeviceInfoEx(AEEDeviceItem nItem, void *pBuff, int *pnSize);

Parameters:
   nItem: Specifies the Item whose info is needed. Please see documentation of
   AEEDeviceItem for the supported Device Items.
   pBuff: Contains the corresponding information on return
   pnSize: Contains the size of pBuff. On return, it contains the size filled. This parameter may
   be NULL for certain device Items.

Return Value: 
   SUCCESS: If successful
   EBADPARM: if bad parameters are passed in
   EUNSUPPORTED: If this item is not supported

Comments:  
   None

Side Effects: 
   None

See Also: 
   AEEDeviceItem

=======================================================================*/
int   OEM_GetDeviceInfoEx(AEEDeviceItem nItem, void *pBuff, int *pnSize)
{
   switch(nItem)
   {
   case AEE_DEVICEITEM_CHIP_ID:
      {
#if defined(AEE_SIMULATOR)
         char szStr[32];

         if(!pnSize)
            return(EBADPARM);

         if(pBuff && *pnSize) {
            STRCPY(szStr,"Simulator");
            STRTOWSTR(szStr,(AECHAR*)pBuff,*pnSize);
         }
         *pnSize = (STRLEN("Simulator")+1)*2;
         return(SUCCESS);
#else
         char szStr[32];

         if(!pnSize)
            return(EBADPARM);

         if(pBuff && *pnSize) {
            STRCPY(szStr,"MSMXXXX");
            STRTOWSTR(szStr,pBuff,*pnSize);
         }
         *pnSize = (STRLEN("MSMXXXX")+1)*2;
         return(SUCCESS);
#endif // AEE_SIMULATOR
      }
   
   case AEE_DEVICEITEM_MOBILE_ID:
      {
         AEEMobileInfo mi;

         MEMSET(&mi,0,sizeof(AEEMobileInfo));

         if(!pnSize)
            return(EBADPARM);

         if(!OEM_GetConfig(CFGI_MOBILEINFO,&mi,sizeof(AEEMobileInfo))) {
            OEM_CompressNumber(mi.szMobileID);
            if(pBuff && *pnSize > 0)
               STRLCPY(pBuff,mi.szMobileID,*pnSize);
            *pnSize = STRLEN(mi.szMobileID)+1;
            return(SUCCESS);
         }
         else
            return(EUNSUPPORTED);
      }
      break;

      case AEE_DEVICEITEM_SOFTKEY_COUNT:
      {
         if (!pnSize)
            return(EBADPARM);
   
         if (!pBuff || *pnSize < sizeof(uint8)) {
            *pnSize = sizeof(uint8);
            return(SUCCESS);
         }
   
#error OEM must fill in the number of Softkeys that are exposed to BREW.
         *((uint8 *)pBuff) = 0;
         return(SUCCESS);
      }
     

      case AEE_DEVICEITEM_CARRIER_ID:
      {
         AEEDownloadInfo di;

         MEMSET((void *)&di,0,sizeof(AEEDownloadInfo));

         if(!pnSize)
            return(EBADPARM);

         if(!OEM_GetConfig(CFGI_DOWNLOAD,(void*)&di,sizeof(AEEDownloadInfo))) {
            if(pBuff && (*pnSize == sizeof(di.dwCarrierID)))
               *(uint32 *)pBuff = di.dwCarrierID;
            *pnSize = sizeof(di.dwCarrierID);
            return(SUCCESS);
         }
         else
            return(EUNSUPPORTED);
      }

      case AEE_DEVICEITEM_AMR_VOCODER_SUPPORT:      // Is AMR (Adaptive Multi-Rate) Vocoder Supported ?
      {
         if(!pnSize)
            return(EBADPARM);

         if(!pBuff || *pnSize < sizeof(boolean)) {
            *pnSize = sizeof(boolean);
            return(SUCCESS);
         }

         *((boolean *)pBuff) = packbridle_OEM_SVCIsVocCapable(VOC_CAP_AMR);  
         *pnSize = sizeof(boolean);
         return(SUCCESS);
      }

      case AEE_DEVICEITEM_EVRC_VOCODER_SUPPORT:      // Is EVRC (Enhanced Variable Rate Codec) Vocoder Supported ?
      {
         if(!pnSize)
            return(EBADPARM);

         if(!pBuff || *pnSize < sizeof(boolean)) {
            *pnSize = sizeof(boolean);
            return(SUCCESS);
         }

         *((boolean *)pBuff) = packbridle_OEM_SVCIsVocCapable(VOC_CAP_IS127); /* EVRC 8K supported?? */  
         *pnSize = sizeof(boolean);
         return(SUCCESS);
      }

      case AEE_DEVICEITEM_IS96_VOCODER_SUPPORT:      // Is QCELP (Qualcomm Code Excited Linear Predictive Coding) Vocoder Supported ?
      {
         if(!pnSize)
            return(EBADPARM);

         if(!pBuff || *pnSize < sizeof(boolean)) {
            *pnSize = sizeof(boolean);
            return(SUCCESS);
         }

         *((boolean *)pBuff) = packbridle_OEM_SVCIsVocCapable(VOC_CAP_IS96); /* QCELP 13K supported?? */  
         *pnSize = sizeof(boolean);
         return(SUCCESS);
      }

      case AEE_DEVICEITEM_IS96A_VOCODER_SUPPORT:      // Is QCELP-IS96 (8K)(Qualcomm Code Excited Linear Predictive Coding) Vocoder Supported ?
      {
         if(!pnSize)
            return(EBADPARM);

         if(!pBuff || *pnSize < sizeof(boolean)) {
            *pnSize = sizeof(boolean);
            return(SUCCESS);
         }

         *((boolean *)pBuff) = packbridle_OEM_SVCIsVocCapable(VOC_CAP_IS96A ); /* QCELP IS-96A (8K) supported?? */  
         *pnSize = sizeof(boolean);
         return(SUCCESS);
      }

      case AEE_DEVICEITEM_IS733_VOCODER_SUPPORT:      // Is QCELP (Qualcomm Code Excited Linear Predictive Coding) Vocoder Supported ?
      {
         if(!pnSize)
            return(EBADPARM);

         if(!pBuff || *pnSize < sizeof(boolean)) {
            *pnSize = sizeof(boolean);
            return(SUCCESS);
         }

         *((boolean *)pBuff) = packbridle_OEM_SVCIsVocCapable(VOC_CAP_IS733); /* QCELP 13K supported?? */  
         *pnSize = sizeof(boolean);
         return(SUCCESS);
      }

   case AEE_DEVICEITEM_SYS_COLORS_DISP1:
      {
         int nSize;

         if(!pnSize)
            return(EBADPARM);

         nSize = MIN(*pnSize, CLR_SYS_LAST * sizeof(RGBVAL));
         *pnSize = CLR_SYS_LAST * sizeof(RGBVAL);

         if (NULL == pBuff) {
            return SUCCESS;
         }

         MEMCPY(pBuff, gSysRGBs, nSize);

         return SUCCESS;
      }

   case AEE_DEVICEITEM_DISPINFO1:
      {
         AEEBitmapInfo  bi;
         int            nSize;

         if(!pnSize)
            return(EBADPARM);

         nSize = MIN(*pnSize, sizeof(AEEBitmapInfo));
         *pnSize = sizeof(AEEBitmapInfo);

         if (NULL == pBuff) {
            return(SUCCESS);
         }

#error OEM must fill in values for cx, cy, and nDepth
         bi.cx = 0;
         bi.cy = 0;
         bi.nDepth = 0;

         MEMCPY(pBuff, &bi, nSize);

         return SUCCESS;
      }

   case AEE_DEVICEITEM_MANNER_MODE:
   {
      if (!pnSize)
         return EBADPARM;

      if (!pBuff || *pnSize < sizeof(uint32))
      {
         *pnSize = sizeof(uint32);
         return(SUCCESS);
      }

      // NOTE to OEMs: OEMs need to set their "global"
      // manner mode flag here in terms of AEE_MANNER_MODE_XXX.
      *((uint32 *)pBuff) = (uint32)AEE_MANNER_MODE_NORMAL;
      *pnSize = sizeof(uint32);
      return SUCCESS;
   }

#if defined(FEATURE_WCDMA) || defined(FEATURE_GSM)
   case AEE_DEVICEITEM_IMEI:
   {
      byte szIMEI[16];
      OEM_ReadIMEI(szIMEI);
      szIMEI[15] = 0;
      if (STRLEN((char*)szIMEI) == STRLEN(" NOT SET")) {
         //return EUNSUPPORTED;
      } // do we have a better test for if the phone has an IMEI?
      if (!pnSize) {
         return(EBADPARM);
      }
        if (!pBuff || *pnSize < STRLEN((char*)pBuff)) {
         *pnSize = STRLEN((char*)szIMEI) + 1;
        } else if (pBuff) {
           STRNCPY((char*)pBuff, (char*)szIMEI, *pnSize);
           *pnSize = (STRLEN((char*)pBuff) + 1);
      }
        *pnSize = 16;
      return(SUCCESS);
   }
   
   case AEE_DEVICEITEM_ICCID:
   {
      byte szICCID[32];

      if (!pnSize) {
         return(EBADPARM);
      }

      MEMSET(szICCID, 0, sizeof(szICCID));

#error OEMs must make szICCID contain null terminated ICCID string

      if (!pBuff || *pnSize < (int)(STRLEN((char*)szICCID) + 1)) {
         *pnSize = STRLEN((char*)szICCID) + 1;
      } else {
         STRNCPY((char*)pBuff, (char*)szICCID, *pnSize);
         *pnSize = (STRLEN((char*)szICCID) + 1);
      }
      return(SUCCESS);
   }
#endif

   case AEE_DEVICEITEM_KEY_SUPPORT:
   {
      KeySupportType* pKeySupport;

      if (!pnSize)
         return EBADPARM;

      if (!pBuff || *pnSize < sizeof(KeySupportType))
      {
         *pnSize = sizeof(KeySupportType);
         return(SUCCESS);
      }

      pKeySupport = (KeySupportType*)pBuff;
      switch(pKeySupport->key)
      {
         case AVK_0:
         case AVK_1:
         case AVK_2:
         case AVK_3:
         case AVK_4:
         case AVK_5:
         case AVK_6:
         case AVK_7:
         case AVK_8:
         case AVK_9:
         case AVK_STAR:
         case AVK_POUND:
         case AVK_SEND:
         case AVK_END:
         case AVK_CLR:
         case AVK_SELECT:
         case AVK_UP:
         case AVK_DOWN:
         case AVK_LEFT:
         case AVK_RIGHT:
            pKeySupport->supported = TRUE;
            break;
#error OEMs must customize this area to reflect the keys they really support
         default:
            pKeySupport->supported = FALSE;
            break;
      }
      return SUCCESS;      
   }

   case AEE_DEVICESTATE_VIBRATOR_ON:
   {
      if (!pnSize) {
         return(EBADPARM);
      }

      if(!pBuff || *pnSize < sizeof(boolean)) {
         *pnSize = sizeof(boolean);
         return(SUCCESS);
      }

      *((boolean *)pBuff) = OEMSound_IsVibratorON();
      *pnSize = sizeof(boolean);

      return(SUCCESS);
   }

   default:
      return(EUNSUPPORTED);
   }
}



/*==================================================================

==================================================================*/
uint32 GetLngCode(void)
{
   uint32 lang = LNG_ENGLISH;
   IShell * shell_ptr = 0;
   
   shell_ptr = AEE_GetShell();

   if (shell_ptr)
   {
      IFileMgr * pfm = 0;
      ISHELL_CreateInstance(shell_ptr, AEECLSID_FILEMGR, (void **) (&pfm));
      if (pfm)
      {
         IFile * pf = 0;
         pf = IFILEMGR_OpenFile(pfm, AEEFS_SYS_DIR"lang.dat", _OFM_READ);
         if (pf)
         {
            char lan_str[11];
            int32 count = IFILE_Read(pf, lan_str, 11);
            if (count)
            {
               char * endptr;
               unsigned long val = STRTOUL(lan_str, &endptr, 16);
               if (val)
                  lang = val;
            }
            IFILE_Release(pf);
         }
         else
         {
            int ferr = IFILEMGR_GetLastError(pfm);
            DBGPRINTF("GetLngCode : open file error = %d", ferr);
         }
         IFILEMGR_Release(pfm);
      }
   }

   return lang;
}
#endif

