#include "stdafx.h" 
#include "uPhone.h" 

#include <stdio.h> 
#include "uMessageQueue.h" 

#ifdef BCPP 
#pragma package(smart_init) 
#endif 

#define DEBUG_OUTPUT(x)    if (MSGMAN.DebugMonitorScreen) MSGMAN.DebugMonitorScreen(x); 
#define PORT_OUTPUT(x, y) if (MSGMAN.PortMonitorScreen) MSGMAN.PortMonitorScreen(x, y); 

Phone::Phone(byte protocol, int port) 
{
    Refresh = true;
    memset(IMEI, 0, 17);
    memset(SoftwareVersion, 0, 10);
    memset(SoftwareDate, 0, 10);
    memset(SoftwareType, 0, 10); 

    if (protocol == PI_MBUS)
        Link = (Protocol*)new MBUS(port);
    else
        Link = (Protocol*)new FBUS(port);

#ifdef BCPP
         if (Link)
             Link->AttachProcessMessage(ProcessMessage); 
#endif 
} 

/** 
 * 
 */ 

void Phone::SendSMSMsg(void)
{
  ERROR_MSG("SendSMSMsg not supported by phone base type");
} 

/** 
 *
 */ 

void Phone::GetSMSMsg(byte location)
{
  ERROR_MSG("GetSMSMsg not supported by phone base type");
} 

/** 
 *
 */ 

void Phone::InitiateConnection(void)
{
  ERROR_MSG("InitiateConnection not supported by phone base type");
} 

/** 
 * 㲥
 */ 

void Phone::SetCellBroadcast(byte enabled)
{
  ERROR_MSG("SetCellBroadcast not supported by phone base type");
}

/** 
 * Ϣ
 */ 

void Phone::SetSMSCenter(void)
{
  ERROR_MSG("SetSMSCenter not supported by phone base type");
} 

/** 
 * Ϣ
 */ 

void Phone::GetSMSCenter(byte priority)
{
  ERROR_MSG("GetSMSCenter not supported by phone base type");
} 

/** 
 *Ϣ
 */ 

void Phone::Handle_SMSHandling(MessageBuffer *Msg)
{
  ERROR_MSG("Handle_SMSHandling not supported by phone base type");
} 
/************************************************************************** 
* PHONEBOOK FUNCTIONS * 
***************************************************************************/ 
/** 
 * Get mem location
 */ 

void Phone::GetMemLocation(byte memtype, byte location)
{
  ERROR_MSG("GetMemLocation not supported by phone base type");
} 

/** 
 * Set mem location
 */ 

void Phone::SetMemLocation(void)
{
  ERROR_MSG("SetMemLocation not supported by phone base type");
} 

/** 
 * Mem status request 
 */ 

void Phone::MemStatusRequest(byte memtype) 
{
  ERROR_MSG("MemStatusRequest not supported by phone base type");
} 

/** 
 * Get caller group name 
 */ 

void Phone::GetCallerGroupData(byte groupID) 
{
  ERROR_MSG("GetCallerGroupData not supported by phone base type");
} 

/** 
 * Set caller group name
 */ 


void Phone::SetCallerGroupData(void)
{
  ERROR_MSG("SetCallerGroupData not supported by phone base type");
} 

/** 
 * Get speed dial 
 */ 

void Phone::GetSpeedDial(byte Index)
{
  ERROR_MSG("GetSpeedDial not supported by phone base type");
} 

/** 
 * Set speed dial 
 */ 

void Phone::SetSpeedDial(void) 
{
  ERROR_MSG("SetSpeedDial not supported by phone base type");
} 

/** 
 * Handle Phone Book messages 
 */ 

void Phone::Handle_PhonebookFunctions(MessageBuffer *Msg)
{
  ERROR_MSG("Handle_PhonebookFunctions not supported by phone base type");
} 

/*************************************************************************** 
* PHONE STATUS * 

***************************************************************************/ 

/** 
 * Phone status 
 */ 

void Phone::PhoneStatus(void) 
{
  ERROR_MSG("PhoneStatus not supported by phone base type");
} 

/** 
 * Request Phone ID 
 */ 

void Phone::RequestPhoneID(void)
{
  ERROR_MSG("RequestPhoneID not supported by phone base type");
} 

/** 
 * Handle Phone Status messages 
 */ 

void Phone::Handle_PhoneStatus(MessageBuffer *Msg)
{
  ERROR_MSG("Handle_PhoneStatus not supported by phone base type");
} 

/*************************************************************************** 
* PROFILE SETTINGS * 
***************************************************************************/ 


/** 
 * Set profile feature
 */ 

void Phone::SetProfileFeature(void)
{
  ERROR_MSG("SetProfileFeature not supported by phone base type");
} 

/** 
 * Get profile feature 
 */ 

void Phone::GetProfileFeature(byte nr, byte feature)
{
  ERROR_MSG("GetProfileFeature not supported by phone base type");
} 

/** 
 * Get Welcome Message 
 */ 

void Phone::GetWelcomeMessage(void)
{
  ERROR_MSG("GetWelcomeMessage not supported by phone base type");
} 

/** 
 * Set welcome message 
 */ 

void Phone::SetWelcomeMessage(void)
{
  ERROR_MSG("SetWelcomeMessage not supported by phone base type");
} 

/**
 * Get profile name
 */ 

void Phone::GetProfilename(byte nr) 
{
  ERROR_MSG("GetProfilename not supported by phone base type");
} 

/** 
 * Set oplogo 
 */ 

void Phone::SetOplogo(void)
{
  ERROR_MSG("SetOplogo not supported by phone base type");
} 

/** 
 * Get oplogo 
 */ 

void Phone::GetOplogo(byte location)
{
  ERROR_MSG("GetOplogo not supported by phone base type");
} 

/** 
 * Set ringtone
 */ 

void Phone::SetRingtone(void)
{
  ERROR_MSG("SetRingtone not supported by phone base type");
} 

/** 
* Get service settings */ 

void Phone::GetServiceSettings(byte setting) 
{
  ERROR_MSG("GetServiceSettings not supported by phone base type"); 
} 

/** 
 * Set call divert 
 */ 

void Phone::SetCallDivert(void)
{
  ERROR_MSG("SetCallDivert not supported by phone base type");
} 

/** 
 * Deactivate call diverts 
 */ 

void Phone::DeactivateCallDiverts(void)
{
  ERROR_MSG("DeactivateCallDiverts not supported by phone base type");
} 

/** 
 * Get call diverts 
 */ 

void Phone::GetCallDiverts(void)
{
  ERROR_MSG("GetCallDiverts not supported by phone base type");
} 

/** 
 * Handle Profile Settings messages 
 */ 

void Phone::Handle_ProfileSettings(MessageBuffer *Msg)
{
  ERROR_MSG("Handle_ProfileSettings not supported by phone base type");
}

/** 
 * Enable extended cmds
 */ 

void Phone::EnableExtendedCMDS(byte cmd)
{
  ERROR_MSG("EnableExtendedCMDS not supported by phone base type");
} 

void Phone::Handle_SecurityCommands(MessageBuffer *Msg) 
{
  ERROR_MSG("Handle_SecurityCommands not supported by phone base type");
} 

void Phone::Init(void)
{
  ERROR_MSG("Phone::Init not supported by phone base type"); 
} 

void __fastcall Phone::ProcessMessage(MessageBuffer *Msg) 
{
  switch (Msg->buffer[3])
  {
    case CMD_N6110_SMSHandling:
      Handle_SMSHandling(Msg); 
      DEBUG_OUTPUT("Handled by PH->Handle_SMSHandling"); 
      break; 
    case CMD_N6110_PhoneBook:
      Handle_PhonebookFunctions(Msg); 
      DEBUG_OUTPUT("Handled by PH->Handle_PhonebookFunctions");
      break; 
    case CMD_N6110_PhoneStatus:
      Handle_PhoneStatus(Msg);
      DEBUG_OUTPUT("Handled by PH->Handle_PhoneStatus");
      break; 
    case CMD_N6110_SecurityCommands:
      Handle_SecurityCommands(Msg);
      DEBUG_OUTPUT("Handled by PH->Handle_SecurityCommands");
      break; 
    case 0xD2:
      Handle_Init(Msg);
      DEBUG_OUTPUT("Handled by PH->Handle_Init");
      break; 

    case CMD_N6110_Ack:  
      { 
        if (Msg->CheckDestAddr(DSA_PC) && Msg->CheckSrcAddr( DSA_Phone ) && Msg->CheckCommand(CMD_N6110_Ack)) { 
          DEBUG_OUTPUT("Phone ACK");} 
        else { 
          DEBUG_OUTPUT("Mirror ACK");}
     }
      break; 

    case 0xD0:
      DEBUG_OUTPUT("Power on message...I think so");
      break; 

    default: 
      {
        char buf[50];
        memset(buf, 0, 50);
        sprintf(buf, "Unkown command (0x%02X)", Msg->buffer[3]);
        DEBUG_OUTPUT(buf); 
     }
        break; 
   }; 


    DEBUG_OUTPUT("I ack the msg"); 
    if (Link) 
        Link->AckMessage(Msg->buffer[Msg->length - 2]); 
} 

 
void Phone::SetSoftware(char *Version, char *Date, char *Type) 
{
  strcpy(SoftwareVersion, Version); 
  strcpy(SoftwareDate, Date); 
  strcpy(SoftwareType, Type); 
  Refresh = true; 
} 


 
void Phone::GetSoftware(char *Version, char *Date, char *Type) 
{
  strcpy(Version, SoftwareVersion); 
  strcpy(Date, SoftwareDate); 
  strcpy(Type, SoftwareType); 
} 
13.2.2  Nokia6110.cppģ
nokiaֻϵͳֵ֧ࡣ 
/************************************************************************** 
 * Include        * 

**************************************************************************/ 

#include "stdafx.h" 
#include "Nokia6110.h" 
#include <stdio.h> 


#ifdef BCPP 
  #pragma package(smart_init) 
#endif 

Nokia6110::Nokia6110(byte protocol, int port):
  Phone(protocol, port) 
{
  MaxRFLevel = 4;
  MinRFLevel = 0;
  MaxBatteryLevel = 4; 
  MinBatteryLevel = 0; 
  AlarmsAvailable   = 1;
  StartupLogoSize.right  = 48; 
  StartupLogoSize.bottom  = 84; 
  StartupLogoSize.left = StartupLogoSize.top = 0; 
  OplogoSize.right = 14; 
  OplogoSize.bottom  = 72; 
  OplogoSize.left = OplogoSize.top = 0; 
  CallerLogoSize.right   = 14; 
  CallerLogoSize.bottom  = 72; 
  CallerLogoSize.left = CallerLogoSize.top = 0; 
  memset(baseModel, 0, 50); 
  strcpy(baseModel, "Nokia 6110"); 


  /* Try to put phone in service mode */ 
  EnableExtendedCMDS(0x02); 
} 

/*************************************************************************** 
* SMS HANDLING (0x02) * 
***************************************************************************/ 
/**
 * Send SMS Message {...}
 */ 

void Nokia6110::SendSMSMsg(void)
{
  INFO_MSG("FIXME - Nokia6110::SendSMSMsg");
} 

/** 
 * Get SMS Message {0x07, 0x02, location, 0x01, 0x64} 
 */ 

void Nokia6110::GetSMSMsg(byte location) 
{
  byte buffer[] = {0x07, 0x02, 0x00 /* location */, 0x01, 0x64};
  buffer[2] = location;
  if (Link) 
    Link->SendMessage(5, CMD_N6110_SMSHandling, buffer);
} 

/** 
 * Initiate connection {0x0d, 0x00, 0x00, 0x02} 
 */ 

void Nokia6110::InitiateConnection(void) 
{
  byte buffer[] = {0x0d, 0x00, 0x00, 0x02};
  if (Link) 
    Link->SendMessage(4, CMD_N6110_SMSHandling, buffer);
} 

/** 
 * Set Cell Broadcast {0x02, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01} 
 */ 

void Nokia6110::SetCellBroadcast(byte enabled)
{
  byte buffer[] = {0x02, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01}; 
  if (!enabled)
  {

    buffer[1] = buffer[2] = buffer[3] = buffer[4] = buffer[5] = buffer[6] = 0; 
 };
  if (Link) 
    Link->SendMessage(7, CMD_N6110_SMSHandling, buffer); 
} 

/** 
 * Set SMS center {...} 
 */ 

void Nokia6110::SetSMSCenter(void) 
{
  INFO_MSG("FIXME - Nokia6110::SetSMSCenter"); 
} 

/** 
 * Get SMS center {0x33, 0x64, priority} 
 */ 

void Nokia6110::GetSMSCenter(byte priority) 
{
  byte buffer[] = {0x33, 0x64, 0x00 /* Priority */}; 
  buffer[2] = priority; 
  if (Link) 
    Link->SendMessage(3, CMD_N6110_SMSHandling, buffer); 
} 

/** 
 * Handle CMD_N6110_SMSHandling messages 
 */ 

void Nokia6110::Handle_SMSHandling(MessageBuffer *Msg) 
{
  switch (Msg->buffer[6])
  {
    case 0x02: 
      INFO_MSG("Message sent"); 
      break; 
    case 0x03: 
      INFO_MSG("Message failed"); 
      break; 
    case 0x0e: 
      INFO_MSG("Initiate ACK"); 
      break; 
    case 0x10:
      INFO_MSG("SMS message received");
      break; 
    case 0x21:
      INFO_MSG("Set Cell Broadcast OK");
      break; 
    case 0x23:
      INFO_MSG("Read Cell Broadcast");
      break; 
    case 0x31:
      INFO_MSG("Set SMS center OK");
      break; 
    case 0x32: 
      INFO_MSG("Set SMS error"); 
      break; 
    case 0x34:
      INFO_MSG("SMS center received");
      break; 
    case 0x35:
      INFO_MSG("SMS center error received");
      break; 
    default: 
      // һӳϢ ... 
      // Ӧÿ ... 
      break; 
 };
} 

/************************************************************************** 
* PHONEBOOK FUNCTIONS (0x03) * 
**************************************************************************/ 
/** 
 * Get mem location {0x01, memtype, location, 0x00} 
 */ 

void Nokia6110::GetMemLocation(byte memtype, byte location) 
{
  byte buffer[] = {0x01, 0x00 /* memtype */, 0x00 /* location */, 0x00}; 
  buffer[1] = memtype;
  buffer[2] = location;
  if (Link) 
      Link->SendMessage(4, CMD_N6110_PhoneBook, buffer); 
} 

/** 
 * Set mem location {...}
 */ 

void Nokia6110::SetMemLocation(void) 
{
  INFO_MSG("FIXME - Nokia6110::SetMemLocation"); 
} 

/** 
 * Mem status request {0x07, memtype} 
 */ 

void Nokia6110::MemStatusRequest(byte memtype) 
{
  byte buffer[] = {0x07, 0x00 /* memtype */}; 
  buffer[1] = memtype; 
  if (Link) 
    Link->SendMessage(2, CMD_N6110_PhoneBook, buffer); 
} 

/** 
 * Get caller group name {0x10, groupID}
 */ 

void Nokia6110::GetCallerGroupData(byte groupID) 
{
  byte buffer[] = {0x10, 0x00 /* groupID */};
  buffer[1] = groupID;
  if (Link) 
    Link->SendMessage(2, CMD_N6110_PhoneBook, buffer);
} 

/** 
 * Set caller group name {...}
 */ 

void Nokia6110::SetCallerGroupData(void)
{
  INFO_MSG("FIXME - Nokia6110::GetCallerGroupName");
} 

/** 
 * Get speed dial {0x16, index(1-9)}
 */ 

void Nokia6110::GetSpeedDial(byte Index) 
{
  byte buffer[] = {0x16, 0x00 /* index */};
  buffer[1] = Index;
  if (Link) 
    Link->SendMessage(2, CMD_N6110_PhoneBook, buffer);
} 

/** 
 * Set speed dial {...}
 */ 

void Nokia6110::SetSpeedDial(void)
{
  INFO_MSG("FIXME - Phone::SetSpeedDial"); 
} 

/** 
 * Handle CMD_N6110_PhoneBook messages */ 


void Nokia6110::Handle_PhonebookFunctions(MessageBuffer *Msg) 
{
  switch (Msg->buffer[6])
  {
    case 0x02: 
      INFO_MSG("Mem location received"); 
      break; 
    case 0x03: 
      INFO_MSG("Mem location error"); 
      break; 
    case 0x05: 
      INFO_MSG("Mem set OK"); 
      break; 
    case 0x06: 
      INFO_MSG("Mem set error"); 
      break; 
    case 0x08: 
      INFO_MSG("Mem status received"); 
      break; 
    case 0x09: 
      INFO_MSG("Mem status error"); 
      break; 
    case 0x11: 
      INFO_MSG("Get caller group OK"); 
      break; 
    case 0x12: 
      INFO_MSG("Get caller group error"); 
      break; 
    case 0x14: 
      INFO_MSG("Set caller group OK"); 
      break; 
    case 0x15: 
      INFO_MSG("Set caller group error"); 
      break; 
    case 0x17: 
      INFO_MSG("Get speed dial OK"); 
      break; 
    case 0x18: 
      INFO_MSG("Get speed dial error"); 
      break; 
    case 0x1a: 
      INFO_MSG("Set speed dial OK"); 
      break; 
    case 0x1b: 
      INFO_MSG("Set speed dial error"); 
      break; 
    default: 
      // һӳϢ... 
      // Ӧÿ... 
      break; 
 }; 
} 


/*************************************************************************** 
* PHONE STATUS (0x04) * 
***************************************************************************/ 
/** 
 * Nokia6110 status {0x01} 
 */ 

void Nokia6110::PhoneStatus(void) 
{
  byte buffer[] = {0x01}; 
  // byte buffer[] = {0x00, 0x01, 0x64, 0x02}; // ڷģʽ 
  if (Link) 
    Link->SendMessage(4, CMD_N6110_PhoneStatus, buffer); 
} 

/** 
 * Request Phone ID {0x03}
 */ 

void Nokia6110::RequestPhoneID(void) 
{
  byte buffer[] = {0x03}; 
  if (Link) 
    Link->SendMessage(1, CMD_N6110_PhoneStatus, buffer); 
} 

/** 
 * Handle CMD_N6110_PhoneStatus messages 
 */ 


void Nokia6110::Handle_PhoneStatus(MessageBuffer *Msg) 
{

} 


/*************************************************************************** 
* PROFILE SETTINGS (0x05) * 
***************************************************************************/ 
/** 
 * Set profile feature {...}  */ 

void Nokia6110::SetProfileFeature(void) 
{
  INFO_MSG("FIXME - Nokia6110::SetProfileFeature");
} 

/** 
 * Get profile feature {0x13, 0x01, nr, feature, 0x01} 
 */ 

void Nokia6110::GetProfileFeature(byte nr, byte feature)
{
  byte buffer[] = {0x13, 0x01, 0x00 /* nr */, 0x00 /* feature */, 0x01}; 
  buffer[2] = nr;
  buffer[3] = feature;
  if (Link) 
    Link->SendMessage(5, CMD_N6110_ProfileSettings, buffer);
} 

/** 
 * Get Welcome Message {0x16}
 */ 

void Nokia6110::GetWelcomeMessage(void) 
{
  byte buffer[] = {0x16};
  if (Link) 
    Link->SendMessage(1, CMD_N6110_ProfileSettings, buffer);
} 

/** 
 * Set welcome message {...} 
 */ 

void Nokia6110::SetWelcomeMessage(void)
{
  INFO_MSG("FIXME - Nokia6110::SetWelcomeMessage"); 
} 

/** 
 * Get profile name {0x1a, nr}
 */ 

void Nokia6110::GetProfilename(byte nr) 
{
  byte buffer[] = {0x1a, 0x00 /* nr */}; buffer[1] = nr;
  if (Link) 
    Link->SendMessage(2, CMD_N6110_ProfileSettings, buffer);
} 

/** 
 * Set oplogo {...}; 
 */ 

void Nokia6110::SetOplogo(void)
{
  INFO_MSG("FIXME - Nokia6110::SetOplogo");
}

/** 
 * Get oplogo {0x33, location}
 */ 

void Nokia6110::GetOplogo(byte location) 
{
  byte buffer[] = {0x33, 0x00 /* location */};
  buffer[1] = location;
  if (Link) 
    Link->SendMessage(2, CMD_N6110_ProfileSettings, buffer);} 

/** 
 * Set ringtone {...}
 */ 

void Nokia6110::SetRingtone(void)
{
  INFO_MSG("FIXME - Nokia6110::SetRingtone");
} 

/** 
 * Get service settings {0x80, setting (2 bytes)} 
 */ 

void Nokia6110::GetServiceSettings(byte setting) 
{
  byte buffer[] = {0x80, 0x00 /* setting Hi */, 0x00 /* setting Lo */};
  if (Link) 
    Link->SendMessage(3, CMD_N6110_ProfileSettings, buffer);
} 

/** 
 * Set call divert {...} 
 */ 

void Nokia6110::SetCallDivert(void) 
{
  INFO_MSG("FIXME - Nokia6110::SetCallDivert");
} 

/** 
 * Deactivate call diverts {...} 
 */ 

void Nokia6110::DeactivateCallDiverts(void)
{
  INFO_MSG("FIXME - Nokia6110::DeactivateCallDiverts");
}

/** 
 * Get call diverts {...}
 */ 

void Nokia6110::GetCallDiverts(void) 
{
  INFO_MSG("FIXME - Nokia6110::GetCallDiverts"); 
} 

/** 
 * Handle CMD_N6110_ProfileSettings messages 
 */ 

void Nokia6110::Handle_ProfileSettings(MessageBuffer *Msg) 
{

} 
/*****************************************************************************************************************************************************/ 

/** 
 * Enable extended cmds {0x64, cmd} 
 */ 

void Nokia6110::EnableExtendedCMDS(byte cmd)
{
  // byte buffer[] = {0x00, 0x01, 0x64, 0x00 /* cmd */}; /* Added 0x00, 0x01 - Why ? */
  // buffer[1] = cmd;
  // if (Link)
  // Link->SendMessage(4, CMD_N6110_SecurityCommands, buffer); 

  byte buffer[] = {0x00, 0x01, 0x00, 0x03}; 
  if (Link) 
  {
    Link->SendMessage(4, 0xD1, buffer); 
  // Sleep(1000); 
  // Link->SendMessage(4, 0xD1, buffer); 
  // Sleep(1000); 
  // Link->SendMessage(4, 0xD1, buffer); 
    } 
} 

void Nokia6110::Handle_Init(MessageBuffer *Msg) 
{
/* char sw[10]; 

  if (data->Model) {
        snprintf(data->Model, 6, "%s", message + 21);
} 


if (data->Revision) {
       sscanf(message + 6, " %9s", sw); 
       snprintf(data->Revision, GSM_MAX_REVISION_LENGTH, "SW %s, HW ????", sw);
}
dprintf("Phone info:\n%s\n", message + 4);
return GE_NONE;*/ 

if (Msg->length > 6) 
{
  char ver[10]; 
  memset(ver, 0, 10); 
  _snprintf(ver, 7, "%s", &Msg->buffer[10]); 

  char date[10]; 
  memset(date, 0, 10); 
  _snprintf(date, 8, "%s", &Msg->buffer[18]); 

  char model[10]; 
  memset(model, 0, 10); 
  _snprintf(model, 5, "%s", &Msg->buffer[27]); 

  SetSoftware(ver, date, model); 
  } 
} 

void Nokia6110::Handle_SecurityCommands(MessageBuffer *Msg) 
{
  switch (Msg->buffer[8]) 
  {
    /* Enable extended commands */ 
    case 0x64:
      //INFO_MSG("Enable extended commands");
      break; 

    /* call management (old style) */ 
    case 0x7c:
      INFO_MSG("call management (old style)");
      //if (message[3] < 0x01 || message[3] > 0x03)
      //return GE_UNHANDLEDFRAME;
      break; 

    /* Netmonitor */ 
    case 0x7e:
      INFO_MSG("Netmonitor");
      //if (message[3] != 0x00 && data->NetMonitor)
      //snprintf(data->NetMonitor->Screen, sizeof(data->NetMonitor->Screen), "%s", message + 4);
      //ͣ; 

    /* Get bin ringtone */ 
    case 0x9e:
      INFO_MSG("Get bin ringtone");
      // л(message[4]) {
      // ʾ0x00:  
      // ͣ
      // ʾ0x0a:
      // GE_UNKNOWN;
      // Ĭ:
      // GE_UNHANDLEDFRAME;
      // }
      // (!data->Ringtone)  GE_INTERNALERROR;
      // data->Ringtone->Location = message[3];
      // snprintf(data->Ringtone->name, sizeof(data->Ringtone->name), "%s", message + 8);
      // if (data->RawData && data->RawData->Data) {
      //       memcpy(data->RawData->Data, message + 24, length -24);
      // data->RawData->Length = length - 24;
      // }
      break; 

    /* Set bin ringtone result */ 
    case 0xa0:
      INFO_MSG("Set bin ringtone result");
      // (message[3] != 0x02)GE_UNHANDLEDFRAME;
      break; 

    default: 
      //  GE_UNHANDLEDFRAME; 
      break; 
  }; 
} 

void Nokia6110::GetNokiaAuth(byte *Imei, byte *MagicBytes, byte *MagicResponse) 
{
  int i, j, CRC = 0; 
  unsigned char Temp[16]; /* This is our temporary working area. */

  /* Here we put FAC (Final Assembly Code) and serial number into our area. */
  memcpy(Temp, Imei + 6, 8); 

  /* And now the TAC (Type Approval Code). */ 
  memcpy(Temp + 8, Imei + 2, 4); 

  /* And now we pack magic bytes from the phone. */ 
  memcpy(Temp + 12, MagicBytes, 4); 

  for (i = 0; i <= 11; i++)
    if (Temp[i + 1] & 1)
        Temp[i]<<=1; 
  switch (Temp[15] & 0x03) 
  {
    case 1: 
    case 2: 
    j = Temp[13] & 0x07;
    for (i = 0; i <= 3; i++)
      Temp[i+j] ^= Temp[i+12];
    break; 

  default: 
    j = Temp[14] & 0x07; 
    for (i = 0; i <= 3; i++) 
      Temp[i + j] |= Temp[i + 12];
} 

for (i = 0; i <= 15; i++)
      CRC ^= Temp[i]; 

for (i = 0; i <= 15; i++){
        switch (Temp[15 - i] & 0x06) {
        case 0: 
              j = Temp[i] | CRC;   
              break; 

        case 2: 
        case 4:
              j = Temp[i] ^ CRC;
              break; 

        case 6:
              j = Temp[i] & CRC;
              break;
        } 
    if (j == CRC) j = 0x2c; 

    if (Temp[i] == 0) j = 0; 

    MagicResponse[i] = j; 
  } 
} 
13.2.3  Userialweb.cppģ
ʵͨѶӿڵĴ
/*************************************************************************** 
 * Include        * 
***************************************************************************/ 
#include "stdafx.h" 
#include <process.h> 
#include "uSerial.h" 
#include <Stdio.h> 
#include "uGeneral.h" 
#include "uMessageQueue.h" 
 
#ifdef BCPP 
  #include <mem.h> 
  #pragma package(smart_init) 
#endif 
 
/** 
 * Media thread -> Handle com port stuff 
 */ 

void MediaThreadBack(LPVOID param) 
{
  SerialWB *com = (SerialWB *)param;
  if ((SerialWB *)NULL == com) 
       ExitThread(1); 

  SetThreadPriority(com->h_th_back, THREAD_PRIORITY_ABOVE_NORMAL); 
  while (com->b_th_run)
    com->Task();
    ExitThread(0);
} 

/** 
 * SerialWB handling constructor
 */ 

SerialWB::SerialWB(int port) 
{
  h_port = INVALID_HANDLE_VALUE; 
  mediaLastError = 0; 
  dwEvtMask = false; 
  h_th_back = INVALID_HANDLE_VALUE; 
  OpenPort(port); 
} 

/** 
 * SerialWB handling constructor
 */ 

SerialWB::~SerialWB(void) 
{
  EndThread(); 
  ClosePort(); 
} 

/** 
 * Send buffer on comm port
 */ 

void SerialWB::SendIt(MessageBuffer *Msg)
{
  if (! Msg) return; 
  if (MSGMAN.PortMonitorScreen) 
MSGMAN.PortMonitorScreen(Msg->DebugString(), true); 
  Out.Push(Msg->buffer, Msg->length);
} 

/** 
 * Open port 
 */ 

bool SerialWB::OpenPort(int port)
{
  char name[10]; 

  ClosePort(); 

  sprintf(name, "\\\\.\\COM%d", port); 
  h_port = CreateFile(name, 

                             GENERIC_READ | GENERIC_WRITE, 
                             0, NULL, OPEN_EXISTING, 
                             FILE_ATTRIBUTE_NORMAL /*| FILE_FLAG_OVERLAPPED /*| FILE_FLAG_NO_BUFFERING*/, 0); 
  if(h_port == INVALID_HANDLE_VALUE) {
    return false; 
}

SetupComm(h_port, WIN_COMMBUF_SIZE, WIN_COMMBUF_SIZE); 
PurgeComm(h_port,  PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR); 

  EscapeCommFunction(h_port, RESETDEV | CLRBREAK | SETDTR); 
  if (!ChangePortSettings()) 
    return false; 

  DetectErrors(false);
  return StartThread();
} 

/** 
 * Change/Set port settings 
 */ 

bool SerialWB::ChangePortSettings(long int SPEED,
                    UCHAR PARITY,
                    UCHAR BITS,
                    UCHAR STPBIT,
                    UCHAR RTSCTS) 
{
  PORTSETTINGS.SPEED = SPEED;
  PORTSETTINGS.PARITY = PARITY;
  PORTSETTINGS.BITS = BITS;
  PORTSETTINGS.STPBIT = STPBIT;
  PORTSETTINGS.RTSCTS = RTSCTS; 

  GetCommState(h_port, &dcb); 
/* dcb.fBinary = true;
  dcb.fOutxDsrFlow = false; 
  dcb.fDtrControl   = DTR_CONTROL_ENABLE;//false; 
  dcb.fDsrSensitivity   = false;
  dcb.fTXContinueOnXoff = false;
  dcb.fOutX = false;
  dcb.fInX = false;
  dcb.fErrorChar  = false;
  dcb.fNull = false;
  dcb.fAbortOnError = true;
  dcb.fParity = true;*/
  dcb.Parity = PARITY; 
//ODDPARITY/EVENPARITY/NOPARITY
  dcb.ByteSize = BITS;
  //if (BITS < 5 || BITS > 8)
  dcb.ByteSize = 8;        // 5|6|7|8 valid 

  switch (STPBIT) 
      {
    case 2:
      dcb.StopBits = TWOSTOPBITS;  // 1|2 valid
      break;
    default:
      dcb.StopBits = ONESTOPBIT;  // 1|2 valid
      break; 
  } // л 

  //dcb.fRtsControl = false; 
  //dcb.fOutxCtsFlow = false; 
  //dcb.fRtsControl = RTS_CONTROL_ENABLE; 

switch(SPEED) 
          {
  case 110: dcb.BaudRate = CBR_110; break;
  case 300: dcb.BaudRate = CBR_300; break; 
 case 600: dcb.BaudRate = CBR_600; break;
  case 1200: dcb.BaudRate = CBR_1200; break;
  case 2400: dcb.BaudRate = CBR_2400; break;
  case 4800: dcb.BaudRate = CBR_4800; break;
  case 9600: dcb.BaudRate = CBR_9600; break;
  case 14400: dcb.BaudRate = CBR_14400; break;
  case 19200: dcb.BaudRate = CBR_19200; break;
  case 38400: dcb.BaudRate = CBR_38400; break;
  case 56000: dcb.BaudRate = CBR_56000; break;
  case 57600: dcb.BaudRate = CBR_57600; break;
  case 115200: dcb.BaudRate = CBR_115200; break;
  case 128000: dcb.BaudRate = CBR_128000; break;
  case 256000: dcb.BaudRate = CBR_256000; break;
  default: dcb.BaudRate = CBR_9600; break; 
} // л

tms.ReadIntervalTimeout = 0xFFFFFFFF; 
tms.ReadTotalTimeoutMultiplier = 0;
tms.ReadTotalTimeoutConstant = 1000;
tms.WriteTotalTimeoutMultiplier = 2 * CBR_9600 / CBR_115200;
tms.WriteTotalTimeoutConstant = 0;

//if(RTSCTS == 'C') {// guess higher values for 232 
//etCommMask(h_port, EV_RXCHAR | EV_RXFLAG | EV_TXEMPTY | EV_CTS);  
//else {
// SetCommMask(h_port, EV_RXCHAR | EV_RXFLAG | EV_TXEMPTY);
//} 

SetCommTimeouts(h_port, &tms); 
if(SetCommState(h_port, &dcb) == false) {
     mediaLastError = GetLastError(); 
     return false; 

} 
return true; 
} 

/** 
 * Close port 
 */ 

bool SerialWB::ClosePort(void) 
{
  if (h_port == INVALID_HANDLE_VALUE) 
      return true; 

  if (h_port != INVALID_HANDLE_VALUE) 
  {
    CancelIo(h_port);
    PurgeComm(h_port, PURGE_TXABORT | PURGE_RXABORT | 
           PURGE_TXCLEAR | PURGE_RXCLEAR); 
    EscapeCommFunction(h_port, RESETDEV | CLRBREAK);
  } 

  if (h_port != INVALID_HANDLE_VALUE) 
  {
    CloseHandle(h_port); 
    h_port = INVALID_HANDLE_VALUE;
  } 

  return true;
}
 
/** 
 * Write data in circular buffer to port 
 */ 

DWORD SerialWB::WriteCommBlock(void) 
{ 
  BOOL  fWriteStat; 
  DWORD  dwBytesWritten;  
  DWORD  dwErrorFlags; 
  DWORD  dwError; 
  DWORD  dwBytesSent = 0; 
  COMSTAT  ComStat;  
  unsigned long n = 0;

  if (Out.Count() == 0) return 0; 

  fWriteStat = WriteFile(h_port, Out.buffer+Out.popIndex, Out.Count(), &n, NULL);//&osWrite); 

  if (!fWriteStat) 
  {
    if (GetLastError() == ERROR_IO_PENDING)
    {

      while (!GetOverlappedResult(h_port, &osWrite, &dwBytesWritten, TRUE)) 
      {
        dwError = GetLastError(); 
  if (dwError == ERROR_IO_INCOMPLETE) 
  {
    /* normal result if not finished */ 
    dwBytesSent += dwBytesWritten; 
    continue; 
  } 
  else 

        {
    /* an error occurred, try to recover */
    ClearCommError(h_port, &dwErrorFlags, &ComStat);
    break; 
  } 
      } 

      dwBytesSent += dwBytesWritten; 
    } 
    else 
    {
      /* some other error occurred */ 
      ClearCommError(h_port, &dwErrorFlags, &ComStat); 
      return 0; 
    }
  } 
  else
  {
    Out.popIndex += n; 
  } 
  return n; 
} 

/** 
 * Read data from comm port and place it into the circular buffer
 */ 

DWORD SerialWB::ReadCommBlock(int nMaxLength) 
{
  BOOL  fReadStat; 
  COMSTAT ComStat; 
  DWORD dwErrorFlags;
  DWORD dwLength = 0;
  DWORD dwError; 

  /* only try to read number of bytes in queue */
  ClearCommError(h_port, &dwErrorFlags, &comStat); 
  dwLength = min((DWORD) nMaxLength, comStat.cbInQue); 

  if (dwLength > 0)
  {
    fReadStat = ReadFile(h_port, In.buffer + In.pushIndex, dwLength, &dwLength, NULL);//&osRead);
    if (!fReadStat)
    {
      if (GetLastError() == ERROR_IO_PENDING)
      {
/* We have to wait for read to complete. 
 * This function will timeout according to the 
 * CommTimeOuts.ReadTotalTimeoutConstant variable 
*  Every time it times out, check for port errors */ 
while (!GetOverlappedResult(h_port, &osRead, &dwLength, TRUE)) 
         {
    dwError = GetLastError();
    if (dwError == ERROR_IO_INCOMPLETE)
            /* normal result if not finished */
        continue;
    else
            {
      /* an error occurred, try to recover */ 
      ClearCommError(h_port, &dwErrorFlags, &ComStat); 
      break; 
    } 
        } 
    } 
    else 
    {
      /* some other error occurred */ 
dwLength = 0; 
ClearCommError(h_port, &dwErrorFlags, &ComStat); 
      } 
    } 
    else 
    {
      In.pushIndex += dwLength; 
      //
      // ȡһ 0x1F - StartϢ... 
      // Ӧ MBUS˲... 
      FlushData(In.pushIndex - In.popIndex, &In.buffer[In.popIndex]); 
      In.popIndex = In.pushIndex; 
    }
  } 
  return (dwLength); 
} 

/** 
 * Start media thread 
 */ 


bool SerialWB::StartThread(void) 
{
  if(h_th_back != INVALID_HANDLE_VALUE) 
    return true; 

  b_th_run = true; 
  h_th_back = (void*)CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)MediaThreadBack, (LPVOID)this, 0, &dw_th_id); 
  if(h_th_back == INVALID_HANDLE_VALUE)
  {
      mediaLastError = GetLastError(); 
    return (b_th_run = false);
  } 
    return true;
} 

void SerialWB::Task(void) 
{
  if (WaitForEvents() && ProcessEvents()) {}
  Sleep(20); 
} 

/** 
 * Wait for comm events 
 */ 


bool SerialWB::WaitForEvents(void)
{
  bool ret = false; 

  switch(mediaLastError = GetLastError()) 
  {
    case ERROR_SUCCESS: 
      if (!dwEvtMask) 
      {
        SetCommMask(h_port, EV_RXCHAR | EV_RXFLAG | EV_TXEMPTY | EV_RLSD); 
    GetCommMask(h_port, &dwEvtMask);
          }
          ret = true;
          break; 
        case ERROR_OPERATION_ABORTED:
          ret = false;
          mediaLastError = 0;
          break; 
        default:
          DetectErrors(0);
          if (mediaLastError)
          {
    Sleep(2000); 
    ret = false; 
        }
        else 
        {
          ret = true;
        }
        break; 
    } 

    return ret; 
} 

/** 
 * Process the comm events
 */ 


bool SerialWB::ProcessEvents(void) 
{

// #define EV_RXCHAR     0x0001	// Any Character received 
// #define EV_RXFLAG 0x0002		// Received certain character 
// #define EV_TXEMPTY 0x0004	// Transmitt Queue Empty 
// #define EV_CTS 0x0008		// CTS changed state 
// #define EV_DSR    0x0010		// DSR changed state 
// #define EV_RLSD 0x0020		// RLSD changed state 
// #define EV_BREAK 0x0040		// BREAK received 
// #define EV_ERR  0x0080		// Line status error occurred 
// #define EV_RING      0x0100	// Ring signal detected 
// #define EV_PERR   0x0200		// Printer error occured 
// #define EV_RX80FULL 0x0400	// Receive buffer is 80 percent full 
// #define EV_EVENT1 0x0800		// Provider specific event 1 
// #define EV_EVENT2 0x1000		// Provider specific event 2 

    if (dwEvtMask)
    {
      // BREAK 
      if (dwEvtMask & EV_BREAK) 
      {
        ClosePort(); 
        Sleep(2000); 
        return false;
      } 

      // Line״
      if ((dwEvtMask & EV_ERR)) 
      {
        DetectErrors(0); 
        if (PORTSETTINGS.RTSCTS != 'N') 
        {
          EscapeCommFunction(h_port, CLRRTS); 
        } 
        ClosePort(); 
        Sleep(2000); 
        return false; 
      } 

      // DSR ޸ĳ
      if (dwEvtMask & EV_DSR)
      {
        if(PORTSETTINGS.RTSCTS != 'N') 
        {
          EscapeCommFunction(h_port, CLRRTS); 
        } // end if 
        if (ReadCommBlock(/*(SBUFSIZ - rxtail)*/512)) 
            SetCommMask(h_port, EV_RXCHAR);
        } 

        // CTS޸ĳ
        if (dwEvtMask & EV_CTS)
        {
          if(PORTSETTINGS.RTSCTS != 'N') 
          {
            EscapeCommFunction(h_port, SETRTS); 
            SetCommMask(h_port, EV_RXCHAR | EV_TXEMPTY); 
          }
          else 
          {
            SetCommMask(h_port, EV_RXCHAR | EV_TXEMPTY | EV_DSR); 
          } 
          if (Out.Count() > 0) 
          WriteCommBlock(); 
      } 

      // Transmitt Queue Empty 
      if ((dwEvtMask & EV_TXEMPTY)) 
      {
        if (Out.Count() > 0) 
        {
    WriteCommBlock(); 
            SetCommMask(h_port, EV_TXEMPTY); 
        } 
    } 

    // Any Character
    //ĳЩַ
    if ((dwEvtMask & EV_RXFLAG) || (dwEvtMask & EV_RXCHAR))
    {
        if (ReadCommBlock(/*(SBUFSIZ - rxtail)*/512))
            SetCommMask(h_port, EV_RXCHAR); 
    } 
    else 
    {
      if (Out.Count() > 0) 
      {
if (PORTSETTINGS.RTSCTS != 'N') {
    EscapeCommFunction(h_port, SETRTS);
    SetCommMask(h_port, EV_RXCHAR | EV_CTS | EV_TXEMPTY | EV_DSR);
} else {
  SetCommMask(h_port, EV_RXCHAR | EV_TXEMPTY); 
} // end if 
WriteCommBlock(); 
      } // end if 
    } 
    return true; 
    } 
    return false;
  } 

/** 
 * Detect errors, fill COMSTAT struct 
 */ 


bool SerialWB::DetectErrors(bool in)
{
  if (0 == ClearCommError(h_port, &errFlags, &comStat))
      ERROR_MSG("ClearComm Failed");
  if (errFlags & CE_FRAME)
      INFO_MSG("CE_FRAME");
  if (errFlags & CE_OVERRUN)
      INFO_MSG("CE_OVERRUN");
  if (errFlags & CE_RXPARITY)
      INFO_MSG("CE_RXPARITY");
  if (errFlags & CE_RXOVER)
      INFO_MSG("CE_RXOVER");
  if (errFlags & CE_BREAK) 
      INFO_MSG("CE_BREAK");
  if (errFlags & CE_TXFULL)
      INFO_MSG("CE_TXFULL"); 

  if (errFlags) 
      return false; 

  return true;
} 

/** 
 * End thread
 */ 


bool SerialWB::EndThread(void) 
{
   b_th_run = false;
   Sleep(100); 

    volatile short loops = 0;
    volatile DWORD dWait;
    volatile bool ret = true; 

    if (h_th_back != INVALID_HANDLE_VALUE) 
    {
      dWait = WaitForSingleObject(h_th_back, 0);
      while (dWait == WAIT_TIMEOUT && loops++ < 30) 
        dWait = WaitForSingleObject(h_th_back, 20);
    if (dWait == WAIT_TIMEOUT) 
        ret = false; 
    CloseHandle(h_th_back); 
    h_th_back = INVALID_HANDLE_VALUE; 
  } // end if
  return ret;
} 

/** 
 * Toggle DTR/RTS 
 */ 

void SerialWB::Set_DTR_RTS(int dtr, int rts) 
{
  DCB dcb; dcb.DCBlength = sizeof(DCB);
  GetCommState(h_port, &dcb);
  dcb.fOutxDsrFlow = 0;
  if (dtr) 
    dcb.fDtrControl = DTR_CONTROL_ENABLE;
  else 
    dcb.fDtrControl = DTR_CONTROL_DISABLE;
  dcb.fOutxCtsFlow = 0;
  if (rts) 
    dcb.fRtsControl = RTS_CONTROL_ENABLE;
  else 
    dcb.fRtsControl = RTS_CONTROL_DISABLE;
  dcb.fInX = dcb.fOutX = 0;
  SetCommState(h_port, &dcb);
} 
