#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <gsl/gl_mutex.h>
#include <gsl/gl_task.h>

#include "al_bluetooth_ctrl.h"
#include "al_bluetooth_upgrader.h"
#include "al_bluetooth.h"
#include "al_console.h"
#include "ap_extern.h"
#include "drv_uart_def.h"
#ifdef CONFIG_BT_RDA5856
#include "bt_core.h"
#endif
#ifdef CONFIG_BT_5851S
#include <gsl/gl_timer.h>

extern GL_Timer_t gBTQuery_timerid;
#elif defined(CONFIG_BT_AK105XT)||defined(CONFIG_BT_RDA5856)
static al_uint8 gBtName[BT_NAME_LEN_MAX] = { 0 };
static al_uint8 gBtMac[BT_MAC_LEN_MAX] = { 0 };
#endif
static al_uint8 gDevName[BT_NAME_LEN_MAX] = { 0 };
static al_uint8 gBtVer[BT_VER_LEN_MAX] = { 0 };
static al_uint8 gBtTelNum[BT_TEL_NUM_LEN_MAX] = { 0 };

extern int uartbfd;
extern CON_UART con_uart;
extern pthread_mutex_t reqMutex;

al_uint8 bStandby = TRUE;
al_uint8 reSendCount = 0;
static al_uint16 conStatus = HB_STATUS_BT_WAIT_CONN;
static al_uint16 playStatus = HB_STATUS_BT_PAUSE;
static al_uint16 phoneStatus = 0;
#ifdef CONFIG_BT_5851S
static al_uint16 adcValue = 0;
#endif
#ifdef CONFIG_BT_RDA5856
static AP_BT_HEART_BEAT gHeartBeat_data = {0};
static volatile al_uint16 requestState = BT_REQ_NONE;
#else
volatile al_uint16 requestState = BT_REQ_NONE;
#endif

al_int32 Al_Bluetooth_Get_Action(al_uint8 inCmd, void * data)
{
    if (data == NULL)
        return AL_FAILURE;

    switch (inCmd)
    {
    #if defined(CONFIG_BT_AK105XT)||defined(CONFIG_BT_RDA5856)
    	case BT_CMD_GET_NAME:
          memcpy((al_uint8*)data, gBtName, BT_NAME_LEN_MAX * sizeof(al_uint8));
          break;
      case BT_CMD_GET_MAC:
          memcpy((al_uint8*)data, gBtMac, BT_MAC_LEN_MAX * sizeof(al_uint8));
          break;
		#endif
      case BT_CMD_GET_PHONE_NUM:
          memcpy((al_uint8*)data, gBtTelNum, BT_TEL_NUM_LEN_MAX * sizeof(al_uint8));
          break;
      case BT_CMD_GET_VER:
          memcpy((al_uint8*)data, gBtVer, BT_VER_LEN_MAX * sizeof(al_uint8));
          break;
      case BT_CMD_GET_PAIRED_NAME:
          memcpy((al_uint8*)data, gDevName, BT_NAME_LEN_MAX * sizeof(al_uint8));
          break;
      case BT_CMD_GET_PLAYSTATUS:
          memcpy((al_uint16*)data,  &playStatus, sizeof(al_uint16));
          break;
      case BT_CMD_GET_CONSTATUS:
          memcpy((al_uint16*)data, &conStatus,  sizeof(al_uint16));
          break;
	  case BT_CMD_GET_PHONESTATUS:
          memcpy((al_uint16*)data, &phoneStatus,  sizeof(al_uint16));
          break;
#ifdef CONFIG_BT_5851S
	case BT_CMD_GET_ADC:
		memcpy((al_uint16*)data, &adcValue,  sizeof(al_uint16));
		break;
#endif
      default:
          printf("Command error.\n");
          return AL_FAILURE;
    }

    return AL_SUCCESS;
}

//**************************************************************************************************************************************
//module 5851S
//**************************************************************************************************************************************
#ifdef CONFIG_BT_5851S
al_int32 Al_Bluetooth_Set_Action(al_uint8 inCmd, al_uint8 * data, al_uint8 size)
{
    al_uint8 *packet = NULL;
    al_uint8 headerLen = 0, traLen = 0, offset = 0;
    al_int packetsize = 0;
    BT_MessageBody_t stEvt = {0};
   
    headerLen = BT_HEADER_LEN;
    traLen = BT_TRAILER_LEN;
   
    if (data != NULL)
    {
        size = (size > BT_INPUT_SIZE_MAX) ? BT_INPUT_SIZE_MAX : size;
    }
    else
        size = 0;

    switch (inCmd)
    {
      case BT_CMD_GET_PHONE_NUM:
				{
					pthread_mutex_lock(&reqMutex);
					if((requestState&BT_REQ_HAD_PHONE_NUM))
					{
						//reSendCount = 10;
						//requestState|=BT_REQ_GET_PHONE_NUM;
        		//requestState&=(~BT_REQ_HAD_PHONE_NUM);
            stEvt.dMessage = BT_MESSAGE_PHONE_NUM;
            stEvt.dParam = 1;
					}
					else
						requestState|=BT_REQ_GET_PHONE_NUM;
					pthread_mutex_unlock(&reqMutex);
				}	
				break;
      case BT_CMD_GET_VER:
				{
					memset(gBtVer,0,BT_VER_LEN_MAX);
					pthread_mutex_lock(&reqMutex);
					if(!(requestState&BT_REQ_GET_VER))
					{
						reSendCount = 10;
						requestState|=BT_REQ_GET_VER;
					}
					pthread_mutex_unlock(&reqMutex);
					packetsize = headerLen+traLen+2;
					packet = malloc(packetsize);
					packet[BT_HEADER_LEN] = 0x54;
					packet[BT_HEADER_LEN+1] = BT_CMD_GET_VER;
					offset = headerLen+2;
				}	
				break;
      case BT_CMD_GET_PAIRED_NAME:
				{
					pthread_mutex_lock(&reqMutex);
					if((requestState&BT_REQ_HAD_PAIRED_NAME))
					{
						//reSendCount = 10;
						//requestState|=BT_REQ_GET_PAIRED_NAME;
						//requestState&=(~BT_REQ_HAD_PAIRED_NAME);
						stEvt.dMessage = BT_MESSAGE_PAIRED_NAME;
            stEvt.dParam = 1;
					}
					else
						requestState|=BT_REQ_GET_PAIRED_NAME;
					pthread_mutex_unlock(&reqMutex);
				}	
				break;
      case BT_CMD_STANDBY:
				bStandby = TRUE;
				GL_TimerDisable(gBTQuery_timerid);
				//memset(gBtTelNum, 0 , sizeof(gBtTelNum));
				//requestState&=(~BT_REQ_HAD_PHONE_NUM);
				return AL_SUCCESS;
      case BT_CMD_SET_BT_MODE:
				{
					bStandby = FALSE;
					stEvt.dMessage = BT_MESSAGE_MODE;
					stEvt.dParam = HB_STATUS_MODE_BT;
					_bt_SendEvt(stEvt);
					if(phoneStatus != 0)
					{
						stEvt.dMessage = BT_MESSAGE_PHONE;
						stEvt.dParam = phoneStatus;
						_bt_SendEvt(stEvt);
					}
					stEvt.dParam = 0;
					GL_TimerEnable(gBTQuery_timerid);
      	}
			case BT_CMD_QUERY_STATUS:
				{
					packetsize = headerLen+traLen+3;
					packet = malloc(packetsize);
					packet[BT_HEADER_LEN] = 0x54;
					packet[BT_HEADER_LEN+1] = BT_CMD_QUERY_STATUS;
					packet[BT_HEADER_LEN+2] = 0xff;
					offset = headerLen+3;
      	}
				break;
      case BT_CMD_PLAYPAUSE:
      case BT_CMD_NEXT:
      case BT_CMD_PREV:
      case BT_CMD_DIS:
			case BT_CMD_GET_ADC:
					if(inCmd == BT_CMD_GET_ADC)
					{
						adcValue=0;
						pthread_mutex_lock(&reqMutex);
						if(!(requestState&BT_REQ_GET_ADC_VALUE))
						{
							requestState|=BT_REQ_GET_ADC_VALUE;
						}
						pthread_mutex_unlock(&reqMutex);
						//printf("Request get ADC value.\n");
					}
					packetsize = headerLen+traLen+3;
					packet = malloc(packetsize);
					packet[BT_HEADER_LEN] = 0x54;
					packet[BT_HEADER_LEN+1] = inCmd;
					packet[BT_HEADER_LEN+2] = 0xff;
					offset = headerLen+3;
          break;
      case BT_CMD_SET_LANG:
					printf("Not support.\n");
          break;
			case BT_CMD_SET_BT_NAME:
					packetsize = headerLen+traLen+size+3;
					packet = malloc(packetsize);
					packet[BT_HEADER_LEN] = 0x54;
					packet[BT_HEADER_LEN+1] = inCmd;
					packet[BT_HEADER_LEN+2] = size;
					memcpy(&packet[BT_HEADER_LEN+3], data, size);
					offset = headerLen+size+3;
					break;
      default:
          printf("Command error.\n");
          return AL_FAILURE;
    }

    //AK105xT packet header/trailer
    if(packet && stEvt.dParam == 0)
    {
	    memcpy(packet, CMD_BT_HEADER, headerLen);
	    packet[offset] = 0xd;
			packet[offset+1] = 0xa;
    }
		
    /*printf("=[size=%d],[0%x%x%x%x,%x%x%x%x,%x%x%x%x,%x%x%x%x,%x%x%x%x]\n",
     packetsize,packet[0],packet[1],packet[2],packet[3],packet[4],packet[5],packet[6],
     packet[7],packet[8],packet[9],packet[10],packet[11],packet[12],packet[13],packet[14],
     packet[15],packet[16],packet[17],packet[18],packet[19]); */
		if (stEvt.dParam != 0 && !bStandby)
		{
			_bt_SendEvt(stEvt);
		}
		else if(packet)
		{
			bluetooth_cmd_send(packet, packetsize);
			free(packet);
		}

    return AL_SUCCESS;
}

void Al_Bluetooth_CheckResend()
{
	al_uint16 tmp = 0;

	tmp = requestState;

	while(tmp)
	{
		/*if(requestState&BT_REQ_GET_PAIRED_NAME && !bStandby)
		{
				Al_Bluetooth_Set_Action(BT_CMD_GET_PAIRED_NAME, NULL, 0);
				tmp&=(~BT_REQ_GET_PAIRED_NAME);
		}
		else if(requestState&BT_REQ_GET_PHONE_NUM && !bStandby)
		{
				Al_Bluetooth_Set_Action(BT_CMD_GET_PHONE_NUM, NULL, 0);
				tmp&=(~BT_REQ_GET_PHONE_NUM);
		}
		else*/ if(requestState&BT_REQ_GET_VER)
		{
				Al_Bluetooth_Set_Action(BT_CMD_GET_VER, NULL, 0);		
				tmp&=(~BT_REQ_GET_VER);
		}
		else
			tmp = BT_REQ_NONE;

		if(tmp)
			GL_TaskSleep(100);
	}

	pthread_mutex_lock(&reqMutex);
	
	if(reSendCount)
		reSendCount--;
	else
	{
		requestState = BT_REQ_NONE;
		reSendCount = 0;
	}
	pthread_mutex_unlock(&reqMutex);
}


al_int8 Al_Bluetooth_PhoneStatusHandler(al_int8 * str)
{
    BT_MessageBody_t stEvt;
    
    
    al_uint16 tmpStatus = 0;
		
    if (str == NULL)
      return AL_FAILURE;

    stEvt.dMessage = 0;
    stEvt.dParam = 0;
    //phoneStatus = 0;
    switch ((tmpStatus=str[0]))
    {
      case HB_STATUS_BT_PHONE_RING: 
          // phone call is ringing
      case HB_STATUS_BT_INCOMING_CALL:
          // phone call in 
      case HB_STATUS_BT_OUTGOING_CALL:
          // phone call out
      case HB_STATUS_BT_PHONE_CALL:
					// phone call is on line
          if (phoneStatus != tmpStatus && !(phoneStatus==HB_STATUS_BT_INCOMING_CALL && tmpStatus==HB_STATUS_BT_PHONE_RING))
          {
          		conStatus = HB_STATUS_BT_CONNECTED;
              playStatus = HB_STATUS_BT_PAUSE;
							if(str[0] == HB_STATUS_BT_PHONE_RING)
							{
								phoneStatus = HB_STATUS_BT_INCOMING_CALL; //or HB_STATUS_BT_OUTGOING_CALL
								tmpStatus=HB_STATUS_BT_INCOMING_CALL;
							}
							else
	              phoneStatus = tmpStatus;
							
              stEvt.dMessage = BT_MESSAGE_PHONE;
              stEvt.dParam = tmpStatus;
          }
					//Al_Bluetooth_CheckResend();
          break;
      default:
          printf("phone status error.\n");
          break;
    }
    
    if (stEvt.dParam != 0)
        _bt_SendEvt(stEvt);
    return AL_SUCCESS;
}

al_int8 Al_Bluetooth_BTStatusHandler(al_int8 * str)
{
    BT_MessageBody_t stEvt;
    al_uint16 tmpStatus = 0;
		
    if (str == NULL)
      return AL_FAILURE;

    stEvt.dMessage = 0;
    stEvt.dParam = 0;
    //phoneStatus = 0;
    switch ((tmpStatus=str[0]))
    {
      case HB_STATUS_BT_CONNECTED: //HB_STATUS_BT_PAUSE
          // waitting for play
          if (playStatus == HB_STATUS_BT_PLAYING || phoneStatus != 0)
          {
              stEvt.dMessage = (phoneStatus != 0) ? BT_MESSAGE_PHONE : BT_MESSAGE_PLAYER;
              stEvt.dParam = (phoneStatus != 0) ? HB_STATUS_BT_PHONE_OFF_CALL : tmpStatus;
              conStatus = tmpStatus;
              playStatus = HB_STATUS_BT_PAUSE;
              phoneStatus = 0;
							requestState&=(~BT_REQ_HAD_PHONE_NUM);
              break;
          }
					//Al_Bluetooth_CheckResend();
      case HB_STATUS_BT_WAIT_CONN:
          //waitting for connection
     //case HB_STATUS_BT_RECONNECT:
          //reconnecting
          if (conStatus != tmpStatus)
          {
              playStatus = HB_STATUS_BT_PAUSE;
              phoneStatus = 0;
              conStatus = tmpStatus;
              stEvt.dMessage = BT_MESSAGE_CON_STATUS;
              stEvt.dParam = tmpStatus;
							memset(gBtTelNum, 0 , sizeof(gBtTelNum));
							memset(gDevName, 0 , sizeof(gDevName));
							requestState&=(~BT_REQ_HAD_PAIRED_NAME);
							requestState&=(~BT_REQ_HAD_PHONE_NUM);
          }
          break;
      case HB_STATUS_BT_PLAYING:
          // music is playing
          if (phoneStatus != 0)
          {
              phoneStatus = 0;
              stEvt.dMessage = BT_MESSAGE_PHONE;
              stEvt.dParam = HB_STATUS_BT_PHONE_OFF_CALL;
              _bt_SendEvt(stEvt);
					}
          if (playStatus != tmpStatus)
          {
          		conStatus = HB_STATUS_BT_CONNECTED;
              playStatus = tmpStatus;
              stEvt.dMessage = BT_MESSAGE_PLAYER;
              stEvt.dParam = tmpStatus;
          }
					//Al_Bluetooth_CheckResend();
          break;
      case HB_STATUS_BT_TEL:
          // phone call status
          if(phoneStatus != HB_STATUS_BT_PHONE_CALL)
	         	Al_Bluetooth_PhoneStatusHandler(str);
          break;
      default:
          printf("BT status error.\n");
          break;
    }
    
    if (stEvt.dParam != 0 && !bStandby)
    {
    	  _bt_SendEvt(stEvt);
    }
    return AL_SUCCESS;
}


al_int Al_Bluetooth_Listener(void *argv)
{
    pCON_DEV pcon = (pCON_DEV) argv;
    al_int8 rec[MAX_CMD_LENGTH] = { 0 }, cmdMode = 0, cmdID=0, dataLen = 0;
    al_uint readLen = 0;
    bool bLeave = false, bReset = false;
    al_uint8 buf[512] = { 0 };
    BT_MessageBody_t stEvt = { 0 };

    uartbfd = open("/dev/uartb", O_RDWR);

    if (uartbfd <= 0)
    {
        //condbg2(pcon->dbg,"Open Console Fail \n");
        return AL_FAILURE;
    }

    pcon->n = 0;
    pcon->pid = getpid();

    while (pcon->bActive)
    {
        while (1)
        {
            con_uart.UART_UARTB_Listen_Status = TRUE;
            memset(buf, 0x0, sizeof(buf));
            GL_TaskSleep(300);
            readLen = read(uartbfd, buf, sizeof(buf));

            if (readLen > 0 || con_uart.uartB_Stop)
            {
                con_uart.UART_UARTB_Listen_Status = FALSE;
                break;
            }
        }

        if (!pcon->bActive)
        {
            break;
        }

        if (readLen <= 0)
        {
            printf("*** UARTB_data->len = 0 *** \n");
        }
		else
		{
		    memcpy(&rec[pcon->n], buf, readLen);
		    pcon->n += readLen;
		}

        switch (rec[0])
        {
              //printf("==[%x][size=%d]==\n",rec[0], pcon->n);
          case 0x41:
              if ((strncmp(rec, CMD_BT_HEADER, strlen(CMD_BT_HEADER)) == 0) && pcon->n > 3)
              {
                  /*printf("==[0x%x,%x,%x,%x,%x,%x - %x,%x,%x,%x - %x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x][size=%d]==\n",
										rec[0],rec[1],rec[2],rec[3],rec[4],rec[5],rec[6],rec[7],rec[8],rec[9],rec[10],rec[11],rec[12],rec[13],rec[14],rec[15],rec[16],rec[17],rec[18],rec[19],
										rec[20],rec[21],rec[22],rec[23],rec[24],rec[25],rec[26],rec[27],rec[28],rec[29],rec[30],rec[31],rec[32],rec[33],rec[34],rec[35],rec[36],rec[37],rec[38],rec[39],rec[40],rec[41],pcon->n);*/
									//	printf("==[0x%x,%x,%x,%x,%x,%x - %x,%x,%x][size=%d]==\n",rec[0],rec[1],rec[2],rec[3],rec[4],rec[5],rec[6],rec[7],rec[8],pcon->n);
									//printf("==[0x%x,%x,%x,%x,%x,%x - %x,%x,%x,%x - %x,%x,%x,%x,%x,%x,%x,%x][size=%d]==\n",
									//	rec[0],rec[1],rec[2],rec[3],rec[4],rec[5],rec[6],rec[7],rec[8],rec[9],rec[10],rec[11],rec[12],rec[13],rec[14],rec[15],rec[16],rec[17],pcon->n);
									cmdMode = rec[3];
									cmdID = rec[4];
                  dataLen = rec[5];
                  
                  stEvt.dMessage = 0;
                  stEvt.dParam = 0;
									if(cmdMode == 0x42) // receive data
									{

	                  switch (cmdID)
	                  {
	                    case BT_REC_PHONE_NUM:
													if (pcon->n >= (unsigned int)(8+dataLen) && rec[BT_HEADER_LEN+3+dataLen]==0xd && rec[BT_HEADER_LEN+3+dataLen+1]==0xa && dataLen>0)
	                        {												
	                        		pthread_mutex_lock(&reqMutex);
															if(requestState & BT_REQ_GET_PHONE_NUM)
															{
																	
		                          		requestState&=(~BT_REQ_GET_PHONE_NUM);
		                              stEvt.dMessage = BT_MESSAGE_PHONE_NUM;
		                              stEvt.dParam = 1;
															}
															else
																requestState|=BT_REQ_HAD_PHONE_NUM;
															pthread_mutex_unlock(&reqMutex);
															memcpy(&gBtTelNum, &rec[6], dataLen);
	                        }
	                        break;
	                    case BT_REC_SW_VER:
	                        if (pcon->n >= (unsigned int)(8+dataLen) && rec[BT_HEADER_LEN+3+dataLen]==0xd && rec[BT_HEADER_LEN+3+dataLen+1]==0xa)
	                        {												
	                        		pthread_mutex_lock(&reqMutex);
	                            if (requestState & BT_REQ_GET_VER)
	                            {
	                            		requestState&=(~BT_REQ_GET_VER);
																	
																	stEvt.dMessage = BT_MESSAGE_VER;
	                                stEvt.dParam = 1;
	                            }
															
															pthread_mutex_unlock(&reqMutex);
															memcpy(&gBtVer, &rec[6], dataLen);
													}
	                        break;
	                    case BT_REC_PAIRED_NAME:
	                        if (pcon->n >= (unsigned int)(8+dataLen) && rec[BT_HEADER_LEN+3+dataLen]==0xd && rec[BT_HEADER_LEN+3+dataLen+1]==0xa)
	                        {
	                        		pthread_mutex_lock(&reqMutex);
	                            if (requestState & BT_REQ_GET_PAIRED_NAME)
	                            {
	                            		
	                            		requestState&=(~BT_REQ_GET_PAIRED_NAME);
																	
	                                stEvt.dMessage = BT_MESSAGE_PAIRED_NAME;
	                                stEvt.dParam = 1;
	                            }
															else
																requestState|=BT_REQ_HAD_PAIRED_NAME;
															pthread_mutex_unlock(&reqMutex);
															memcpy(&gDevName, &rec[6], dataLen);
	                        }
	                        break;
											case BT_REC_PHONE_STATUS:
													if (pcon->n >= (unsigned int)(8+dataLen) && rec[BT_HEADER_LEN+3+dataLen]==0xd && rec[BT_HEADER_LEN+3+dataLen+1]==0xa)
	                        {
															if(dataLen == 1)
															{
	                            	Al_Bluetooth_PhoneStatusHandler(&rec[6]);
															}
	                        }
													break;
	                    case BT_REC_STATUS: //receive bt status
													if (pcon->n >= (unsigned int)(8+dataLen) && rec[BT_HEADER_LEN+3+dataLen]==0xd && rec[BT_HEADER_LEN+3+dataLen+1]==0xa)
	                        {
	                        		if(dataLen == 1)
															{
	                            	Al_Bluetooth_BTStatusHandler(&rec[6]);
															}
	                        }
	                        break;
											case BT_REC_ADC_VALUE:
													//printf("Receive BT module feedback ADC response:0x%x,%x,%x,%x,%x,%x,%x,%x,%x,%x.\n",rec[0],rec[1],rec[2],
													//	rec[3],rec[4],rec[5],rec[6],rec[7],rec[8],rec[9]);
													if (pcon->n >= (unsigned int)(8+dataLen) && rec[BT_HEADER_LEN+3+dataLen]==0xd && rec[BT_HEADER_LEN+3+dataLen+1]==0xa)
	                        {
															if(dataLen == 2)
															{
																adcValue = (rec[6]*16+rec[7]);
																pthread_mutex_lock(&reqMutex);
		                            if (requestState & BT_REQ_GET_ADC_VALUE)
		                            {
		                            		requestState&=(~BT_REQ_GET_ADC_VALUE);
																		
																		stEvt.dMessage = BT_MESSAGE_ADC_VALUE;
		                                stEvt.dParam = 1;
		                            }
																pthread_mutex_unlock(&reqMutex);
	                            	printf("ADC value=%d.\n",adcValue);
															}
	                        }
													break;
	                  }
									}
              }
							bReset = true;
              break;
          default:
              bReset = true;
              break;
        }

        if (stEvt.dParam != 0 && !bStandby)
            _bt_SendEvt(stEvt);

        if (bReset)
        {
            bReset = false;
            memset(&rec, 0, pcon->n);
            pcon->n = 0;
        }

        if (bLeave)
        {
            pcon->bActive = FALSE; // for UART B to leave its while loop
            con_uart.uartB_Stop = TRUE;
            break;
        }
    }

    pcon->pid = 0;
    close(uartbfd);

    return AL_SUCCESS;

}


//**************************************************************************************************************************************
//module AK105XT
//**************************************************************************************************************************************
#elif defined(CONFIG_BT_AK105XT)

al_int32 Al_Bluetooth_Set_Action(al_uint8 inCmd, al_uint8 * data, al_uint8 size)
{
    al_uint8 *packet = NULL;
    al_uint8 otherSize = 0, headerLen = 0, traLen = 0, offset = 0;
    al_uint16 tmp = 0, i = 0, crc = 0;
    al_int packetsize = 0;
	    
    if (bStandby && !(inCmd == BT_CMD_SET_BT_MODE || inCmd == BT_CMD_SET_NAME || inCmd == BT_CMD_SET_LANG || inCmd == BT_CMD_TEST
			|| inCmd == BT_CMD_TEST_WAIT_CONN || inCmd == BT_CMD_GET_MAC || inCmd == BT_CMD_GET_VER || inCmd == BT_CMD_GET_NAME))
    {
        printf("Mode error.\n");
        return AL_FAILURE;
    }

		
		Al_BT_Cmd_Head btHead = {
						.cmd = inCmd,
						.len = 4 + size 				//crc+cmd+len+dataLen 
				};

		if(inCmd == BT_CMD_TEST || inCmd == BT_CMD_TEST_WAIT_CONN)
		{
			if(size<=8)
				btHead.len+=(8-size);
			else
			{
				btHead.len = (btHead.len-size)+8;
				size = 8;
			}
			
		}
    for (i = 0; i < size; i++)
        tmp += (*(data + i));
    crc += ((btHead.cmd + btHead.len + tmp) & 0xffff);

    btHead.crc = (crc & 0xffff); //(((crc>>8)&0xff)|((crc<<8)&0xff00));
    headerLen = strlen(CMD_BT_HEADER);
    traLen = strlen(CMD_BT_TRAILER);
    otherSize = headerLen + traLen;

    if (data != NULL)
    {
        size = (size > BT_INPUT_SIZE_MAX) ? BT_INPUT_SIZE_MAX : size;
    }
    else
        size = 0;

    switch (inCmd)
    {
			
    	case BT_CMD_GET_NAME:
				{
					pthread_mutex_lock(&reqMutex);
					if(!(requestState&BT_REQ_GET_NAME))
					{
						reSendCount = 10;
						requestState|=BT_REQ_GET_NAME;
					}
					pthread_mutex_unlock(&reqMutex);
				}
      case BT_CMD_GET_MAC:
				if(inCmd == BT_CMD_GET_MAC)
				{
					pthread_mutex_lock(&reqMutex);
					memset(gBtMac,0,BT_MAC_LEN_MAX);
					if(!(requestState&BT_REQ_GET_MAC))
					{
						reSendCount = 10;
						requestState|=BT_REQ_GET_MAC;
					}
					pthread_mutex_unlock(&reqMutex);
				}
      case BT_CMD_GET_PHONE_NUM:
				if(inCmd == BT_CMD_GET_PHONE_NUM)
				{
					pthread_mutex_lock(&reqMutex);
					if(!(requestState&BT_REQ_GET_PHONE_NUM))
					{
						reSendCount = 10;
						requestState|=BT_REQ_GET_PHONE_NUM;
					}
					pthread_mutex_unlock(&reqMutex);
				}	
      case BT_CMD_GET_VER:
				if(inCmd == BT_CMD_GET_VER)
				{
					pthread_mutex_lock(&reqMutex);
					memset(gBtVer,0,BT_VER_LEN_MAX);
					if(!(requestState&BT_REQ_GET_VER))
					{
						reSendCount = 10;
						requestState|=BT_REQ_GET_VER;
					}
					pthread_mutex_unlock(&reqMutex);
					printf("[Ethan],[%s, get bt ver]\n",__FUNCTION__);
				}	
      case BT_CMD_GET_PAIRED_NAME:
				if(inCmd == BT_CMD_GET_PAIRED_NAME)
				{
					pthread_mutex_lock(&reqMutex);
					if(!(requestState&BT_REQ_GET_PAIRED_NAME))
					{
						reSendCount = 10;
						requestState|=BT_REQ_GET_PAIRED_NAME;
					}
					pthread_mutex_unlock(&reqMutex);
				}	
      case BT_CMD_STANDBY:
      case BT_CMD_SET_BT_MODE:
      case BT_CMD_HEART_BEAT:
      case BT_CMD_PLAYPAUSE:
      case BT_CMD_NEXT:
      case BT_CMD_PREV:
      case BT_CMD_DIS:
      case BT_CMD_RECON:
      case BT_CMD_RESET_CONFIG:
      case BT_CMD_PHONE_ANSWER:
      case BT_CMD_PHONE_REDIAL:
      case BT_CMD_PHONE_REJECT:
      case BT_CMD_PHONE_CNACEL:
      case BT_CMD_PHONE_SWITCH_SCO:
      case BT_CMD_PHONE_CONNECT_SCO:
      case BT_CMD_PHONE_DISCONNECT_SCO:
          offset = 0;
          packetsize = sizeof(Al_BT_Cmd_Head) + otherSize;
          packet = malloc(packetsize);
          offset += headerLen;
          memcpy((packet + offset), &btHead, sizeof(Al_BT_Cmd_Head));
          offset += sizeof(Al_BT_Cmd_Head);
          break;
      case BT_CMD_TEST:
      case BT_CMD_TEST_WAIT_CONN:
				
          offset = 0;
          packetsize = sizeof(Al_BT_Test_Packet) + otherSize;
          packet = malloc(packetsize);
          offset += headerLen;
          memcpy((packet + offset), &btHead, sizeof(Al_BT_Cmd_Head));
          offset += sizeof(Al_BT_Cmd_Head);
          memset((packet + offset), 0, 8); //mac+reserve:8bytes
          memcpy((packet + offset), data, size);
          offset += 8;
					break;
      case BT_CMD_SET_NAME:
          offset = 0;
          packetsize = sizeof(Al_BT_Name_Packet) + otherSize;
          packet = malloc(packetsize);
          offset += headerLen;
          memcpy((packet + offset), &btHead, sizeof(Al_BT_Cmd_Head));
          offset += sizeof(Al_BT_Cmd_Head);
          memset((packet + offset), 0, sizeof(al_uint8) * BT_NAME_LEN_MAX);
          memcpy((packet + offset), data, size);
          offset += BT_NAME_LEN_MAX;
          break;
      case BT_CMD_SET_LANG:
          offset = 0;
          packetsize = sizeof(Al_BT_Set_Lang_Packet) + otherSize;
          packet = malloc(packetsize);
          offset += headerLen;
          memcpy((packet + offset), &btHead, sizeof(Al_BT_Cmd_Head));
          offset += sizeof(Al_BT_Cmd_Head);
          memset((packet + offset), 0, sizeof(al_uint32));
          memcpy((packet + offset), data, size);
          offset += sizeof(al_uint32);
          break;
      default:
          printf("Command error.\n");
          return AL_FAILURE;
    }

    //AK105xT packet header/trailer
    memcpy(packet, CMD_BT_HEADER, strlen(CMD_BT_HEADER));
    memcpy(packet + offset, CMD_BT_TRAILER, strlen(CMD_BT_TRAILER));
		
    /*printf("=[size=%d],[0%x%x%x%x,%x%x%x%x,%x%x%x%x,%x%x%x%x,%x%x%x%x]\n",
     packetsize,packet[0],packet[1],packet[2],packet[3],packet[4],packet[5],packet[6],
     packet[7],packet[8],packet[9],packet[10],packet[11],packet[12],packet[13],packet[14],
     packet[15],packet[16],packet[17],packet[18],packet[19]); */
    bluetooth_cmd_send(packet, packetsize);

    return AL_SUCCESS;
}

void Al_Bluetooth_CheckResend()
{
	al_uint16 tmp = 0;

	tmp = requestState;

	while(tmp)
	{
		if(requestState&BT_REQ_GET_NAME && !bStandby)
		{
				Al_Bluetooth_Set_Action(BT_CMD_GET_NAME, NULL, 0);
				tmp&=(~BT_REQ_GET_NAME);
		}
		else if(requestState&BT_REQ_GET_MAC)
		{
				Al_Bluetooth_Set_Action(BT_CMD_GET_MAC, NULL, 0);
				tmp&=(~BT_REQ_GET_MAC);
		}
		else if(requestState&BT_REQ_GET_PAIRED_NAME && !bStandby)
		{
				Al_Bluetooth_Set_Action(BT_CMD_GET_PAIRED_NAME, NULL, 0);
				tmp&=(~BT_REQ_GET_PAIRED_NAME);
		}
		else if(requestState&BT_REQ_GET_PHONE_NUM && !bStandby)
		{
				Al_Bluetooth_Set_Action(BT_CMD_GET_PHONE_NUM, NULL, 0);
				tmp&=(~BT_REQ_GET_PHONE_NUM);
		}
		else if(requestState&BT_REQ_GET_VER)
		{
				Al_Bluetooth_Set_Action(BT_CMD_GET_VER, NULL, 0);		
				tmp&=(~BT_REQ_GET_VER);
		}
		else
			tmp = BT_REQ_NONE;

		if(tmp)
			GL_TaskSleep(100);
	}

	pthread_mutex_lock(&reqMutex);
	
	if(reSendCount)
		reSendCount--;
	else
	{
		requestState = BT_REQ_NONE;
		reSendCount = 0;
	}
	pthread_mutex_unlock(&reqMutex);
}

al_int8 Al_Bluetooth_HeartBeatHandler(al_int8 * str, al_uint8 len)
{
    BT_MessageBody_t stEvt;
    al_uint8 i = 0;
    al_uint hb_Status = 0;
    al_uint16 tmpStatus = 0;
		
    if (str == NULL || len == 0)
        return AL_FAILURE;

    for (i = 0; i < 4; i++)
        hb_Status = ((hb_Status << 8) | (str[13 - i] & 0xff));
    //printf("hb_status=0x%x.\n",hb_Status);
    if (hb_Status & HB_STATUS_MODE_BT)
    {
        if (bStandby)
        {
            stEvt.dMessage = BT_MESSAGE_MODE;
            stEvt.dParam = (hb_Status & 0xff00);
            if (stEvt.dParam != 0)
                _bt_SendEvt(stEvt);
        }
        bStandby = FALSE;
        stEvt.dMessage = 0;
        stEvt.dParam = 0;
        //phoneStatus = 0;
        switch (tmpStatus = (hb_Status & 0xff))
        {
          case HB_STATUS_BT_CONNECTED: //HB_STATUS_BT_PAUSE
              // waitting for play
              if (playStatus == HB_STATUS_BT_PLAYING || phoneStatus != 0)
              {
                  stEvt.dMessage = (phoneStatus != 0) ? BT_MESSAGE_PHONE : BT_MESSAGE_PLAYER;
                  stEvt.dParam = (phoneStatus != 0) ? HB_STATUS_BT_PHONE_OFF_CALL : tmpStatus;
                  conStatus = tmpStatus;
                  playStatus = HB_STATUS_BT_PAUSE;
                  phoneStatus = 0;
                  break;
              }
							Al_Bluetooth_CheckResend();
          case HB_STATUS_BT_WAIT_CONN:
              //waitting for connection
          case HB_STATUS_BT_RECONNECT:
              //reconnecting
              if (conStatus != tmpStatus)
              {
                  playStatus = HB_STATUS_BT_PAUSE;
                  phoneStatus = 0;
                  conStatus = tmpStatus;
                  stEvt.dMessage = BT_MESSAGE_CON_STATUS;
                  stEvt.dParam = tmpStatus;
              }
              break;
          case HB_STATUS_BT_PLAYING:
              // music is playing
              if (phoneStatus != 0)
              {
                  phoneStatus = 0;
                  stEvt.dMessage = BT_MESSAGE_PHONE;
                  stEvt.dParam = HB_STATUS_BT_CONNECTED;
                  _bt_SendEvt(stEvt);
              }
              if (playStatus != tmpStatus)
              {
              		conStatus = HB_STATUS_BT_CONNECTED;
                  playStatus = tmpStatus;
                  stEvt.dMessage = BT_MESSAGE_PLAYER;
                  stEvt.dParam = tmpStatus;
              }
							Al_Bluetooth_CheckResend();
              break;
          case HB_STATUS_BT_ONGOING_CALL: //HB_STATUS_BT_PHONE_CALL
              // phone call is on line
          case HB_STATUS_BT_INCOMING_CALL:
              // phone call in 
          case HB_STATUS_BT_OUTGOING_CALL:
              // phone call out
              if (phoneStatus != tmpStatus)
              {
              		conStatus = HB_STATUS_BT_CONNECTED;
                  playStatus = HB_STATUS_BT_PAUSE;
                  phoneStatus = tmpStatus;
                  stEvt.dMessage = BT_MESSAGE_PHONE;
                  stEvt.dParam = tmpStatus;
              }
							Al_Bluetooth_CheckResend();
              break;
          default:
              printf("Heart beat status error.\n");
              break;
        }
    }
    else
    {
        //standby mode
        if (!bStandby)
        {
            stEvt.dMessage = BT_MESSAGE_MODE;
            stEvt.dParam = (hb_Status & 0xff00);
        }
	    	conStatus = HB_STATUS_BT_WAIT_CONN;
	   		playStatus = HB_STATUS_BT_PAUSE;
		    phoneStatus = 0;
			memset(gDevName,0,BT_NAME_LEN_MAX);
			memset(gBtName,0,BT_NAME_LEN_MAX);
			memset(gBtTelNum,0,BT_TEL_NUM_LEN_MAX);
			if(requestState & BT_REQ_GET_MAC || requestState & BT_REQ_GET_VER)
				Al_Bluetooth_CheckResend();
			else
			{
				requestState = BT_REQ_NONE;
				reSendCount = 0;
			}
	      bStandby = TRUE;
    }

    if (stEvt.dParam != 0)
        _bt_SendEvt(stEvt);
    return AL_SUCCESS;
}

al_int Al_Bluetooth_Listener(void *argv)
{
    pCON_DEV pcon = (pCON_DEV) argv;
    al_int8 rec[MAX_CMD_LENGTH] = { 0 }, i = 0, cmdID = 0, cmdLen = 0, crcLen = 0;
    al_uint readLen = 0;
    bool bLeave = false, bReset = false;
		al_int16 checksum = 0, clrsum = 0;
		al_uint16 uuclrsum = 0;
    al_uint8 buf[512] = { 0 };
    BT_MessageBody_t stEvt = { 0 };

    uartbfd = open("/dev/uartb", O_RDWR);

    if (uartbfd <= 0)
    {
        //condbg2(pcon->dbg,"Open Console Fail \n");
        return AL_FAILURE;
    }

    pcon->n = 0;
    pcon->pid = getpid();

    while (pcon->bActive)
    {
        while (1)
        {
            con_uart.UART_UARTB_Listen_Status = TRUE;
            memset(buf, 0x0, sizeof(buf));
            GL_TaskSleep(300);
            readLen = read(uartbfd, buf, sizeof(buf));

            if (readLen > 0 || con_uart.uartB_Stop)
            {
                con_uart.UART_UARTB_Listen_Status = FALSE;
                break;
            }
        }

        if (!pcon->bActive)
        {
            break;
        }

        if (readLen <= 0)
        {
            printf("*** UARTB_data->len = 0 *** \n");
        }
				else
				{
	        memcpy(&rec[pcon->n], buf, readLen);
	        pcon->n += readLen;
					uuclrsum = 0;
	        checksum = 0;
	        if (pcon->n >= 20)
	            for (i = 0; i < 2; i++)
	                checksum = ((checksum << 8) | (rec[7 - i] & 0xff));
				}

        switch (rec[0])
        {
              //printf("==[%x][size=%d]==\n",rec[0], pcon->n);
          case 0x47:
              if ((strncmp(rec, CMD_BT_HEADER, strlen(CMD_BT_HEADER)) == 0) && pcon->n > 6)
              {
                  /*printf("==[0x%x,%x,%x,%x,%x,%x - %x,%x,%x,%x - %x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x][size=%d]==\n",
										rec[0],rec[1],rec[2],rec[3],rec[4],rec[5],rec[6],rec[7],rec[8],rec[9],rec[10],rec[11],rec[12],rec[13],rec[14],rec[15],rec[16],rec[17],rec[18],rec[19],
										rec[20],rec[21],rec[22],rec[23],rec[24],rec[25],rec[26],rec[27],rec[28],rec[29],rec[30],rec[31],rec[32],rec[33],rec[34],rec[35],rec[36],rec[37],rec[38],rec[39],rec[40],rec[41],pcon->n);*/
                  cmdID = rec[8];
                  cmdLen = rec[9];
                  crcLen = cmdLen - 2;
                  clrsum = 0;
                  stEvt.dMessage = 0;
                  stEvt.dParam = 0;

                  switch (cmdID)
                  {
                    case BT_CMD_GET_NAME:
                        if (pcon->n >= 20
                            && strncmp(&rec[BT_HEADER_LEN + sizeof(Al_BT_Name_Packet)], CMD_BT_TRAILER,
                                       strlen(CMD_BT_TRAILER)) == 0)
                        {
                            for (i = 0; i < crcLen; i++)
                                clrsum += rec[8 + i];

                            if (checksum == clrsum && (requestState & BT_REQ_GET_NAME))
                            {
                            		pthread_mutex_lock(&reqMutex);
                            		requestState&=(~BT_REQ_GET_NAME);
																pthread_mutex_unlock(&reqMutex);
                                memcpy(&gBtName, &rec[10], BT_NAME_LEN_MAX);
                                stEvt.dMessage = BT_MESSAGE_BT_NAME;
                                stEvt.dParam = 1;
                            }
                        }
                        break;
                    case BT_CMD_GET_MAC:
                        if (pcon->n >= 20
                            && strncmp(&rec[BT_HEADER_LEN + sizeof(Al_BT_Get_MAC_Packet)], CMD_BT_TRAILER,
                                       strlen(CMD_BT_TRAILER)) == 0)
                        {
														for (i = 0; i < crcLen; i++)
                                uuclrsum += (al_uint8)rec[8 + i];
														
														if (checksum == uuclrsum && (requestState & BT_REQ_GET_MAC))
                            {
                            		pthread_mutex_lock(&reqMutex);
                            		requestState&=(~BT_REQ_GET_MAC);
																pthread_mutex_unlock(&reqMutex);
                                memcpy(&gBtMac, &rec[10], BT_MAC_LEN_MAX);
																stEvt.dMessage = BT_MESSAGE_MAC;
                                stEvt.dParam = 1;
                            }
                        }
                        break;
                    case BT_CMD_GET_PHONE_NUM:
                        if (pcon->n >= 20
                            && strncmp(&rec[BT_HEADER_LEN + sizeof(Al_BT_Get_Phone_Num_Packet)], CMD_BT_TRAILER,
                                       strlen(CMD_BT_TRAILER)) == 0)
                        {
                            for (i = 0; i < crcLen; i++)
                                uuclrsum += (al_uint8)rec[8 + i];
																												
                            if (checksum == uuclrsum && (requestState & BT_REQ_GET_PHONE_NUM))
                            {
                            		pthread_mutex_lock(&reqMutex);
                            		requestState&=(~BT_REQ_GET_PHONE_NUM);
																pthread_mutex_unlock(&reqMutex);
                                stEvt.dMessage = BT_MESSAGE_PHONE_NUM;
                                stEvt.dParam = 1;
                                memcpy(&gBtTelNum, &rec[10], BT_TEL_NUM_LEN_MAX);
                            }
                        }
                        break;
                    case BT_CMD_GET_VER:
                        if (pcon->n >= 20
                            && strncmp(&rec[BT_HEADER_LEN + sizeof(Al_BT_Get_Ver_Packet)], CMD_BT_TRAILER,
                                       strlen(CMD_BT_TRAILER)) == 0)
                        {
                            for (i = 0; i < crcLen; i++)
                                uuclrsum += (al_uint8)rec[8 + i];
																												
                            if (checksum == uuclrsum && (requestState & BT_REQ_GET_VER))
                            {
                            		pthread_mutex_lock(&reqMutex);
                            		requestState&=(~BT_REQ_GET_VER);
																pthread_mutex_unlock(&reqMutex);
                                memcpy(&gBtVer, &rec[10], BT_VER_LEN_MAX);
																stEvt.dMessage = BT_MESSAGE_VER;
                                stEvt.dParam = 1;
                            }
                        }
                        break;
                    case BT_CMD_GET_PAIRED_NAME:
                        if (pcon->n >= 20
                            && strncmp(&rec[BT_HEADER_LEN + sizeof(Al_BT_Name_Packet)], CMD_BT_TRAILER,
                                       strlen(CMD_BT_TRAILER)) == 0)
                        {
                            for (i = 0; i < crcLen; i++)
                                clrsum += rec[8 + i];

                            if (checksum == clrsum && (requestState & BT_REQ_GET_PAIRED_NAME))
                            {
                            		pthread_mutex_lock(&reqMutex);
                            		requestState&=(~BT_REQ_GET_PAIRED_NAME);
																pthread_mutex_unlock(&reqMutex);
                                memcpy(&gDevName, &rec[10], BT_NAME_LEN_MAX);
                                stEvt.dMessage = BT_MESSAGE_PAIRED_NAME;
                                stEvt.dParam = 1;
                            }
                        }
                        break;
                    case BT_CMD_HEART_BEAT:
                        if (pcon->n >= 20
                            && strncmp(&rec[BT_HEADER_LEN + sizeof(Al_BT_Respond_Cmd_Head)], CMD_BT_TRAILER,
                                       strlen(CMD_BT_TRAILER)) == 0)
                        {
                            for (i = 0; i < crcLen; i++)
                                uuclrsum += (al_uint8)rec[8 + i];
														
                            //printf("==[heartBeat,clrsum=0x%x,checksum=0x%x]==\n", clrsum, checksum);
                            if (checksum == uuclrsum)
                                Al_Bluetooth_HeartBeatHandler(rec, pcon->n);
                        }
                        break;
                  }
              }
							bReset = true;
              break;
          default:
              bReset = true;
              break;
        }

        if (stEvt.dParam != 0)
            _bt_SendEvt(stEvt);

        if (bReset)
        {
            bReset = false;
            memset(&rec, 0, pcon->n);
            pcon->n = 0;
        }

        if (bLeave)
        {
            pcon->bActive = FALSE; // for UART B to leave its while loop
            con_uart.uartB_Stop = TRUE;
            break;
        }
    }

    pcon->pid = 0;
    close(uartbfd);

    return AL_SUCCESS;

}
#elif defined(CONFIG_BT_RDA5856)
int Al_Bluetooth_calc_uartdata_checksum(char *p_data, int len)
{
	int i = 0;
	int sum = 0;
	
	if(p_data == NULL)
		return 0;

	for(i=0; i< len ;i++)
	{
		sum = (sum + p_data[i])& 0xFF;
	}
	return sum;
}

al_int32 Al_Bluetooth_Set_BT_requestState(al_uint8 inCmd)
{
    switch (inCmd)
    {
	  case BT_CMD_GET_NAME:
		  if(inCmd == BT_CMD_GET_NAME)
		  {
			  pthread_mutex_lock(&reqMutex);
			  if(!(requestState&BT_REQ_GET_NAME))
			  {
				  reSendCount = 10;
				  requestState|=BT_REQ_GET_NAME;
			  }
			  pthread_mutex_unlock(&reqMutex);
		  }
	case BT_CMD_GET_MAC:
		  if(inCmd == BT_CMD_GET_MAC)
		  {
			  pthread_mutex_lock(&reqMutex);
			  memset(gBtMac,0,BT_MAC_LEN_MAX);
			  if(!(requestState&BT_REQ_GET_MAC))
			  {
				  reSendCount = 10;
				  requestState|=BT_REQ_GET_MAC;
			  }
			  pthread_mutex_unlock(&reqMutex);
		  }
	case BT_CMD_GET_PHONE_NUM:
		  if(inCmd == BT_CMD_GET_PHONE_NUM)
		  {
			  pthread_mutex_lock(&reqMutex);
			  if(!(requestState&BT_REQ_GET_PHONE_NUM))
			  {
				  reSendCount = 10;
				  requestState|=BT_REQ_GET_PHONE_NUM;
			  }
			  pthread_mutex_unlock(&reqMutex);
		  }   
	case BT_CMD_GET_VER:
		  if(inCmd == BT_CMD_GET_VER)
		  {
			  pthread_mutex_lock(&reqMutex);
			  memset(gBtVer,0,BT_VER_LEN_MAX);
			  if(!(requestState&BT_REQ_GET_VER))
			  {
				  reSendCount = 10;
				  requestState|=BT_REQ_GET_VER;
			  }
			  pthread_mutex_unlock(&reqMutex);
			  printf("[Ethan],[%s, get bt ver]\n",__FUNCTION__);
		  }   
	case BT_CMD_GET_PAIRED_NAME:
		  if(inCmd == BT_CMD_GET_PAIRED_NAME)
		  {
			  pthread_mutex_lock(&reqMutex);
			  if(!(requestState&BT_REQ_GET_PAIRED_NAME))
			  {
				  reSendCount = 10;
				  requestState|=BT_REQ_GET_PAIRED_NAME;
			  }
			  pthread_mutex_unlock(&reqMutex);
		  }
		  break;
	case BT_CMD_GET_PAIRERED_DEVICE:
		if(inCmd == BT_CMD_GET_PAIRERED_DEVICE)
		{
			pthread_mutex_lock(&reqMutex);
			if(!(requestState&BT_REQ_GET_PAIRED_DEVICE))
			{
				reSendCount = 10;
				requestState|=BT_REQ_GET_PAIRED_DEVICE;
			}
			pthread_mutex_unlock(&reqMutex);
		}
		break;
	default:
		break;
	}
	return 0;
}

al_int8 Al_Bluetooth_HostCalcAKH(al_uint16 rec,al_uint16 *number,al_uint16 *akh)
{
	mid_generate_host_akh(rec,number,akh);	
	return 0;
}

al_int32 Al_Bluetooth_Set_Action(al_uint8 inCmd, al_uint8 * data, al_uint8 size)
{
    al_uint8 *packet = NULL;
    al_uint8 otherSize = 0, headerLen = 0, traLen = 0, offset = 0;
    al_uint16 tmp = 0, i = 0, checksum = 0;
    al_int packetsize = 0;
	
	Al_RBT_Cmd_Head btHead = {
					.len = 3 + size, 				//len + cmd + dataLen + sum
					.cmd = inCmd,
			};
	
    if (bStandby && (inCmd == BT_CMD_SET_NAME || inCmd == BT_CMD_SET_LANG
			|| inCmd == BT_CMD_GET_MAC
			|| inCmd == BT_CMD_GET_NAME))
    {
        printf("Mode error.\n");
        return AL_FAILURE;
    }

	//calc sum
    for (i = 0; i < size; i++)
        tmp += (*(data + i));
	
    checksum += ((btHead.cmd + btHead.len + tmp) & 0xff);
    headerLen = strlen(CMD_BT_HEADER);
    traLen = strlen(CMD_BT_TRAILER);
    otherSize = headerLen + traLen;

    if (data != NULL)
    {
        size = (size > BT_INPUT_SIZE_MAX) ? BT_INPUT_SIZE_MAX : size;
    }
    else
        size = 0;

	packetsize = btHead.len+ otherSize;
	packet = malloc(packetsize);
	if(packet == NULL)
		return AL_FAILURE;		  

    switch (inCmd)
    {
		case BT_CMD_STANDBY:
		case BT_CMD_SET_BT_MODE:
		//case BT_CMD_HEART_BEAT:
		case BT_CMD_PLAYPAUSE:
		case BT_CMD_NEXT:
		case BT_CMD_PREV:
		case BT_CMD_DISCONNECT:
		case BT_CMD_RECONNECT:
		case BT_CMD_RESET_CONFIG:
		case BT_CMD_PHONE_ANSWER:
		case BT_CMD_PHONE_REDIAL:
		case BT_CMD_PHONE_REJECT:
		case BT_CMD_PHONE_CNACEL:
		case BT_CMD_PHONE_SWITCH_SCO:
		case BT_CMD_PHONE_CONNECT_SCO:
		case BT_CMD_PHONE_DISCONNECT_SCO:
		case BT_CMD_SET_NAME:
		case BT_CMD_SET_LANG:
		case BT_CMD_BTINQUIRY:
		case BT_CMD_BTINQUIRYCANCEL:
		case BT_CMD_BTCONNECT:
		case BT_CMD_GET_PAIRERED_DEVICE:
		case BT_CMD_GET_CONNECTED_DEVICE:
		case BT_CMD_CANCEL_PAIRER:
		case BT_CMD_BT_VISIBLE:			
		case BT_CMD_GET_NAME: 		
		case BT_CMD_GET_MAC: 		
		case BT_CMD_GET_PAIRED_NAME: 		
		case BT_CMD_GET_PHONE_NUM: 		
		case BT_CMD_GET_VER:
		case BT_CMD_BT_VOLADD:
		case BT_CMD_BT_VOLSUB:
		case BT_CMD_SEARCH_ALL:
		case BT_CMD_GPIO_CONTROL:
		case BT_CMD_MUTE_CONTROL:
		case BT_CMD_CANCEL_ALL_PAIRER:
		case BT_CMD_SYSRESTART:
		case BT_CMD_GET_HOST_AKH:
		case BT_CMD_PLAY_1K_AUDIO:
          break;
      default:
          printf("Command error.\n");
          free(packet);
          packet = NULL;
          return AL_FAILURE;
    }

    //packet header/trailer
    offset = 0;
    memcpy(packet + offset, CMD_BT_HEADER, strlen(CMD_BT_HEADER));
	offset += strlen(CMD_BT_HEADER);
    memcpy(packet + offset, &btHead, sizeof(Al_RBT_Cmd_Head));
	offset += sizeof(Al_RBT_Cmd_Head);
	if((size != 0) && (data != NULL))
	{
		memcpy(packet + offset, data, size);
		offset += size;
	}
    memcpy(packet + offset, &checksum, 1);
	offset += 1;
    memcpy(packet + offset, CMD_BT_TRAILER, strlen(CMD_BT_TRAILER));
	if(packet)
	{
		bluetooth_cmd_send(packet, packetsize);
		free(packet);
		packet = NULL;
	}

    return AL_SUCCESS;
}

void Al_Bluetooth_CheckResend()
{
	al_uint16 tmp = 0;
	al_int32 ret = AL_FAILURE;

	tmp = requestState;

	while(tmp)
	{
		if(requestState&BT_REQ_GET_NAME && !bStandby)
		{
				ret = Al_Bluetooth_Set_Action(BT_CMD_GET_NAME, NULL, 0);
				tmp&=(~BT_REQ_GET_NAME);
		}
		else if(requestState&BT_REQ_GET_MAC)
		{
				ret = Al_Bluetooth_Set_Action(BT_CMD_GET_MAC, NULL, 0);
				tmp&=(~BT_REQ_GET_MAC);
		}
		else if(requestState&BT_REQ_GET_PAIRED_NAME && !bStandby)
		{
				ret = Al_Bluetooth_Set_Action(BT_CMD_GET_PAIRED_NAME, NULL, 0);
				tmp&=(~BT_REQ_GET_PAIRED_NAME);
		}
		else if(requestState&BT_REQ_GET_PHONE_NUM && !bStandby)
		{
				ret = Al_Bluetooth_Set_Action(BT_CMD_GET_PHONE_NUM, NULL, 0);
				tmp&=(~BT_REQ_GET_PHONE_NUM);
		}
		else if(requestState&BT_REQ_GET_VER)
		{
				ret = Al_Bluetooth_Set_Action(BT_CMD_GET_VER, NULL, 0);		
				tmp&=(~BT_REQ_GET_VER);
		}
		else if(requestState&BT_REQ_GET_PAIRED_DEVICE)
		{
				ret = Al_Bluetooth_Set_Action(BT_CMD_GET_PAIRERED_DEVICE, NULL, 0);		
				tmp&=(~BT_REQ_GET_PAIRED_DEVICE);
		}
		else
			requestState = BT_REQ_NONE;

		
		pthread_mutex_lock(&reqMutex);
		if(ret == AL_SUCCESS)
			requestState = tmp;
		pthread_mutex_unlock(&reqMutex);
		
		if(requestState)
			GL_TaskSleep(100);
	}
}

al_int8 Al_Bluetooth_HeartBeatHandler(void)
{
    BT_MessageBody_t stEvt = { 0 };
    al_uint16 tmpStatus = 0;

	//printf("bt mode: %d; bt status: %d; Ready:%d\n",gHeartBeat_data.bt_mode,gHeartBeat_data.bt_status,gHeartBeat_data.bt_ready);

	memset(&stEvt,0x0,sizeof(BT_MessageBody_t));
    if ((gHeartBeat_data.bt_mode >= 1) && (gHeartBeat_data.bt_mode <= 5))
    {
        if (bStandby)
        {
            stEvt.dMessage = BT_MESSAGE_MODE;
            stEvt.dParam = gHeartBeat_data.bt_mode;
            if (stEvt.dParam != 0)
                _bt_SendEvt(stEvt);
        }
        bStandby = FALSE;
        stEvt.dMessage = 0;
        stEvt.dParam = 0;
        //phoneStatus = 0;
        switch (tmpStatus = gHeartBeat_data.bt_status)
        {
          case HB_STATUS_BT_CONNECTED: //HB_STATUS_BT_PAUSE
              // waitting for play
              if (playStatus == HB_STATUS_BT_PLAYING || phoneStatus != 0)
              {
                  stEvt.dMessage = (phoneStatus != 0) ? BT_MESSAGE_PHONE : BT_MESSAGE_PLAYER;
                  stEvt.dParam = (phoneStatus != 0) ? HB_STATUS_BT_PHONE_OFF_CALL : tmpStatus;
                  conStatus = tmpStatus;
                  playStatus = HB_STATUS_BT_PAUSE;
                  phoneStatus = 0;
                  break;
              }
			  Al_Bluetooth_CheckResend();
          case HB_STATUS_BT_WAIT_CONN:
              //waitting for connection
          case HB_STATUS_BT_RECONNECT:
              //reconnecting
              if (conStatus != tmpStatus)
              {
                  playStatus = HB_STATUS_BT_PAUSE;
                  phoneStatus = 0;
                  conStatus = tmpStatus;
                  stEvt.dMessage = BT_MESSAGE_CON_STATUS;
                  stEvt.dParam = tmpStatus;
              }
              break;
          case HB_STATUS_BT_PLAYING:
              // music is playing
              if (phoneStatus != 0)
              {
                  phoneStatus = 0;
                  stEvt.dMessage = BT_MESSAGE_PHONE;
                  stEvt.dParam = HB_STATUS_BT_PHONE_OFF_CALL;
                  _bt_SendEvt(stEvt);
              }
              if (playStatus != tmpStatus)
              {
              	  conStatus = HB_STATUS_BT_CONNECTED;
                  playStatus = tmpStatus;
                  stEvt.dMessage = BT_MESSAGE_PLAYER;
                  stEvt.dParam = tmpStatus;
              }
			  Al_Bluetooth_CheckResend();
              break;
          case HB_STATUS_BT_ONGOING_CALL: //HB_STATUS_BT_PHONE_CALL
              // phone call is on line
          case HB_STATUS_BT_INCOMING_CALL:
              // phone call in 
          case HB_STATUS_BT_OUTGOING_CALL:
              // phone call out
              if (phoneStatus != tmpStatus)
              {
              		conStatus = HB_STATUS_BT_CONNECTED;
                  playStatus = HB_STATUS_BT_PAUSE;
                  phoneStatus = tmpStatus;
                  stEvt.dMessage = BT_MESSAGE_PHONE;
                  stEvt.dParam = tmpStatus;
              }
			  Al_Bluetooth_CheckResend();
              break;
          default:
			  Al_Bluetooth_CheckResend();
              printf("Heart beat status error.\n");
              break;
        }
    }
    else
    {
        //standby mode
        if (!bStandby)
        {
            stEvt.dMessage = BT_MESSAGE_MODE;
            stEvt.dParam = BT_MODE_OFF;
        }
    	conStatus = HB_STATUS_BT_WAIT_CONN;
   		playStatus = HB_STATUS_BT_PAUSE;
	    phoneStatus = 0;
		memset(gDevName,0,BT_NAME_LEN_MAX);
		memset(gBtName,0,BT_NAME_LEN_MAX);
		memset(gBtTelNum,0,BT_TEL_NUM_LEN_MAX);
		if(requestState & BT_REQ_GET_MAC || requestState & BT_REQ_GET_VER)
			Al_Bluetooth_CheckResend();
		else
		{
			requestState = BT_REQ_NONE;
			reSendCount = 0;
		}
	    bStandby = TRUE;
    }

    if (stEvt.dParam != 0)
        _bt_SendEvt(stEvt);
    return AL_SUCCESS;
}

/**
UART_CMD_Definition
Head | Len | CMD | DATA0 | DATA1 | ... | CheckSum | End
Head:RB#
Len:strlen(Head + Len + CMD + DATA0...CheckSum)
CheckSum = (Len+CMD+Data0+Data1+...)&0xFF
End:#BR
**/

al_int Al_Bluetooth_Listener(void *argv)
{
    pCON_DEV pcon = (pCON_DEV) argv;
    al_int8 rec[MAX_CMD_LENGTH] = { 0 };
    al_int8 rectemp[512] = { 0 };
    al_uint readLen = 0;
    al_uint uartdataright = false;
    al_uint bneedparsernextcmd = false;
    bool bLeave = false, bReset = false;
	al_uint clrsum = 0, calcsum = 0;
    al_uint8 buf[512] = { 0 },cmdID = 0, cmdLen = 0;
    BT_MessageBody_t stEvt = { 0 };
	int datalen = 0;

    uartbfd = open("/dev/uartb", O_RDWR);

    if (uartbfd <= 0)
    {
        //condbg2(pcon->dbg,"Open Console Fail \n");
        return AL_FAILURE;
    }

    pcon->n = 0;
    pcon->pid = getpid();

    while (pcon->bActive)
    {
        while (1)
        {
            con_uart.UART_UARTB_Listen_Status = TRUE;
            memset(buf, 0x0, sizeof(buf));
            GL_TaskSleep(300);
            readLen = read(uartbfd, buf, sizeof(buf));

            if (readLen > 0 || con_uart.uartB_Stop)
            {
                con_uart.UART_UARTB_Listen_Status = FALSE;
                break;
            }
        }

        if (!pcon->bActive)
        {
            break;
        }

        if (readLen <= 0)
        {
            printf("*** UARTB_data->len = 0 *** \n");
        }
		else
		{
		    memcpy(&rec[pcon->n], buf, readLen);
		    pcon->n += readLen;
		}
		
#ifdef CONFIG_BLUETOOTH_UPGRADE_SUPPORT
		if(Al_Get_BTUpgradeFlag() == TRUE)
		{
			rda58xx_rx_handler(&rec[0],pcon->n);
			switch (rec[0])
			{
			  default:
				  bReset = true;
				  break;
			}
		}
		else
#endif
		{
				datalen = pcon->n;		
		BEGIN:	
				bneedparsernextcmd = FALSE;
				memset(&stEvt,0x0,sizeof(BT_MessageBody_t));
				switch (rec[0])
				{
					  //printf("==[%x][size=%d]==\n",rec[0], pcon->n);
				  case 0x52:
					  if ((strncmp(rec, CMD_BT_HEADER, strlen(CMD_BT_HEADER)) == 0) && datalen >= 9)
					  {
						  cmdID = rec[4];
						  cmdLen = rec[3];
						  clrsum = (al_uint8)rec[3+cmdLen-1];
						  stEvt.dMessage = 0;
						  stEvt.dParam = 0;
						  uartdataright = FALSE;

						  //check sum
						  //calcsum = Al_Bluetooth_calc_uartdata_checksum(&rec[3],pcon->n-7);
						  calcsum = Al_Bluetooth_calc_uartdata_checksum(&rec[3],cmdLen-1);
						  //printf("==cmd[0x%x][size=0x%x]==cmdLen:0x%x, clrsum:0x%x, calcsum:0x%x\n",rec[4], datalen,cmdLen,clrsum,calcsum);
						  if((datalen == (int)cmdLen + 6)&&(clrsum == calcsum))
						  {
							  uartdataright = TRUE;
						  }
						  else if((datalen > (int)cmdLen + 6)&&(clrsum == calcsum)&&
							(strncmp(&rec[3+cmdLen], CMD_BT_TRAILER, strlen(CMD_BT_TRAILER)) == 0))
						  {
							  printf("---%s, line:%d\n",__FUNCTION__,__LINE__);
							  uartdataright = TRUE;
							  bneedparsernextcmd = TRUE;
						  }

						  if(uartdataright ==  FALSE)
						  {
							  bReset = true;
							  printf("==cmd error !\n");
							  break;
						  }
						  else
						  {
							  //printf("==cmd right !\n");
							  stEvt.dMessageCmd = cmdID;
							  if(datalen > 9)
							  {
								  stEvt.dCmdSize = cmdLen - 3;//not include head+cmd+sum
								  stEvt.pdata = (al_uint8*)&rec[5]; 			
							  }
						  }

						  switch (cmdID)
						  {
							case BT_CMD_UPDATE_TVBTADDRS:
							case BT_CMD_UPDATE_TVBTINQUIRYOVER:
							case BT_CMD_RESP_PAIRERED_DEVICE:
							case BT_CMD_RESP_CONNECTED_DEVICE:
							case BT_CMD_AVRCP_PASSTHROUGH:
							case BT_CMD_SPP_PASSTHROUGH:
							case BT_CMD_SEND_FMFREQ:
							case BT_CMD_SEND_FMSCAN:
							case BT_CMD_RESP_NAME:
							case BT_CMD_RESP_VER:
							case BT_CMD_RESP_CONNECT_FAIL:
							case BT_CMD_RESP_CMD_NOACTION:
							case BT_CMD_GET_HOST_AKH:
								stEvt.dMessageCmd = cmdID;
								stEvt.dParam = 1;
								break;

							case BT_CMD_HEART_BEAT:
								{
									memset(&gHeartBeat_data,0x0,sizeof(AP_BT_HEART_BEAT));
									memcpy(&gHeartBeat_data,&rec[5],sizeof(AP_BT_HEART_BEAT));
									Al_Bluetooth_HeartBeatHandler();
								}
								stEvt.dMessageCmd = cmdID;
								stEvt.dParam = 1;
								break;
								
							case BT_CMD_GET_NAME:
								{
									if (requestState & BT_REQ_GET_NAME)
									{
										pthread_mutex_lock(&reqMutex);
										requestState&=(~BT_REQ_GET_NAME);
										pthread_mutex_unlock(&reqMutex);
										memcpy(&gBtName, &rec[10], BT_NAME_LEN_MAX);
										stEvt.dMessage = BT_MESSAGE_BT_NAME;
										stEvt.dParam = 1;
									}
								}
								break;
							case BT_CMD_GET_MAC:
								{
									if (requestState & BT_REQ_GET_MAC)
									{
										pthread_mutex_lock(&reqMutex);
										requestState&=(~BT_REQ_GET_MAC);
										pthread_mutex_unlock(&reqMutex);
										memcpy(&gBtMac, &rec[10], BT_MAC_LEN_MAX);
										stEvt.dMessage = BT_MESSAGE_MAC;
										stEvt.dParam = 1;
									}
								}
								break;
							case BT_CMD_GET_PHONE_NUM:
								{
									//if (requestState & BT_REQ_GET_PHONE_NUM)
									{
										pthread_mutex_lock(&reqMutex);
										requestState&=(~BT_REQ_GET_PHONE_NUM);
										pthread_mutex_unlock(&reqMutex);
										stEvt.dMessage = BT_MESSAGE_PHONE_NUM;
										stEvt.dMessageCmd = cmdID;
										stEvt.dParam = 1;
										memcpy(&gBtTelNum, &rec[5], BT_TEL_NUM_LEN_MAX);
									}
								}
								break;
							case BT_CMD_GET_VER:
								{
									if (requestState & BT_REQ_GET_VER)
									{
										pthread_mutex_lock(&reqMutex);
										requestState&=(~BT_REQ_GET_VER);
										pthread_mutex_unlock(&reqMutex);
										memcpy(&gBtVer, &rec[10], BT_VER_LEN_MAX);
										stEvt.dMessage = BT_MESSAGE_VER;
										stEvt.dParam = 1;
									}
								}
								break;
							case BT_CMD_GET_PAIRED_NAME:
								{
									if (requestState & BT_REQ_GET_PAIRED_NAME)
									{
										pthread_mutex_lock(&reqMutex);
										requestState&=(~BT_REQ_GET_PAIRED_NAME);
										pthread_mutex_unlock(&reqMutex);
										memcpy(&gDevName, &rec[10], BT_NAME_LEN_MAX);
										stEvt.dMessage = BT_MESSAGE_PAIRED_NAME;
										stEvt.dParam = 1;
									}
								}
								break;
						  }
					  }
					  bReset = true;
					  break;
				  default:
					  bReset = true;
					  break;
				}

				if (stEvt.dParam != 0)
					_bt_SendEvt(stEvt);
				
				if(bneedparsernextcmd == TRUE)
				{
					memset(rectemp,0x0,512);
					datalen = datalen-(int)cmdLen - 6;
					memcpy(rectemp,&rec[cmdLen+6],datalen>512?512:datalen);
					memset(rec,0x0,MAX_CMD_LENGTH);
					memcpy(rec,rectemp,datalen);		
					goto BEGIN;
				}
		}
		
        if (bReset)
        {
            bReset = false;
            memset(&rec, 0, pcon->n);
            pcon->n = 0;
        }

        if (bLeave)
        {
            pcon->bActive = FALSE; // for UART B to leave its while loop
            con_uart.uartB_Stop = TRUE;
            break;
        }
    }

    pcon->pid = 0;
    close(uartbfd);

    return AL_SUCCESS;

}

#endif

