// Pam.cpp : Defines the entry point for the DLL application. // #include "stdAfx.h" // Pam.cpp : Defines the entry point for the DLL application. // Pam.cpp : Defines the class behaviors for the application. // // Waarschuwing bij debuggen: in een sessie wordt een key bepaald met een geldigheidsduur van X seconden. // Bij het verzenden van beschermde berichten moet deze key nog geldig zijn. Let hierop bij het plaatsen // van breakpoints. #include "Pam.h" #include "StandardDlg.h" #include "DebugDlg.h" #include "AboutDlg.h" #include "ProgressDlg.h" #include "url.h" #include "GrabWininet.h" #include "TaskBarApplet.hpp" #define _MFC_TASKBAR_APPLET #include "TaskBarAppletMain.hpp" #ifdef USE_COM_PORTS #include "serialWnd.h" #else #include "SiUSBXp.h" #endif #include "betronic.h" #include // for XOR operator??? #include // for XOR operator??? BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { return TRUE; } #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif // Definieer de types die uit de WinHttp.dll nodig zijn: #include typedef BOOL (WINAPI *TFWinHttpReadData)( IN HINTERNET hRequest, IN LPVOID lpBuffer, IN DWORD dwNumberOfBytesToRead, OUT LPDWORD lpdwNumberOfBytesRead ); typedef HINTERNET (WINAPI *TFWinHttpOpen)( IN LPCWSTR pwszUserAgent, IN DWORD dwAccessType, IN LPCWSTR pwszProxyName OPTIONAL, IN LPCWSTR pwszProxyBypass OPTIONAL, IN DWORD dwFlags ); typedef HINTERNET (WINAPI *TFWinHttpConnect)( IN HINTERNET hSession, IN LPCWSTR pswzServerName, IN INTERNET_PORT nServerPort, IN DWORD dwReserved ); typedef HINTERNET (WINAPI *TFWinHttpOpenRequest)( IN HINTERNET hConnect, IN LPCWSTR pwszVerb, IN LPCWSTR pwszObjectName, IN LPCWSTR pwszVersion, IN LPCWSTR pwszReferrer OPTIONAL, IN LPCWSTR FAR * ppwszAcceptTypes OPTIONAL, IN DWORD dwFlags ); typedef BOOL (WINAPI *TFWinHttpSendRequest)( IN HINTERNET hRequest, IN LPCWSTR pwszHeaders OPTIONAL, IN DWORD dwHeadersLength, IN LPVOID lpOptional OPTIONAL, IN DWORD dwOptionalLength, IN DWORD dwTotalLength, IN DWORD_PTR dwContext ); typedef BOOL (WINAPI *TFWinHttpReceiveResponse) ( IN HINTERNET hRequest, IN LPVOID lpReserved ); typedef BOOL (WINAPI *TFWinHttpQueryDataAvailable)( IN HINTERNET hRequest, OUT LPDWORD lpdwNumberOfBytesAvailable OPTIONAL ); ///////////////////////////////////////////////////////////////////////////// // CPamTaskBar: // class CPamTaskBar : public CJBTaskBarApplet { public: //MFCApplet(); private: extern "C" bool __declspec(dllexport) __stdcall InitInstance(LPSTR lpCmdLine); extern "C" void __declspec(dllexport) __stdcall OnLeftDoubleClick(); // extern "C" void __declspec(dllexport) __stdcall void SettingsDialog(); extern "C" void __declspec(dllexport) __stdcall AboutDialog(); extern "C" HICON __declspec(dllexport) __stdcall GetIcon(); extern "C" HMENU __declspec(dllexport) __stdcall GetMenu(); extern "C" void __declspec(dllexport) __stdcall HandleMenuCommand(int command); enum menuIDs { ID_CLOSE = 1, ID_OPEN, ID_ABOUT, ID_UPLOAD, ID_PAM }; extern "C" bool ShowError __declspec(dllexport) __stdcall (LONG lError, LPCTSTR lptszMessage, BOOL bShowPopup); extern "C" void __declspec(dllexport) __stdcall OnSerialMessage(WPARAM wParam); extern "C" void __declspec(dllexport) __stdcall OnTimerMessage(WPARAM wParam); CSerialWnd m_serial; extern "C" void __declspec(dllexport) __stdcall NotifyUser(CString strMsg, BOOL bShow, BOOL bReset); ProgressDlg * m_pProgressDlg; CString m_TrayTip; extern "C" LPCTSTR __declspec(dllexport) __stdcall GetTrayTip(); #ifdef USE_COM_PORTS extern "C" bool __stdcall OpenComPort(); extern "C" bool __declspec(dllexport) __stdcall CloseComPort(); #else extern "C" bool __declspec(dllexport) __stdcall OpenUSB(); extern "C" bool __declspec(dllexport) __stdcall CloseUSB(); extern "C" bool __declspec(dllexport) __stdcall ReadUSB(); extern "C" bool __declspec(dllexport) __stdcall PamStillThere(); #endif extern "C" bool __declspec(dllexport) __stdcall PamToggleMode(); extern "C" bool __declspec(dllexport) __stdcall PamSetTime(); extern "C" bool __declspec(dllexport) __stdcall PamGetTime(); extern "C" bool __declspec(dllexport) __stdcall PamReadMode(); extern "C" bool __declspec(dllexport) __stdcall PamSetMode(BYTE mode, BYTE key_return); // added by E. Damen for AM200 extern "C" bool __declspec(dllexport) __stdcall PamSetAux(BYTE CalorieperPam); // added by E. Damen for AM200 extern "C" bool __declspec(dllexport) __stdcall PamStaticMode(); extern "C" bool __declspec(dllexport) __stdcall PamReadSerialNumber(); extern "C" bool __declspec(dllexport) __stdcall PamReadDockingDate(); extern "C" bool __declspec(dllexport) __stdcall PamReadCalibrationFactor(); extern "C" bool __declspec(dllexport) __stdcall PamReadEeprom(); extern "C" bool __declspec(dllexport) __stdcall PamReadToday(); extern "C" bool __declspec(dllexport) __stdcall PamReadEepromPage0(BYTE key_return); // added by E. Damen for AM102 extern "C" bool __declspec(dllexport) __stdcall PamReadEepromPage1(BYTE key_return); // added by E. Damen for AM102 extern "C" bool __declspec(dllexport) __stdcall PamReadEepromPage2(BYTE key_return); // added by E. Damen for AM102 extern "C" bool __declspec(dllexport) __stdcall PamReadEepromPage3(BYTE key_return); // added by E. Damen for AM102 extern "C" bool __declspec(dllexport) __stdcall PamUploadData(); extern "C" bool __declspec(dllexport) __stdcall PamReadRam(UINT address); extern "C" bool __declspec(dllexport) __stdcall SendCommand(struct Message *message, BOOL bReading); extern "C" void __declspec(dllexport) __stdcall StartHeartbeat(); int m_State; int m_TimeOut; extern "C" void __declspec(dllexport) __stdcall ProcessBreak(); extern "C" BOOL __declspec(dllexport) __stdcall ProcessMessage(); BYTE m_Buffer[256]; DWORD m_dwEob; BOOL m_DiscardInput; BOOL m_bSkipBreak; UINT m_bSkipCounter; UINT m_SerialNumber; struct { UINT Major; UINT Minor; UINT Build; } m_VersionNumber; DWORD m_Config; BYTE m_Key; BYTE m_Key_return; BYTE m_PamMode; BYTE m_CalorieperPam; // Added by E. Damen for AM200 BYTE m_UpdateDockDay; // Added by E. Damen for AM200 BYTE m_PamDayScore16; UINT m_PamLowScore; UINT m_PamMedScore; UINT m_PamHighScore; UINT m_PamDistanceTD; UINT m_PamFruitTD; BOOL m_ConsumerMode; // The real mode in which the docked Pam is running CTime m_Time; UINT m_Heartbeat; UINT m_GainAdjustMultiplier; UINT m_GainAdjustDivider; UINT m_TresholdHeavy; UINT m_TresholdLight; UINT m_Fifo; // The current pointer in the PAM data UINT m_Size; UINT m_Pam[512]; // changed by E. Damen for AM102 UINT m_LightActivity[512]; // changed by E. Damen for AM102 UINT m_MediumActivity[512]; // changed by E. Damen for AM102 UINT m_HeavyActivity[512]; // changed by E. Damen for AM102 UINT m_Distance[512]; // added by E. Damen for AM200 UINT m_Fruit[512]; // added by E. Damen for AM200 UINT m_code1[512]; // added by E. Damen for AM200 UINT m_code2[512]; // added by E. Damen for AM200 BOOL m_bMilitary; BYTE Eepromt[0x1FF]; // changed by E. Damen for AM102 HANDLE m_hUSBDevice; // Dit zijn variabelen die de adressen naar de WinHTTP functies gaan bevatten: TFWinHttpReadData FWinHttpReadData; TFWinHttpConnect FWinHttpConnect; TFWinHttpOpen FWinHttpOpen; TFWinHttpOpenRequest FWinHttpOpenRequest; TFWinHttpSendRequest FWinHttpSendRequest; TFWinHttpReceiveResponse FWinHttpReceiveResponse; TFWinHttpQueryDataAvailable FWinHttpQueryDataAvailable; // Hier komen onze varianten van de WinHTTP functies: extern "C" BOOL __declspec(dllexport) __stdcall WinHttpReadData ( IN HINTERNET hRequest, IN LPVOID lpBuffer, IN DWORD dwNumberOfBytesToRead, OUT LPDWORD lpdwNumberOfBytesRead ); extern "C" HINTERNET __declspec(dllexport) __stdcall WinHttpConnect ( IN HINTERNET hSession, IN LPCWSTR pswzServerName, IN INTERNET_PORT nServerPort, IN DWORD dwReserved ); extern "C" HINTERNET __declspec(dllexport) __stdcall WinHttpOpen( IN LPCWSTR pwszUserAgent, IN DWORD dwAccessType, IN LPCWSTR pwszProxyName OPTIONAL, IN LPCWSTR pwszProxyBypass OPTIONAL, IN DWORD dwFlags ); extern "C" HINTERNET __declspec(dllexport) __stdcall WinHttpOpenRequest( IN HINTERNET hConnect, IN LPCWSTR pwszVerb, IN LPCWSTR pwszObjectName, IN LPCWSTR pwszVersion, IN LPCWSTR pwszReferrer OPTIONAL, IN LPCWSTR FAR * ppwszAcceptTypes OPTIONAL, IN DWORD dwFlags ); extern "C" BOOL __declspec(dllexport) __stdcall WinHttpSendRequest( IN HINTERNET hRequest, IN LPCWSTR pwszHeaders OPTIONAL, IN DWORD dwHeadersLength, IN LPVOID lpOptional OPTIONAL, IN DWORD dwOptionalLength, IN DWORD dwTotalLength, IN DWORD_PTR dwContext ); extern "C" BOOL __declspec(dllexport) __stdcall WinHttpReceiveResponse( IN HINTERNET hRequest, IN LPVOID lpReserved ); extern "C" BOOL __declspec(dllexport) __stdcall WinHttpQueryDataAvailable( IN HINTERNET hRequest, OUT LPDWORD lpdwNumberOfBytesAvailable OPTIONAL ); BOOL m_bUseWinHttp; extern "C" BOOL CPamTaskBar::GrabWinHttpFile(LPCWSTR strServer, LPCWSTR strUrl, CString &strBuffer, LPCWSTR strAgentName); }; #define STATE_NULL 0 #define STATE_UNDOCKED 1 #define STATE_RDSERNR 100 #define STATE_READMODE 101 #define STATE_READCAL_FACTOR 102 #define STATE_STATICMODE 103 #define STATE_READEEP 104 #define STATE_READDAYSCORE 105 #define STATE_READMEDSCORE 106 #define STATE_READHEAVYSCORE 107 #define STATE_UPLOADDATA 108 #define STATE_VERIFYCLK 111 #define STATE_READEEPP0 112 // added by E. Damen for AM102 #define STATE_READEEPP1 113 // added by E. Damen for AM102 #define STATE_READEEPP2 114 // added by E. Damen for AM102 #define STATE_READEEPP3 115 // added by E. Damen for AM102 #define STATE_READDAYSCORE102 116 // added by E. Damen for AM102 #define STATE_READMEDSCORE102 117 // added by E. Damen for AM102 #define STATE_READHEAVYSCORE102 118 // added by E. Damen for AM102 #define STATE_READTODAY 119 // added by E. Damen for AM200 #define STATE_SETMODE 120 // added by E. Damen for AM200 #define STATE_SETAUX 121 // added by E. Damen for AM200 #define STATE_READCLK 200 #define STATE_SETCLK 201 #define STATE_TOGGLEMODE 300 #define STATE_DOCKED 800 ///////////////////////////////////////////////////////////////////////////// // Serial and USB communications. // bool __stdcall CPamTaskBar::ShowError (LONG lError, LPCTSTR lptszMessage, BOOL bShowPopup) { // Generate a message text m_TrayTip = lptszMessage; if ( bShowPopup ) { CString msg; msg.Format(_T("%s\nError code %d"), lptszMessage, lError); // Display message-box and return with an error-code ::MessageBox(0, msg, _T(DRIVER_NAME), MB_ICONSTOP|MB_OK); } TRACE("ERROR: %s (error code %d)\n", lptszMessage, lError); return FALSE; } #ifdef USE_COM_PORTS bool __stdcall CPamTaskBar::OpenComPort() { LONG lLastError = ERROR_SUCCESS; CWinApp* pApp = AfxGetApp(); CString ComPort = pApp->GetProfileString(_T(PAM_VERSION), _T(REG_COM_PORT), _T("COM1")); m_bSkipBreak = TRUE; // Attempt to open the serial port. lLastError = m_serial.Open(ComPort, s_hWnd, WM_NULL, (LPARAM)m_nObjectIndex); if ( lLastError != ERROR_SUCCESS ) return ShowError(m_serial.GetLastError(), _T("Unable to open COM-port"), TRUE); // Setup no handshaking (DTR high, CTS low). lLastError = m_serial.SetupHandshaking(CSerial::EHandshakePam); if ( lLastError != ERROR_SUCCESS ) return ShowError(m_serial.GetLastError(), _T("Unable to set COM-port handshaking"), TRUE); // Setup the serial port (1200,N81). lLastError = m_serial.Setup(CSerial::EBaud1200, CSerial::EData8, CSerial::EParNone, CSerial::EStop1); if ( lLastError != ERROR_SUCCESS ) return ShowError(m_serial.GetLastError(), _T("Unable to set COM-port setting"), TRUE); // Register only for the receive event // lLastError = m_serial.SetMask(CSerial::EEventBreak | CSerial::EEventRecv); lLastError = m_serial.SetMask(CSerial::EEventRecv); if ( lLastError != ERROR_SUCCESS ) return ShowError(m_serial.GetLastError(), _T("Unable to set COM-port event mask"), TRUE); // The serial port is now ready and we can send/receive data. return TRUE; } #else bool __stdcall CPamTaskBar::OpenUSB() { DWORD device = 0, dwNumDevices = 0; SI_STATUS status; status = SI_GetNumDevices(&dwNumDevices); if ( status != SI_SUCCESS || dwNumDevices == 0 ) { return ShowError(status, _T("Undocked"), FALSE); } for (device = 0; device < dwNumDevices; device++) { SI_DEVICE_STRING devStr; // status = SI_GetProductString(device, devStr, SI_RETURN_SERIAL_NUMBER); status = SI_GetProductString(device, devStr, SI_RETURN_VID); if ( status != SI_SUCCESS || strcmp(devStr, "10c4") != 0 ) { continue; } status = SI_GetProductString(device, devStr, SI_RETURN_PID); if ( status != SI_SUCCESS || strcmp(devStr, "82b0") != 0 ) { continue; } // We ondersteunen alleen 1 Pam, en nemen dus altijd de eerste die we vinden. break; // We found one!!! } if ( device >= dwNumDevices ) { // Helaas, er hangen geen Pammetjes aan... return ShowError(status, _T("Undocked"), FALSE); } if ( m_hUSBDevice ) { // Driver already opened return TRUE; } status = SI_Open(device, &m_hUSBDevice); if ( status != SI_SUCCESS ) { return ShowError(status, _T("Error: could not open Pam"), TRUE); } // Setup the serial port (2400) for USB. the old Pam used 1200 baud. status = SI_SetBaudRate(m_hUSBDevice, 2400); if ( status != SI_SUCCESS ) { return ShowError(status, _T("Error: Failed to set baud rate"), TRUE); } // Setup the serial port (N81). status = SI_SetLineControl(m_hUSBDevice, 0x0800); if ( status != SI_SUCCESS ) { return ShowError(status, _T("Error: Failed to set line control"), TRUE); } // Setup no handshaking (DTR high, CTS low). status = SI_SetFlowControl(m_hUSBDevice, /*bCTS_MaskCode */ SI_STATUS_INPUT, /*bRTS_MaskCode */ SI_HELD_INACTIVE, /*bDTR_MaskCode */ SI_HELD_INACTIVE, // SI_HELD_INACTIVE /*bDSRMaskCode */ SI_STATUS_INPUT, /*bDCD_MaskCode */ SI_STATUS_INPUT, /*bFlowXonXoff */ FALSE); if ( status != SI_SUCCESS ) { return ShowError(status, _T("Error: Failed to set flow control"), TRUE); } // Maak reads non-blocking. Write time-out seconde status = SI_SetTimeouts(0, /*DEFAULT_HEARTBEAT * 0.8*/0); if ( status != SI_SUCCESS ) { return ShowError(status, _T("Error: Failed to write timeout Pam"), TRUE); } status = SI_FlushBuffers(m_hUSBDevice, TRUE, TRUE); if ( status != SI_SUCCESS ) { return ShowError(status, _T("Error: Failed to purge Pam"), TRUE); } return TRUE; } #endif #ifdef USE_COM_PORTS bool __stdcall CPamTaskBar::CloseComPort() { LONG lLastError = ERROR_SUCCESS; // Attempt to open the serial port. lLastError = m_serial.Close(); if ( lLastError != ERROR_SUCCESS ) return ShowError(m_serial.GetLastError(), _T("Unable to close COM-port"), TRUE); return TRUE; } #else bool __stdcall CPamTaskBar::CloseUSB() { if ( m_hUSBDevice ) { SI_STATUS status = SI_Close(m_hUSBDevice); if ( status != SI_SUCCESS ) { return ShowError(status, _T("Error: Failed to close Pam"), FALSE); } m_hUSBDevice = 0; } return TRUE; } #endif #ifndef USE_COM_PORTS bool __stdcall CPamTaskBar::PamStillThere() { BYTE PartNum; SI_STATUS status = SI_GetPartNumber (m_hUSBDevice, &PartNum); return status == SI_SUCCESS; } bool __stdcall CPamTaskBar::ReadUSB() { bool DataAvailable; do { if ( m_dwEob >= sizeof m_Buffer ) { m_dwEob = 0; // should not occur, prevent buffer overflow TRACE("\nERROR: ######################### buffer overflow ########################\n"); } DWORD dwBytesRead = 0; SI_STATUS status = SI_Read(m_hUSBDevice, m_Buffer + m_dwEob, sizeof m_Buffer - m_dwEob, &dwBytesRead); if ( status != SI_SUCCESS ) { ShowError(status, _T("Error: Failed to read Pam"), TRUE); return false; } if ( 0 /* debugging */ ) { unsigned int i; for ( i = 0 ; i < dwBytesRead ; i++ ) TRACE(" [%02x]", m_Buffer[m_dwEob+i]); } m_dwEob += dwBytesRead; DataAvailable = (m_dwEob == sizeof m_Buffer); while ( ProcessMessage() ) {}; } while ( DataAvailable ); return true; } #endif bool __stdcall CPamTaskBar::SendCommand(struct Message *message, BOOL bReading) { #ifdef USE_COM_PORTS long lLastError = m_serial.Write(message->data, message->size); if ( lLastError != ERROR_SUCCESS ) { return ShowError(m_serial.GetLastError(), _T("Unable to send data"), TRUE); } #else DWORD written; // Voorlopig een blocking write. Misschien later asynchroon. SI_STATUS status = SI_Write(m_hUSBDevice, message->data, message->size, &written); if ( status != SI_SUCCESS ) { return ShowError(status, _T("Error: Failed to write to Pam"), TRUE); } #endif CString msg(bReading ? _T("Reading ") : _T("Updating ")); msg += PAM_NAME; NotifyUser(msg, TRUE, FALSE); return TRUE; } bool __stdcall CPamTaskBar::PamGetTime() { CWinApp* pApp = AfxGetApp(); #ifdef USE_COM_PORTS bool sync_clock = pApp->GetProfileInt(_T(PAM_VERSION), _T(REG_SYNC_CLOCK), 1) != 0; #else bool sync_clock = TRUE; #endif if ( sync_clock && m_State != STATE_VERIFYCLK ) { m_Time = CTime::GetCurrentTime(); if ( m_State == STATE_READCLK ) { m_State = STATE_SETCLK; TRACE("STATE: SETCLK\n"); } return true; } else { struct Message message; if ( ! MakeGetClockMessage(&message) ) { return ShowError(0, _T("Unable to get time"), TRUE); } return SendCommand(&message, TRUE); } } bool __stdcall CPamTaskBar::PamSetTime() { CWinApp* pApp = AfxGetApp(); // Load the clock setting from the registry. #ifdef USE_COM_PORTS int nClock = pApp->GetProfileInt(_T(PAM_VERSION), _T(REG_CLOCK_MODE), 0); #else int nClock = m_bMilitary ? 0 : 1; #endif struct Message message; m_Time = CTime::GetCurrentTime(); // Voorheen werd dit gedaan in PamGetTime(). Dit wordt niet meer gebruikt. if ( ! MakeSetClockMessage(&message, m_Time.GetHour(), m_Time.GetMinute(), nClock == 0) ) { return ShowError(0, _T("Unable to set time"), TRUE); } return SendCommand(&message, FALSE); } bool __stdcall CPamTaskBar::PamReadMode() { struct Message message; if ( ! MakeReadModeMessage(&message) ) { return ShowError(0, _T("Unable to read mode"), TRUE); } return SendCommand(&message, TRUE); } bool __stdcall CPamTaskBar::PamSetMode(BYTE mode, BYTE key_return) // added by E. Damen for AM200 { struct Message message; if ( ! MakeSetModeMessage(&message, mode, key_return) ) { return ShowError(0, _T("Unable to set mode"), TRUE); } return SendCommand(&message, TRUE); } bool __stdcall CPamTaskBar::PamSetAux(BYTE CalorieperPam) // added by E. Damen for AM200 { struct Message message; if ( ! MakeSetAuxMessage(&message, CalorieperPam) ) { return ShowError(0, _T("Unable to set Calorie per Pam unit"), TRUE); } return SendCommand(&message, TRUE); } /* bool CPamTaskBar::PamStaticMode() { struct Message message; CWinApp* pApp = AfxGetApp(); if ( ! MakeSetModeMessage(&message, m_PamMode | BIT_MODE_INTEGRATOR) ) { return ShowError(0, _T("Unable to set static mode"), TRUE); } return SendCommand(&message, TRUE); } bool CPamTaskBar::PamReadDockingDate() { struct Message message; if ( ! MakeReadDockingDateMessage(&message) ) { return ShowError(0, _T("Unable to read docking date"), TRUE); } return SendCommand(&message, TRUE); } bool CPamTaskBar::PamToggleMode() { struct Message message; CWinApp* pApp = AfxGetApp(); if ( ! MakeSetModeMessage(&message, m_PamMode ^ BIT_MODE_PAM_MODE) ) { return ShowError(0, _T("Unable to set mode"), TRUE); } return SendCommand(&message, TRUE); } */ bool __stdcall CPamTaskBar::PamReadToday() { struct Message message; if ( ! MakeReadTodayMessage(&message) ) { return ShowError(0, _T("Unable to read today"), TRUE); } return SendCommand(&message, TRUE); } bool __stdcall CPamTaskBar::PamReadEepromPage0(BYTE key_return) // added by E. Damen for AM102 { struct Message message; if ( ! MakeReadEepromPage0Message(&message, key_return) ) { return ShowError(0, _T("Unable to read eeprom"), TRUE); } return SendCommand(&message, TRUE); } bool __stdcall CPamTaskBar::PamReadEepromPage1(BYTE key_return) // added by E. Damen for AM102 { struct Message message; if ( ! MakeReadEepromPage1Message(&message, key_return) ) { return ShowError(0, _T("Unable to read eeprom"), TRUE); } return SendCommand(&message, TRUE); } bool __stdcall CPamTaskBar::PamReadEepromPage2(BYTE key_return) // added by E. Damen for AM102 { struct Message message; if ( ! MakeReadEepromPage2Message(&message, key_return) ) { return ShowError(0, _T("Unable to read eeprom"), TRUE); } return SendCommand(&message, TRUE); } bool __stdcall CPamTaskBar::PamReadEepromPage3(BYTE key_return) // added by E. Damen for AM102 { struct Message message; if ( ! MakeReadEepromPage3Message(&message, key_return) ) { return ShowError(0, _T("Unable to read eeprom"), TRUE); } return SendCommand(&message, TRUE); } bool __stdcall CPamTaskBar::PamReadCalibrationFactor() { struct Message message; if ( ! MakeReadCalibrationFactorMessage(&message) ) { return ShowError(0, _T("Unable to read calibration factor"), TRUE); } return SendCommand(&message, TRUE); } bool __stdcall CPamTaskBar::PamReadSerialNumber() { struct Message message; if ( ! MakeReadSerialNumberMessage(&message) ) { return ShowError(0, _T("Unable to read serial number"), TRUE); } return SendCommand(&message, TRUE); } bool __stdcall CPamTaskBar::PamReadRam(UINT address) { struct Message message; if ( ! MakeReadRamMessage(&message, address) ) { return ShowError(0, _T("Unable to read ram"), TRUE); } return SendCommand(&message, TRUE); } CString GetValueByKey(CString strBuffer, CString strKeyword) { strKeyword += ": "; int pos = strBuffer.Find(strKeyword); if ( pos != -1 ) { return strBuffer.Mid(pos + strKeyword.GetLength()).SpanExcluding("\n\r"); } else { return ""; } } BOOL __stdcall CPamTaskBar::GrabWinHttpFile(LPCWSTR strServer, LPCWSTR strUrl, CString &strBuffer, LPCWSTR strAgentName) { DWORD dwSize = 0; DWORD dwDownloaded = 0; LPSTR pszOutBuffer; BOOL bResults = FALSE; HINTERNET hSession = NULL, hConnect = NULL, hRequest = NULL; hSession = CPamTaskBar::WinHttpOpen( strAgentName, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0 /*synchrone*/ ); // Specify an HTTP server. if ( hSession ) hConnect = CPamTaskBar::WinHttpConnect( hSession, strServer, INTERNET_DEFAULT_HTTP_PORT, 0 ); // Create an HTTP request handle. if( hConnect ) hRequest = CPamTaskBar::WinHttpOpenRequest( hConnect, L"GET", strUrl, NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_REFRESH ); // Send a request. if( hRequest ) { bResults = CPamTaskBar::WinHttpSendRequest( hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, /* voor een post*/ 0, 0 ); } // End the request. if( bResults ) bResults = CPamTaskBar::WinHttpReceiveResponse( hRequest, NULL ); // Keep checking for data until there is nothing left. if( bResults ) { do { // Check for available data. dwSize = 0; bResults = CPamTaskBar::WinHttpQueryDataAvailable( hRequest, &dwSize ); if( ! bResults ) TRACE( "Error %u in WinHttpQueryDataAvailable.\n", GetLastError( ) ); // Allocate space for the buffer. pszOutBuffer = new char[dwSize+1]; if( !pszOutBuffer ) { TRACE( "Out of memory\n" ); bResults = FALSE; } else { // Read the data. ZeroMemory( pszOutBuffer, dwSize+1 ); if( !CPamTaskBar::WinHttpReadData( hRequest, (LPVOID)pszOutBuffer, dwSize, &dwDownloaded ) ) { TRACE( "Error %u in WinHttpReadData.\n", GetLastError( ) ); bResults = FALSE; } else { strBuffer += pszOutBuffer; } // Free the memory allocated to the buffer. delete [] pszOutBuffer; } } while( dwSize > 0 && bResults ); } if ( ! bResults ) { TRACE( "Error %u in GrabWinHttpFile.\n", GetLastError( ) ); } return bResults; } bool __stdcall CPamTaskBar::PamUploadData() { CWinApp* pApp = AfxGetApp(); NotifyUser(_T("Uploading data"), TRUE, FALSE); // Build the upload URL and add all Pam data to it. CString strServerUrl; strServerUrl.Format(_T(UPLOAD_PAGE "?software=%u&firmware=%u&sn=%u&days=%d&tz=%d&config=%u&ds=%u&living=%u&health=%u&sports=%u&distance=%u&fruit=%u"), (VERSION_MAJOR << 8) | VERSION_MINOR, (m_VersionNumber.Major << 16) | (m_VersionNumber.Minor << 8) | (m_VersionNumber.Build << 0), m_SerialNumber, m_Size, /*_timezone*/ _get_timezone, m_Config, m_PamDayScore16, m_PamLowScore, m_PamMedScore, m_PamHighScore, m_PamDistanceTD, m_PamFruitTD ); // strServerUrl += "&eep="; // The rest of the routine is written by E. Damen for AM102. // Because a URL has a maximum length of 2023 bytes and the numbers of days in AM102 // in scientific mode is 4 times larger, data has to be compressed to fit in the URL for ( UINT day = 0 ; day < m_Size ; day++ ) { CString strData; // long int code = m_Pam[day] *16777216; // code += m_LightActivity[day]*65536; // code += m_MediumActivity[day]*256; // code += m_HeavyActivity[day]; strData.Format(_T("&q[]=%06x%08x"), m_code2[day],m_code1[day]); strServerUrl += strData; } // m_State = STATE_READCLK; // TRACE("STATE: READCLK\n"); m_State = STATE_SETMODE; TRACE("STATE: SETMODE\n"); // if ( ::MessageBox(0, msg, _T("Pam mode"), MB_OKCANCEL|MB_ICONWARNING) != IDOK ) CString message; do { INT_PTR rc = 0; CURL url; #ifdef USE_ONE_WAY_COM rc = url.Open(_T("http://" + SITE_SERVER + strServerUrl, false); #else // Connect to the upload server and expect the redirection URL back. CString strBuffer; BOOL bUploadedData; if ( !m_bUseWinHttp ) { bUploadedData = GrabWinHttpFile(CT2CW(SITE_SERVER), CT2CW( (LPCTSTR) strServerUrl), strBuffer, CT2CW(PAM_NAME " " PAM_VERSION)); } else { bUploadedData = GrabWininetFile(_T("http://" SITE_SERVER) + strServerUrl, strBuffer, _T(PAM_NAME " " PAM_VERSION)); } if ( bUploadedData ) { // Parseer het van de server verkregen resultaat. Ondermeer de URL die we moeten tonen. CString strKeyword; strKeyword = GetValueByKey(strBuffer, "Calorie"); m_CalorieperPam = atoi(strKeyword); strKeyword = GetValueByKey(strBuffer, "MilitaryClock"); m_bMilitary = atoi(strKeyword); strKeyword = GetValueByKey(strBuffer, "Paid"); m_UpdateDockDay = atoi(strKeyword); strKeyword = GetValueByKey(strBuffer, "Location"); if ( strKeyword != "" ) { TRACE("INFO: launching %s\n", strKeyword); //strKeyword = "url:" + strKeyword; //::ShellExecute(NULL, NULL, strKeyword, NULL, NULL, SW_SHOWNORMAL); rc = url.Open(strKeyword, false); // if ( m_State == STATE_UPLOADINGDATA ) { // m_State = STATE_READCLK; // TRACE("STATE: READCLK\n"); // } // } else if ( m_State == STATE_UPLOADINGDATA ) { // m_State = STATE_READCLK; // TRACE("STATE: READCLK\n"); } } #endif if ( rc > 32 ) break; // No error, continue. message.Format(_T("Could not connect to the %s web site.\n\nMake sure that you have a working internet connection. In case you installed a firewall, make sure it allows the %s to access the internet.\n(error code %d)"), PAM_NAME, DRIVER_NAME, rc); } while ( ::MessageBox(0, message, _T(DRIVER_NAME), MB_ICONWARNING|MB_RETRYCANCEL) == IDRETRY); // Added by E. Damen for AM200: information comes back from server: 1) paid or not paid // 2) Calories per Pam unit // if paid then m_UpdateDockDay = 1 else m_UpdateDockDay=0 // Calories per Pam unit should be stored in m_CalorieperPam m_PamMode = (m_PamMode & 0xFE) + m_UpdateDockDay; // Added by E. Damen for AM200 return true; } void __stdcall CPamTaskBar::StartHeartbeat() { CWinApp* pApp = AfxGetApp(); #ifdef USE_COM_PORTS m_Heartbeat = pApp->GetProfileInt(_T(PAM_VERSION), _T(REG_HEARTBEAT), DEFAULT_HEARTBEAT); #else m_Heartbeat = DEFAULT_HEARTBEAT; #endif SetTimer(s_hWnd, // hWnd of the Taskbar Applet 1, // Timer identifier m_Heartbeat, // Timeout value in order to give the PAM time to process (TIMERPROC)m_nObjectIndex); // identifier of the taskbar instance TRACE("INFO: timer started (%u ms)\n", m_Heartbeat); } bool __stdcall CPamTaskBar::InitInstance(LPSTR lpCmdLine) { _tzset(); // Sets time environment variables. // http://groups.google.com/groups?q=CWnd::FindWindow&hl=nl&lr=&ie=UTF-8&selm=34353492.1572921%40msnews.microsoft.com&rnum=1 // http://groups.google.com/groups?q=CWnd::FindWindow&hl=nl&lr=&ie=UTF-8&selm=8psnq1%24oco%241%40fe1.cs.interbusiness.it&rnum=10 HANDLE hMutex = CreateMutex(NULL, FALSE, _T("MutexToEnforceSinglePamDriver")); if ( GetLastError() == ERROR_ALREADY_EXISTS ) { return FALSE; // Leave quietly the application } m_DiscardInput = FALSE; /* CWinApp* pApp = AfxGetApp(); pApp->SetRegistryKey(COMPANY_NAME); */ m_TrayTip = _T(DRIVER_NAME); m_SerialNumber = m_Config = 0; m_pProgressDlg = NULL; m_State = STATE_NULL; TRACE("STATE: NULL\n"); m_bSkipBreak = TRUE; #ifdef USE_COM_PORTS if ( OpenComPort() ) { m_State = STATE_UNDOCKED; m_SerialNumber = m_Config = 0; TRACE("STATE: UNDOCKED\n"); } #endif // Bepaal of we WinHTTP kunnen gebruiken /* SystemInfo sysInfo; if ( sysInfo.GetMajorVersion() < 5 ) { // Windows ME en ouder ondersteunen geen WinHttp m_bUseWinHttp = FALSE; } else { switch ( sysInfo.GetMinorVersion() ) { case 0: // Windows 2000, SP 3 ondersteunt WinHttp m_bUseWinHttp = sysInfo.GetServicePackMajor() >= 3; break; case 1: // Windows XP, SP 1 ondersteunt WinHttp m_bUseWinHttp = sysInfo.GetServicePackMajor() >= 1; break; default: // Nieuwere OSsen m_bUseWinHttp = TRUE; break; } } */ // Nu gaan we proberen om de WinHttp.dll dynamisch te laden. Als dat lukt: // - zetten we m_bUseWinHttp op TRUE; // - halen we de adressen op van de WinHttp functies. HINSTANCE hHandle; hHandle = ::LoadLibrary("WINHTTP.DLL"); if ( hHandle != NULL ) { FWinHttpReadData = (TFWinHttpReadData)::GetProcAddress(hHandle, _T("WinHttpReadData")); FWinHttpConnect = (TFWinHttpConnect)::GetProcAddress(hHandle, _T("WinHttpConnect")); FWinHttpOpen = (TFWinHttpOpen)::GetProcAddress(hHandle, _T("WinHttpOpen")); FWinHttpOpenRequest = (TFWinHttpOpenRequest)::GetProcAddress(hHandle, _T("WinHttpOpenRequest")); FWinHttpSendRequest = (TFWinHttpSendRequest)::GetProcAddress(hHandle, _T("WinHttpSendRequest")); FWinHttpReceiveResponse = (TFWinHttpReceiveResponse)::GetProcAddress(hHandle, _T("WinHttpReceiveResponse")); FWinHttpQueryDataAvailable = (TFWinHttpQueryDataAvailable)::GetProcAddress(hHandle, _T("WinHttpQueryDataAvailable")); } m_bUseWinHttp = hHandle != NULL && FWinHttpReadData != NULL && FWinHttpConnect != NULL && FWinHttpOpen != NULL && FWinHttpOpenRequest != NULL && FWinHttpSendRequest != NULL && FWinHttpReceiveResponse != NULL && FWinHttpQueryDataAvailable != NULL; ASSERT(s_hWnd != NULL); StartHeartbeat(); return TRUE; } BOOL __stdcall CPamTaskBar::WinHttpReadData ( IN HINTERNET hRequest, IN LPVOID lpBuffer, IN DWORD dwNumberOfBytesToRead, OUT LPDWORD lpdwNumberOfBytesRead ) { ASSERT(FWinHttpReadData != NULL); if (FWinHttpReadData) return FWinHttpReadData(hRequest,lpBuffer,dwNumberOfBytesToRead,lpdwNumberOfBytesRead); return FALSE; } HINTERNET __stdcall CPamTaskBar::WinHttpConnect ( IN HINTERNET hSession, IN LPCWSTR pswzServerName, IN INTERNET_PORT nServerPort, IN DWORD dwReserved ) { ASSERT(FWinHttpConnect != NULL); if (FWinHttpConnect) return FWinHttpConnect(hSession,pswzServerName,nServerPort,dwReserved); return FALSE; } HINTERNET __stdcall CPamTaskBar::WinHttpOpen( IN LPCWSTR pwszUserAgent, IN DWORD dwAccessType, IN LPCWSTR pwszProxyName OPTIONAL, IN LPCWSTR pwszProxyBypass OPTIONAL, IN DWORD dwFlags ) { ASSERT(FWinHttpOpen != NULL); if (FWinHttpOpen) return FWinHttpOpen(pwszUserAgent,dwAccessType,pwszProxyName,pwszProxyBypass,dwFlags); return FALSE; } HINTERNET __stdcall CPamTaskBar::WinHttpOpenRequest( IN HINTERNET hConnect, IN LPCWSTR pwszVerb, IN LPCWSTR pwszObjectName, IN LPCWSTR pwszVersion, IN LPCWSTR pwszReferrer OPTIONAL, IN LPCWSTR FAR * ppwszAcceptTypes OPTIONAL, IN DWORD dwFlags ) { ASSERT(FWinHttpOpenRequest != NULL); if (FWinHttpOpenRequest) return FWinHttpOpenRequest(hConnect,pwszVerb,pwszObjectName,pwszVersion,pwszReferrer,ppwszAcceptTypes,dwFlags); return FALSE; } BOOL __stdcall CPamTaskBar::WinHttpSendRequest( IN HINTERNET hRequest, IN LPCWSTR pwszHeaders OPTIONAL, IN DWORD dwHeadersLength, IN LPVOID lpOptional OPTIONAL, IN DWORD dwOptionalLength, IN DWORD dwTotalLength, IN DWORD_PTR dwContext ) { ASSERT(FWinHttpSendRequest != NULL); if (FWinHttpSendRequest) return FWinHttpSendRequest(hRequest,pwszHeaders,dwHeadersLength,lpOptional,dwOptionalLength,dwTotalLength,dwContext); return FALSE; } BOOL __stdcall CPamTaskBar::WinHttpReceiveResponse( IN HINTERNET hRequest, IN LPVOID lpReserved ){ ASSERT(FWinHttpReceiveResponse != NULL); if (FWinHttpReceiveResponse) return FWinHttpReceiveResponse(hRequest,lpReserved); return FALSE; } BOOL __stdcall CPamTaskBar::WinHttpQueryDataAvailable( IN HINTERNET hRequest, OUT LPDWORD lpdwNumberOfBytesAvailable OPTIONAL ) { ASSERT(FWinHttpQueryDataAvailable != NULL); if (FWinHttpQueryDataAvailable) return FWinHttpQueryDataAvailable(hRequest,lpdwNumberOfBytesAvailable); return FALSE; } ///////////////////////////////////////////////////////////////////////////// // Instantiate the CPamTaskBar applet. // CPamTaskBar theApplet; ///////////////////////////////////////////////////////////////////////////// // Define the methods of CPamTaskBar. // void __stdcall CPamTaskBar::OnTimerMessage(WPARAM wParam) { m_DiscardInput = FALSE; /* Start from scratch */ TRACE("heartbeat: counter=%d\n", m_TimeOut); #ifndef USE_COM_PORTS if ( m_State == STATE_NULL ) { if ( OpenUSB() ) { NotifyUser(_T("Pam found"), FALSE, TRUE); m_PamMode = -1; m_State = STATE_UNDOCKED; TRACE("STATE: UNDOCKED\n"); } } else if ( m_State == STATE_DOCKED ) { // Kijk of de Pam er nog steeds aanhangt if ( ! PamStillThere() ) { CloseUSB(); m_State = STATE_NULL; TRACE("STATE: NULL\n"); NotifyUser(_T("Undocked"), FALSE, TRUE); } } else { // Kijk of er iets op te halen is. Vanwege de heartbeat, mag deze polling. if ( ReadUSB() ) { m_TimeOut = BREAK_RETRY * 1000 / m_Heartbeat + 1; // always round up } } #endif switch ( m_State ) { case STATE_UNDOCKED: // Hier mogen we eigenlijk niet meer komen met de USB variant... m_TimeOut = MSG_RETRY; /* Start counting from now. */ m_State = STATE_RDSERNR; TRACE("STATE: RDSERNR\n"); // Fall through case STATE_RDSERNR: PamReadSerialNumber(); break; // case STATE_READMODE: // PamReadMode(); // break; // case STATE_STATICMODE: // PamStaticMode(); // break; // case STATE_READCAL_FACTOR: // PamReadCalibrationFactor(); // break; // case STATE_READEEP: // PamReadEeprom(); // break; case STATE_READEEPP0: // added by E. Damen for AM102 PamReadEepromPage0(m_Key_return); break; case STATE_READEEPP1: // added by E. Damen for AM102 PamReadEepromPage1(m_Key_return); break; case STATE_READEEPP2: // added by E. Damen for AM102 PamReadEepromPage2(m_Key_return); break; case STATE_READEEPP3: // added by E. Damen for AM102 PamReadEepromPage3(m_Key_return); break; case STATE_UPLOADDATA: PamUploadData(); break; // case STATE_READDAYSCORE: // PamReadRam(RAM_DAYSCORE); // break; // case STATE_READMEDSCORE: // PamReadRam(RAM_MEDSCORE); // break; // case STATE_READHEAVYSCORE: // PamReadRam(RAM_HEAVYSCORE); // break; // case STATE_READDAYSCORE102: // added by E. Damen for AM102 // PamReadRam(RAM_DAYSCORE102); // break; // case STATE_READMEDSCORE102: // added by E. Damen for AM102 // PamReadRam(RAM_MEDSCORE102); // break; // case STATE_READHEAVYSCORE102: // added by E. Damen for AM102 // PamReadRam(RAM_HEAVYSCORE102); // break; case STATE_READTODAY: // added for AM200 PamReadToday(); break; // case STATE_TOGGLEMODE: // PamToggleMode(); // break; case STATE_SETMODE: // added for AM200 to set UpdateDockDay PamSetMode(m_PamMode, m_Key_return); break; case STATE_SETAUX: // added for AM200 to set Calories per Pam unit PamSetAux(m_CalorieperPam); break; case STATE_VERIFYCLK: case STATE_READCLK: PamGetTime(); break; case STATE_SETCLK: PamSetTime(); break; } /* Check the time out. */ if ( m_State != STATE_NULL && m_State != STATE_UNDOCKED && m_State != STATE_DOCKED && m_TimeOut-- == 0 ) { // We didn't get an event on time. Reset state to undocked. if ( m_State == STATE_DOCKED ) { NotifyUser(_T("Undocked"), FALSE, TRUE); } else { CString msg(_T("Could not synchronize " PAM_NAME "...")); NotifyUser(msg, FALSE, TRUE); } m_State = STATE_UNDOCKED; m_SerialNumber = m_Config = 0; TRACE("STATE: UNDOCKED\n"); } } void __stdcall CPamTaskBar::NotifyUser(CString strMsg, BOOL bShow, BOOL bReset) { if ( m_pProgressDlg == NULL ) { m_pProgressDlg = new ProgressDlg; m_pProgressDlg->Create(IDD_PROGRESS); m_pProgressDlg->m_ctlProgressBar.SetRange(0,12); m_pProgressDlg->m_ctlProgressBar.SetStep(1); m_pProgressDlg->m_ctlProgressBar.SetPos(0); m_pProgressDlg->SetIcon(LoadIcon(::AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_ICONBIG)), TRUE); m_pProgressDlg->m_bDismissed = FALSE; } if ( m_pProgressDlg != NULL ) { m_pProgressDlg->m_strProgress = strMsg; m_pProgressDlg->UpdateData(FALSE); m_pProgressDlg->SetWindowText(strMsg); if ( bReset ) { m_pProgressDlg->m_ctlProgressBar.SetPos(0); m_pProgressDlg->m_bDismissed = FALSE; } else { m_pProgressDlg->m_ctlProgressBar.StepIt(); } if ( ! m_pProgressDlg->m_bDismissed ) { m_pProgressDlg->ShowWindow(bShow ? SW_SHOW : SW_HIDE); } } m_TrayTip = strMsg; UpdateShellInfo(); } void __stdcall CPamTaskBar::ProcessBreak() { if ( m_State == STATE_UNDOCKED ) { if ( m_bSkipBreak ) { m_bSkipCounter += 1; if (m_bSkipCounter == 2) { m_bSkipBreak = FALSE;} } else { // m_dwEob = 0; /* Flush the message buffer. */ m_TimeOut = MSG_RETRY; /* Start counting from now. */ m_State = STATE_RDSERNR; // Always first determine Pam version! TRACE("STATE: RDSERNR\n"); } } else if ( m_State == STATE_DOCKED ) { m_TimeOut = BREAK_RETRY * 1000 / m_Heartbeat + 1; // always round up } } void __stdcall CPamTaskBar::OnSerialMessage(WPARAM wParam) // Deze functie wordt aangeroepen indien er seriele communicatie binnenkomt. // In geval van een USB device, wordt dit niet gebruikt. { # ifdef USE_COM_PORTS const CSerialWnd::EEvent eEvent = CSerialWnd::EEvent(LOWORD(wParam)); const CSerialWnd::EError eError = CSerialWnd::EError(HIWORD(wParam)); if ( eEvent & CSerialWnd::EEventBreak ) { TRACE("\nRECEIVE: hardware break\n"); } if ( eEvent & CSerialWnd::EEventRecv ) { bool DataAvailable; do { // Read data from the COM-port DWORD dwBytesRead = 0; if ( m_dwEob >= sizeof m_Buffer ) { m_dwEob = 0; // should not occur, prevent buffer overflow TRACE("\nERROR: ######################### buffer overflow ########################\n"); } long lLastError = m_serial.Read(m_Buffer + m_dwEob, sizeof m_Buffer - m_dwEob, &dwBytesRead); if ( FALSE /* debugging */ ) { unsigned int i; for ( i = 0 ; i < dwBytesRead ; i++ ) TRACE(" [%02x]", m_Buffer[m_dwEob+i]); } m_dwEob += dwBytesRead; if ( lLastError != ERROR_SUCCESS ) { ShowError(m_serial.GetLastError(), _T("Unable to read from COM-port."), TRUE); return; } DataAvailable = (m_dwEob == sizeof m_Buffer); while ( ProcessMessage() ) {}; } while ( DataAvailable ); } if ( eEvent & CSerialWnd::EEventError ) { switch ( eError ) { case CSerial::EErrorBreak: TRACE("\nERROR: serial break condition\n"); break; case CSerial::EErrorFrame: TRACE("\nERROR: serial framing error\n"); break; case CSerial::EErrorIOE: TRACE("\nERROR: serial IO device error\n"); break; case CSerial::EErrorMode: TRACE("\nERROR: serial unsupported mode\n"); break; case CSerial::EErrorOverrun: TRACE("\nERROR: serial buffer overrun\n"); break; case CSerial::EErrorRxOver: TRACE("\nERROR: serial input buffer overflow\n"); break; case CSerial::EErrorParity: TRACE("\nERROR: serial input parity error\n"); break; case CSerial::EErrorTxFull: TRACE("\nERROR: serial output buffer full\n"); break; default: TRACE("\nERROR: serial %d\n", eError); break; } } #endif } BOOL __stdcall CPamTaskBar::ProcessMessage() { if ( m_DiscardInput ) { if ( m_dwEob > 0 ) { TRACE("\nERROR: %d bytes dropped\n", m_dwEob); } m_dwEob = 0; return false; } while ( m_dwEob > 0 && m_Buffer[0] == 0x00 ) { memmove(m_Buffer + 1, m_Buffer, --m_dwEob); TRACE("\nRECEIVE: software break\n"); ProcessBreak(); } if ( m_dwEob < 5 ) { return false; // Partial (or empty) message, wait for more. } BYTE Length = m_Buffer[2]; BYTE Command = m_Buffer[1]; BYTE Checksum = 0; if ( m_Buffer[0] != PAM_STX ) { TRACE("\nERROR: ##################### STX missing (0x%02x) #####################\n", PAM_STX); m_DiscardInput = TRUE; return true; } if ( Length > 170 || Length < 5 ) { TRACE("##################### bad length (%d) #######################", Length); m_DiscardInput = TRUE; return true; } if ( m_dwEob < Length ) { return false; // Partial message, wait for more. } TRACE("["); { unsigned int i; for ( i = 0 ; i < m_dwEob ; i++ ) TRACE("%02x", m_Buffer[i]); } TRACE("] "); for ( int i = 0 ; i < Length - 2 ; i++ ) { Checksum += m_Buffer[i]; } if ( m_Buffer[Length - 2] != Checksum ) { if ( m_VersionNumber.Major == 0 && m_VersionNumber.Minor == 1 && (Command == ACK_READCLK || Command == ACK_READMODE) ) { // Work around Pam bug: ignore checksum failure } else if ( m_VersionNumber.Major == 0 && m_VersionNumber.Minor == 2 && Command == ACK_READEEP ) { // Work around a new Pam bug: ignore checksum failure } else { TRACE("\nERROR: ##################### Checksum failure ##################### \n"); m_DiscardInput = TRUE; return true; } } if ( m_Buffer[Length - 1] != PAM_EOT ) { TRACE("\nERROR: ##################### EOT missing (0x%0x) #####################\n", m_Buffer[Length - 1]); if ( (m_VersionNumber.Major == 1 && m_VersionNumber.Minor == 0) || (m_VersionNumber.Major == 0) ) { if ( Command == ACK_READEEP ) { // Work around a new Pam bug: reset timer on checksum failure m_TimeOut = MSG_RETRY; /* Start counting from now. */ } } m_DiscardInput = TRUE; return true; } // Now we have a properly formatted message layout. So reset the passed-out counter. m_TimeOut = MSG_RETRY; switch ( Command ) { case NACK: // Negative acknowledgment, ignore it. Our app will retry in a second. TRACE("\nRECEIVE: NACK\n"); break; /* case ACK_READRAM: switch ( (m_Buffer[3] << 8) | m_Buffer[4] ) { case RAM_DAYSCORE: { m_PamDayScore16 = m_Buffer[5]; TRACE("\nRECEIVE: ack READDAYSCORE: %u\n", m_PamDayScore16); m_State = STATE_READMEDSCORE; TRACE("STATE: READMEDSCORE\n"); break; } case RAM_MEDSCORE: { m_PamMedScore = (m_Buffer[6] << 8) | m_Buffer[5]; TRACE("\nRECEIVE: ack READMEDSCORE: %u\n", m_PamMedScore); m_State = STATE_READHEAVYSCORE; TRACE("STATE: READHEAVYSCORE\n"); break; } case RAM_HEAVYSCORE: // changed by E. Damen for AM102 { if (m_VersionNumber.Major == 1 && m_VersionNumber.Minor < 3) { m_PamHighScore = (m_Buffer[6] << 8) | m_Buffer[5]; } else { m_PamHighScore = (m_Buffer[6] & 0xF0 << 4) | (m_Buffer[5] & 0x0F << 4) | (m_Buffer[5] & 0xF0 >> 4); } TRACE("\nRECEIVE: ack READHEAVYSCORE: %u\n", m_PamHighScore); m_State = STATE_UPLOADDATA; TRACE("STATE: UPLOADDATA\n"); break; } case RAM_DAYSCORE102: // added by E. Damen for AM102 { m_PamDayScore16 = m_Buffer[5]; TRACE("\nRECEIVE: ack READDAYSCORE: %u\n", m_PamDayScore16); m_State = STATE_READMEDSCORE102; TRACE("STATE: READMEDSCORE102\n"); break; } case RAM_MEDSCORE102: // added by E. Damen for AM102 { m_PamMedScore = (m_Buffer[6] & 0xF0 << 4) | (m_Buffer[5] & 0x0F << 4) | (m_Buffer[5] & 0xF0 >> 4); TRACE("\nRECEIVE: ack READMEDSCORE: %u\n", m_PamMedScore); m_State = STATE_READHEAVYSCORE102; TRACE("STATE: READHEAVYSCORE102\n"); break; } default: { TRACE("\nRECEIVE: ack READRAM unexpected address: 0x%04x\n", (m_Buffer[3] << 8) | m_Buffer[4]); break; } } break; */ case ACK_RDSERNR: // Erik Damen: changed for AM200 // m_Buffer contains unsigned values, so shifting is safe. // MSB and LSB swapped according to new specs m_SerialNumber = m_Buffer[6] | (m_Buffer[5] << 8) | (m_Buffer[4] << 16) | (m_Buffer[3] << 24); m_VersionNumber.Major = m_Buffer[7]; m_VersionNumber.Minor = m_Buffer[8]; m_VersionNumber.Build = m_Buffer[9]; m_Key = m_Buffer[10] ; m_Key_return = m_Key ^ 0xAA ; // key encryption for AM200 secured commands (^ means XOR) TRACE("\nRECEIVE: ack RDSERNR 0x%08x, version %d.%d.%d, key %d\n", m_SerialNumber, m_VersionNumber.Major, m_VersionNumber.Minor, m_VersionNumber.Build, m_Key); if ( m_State == STATE_RDSERNR ) { m_State = STATE_READEEPP0; // Erik Damen: changed state machine TRACE("STATE: READEEPP0\n"); } break; case ACK_READTODAY: // Erik Damen: added for AM200 m_PamDayScore16 = m_Buffer[3] + ((m_Buffer[4]&0x1F)<<8); m_PamLowScore = ((m_Buffer[4]&0xE0)>>5) + (m_Buffer[5]<<3); m_PamMedScore = m_Buffer[6] + ((m_Buffer[7]&0x03)<<8); m_PamHighScore = ((m_Buffer[7]&0xFC)>>2) + ((m_Buffer[8]&0x03)<<6); m_PamDistanceTD = ((m_Buffer[8]&0xFC)>>2) + ((m_Buffer[9]&0x0F)<<6); m_PamFruitTD = ((m_Buffer[9]&0xF0)>>4); TRACE("\nRECEIVE: ack READTODAY %d\n", m_PamDayScore16 >> 4); if ( m_State == STATE_READTODAY ) { m_State = STATE_UPLOADDATA; // Erik Damen: changed state machine TRACE("STATE: UPLOADDATA\n"); } break; case ACK_READMODE: TRACE("\nRECEIVE: ack READMODE\n"); /* m_PamMode = m_Buffer[3]; m_ConsumerMode = (m_PamMode & BIT_MODE_PAM_MODE) == BIT_MODE_CONSUMER; TRACE("\nRECEIVE: ack %s 0x%02x (%s)\n", m_State == STATE_READMODE ? "READMODE" : "SETMODE", m_PamMode, m_ConsumerMode ? "consumer" : "scientific"); if ( m_State == STATE_READMODE || m_State == STATE_STATICMODE ) { if ( (m_PamMode & BIT_MODE_INTEGRATOR) == 0 && m_VersionNumber.Major == 1 && m_VersionNumber.Minor < 3) { TRACE("WARNING: Pam in dynamic mode!\n"); m_State = STATE_STATICMODE; TRACE("STATE: STATICMODE\n"); } else { if (m_VersionNumber.Major == 1 && m_VersionNumber.Minor == 3) { m_State = STATE_READEEPP0;} else { m_State = STATE_READEEP;} TRACE("STATE: READEEP\n"); } } else if ( m_State == STATE_TOGGLEMODE ) { m_Fifo = 0x10; m_State = STATE_READCLK; TRACE("STATE: READCLK\n"); } */ m_State = STATE_SETAUX; TRACE("STATE: SETAUX\n"); break; case ACK_READAUX: TRACE("\nRECEIVE: ack READAUX\n"); m_State = STATE_SETCLK; TRACE("STATE: STATE_SETCLK\n"); break; case ACK_READCAL_FACTOR: // m_Buffer contains unsigned values, so shifting is safe. m_GainAdjustMultiplier = m_Buffer[3]; m_GainAdjustDivider = m_Buffer[4]; m_TresholdLight = m_Buffer[5] | (m_Buffer[6] << 8); m_TresholdHeavy = m_Buffer[7] | (m_Buffer[8] << 8); TRACE("\nRECEIVE: ack READCL_FACTOR mult=%d, div=%d, light=%d, heavy=%d\n", m_GainAdjustMultiplier, m_GainAdjustDivider, m_TresholdLight, m_TresholdHeavy); if ( m_State == STATE_READCAL_FACTOR ) { //m_State = STATE_READDOCKINGDATE; TRACE("STATE: READDOCKINGDATE\n"); } break; case ACK_READADDRESS: TRACE("\nWARNING : SHOULD NOT OCCUR!\n"); if ( m_Buffer[3] == ADDRESS_FIFO && m_Buffer[4] == m_Fifo /*&& m_State == STATE_SETDOCKINGDATE */ ) { TRACE("\nRECEIVE: ack SETFIFO\n"); m_Size = 0; m_State = STATE_READCLK; TRACE("STATE: READCLK\n"); } else { TRACE("\nRECEIVE: ack READADDRESS not asked for!"); TRACE(" (0x%02x, 0x%02x)\n", m_Buffer[3], m_Buffer[4]); } break; case ACK_READCLK: if ( m_State == STATE_VERIFYCLK ) { if ( m_Buffer[3] != m_Time.GetMinute() || m_Buffer[4] != m_Time.GetHour() ) { TRACE("\nRECEIVE: ack READCLK, nok!!!"); m_State = STATE_SETCLK; TRACE("STATE: SETCLK"); break; } } if ( m_State == STATE_READCLK ) { m_Time = CTime(2000, 1, 1, m_Buffer[4], m_Buffer[3], 0, 0); TRACE("\nRECEIVE: ack READCLK %d:%02d\n", m_Buffer[4], m_Buffer[3]); m_State = STATE_SETCLK; TRACE("STATE: SETCLK\n"); } else if ( m_State == STATE_SETCLK ) { TRACE("\nRECEIVE: ack SETCLK\n"); CString msg(_T(" docked")); msg = PAM_NAME + msg; NotifyUser(msg, FALSE, TRUE); // NotifyUser(_T("Pam docked"), FALSE, TRUE); m_State = STATE_DOCKED; TRACE("STATE: DOCKED\n"); m_TimeOut = IDLE_RETRY * 1000 / m_Heartbeat + 1; /* Start counting from now. Within x seconds we expect a break signal. */ } else if ( m_State == STATE_VERIFYCLK ) { TRACE("\nRECEIVE: ack READCLK, ok\n"); CString msg(_T(" docked")); msg = PAM_NAME + msg; NotifyUser(msg, FALSE, TRUE); // NotifyUser(_T("Pam docked"), FALSE, TRUE); m_State = STATE_DOCKED; TRACE("STATE: DOCKED\n"); m_TimeOut = IDLE_RETRY * 1000 / m_Heartbeat + 1; /* Start counting from now. Within x seconds we expect a break signal. */ } else { TRACE("\nRECEIVE: ack READCLK not asked for!\n"); } break; } if (m_VersionNumber.Major == 1 && m_VersionNumber.Minor < 3) // changed by E. Damen for AM102 {switch ( Command ) { case ACK_READEEP: { BYTE *Eeprom = m_Buffer + 3; m_Fifo = Eeprom[0x0f]; TRACE("\nRECEIVE: ack READEEP "); m_Config = Eeprom[0x0a] | (Eeprom[0x09] << 8) | (Eeprom[0x08] << 16) | (Eeprom[0x07] << 24); if ( ! m_ConsumerMode ) { _ASSERTE((m_Fifo - 0x10) % RAM_BYTES_PER_DAY == 0); } m_Size = 0; UINT Fifo = m_Fifo; do { m_Pam[m_Size] = Eeprom[Fifo++]; if ( ! m_ConsumerMode ) { m_LightActivity[m_Size] = (Eeprom[Fifo + 1] << 8) | Eeprom[Fifo]; Fifo += 2; m_MediumActivity[m_Size] = (Eeprom[Fifo + 1] << 8) | Eeprom[Fifo]; Fifo += 2; m_HeavyActivity[m_Size] = (Eeprom[Fifo + 1] << 8) | Eeprom[Fifo]; Fifo += 2; } if ( Fifo >= 0x80 ) Fifo = 0x10; // Modulo de geheugen grootte. TRACE("%d ", m_Pam[m_Size]); m_Size++; } while ( Fifo != m_Fifo ); TRACE("\n%d days, fifo=0x%02x\n", m_Size, m_Fifo); if ( m_State == STATE_READEEP ) { m_State = STATE_READDAYSCORE; TRACE("STATE: READDAYSCORE\n"); } break; } }} else {switch ( Command ) { case ACK_READEEPPAGE0: { BYTE *Eeprom = m_Buffer + 3; for (int i=0;i<128;i++) { Eepromt[i] = m_Buffer[i+3];} TRACE("\nRECEIVE: ack READEEPPAGE0 "); // m_Fifo = Eeprom[0x0f] +256*Eeprom[0x10]; // fifo is 2 bytes long in AM102 // // TRACE("\nm_Fifo = %d ",m_Fifo); // // m_Config = Eeprom[0x0a] | (Eeprom[0x09] << 8) | (Eeprom[0x08] << 16) | (Eeprom[0x07] << 24); m_Fifo = (Eeprom[0x30] - 1) * RAM_BYTES_PER_DAY + RAM_START_DAY_ADDR; // Today_index times 7 + offset m_PamMode = Eeprom[0x05]; m_Config = Eeprom[0x0B] | (Eeprom[0x07] << 8) | (Eeprom[0x06] << 16) | (Eeprom[0x05] << 24); // for AM200: GCorr, Calories per Pam unit, Last Docking Day Index, Mode setting if ( m_State == STATE_READEEPP0 ) { m_State = STATE_READEEPP1; TRACE("STATE: READEEPPAGE1\n"); } break; } case ACK_READEEPPAGE1: { for (int i=0;i<128;i++) { Eepromt[i+0x80] = m_Buffer[i+3];} TRACE("\nRECEIVE: ack READEEPPAGE1 "); if ( m_State == STATE_READEEPP1 ) { m_State = STATE_READEEPP2; TRACE("STATE: READEEPPAGE2\n"); } break; } case ACK_READEEPPAGE2: { for (int i=0;i<128;i++) { Eepromt[i+0x100] = m_Buffer[i+3];} TRACE("\nRECEIVE: ack READEEPPAGE2 "); if ( m_State == STATE_READEEPP2 ) { m_State = STATE_READEEPP3; TRACE("STATE: READEEPPAGE3\n"); } break; } case ACK_READEEPPAGE3: { for (int i=0;i<128;i++) { Eepromt[i+0x180] = m_Buffer[i+3];} TRACE("\nm_Fifo = %d ",m_Fifo); TRACE("\nRECEIVE: ack READEEPPAGE3 "); if ( ! m_ConsumerMode ) { _ASSERTE((m_Fifo - RAM_START_DAY_ADDR) % RAM_BYTES_PER_DAY == 0); } m_Size = 0; UINT Fifo = m_Fifo; do { m_Pam[m_Size] = Eepromt[Fifo]; // Erik, check dit: // Fifo++; // if ( ! m_ConsumerMode ) // { // m_LightActivity[m_Size] = Eepromt[Fifo]; Fifo++; // m_MediumActivity[m_Size] = Eepromt[Fifo]; Fifo++; // m_HeavyActivity[m_Size] = Eepromt[Fifo]; Fifo++; // } // For the AM200, the day is stored in a different way from the AM102: // Pam Score: 13 bits // Low activity minutes: 11 bits // Medium activity minutes: 10 bits // High activity minutes: 8 bits // Distance: 10 bits // Fruit: 4 bits // m_Pam[m_Size] = Eepromt[Fifo] + (Eepromt[Fifo+1]&0x1F)<<8; // m_LightActivity[m_Size] = (Eepromt[Fifo+1]&0xE0)>>5 + Eepromt[Fifo+2]<<3; // m_MediumActivity[m_Size] = Eepromt[Fifo+3] + (Eepromt[Fifo+4]&0x03)<<8; // m_HeavyActivity[m_Size] = (Eepromt[Fifo+4]&0xFC)>>2 + (Eepromt[Fifo+5]&0x03)<<6; // m_Distance[m_Size] = (Eepromt[Fifo+5]&0xFC)>>2 + (Eepromt[Fifo+6]&0x0F)<<6; // m_Fruit[m_Size] = (Eepromt[Fifo+6]&0xF0)>>4; m_code1[m_Size] = Eepromt[Fifo] + (Eepromt[Fifo+1]<<8) + (Eepromt[Fifo+2]<<16) + (Eepromt[Fifo+3]<<24); m_code2[m_Size] = Eepromt[Fifo+4] + (Eepromt[Fifo+5]<<8) + (Eepromt[Fifo+6]<<16); Fifo = Fifo + RAM_BYTES_PER_DAY; if ( Fifo >= RAM_END_DAY_ADDR ) Fifo = RAM_START_DAY_ADDR; // Modulo memory size m_Size++; } while ( Fifo != m_Fifo ); TRACE("\n%d days, fifo=0x%02x\n", m_Size, m_Fifo); if ( m_State == STATE_READEEPP3 ) { m_State = STATE_READTODAY; TRACE("STATE: READTODAY\n"); } break; } }} m_dwEob -= Length; return true; } ////////////////////////////////////////////////////////////////// void __stdcall CPamTaskBar::OnLeftDoubleClick() { #ifdef USE_COM_PORTS SettingsDialog(); #else AboutDialog(); #endif } void __stdcall CPamTaskBar::AboutDialog() { CAboutDlg dlgAbout; if ( m_SerialNumber == 0 ) { CString msg; msg.Format(_T("Serial number unknown (%s not docked)"), PAM_NAME); dlgAbout.m_strSerial = msg; } else { int country = m_SerialNumber >> 24; dlgAbout.m_strSerial.Format(IDS_ABOUT_SERIAL_FIRMWARE, m_SerialNumber & 0x00ffffff, country == COUNTRY_US ? " (US)" : (country == COUNTRY_UK ? " (UK)": ""), m_VersionNumber.Major, m_VersionNumber.Minor, m_VersionNumber.Build, PAM_NAME, m_PamDayScore16 >> 4); } if ( m_Config == 0 ) { dlgAbout.m_strConfig = m_bUseWinHttp ? "WinHTTP mode" : "WinINet mode"; } else { dlgAbout.m_strConfig.Format(IDS_ABOUT_CONFIG_FIRMWARE, m_Config, m_bUseWinHttp ? "WinHTTP" : "WinINet"); } CString Msg; Msg.Format(_T("%s Version %d.%d"), DRIVER_NAME, VERSION_MAJOR, VERSION_MINOR); dlgAbout.m_strVersion = Msg; dlgAbout.DoModal(); } /* void CPamTaskBar::SettingsDialog() { //IDC_STATIC_PAMMODE CString Msg; Msg.Format(_T("%s Settings"), DRIVER_NAME); CPropertySheet dlg(Msg); StandardDlg dlgStandard; DebugDlg dlgDebug; CWinApp* pApp = AfxGetApp(); // Load the settings from the registry. CString strComPort = pApp->GetProfileString(_T(PAM_VERSION), _T(REG_COM_PORT), _T("COM1")); LONG nClock = pApp->GetProfileInt(_T(PAM_VERSION), _T(REG_CLOCK_MODE), 0); BOOL bSyncToPC = pApp->GetProfileInt(_T(PAM_VERSION), _T(REG_SYNC_CLOCK), 1) != 0; int nPamMode; if ( m_State != STATE_DOCKED ) { nPamMode = -1; } else if ( ((m_VersionNumber.Major << 16) | (m_VersionNumber.Minor << 8) | (m_VersionNumber.Build << 0)) < 0x010200 ) { // version < 1.2.0 nPamMode = -1; } else { nPamMode = m_ConsumerMode ? 0 : 1; } dlgStandard.m_pSerial = &m_serial; dlgStandard.m_strComPort = strComPort; dlgStandard.m_bSyncToPC = bSyncToPC; dlgStandard.m_nClock = nClock; dlgStandard.m_nPamMode = nPamMode; dlgStandard.m_bModeSwitchAllowed = TRUE; // functie wordt niet gebruikt Msg.Format(_T("%s mode:"), PAM_NAME); dlgStandard.m_PamModeLabel = Msg; dlgDebug.m_strUploadServer = pApp->GetProfileString(_T(PAM_VERSION), _T(REG_SERVER_URL), _T(UPLOAD_URL)); dlgDebug.m_lHeartbeat = pApp->GetProfileInt(_T(PAM_VERSION), _T(REG_HEARTBEAT), DEFAULT_HEARTBEAT); dlg.AddPage(&dlgStandard); if ( pApp->GetProfileInt(_T(PAM_VERSION), _T(REG_GODDESS), 0) != 0 ) { dlg.AddPage(&dlgDebug); } INT_PTR nResponse = dlg.DoModal(); if ( nResponse == IDOK ) { if ( dlgStandard.m_nPamMode != nPamMode ) { CString msg; msg = _T("Are you sure you want to set your "); msg += PAM_NAME; if ( m_ConsumerMode ) { msg += " to Advanced Mode?"; } else { msg += " to Memory Mode?"; } if ( ::MessageBox(0, msg, _T("Pam mode"), MB_OKCANCEL|MB_ICONWARNING) != IDOK ) { // Restore old value dlgStandard.m_nPamMode = nPamMode; } } // Save the settings to the registry. #ifdef USE_COM_PORTS pApp->WriteProfileString(_T(PAM_VERSION), _T(REG_COM_PORT), dlgStandard.m_strComPort); pApp->WriteProfileInt (_T(PAM_VERSION), _T(REG_CLOCK_MODE), dlgStandard.m_nClock); pApp->WriteProfileInt (_T(PAM_VERSION), _T(REG_SYNC_CLOCK), dlgStandard.m_bSyncToPC); pApp->WriteProfileString(_T(PAM_VERSION), _T(REG_SERVER_URL), dlgDebug.m_strUploadServer); pApp->WriteProfileInt (_T(PAM_VERSION), _T(REG_HEARTBEAT), dlgDebug.m_lHeartbeat); #endif if ( dlgDebug.m_lHeartbeat != m_Heartbeat ) { StartHeartbeat(); } # ifdef USE_COM_PORTS if ( dlgStandard.m_strComPort != strComPort || m_State == STATE_NULL ) { // Close the current com port and open the newly selected one. m_State = STATE_NULL; TRACE("STATE: NULL\n"); CloseComPort(); if ( OpenComPort() ) { NotifyUser(_T("Undocked"), TRUE, TRUE); m_State = STATE_UNDOCKED; m_PamMode = -1; TRACE("STATE: UNDOCKED\n"); } } else # endif if ( dlgStandard.m_nPamMode != nPamMode && m_State == STATE_DOCKED ) { // The user has toggled the Pammode setting. m_State = STATE_TOGGLEMODE; TRACE("STATE: TOGGLEMODE\n"); } else if ( dlgStandard.m_bSyncToPC != bSyncToPC && m_State == STATE_DOCKED && dlgStandard.m_bSyncToPC ) { // The user checked the synchronise button, so set the time again. m_State = STATE_READCLK; TRACE("STATE: READCLK\n"); } else if ( dlgStandard.m_nClock != nClock && m_State == STATE_DOCKED ) { // The user has toggled the clock setting, so set the time again. m_State = STATE_READCLK; TRACE("STATE: READCLK\n"); } } else if (nResponse == IDCANCEL) { } } */ LPCTSTR __stdcall CPamTaskBar::GetTrayTip() { return m_TrayTip; } HICON __stdcall CPamTaskBar::GetIcon() { return ::LoadIcon(::AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_ICONSMALL)); } HMENU __stdcall CPamTaskBar::GetMenu() { HMENU hMenu = CreatePopupMenu(); MENUITEMINFO item; memset(&item, 0, sizeof(MENUITEMINFO)); item.cbSize = sizeof(MENUITEMINFO); /////////////////////////////////////// #ifdef USE_COM_PORTS item.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE; item.wID = ID_OPEN; item.fType = MFT_STRING; item.dwTypeData = _T("&Settings"); item.fState = MFS_DEFAULT; InsertMenuItem(hMenu, 0, FALSE, &item); #endif /////////////////////////////////////// item.fMask = MIIM_TYPE | MIIM_ID; item.wID = ID_PAM; item.fType = MFT_STRING; item.dwTypeData = _T("&Open " PAM_NAME " site"); InsertMenuItem(hMenu, 0, FALSE, &item); /////////////////////////////////////// /* item.fMask = MIIM_TYPE | MIIM_ID; item.wID = ID_UPLOAD; item.fType = MFT_STRING; item.dwTypeData = _T("&Upload Data"); InsertMenuItem(hMenu, 0, FALSE, &item); */ /////////////////////////////////////// item.wID = ID_ABOUT; item.fType = MFT_STRING; item.dwTypeData = _T("&About"); #ifdef USE_COM_PORTS item.fMask = MIIM_TYPE | MIIM_ID; #else item.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE; item.fState = MFS_DEFAULT; #endif InsertMenuItem(hMenu, 0, FALSE, &item); /////////////////////////////////////// item.fMask = MIIM_TYPE | MIIM_ID; item.fType = MFT_SEPARATOR; InsertMenuItem(hMenu, 0, FALSE, &item); /////////////////////////////////////// item.wID = ID_CLOSE; item.fType = MFT_STRING; item.dwTypeData = _T("E&xit"); InsertMenuItem(hMenu, 0, FALSE, &item); /////////////////////////////////////// return hMenu; } void __stdcall CPamTaskBar::HandleMenuCommand(int command) { switch (command) { case ID_CLOSE: { CloseApplet(); break; } case ID_ABOUT: { AboutDialog(); break; } case ID_UPLOAD: { if ( m_State == STATE_DOCKED ) { NotifyUser(_T(DRIVER_NAME), TRUE, TRUE); m_State = STATE_NULL; m_PamMode = -1; } else if ( m_State == STATE_NULL ) { #ifdef USE_COM_PORTS CloseComPort(); if ( OpenComPort() ) { NotifyUser(_T("Undocked"), TRUE, TRUE); m_State = STATE_UNDOCKED; //m_State = STATE_RDSERNR; m_PamMode = -1; TRACE("STATE: UNDOCKED\n"); } #else /* CloseUSB(); if ( OpenUSB() ) { NotifyUser(_T("Undocked"), TRUE, TRUE); m_State = STATE_UNDOCKED; //m_State = STATE_RDSERNR; m_PamMode = -1; TRACE("STATE: UNDOCKED\n"); } */ #endif } break; } /* case ID_OPEN: { SettingsDialog(); break; } */ case ID_OPEN: case ID_PAM: { CURL url; url.Open(_T(SITE_URL), false); break; } } }