Merge branch 'master' into release
authorLars Op den Kamp <lars@opdenkamp.eu>
Mon, 6 Feb 2012 14:14:37 +0000 (15:14 +0100)
committerLars Op den Kamp <lars@opdenkamp.eu>
Mon, 6 Feb 2012 14:14:37 +0000 (15:14 +0100)
79 files changed:
.gitignore
COPYING
ChangeLog
debian/changelog
driver/p8usb-cec.cat [new file with mode: 0644]
driver/p8usb-cec.inf [moved from OEM001.inf with 100% similarity]
include/cec.h
include/cecc.h
include/cecloader.h
include/cectypes.h
project/LibCecSharp-dev.snk [deleted file]
project/LibCecSharp.vcproj
project/libCEC.nsi
project/libcec.rc
project/libcec.vcxproj
project/libcec.vcxproj.filters
project/p8-usbcec-driver.nsi [new file with mode: 0644]
project/testclient.rc
project/testclient.vcxproj
project/testclient.vcxproj.filters
src/CecSharpTester/Properties/AssemblyInfo.cs
src/LibCecSharp/AssemblyInfo.cpp
src/LibCecSharp/LibCecSharp.cpp
src/lib/CECProcessor.cpp
src/lib/CECProcessor.h
src/lib/LibCEC.cpp
src/lib/LibCEC.h
src/lib/LibCECC.cpp
src/lib/LibCECDll.cpp
src/lib/Makefile.am
src/lib/adapter/AdapterCommunication.cpp [deleted file]
src/lib/adapter/AdapterCommunication.h
src/lib/adapter/USBCECAdapterCommunication.cpp [new file with mode: 0644]
src/lib/adapter/USBCECAdapterCommunication.h [new file with mode: 0644]
src/lib/adapter/USBCECAdapterDetection.cpp [moved from src/lib/adapter/AdapterDetection.cpp with 97% similarity]
src/lib/adapter/USBCECAdapterDetection.h [moved from src/lib/adapter/AdapterDetection.h with 92% similarity]
src/lib/adapter/USBCECAdapterMessage.h [moved from src/lib/adapter/AdapterMessage.h with 95% similarity]
src/lib/devices/CECAudioSystem.cpp
src/lib/devices/CECAudioSystem.h
src/lib/devices/CECBusDevice.cpp
src/lib/devices/CECBusDevice.h
src/lib/devices/CECPlaybackDevice.cpp
src/lib/devices/CECPlaybackDevice.h
src/lib/devices/CECRecordingDevice.cpp
src/lib/devices/CECRecordingDevice.h
src/lib/devices/CECTV.cpp
src/lib/devices/CECTV.h
src/lib/devices/CECTuner.cpp
src/lib/devices/CECTuner.h
src/lib/implementations/ANCommandHandler.cpp
src/lib/implementations/ANCommandHandler.h
src/lib/implementations/CECCommandHandler.cpp
src/lib/implementations/CECCommandHandler.h
src/lib/implementations/SLCommandHandler.cpp
src/lib/implementations/SLCommandHandler.h
src/lib/implementations/VLCommandHandler.cpp
src/lib/implementations/VLCommandHandler.h
src/lib/platform/os.h
src/lib/platform/posix/os-socket.h [new file with mode: 0644]
src/lib/platform/posix/os-threads.h
src/lib/platform/posix/os-types.h
src/lib/platform/posix/serialport.cpp
src/lib/platform/serialport/serialport.h [deleted file]
src/lib/platform/sockets/serialport.h [new file with mode: 0644]
src/lib/platform/sockets/socket.h [new file with mode: 0644]
src/lib/platform/sockets/tcp.h [new file with mode: 0644]
src/lib/platform/threads/mutex.h
src/lib/platform/threads/threads.h
src/lib/platform/util/StdString.h [moved from src/lib/platform/StdString.h with 99% similarity]
src/lib/platform/util/baudrate.h [moved from src/lib/platform/serialport/baudrate.h with 98% similarity]
src/lib/platform/util/buffer.h [moved from src/lib/platform/buffer.h with 95% similarity]
src/lib/platform/util/timeutils.h [moved from src/lib/platform/timeutils.h with 95% similarity]
src/lib/platform/windows/os-socket.h [new file with mode: 0644]
src/lib/platform/windows/os-threads.h
src/lib/platform/windows/os-types.h
src/lib/platform/windows/serialport.cpp
src/testclient/main.cpp
support/create-driver-installer.cmd [new file with mode: 0644]
support/create-installer.cmd

index 4da907e4f5e469f6fcdbc3fde5f5b5ea514d8932..30608704e16ab0aadf48b5562187f1ae00e9ea27 100644 (file)
@@ -14,6 +14,8 @@
 *.suo
 *.user
 
+/support/sign-binary.cmd
+
 aclocal.m4
 autom4te.cache
 config.guess
diff --git a/COPYING b/COPYING
index 158b31e7ba15b7a48f7a80d64ac1293fdc65576a..d07d89b3f912ec23da397fb040c4399de2fb951e 100644 (file)
--- a/COPYING
+++ b/COPYING
@@ -1,7 +1,7 @@
 /*
  * This file is part of the libCEC(R) library.
  *
- * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
  * libCEC(R) is a original work, containing original code.
  *
  * libCEC(R) is a trademark of Pulse-Eight Limited.
index 49b0e7eebe6e1d8b4232d81fc26c3d67d77b1509..a4f65e1da52ef01533b2d7b6493d1dc1f9bec9ee 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,55 @@
+libcec (1.4-4) unstable; urgency=low
+
+  * changed/added:
+    * added tcp client sockets to lib/platform (WIP)
+    * clean up lib/platform
+    * added: set controlled mode on after opening a connection to the adapter
+      (for firmware v2)
+    * added an IAdapterCommunicationCallback interface an use a callback method
+      to pass newly received cec_commands to CCECProcessor
+    * added "driver only" and "driver + libcec" sections to the installer
+    * added a signed driver
+    * created a separate driver installer, which is included in the libCEC
+      installer. uninstalls the old unsigned version of libCEC and the driver
+      when it's found and installs the new one in C:\Program Files(x86)\
+      Pulse Eight\USB-CEC Adapter.
+    * don't sign development binaries with a temporary key. devs can do that
+      themselves when they want LibCecSharp in the GAC
+  * interface changes:
+    * added SetStreamPath()/cec_set_stream_path_logical()/
+      cec_set_stream_path_physical() to the interface, to send a
+      "set stream path" command over the CEC bus, used to activate another
+      source.
+  * fixed:
+    * transmit 'menu state activated' after the stream path has been set to a
+      device that is handled by libCEC. should fix remote commands not working
+      properly on Panasonic TVs and after another source has been active.
+      bugzid: 233
+    * set the ackmask to 0x0 when trying to find a free logical address
+    * keep trying to reconnect to the com port until the timeout runs out.
+      bugzid: 230
+    * wait 500 ms before trying to retransmit a command. always wait for the
+      result of a transmission in CCECCommandHandler::Transmit()
+    * receive and send full cec_commands, not CCECAdapterMessages in
+      CAdapterCommunication. extract an IAdapterCommunication interface. fixed
+      potentially missed data in CAdapterCommunication
+    * close and delete the connection when the processor thread ends. fixes
+      reconnect after standby (access denied / connection already opened)
+    * don't replace handlers when not initialised, or the primary device's
+      logical addres isn't known yet, which can lead to crashes. don't call
+      handlers directly in CCECProcessor without holding a lock on them
+    * fixed possible crash when command handler were switched while it was
+      being used
+    * keep the mutex locked when calling ReplaceHandlers() in CCECProcessor
+    * win32: also timeout when data is received in SocketRead()
+    * win32: fixed < vista runtime and compilation
+    * win32: ping the adapter and request the firmware version in
+      CUSBCECAdapterCommunication instead of CCECProcesssor. fixes failed
+      libCEC inits
+    * win32: fixed crash on exit in LibCecSharp
+
+ -- Pulse-Eight Packaging <packaging@pulse-eight.com>  Mon, 6 Feb 2012 14:26:00 +0100
+
 libcec (1.4-3) unstable; urgency=low
 
   * fixed:
index 49b0e7eebe6e1d8b4232d81fc26c3d67d77b1509..a4f65e1da52ef01533b2d7b6493d1dc1f9bec9ee 100644 (file)
@@ -1,3 +1,55 @@
+libcec (1.4-4) unstable; urgency=low
+
+  * changed/added:
+    * added tcp client sockets to lib/platform (WIP)
+    * clean up lib/platform
+    * added: set controlled mode on after opening a connection to the adapter
+      (for firmware v2)
+    * added an IAdapterCommunicationCallback interface an use a callback method
+      to pass newly received cec_commands to CCECProcessor
+    * added "driver only" and "driver + libcec" sections to the installer
+    * added a signed driver
+    * created a separate driver installer, which is included in the libCEC
+      installer. uninstalls the old unsigned version of libCEC and the driver
+      when it's found and installs the new one in C:\Program Files(x86)\
+      Pulse Eight\USB-CEC Adapter.
+    * don't sign development binaries with a temporary key. devs can do that
+      themselves when they want LibCecSharp in the GAC
+  * interface changes:
+    * added SetStreamPath()/cec_set_stream_path_logical()/
+      cec_set_stream_path_physical() to the interface, to send a
+      "set stream path" command over the CEC bus, used to activate another
+      source.
+  * fixed:
+    * transmit 'menu state activated' after the stream path has been set to a
+      device that is handled by libCEC. should fix remote commands not working
+      properly on Panasonic TVs and after another source has been active.
+      bugzid: 233
+    * set the ackmask to 0x0 when trying to find a free logical address
+    * keep trying to reconnect to the com port until the timeout runs out.
+      bugzid: 230
+    * wait 500 ms before trying to retransmit a command. always wait for the
+      result of a transmission in CCECCommandHandler::Transmit()
+    * receive and send full cec_commands, not CCECAdapterMessages in
+      CAdapterCommunication. extract an IAdapterCommunication interface. fixed
+      potentially missed data in CAdapterCommunication
+    * close and delete the connection when the processor thread ends. fixes
+      reconnect after standby (access denied / connection already opened)
+    * don't replace handlers when not initialised, or the primary device's
+      logical addres isn't known yet, which can lead to crashes. don't call
+      handlers directly in CCECProcessor without holding a lock on them
+    * fixed possible crash when command handler were switched while it was
+      being used
+    * keep the mutex locked when calling ReplaceHandlers() in CCECProcessor
+    * win32: also timeout when data is received in SocketRead()
+    * win32: fixed < vista runtime and compilation
+    * win32: ping the adapter and request the firmware version in
+      CUSBCECAdapterCommunication instead of CCECProcesssor. fixes failed
+      libCEC inits
+    * win32: fixed crash on exit in LibCecSharp
+
+ -- Pulse-Eight Packaging <packaging@pulse-eight.com>  Mon, 6 Feb 2012 14:26:00 +0100
+
 libcec (1.4-3) unstable; urgency=low
 
   * fixed:
diff --git a/driver/p8usb-cec.cat b/driver/p8usb-cec.cat
new file mode 100644 (file)
index 0000000..5a85256
Binary files /dev/null and b/driver/p8usb-cec.cat differ
similarity index 100%
rename from OEM001.inf
rename to driver/p8usb-cec.inf
index 9e09902fe01aa1e676dcec72f1687846f7c395eb..97e75a46f8e778b7d05471c9ea1e3f58afa81c97 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * This file is part of the libCEC(R) library.
  *
- * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
  * libCEC(R) is an original work, containing original code.
  *
  * libCEC(R) is a trademark of Pulse-Eight Limited.
@@ -350,6 +350,20 @@ namespace CEC
      */
     virtual bool IsActiveSource(cec_logical_address iAddress) = 0;
 
+    /*!
+     * @brief Sets the stream path to the device on the given logical address.
+     * @param iAddress The address to activate.
+     * @return True when the command was sent, false otherwise.
+     */
+    virtual bool SetStreamPath(cec_logical_address iAddress) = 0;
+
+    /*!
+     * @brief Sets the stream path to the device on the given logical address.
+     * @param iPhysicalAddress The address to activate.
+     * @return True when the command was sent, false otherwise.
+     */
+    virtual bool SetStreamPath(uint16_t iPhysicalAddress) = 0;
+
     virtual const char *ToString(const cec_menu_state state) = 0;
     virtual const char *ToString(const cec_version version) = 0;
     virtual const char *ToString(const cec_power_status status) = 0;
index 8c9bc932b82907edcf8936c6f45d31bde95bff6d..dc4b7953e0484c4b773cef9951f5af5bdd3bd250 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * This file is part of the libCEC(R) library.
  *
- * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
  * libCEC(R) is an original work, containing original code.
  *
  * libCEC(R) is a trademark of Pulse-Eight Limited.
@@ -259,6 +259,14 @@ extern DECLSPEC cec_osd_name cec_get_device_osd_name(cec_logical_address iAddres
 
 extern DECLSPEC int cec_enable_physical_address_detection(void);
 
+#ifdef __cplusplus
+extern DECLSPEC int cec_set_stream_path_logical(CEC::cec_logical_address iAddress);
+#else
+extern DECLSPEC int cec_set_stream_path_logical(cec_logical_address iAddress);
+#endif
+
+extern DECLSPEC int cec_set_stream_path_physical(uint16_t iPhysicalAddress);
+
 #ifdef __cplusplus
 };
 #endif
index 1e6d7167710053aa5d5222b87f0748748e849ac1..3e48b26ed16abda5d5c6fc3c02f426100b87dabd 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * This file is part of the libCEC(R) library.
  *
- * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
  * libCEC(R) is an original work, containing original code.
  *
  * libCEC(R) is a trademark of Pulse-Eight Limited.
index 86be2a258e2969fe80e7ff788933e7810a2a8f72..d8376206f31d442dfb6957aa9796e48eda0a77c6 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * This file is part of the libCEC(R) library.
  *
- * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
  * libCEC(R) is an original work, containing original code.
  *
  * libCEC(R) is a trademark of Pulse-Eight Limited.
@@ -73,9 +73,10 @@ namespace CEC {
 #define CEC_POWER_STATE_REFRESH_TIME 30000
 #define CEC_FW_VERSION_UNKNOWN       0xFFFF
 
-#define CEC_DEFAULT_TRANSMIT_TIMEOUT 1000
-#define CEC_DEFAULT_TRANSMIT_WAIT    2000
-#define CEC_DEFAULT_TRANSMIT_RETRIES 1
+#define CEC_DEFAULT_TRANSMIT_RETRY_WAIT 500
+#define CEC_DEFAULT_TRANSMIT_TIMEOUT    1000
+#define CEC_DEFAULT_TRANSMIT_WAIT       2000
+#define CEC_DEFAULT_TRANSMIT_RETRIES    1
 
 #define CEC_MIN_LIB_VERSION          1
 #define CEC_LIB_VERSION_MAJOR        1
@@ -593,6 +594,8 @@ typedef enum cec_adapter_messagecode
   MSGCODE_TRANSMIT_FAILED_TIMEOUT_LINE,
   MSGCODE_FIRMWARE_VERSION,
   MSGCODE_START_BOOTLOADER,
+  MSGCODE_SET_POWERSTATE,
+  MSGCODE_SET_CONTROLLED,
   MSGCODE_FRAME_EOM = 0x80,
   MSGCODE_FRAME_ACK = 0x40,
 } cec_adapter_messagecode;
@@ -873,10 +876,9 @@ typedef struct cec_logical_addresses
 #endif
 } cec_logical_addresses;
 
-
 typedef int (CEC_CDECL* CBCecLogMessageType)(void *param, const CEC::cec_log_message &);
-typedef int (CEC_CDECL* CBCecKeyPressType)(void *param, const cec_keypress &key);
-typedef int (CEC_CDECL* CBCecCommandType)(void *param, const cec_command &command);
+typedef int (CEC_CDECL* CBCecKeyPressType)(void *param, const cec_keypress &);
+typedef int (CEC_CDECL* CBCecCommandType)(void *param, const cec_command &);
 
 typedef struct ICECCallbacks
 {
diff --git a/project/LibCecSharp-dev.snk b/project/LibCecSharp-dev.snk
deleted file mode 100644 (file)
index 859e7bc..0000000
Binary files a/project/LibCecSharp-dev.snk and /dev/null differ
index 40f9eb63c7acd59f148b46c771f09134efab0b5b..081a3a0327750194d69c531f0c6255c2fe8eeb2f 100644 (file)
@@ -71,7 +71,6 @@
                                GenerateDebugInformation="true"
                                AssemblyDebug="1"
                                TargetMachine="1"
-                               KeyFile="$(SolutionDir)LibCecSharp-dev.snk"
                        />
                        <Tool
                                Name="VCALinkTool"
                                LinkIncremental="1"
                                GenerateDebugInformation="true"
                                TargetMachine="1"
-                               KeyFile="$(SolutionDir)LibCecSharp-dev.snk"
                        />
                        <Tool
                                Name="VCALinkTool"
                        <Tool
                                Name="VCLinkerTool"
                                AdditionalDependencies="$(OutDir)libcec.x64.lib"
-                               KeyFile="$(SolutionDir)LibCecSharp-dev.snk"
                        />
                        <Tool
                                Name="VCALinkTool"
index 23f341afd69c169022c092eee8c10a8de271a654..2d73500192f3a4366719e09eed4205f79d1ffe5a 100644 (file)
@@ -1,5 +1,5 @@
 ;libCEC installer
-;Copyright (C) 2011 Pulse-Eight Ltd.
+;Copyright (C) 2012 Pulse-Eight Ltd.
 ;http://www.pulse-eight.com/
 
 !include "MUI2.nsh"
@@ -7,12 +7,12 @@
 !include "LogicLib.nsh"
 !include "x64.nsh"
 
-Name "libCEC"
+Name "Pulse-Eight USB-CEC Adapter"
 OutFile "..\build\libCEC-installer.exe"
 
 XPStyle on
-InstallDir "$PROGRAMFILES\libCEC"
-InstallDirRegKey HKCU "Software\libCEC" ""
+InstallDir "$PROGRAMFILES\Pulse-Eight\USB-CEC Adapter"
+InstallDirRegKey HKLM "Software\Pulse-Eight\USB-CEC Adapter software" ""
 RequestExecutionLevel admin
 Var StartMenuFolder
 
@@ -22,10 +22,11 @@ Var StartMenuFolder
 
 !insertmacro MUI_PAGE_WELCOME
 !insertmacro MUI_PAGE_LICENSE "..\COPYING"
+!insertmacro MUI_PAGE_COMPONENTS
 !insertmacro MUI_PAGE_DIRECTORY
 
-!define MUI_STARTMENUPAGE_REGISTRY_ROOT "HKCU
-!define MUI_STARTMENUPAGE_REGISTRY_KEY "Software\libCEC
+!define MUI_STARTMENUPAGE_REGISTRY_ROOT "HKLM
+!define MUI_STARTMENUPAGE_REGISTRY_KEY "Software\Pulse-Eight\USB-CEC Adapter sofware
 !define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "Start Menu Folder"
 !insertmacro MUI_PAGE_STARTMENU Application $StartMenuFolder  
 
@@ -39,23 +40,87 @@ Var StartMenuFolder
 
 !insertmacro MUI_LANGUAGE "English"
 
-InstType "Full"
+InstType "USB-CEC driver & libCEC"
+InstType "USB-CEC driver only"
+InstType "Full installation"
 
-Section "libCEC" SecLibCEC
+Section "USB-CEC driver" SecDriver
   SetShellVarContext current
   SectionIn RO
-  SectionIn 1 #section is in installtype Full
+  SectionIn 1 2 3
+
+  ; Uninstall the old unsigned software if it's found
+  ReadRegStr $1 HKCU "Software\libCEC" ""
+  ${If} $1 != ""
+    MessageBox MB_OK \
+         "A previous libCEC and USB-CEC driver was found. This update requires the old version to be uninstalled. Press OK to uninstall the old version."
+    ExecWait '"$1\Uninstall.exe" /S _?=$1'
+       Delete "$1\Uninstall.exe"
+       RMDir "$1"
+  ${EndIf}
 
   ; Copy to the installation directory
   SetOutPath "$INSTDIR"
   File "..\AUTHORS"
-  File /x dpinst*.exe "..\build\*.exe"
-  File "..\ChangeLog"
   File "..\COPYING"
+
+  ; Copy the driver installer
+  SetOutPath "$INSTDIR\driver"
+  File "..\build\p8-usbcec-driver-installer.exe"
+
+  ;Store installation folder
+  WriteRegStr HKLM "Software\Pulse-Eight\USB-CEC Adapter software" "" $INSTDIR
+
+  ;Create uninstaller
+  WriteUninstaller "$INSTDIR\Uninstall.exe"
+
+  !insertmacro MUI_STARTMENU_WRITE_BEGIN Application
+  SetOutPath "$INSTDIR"
+
+  CreateDirectory "$SMPROGRAMS\$StartMenuFolder"
+  CreateShortCut "$SMPROGRAMS\$StartMenuFolder\Uninstall Pulse-Eight USB-CEC Adapter software.lnk" "$INSTDIR\Uninstall.exe" \
+    "" "$INSTDIR\Uninstall.exe" 0 SW_SHOWNORMAL \
+    "" "Uninstall Pulse-Eight USB-CEC Adapter software."
+
+  WriteINIStr "$SMPROGRAMS\$StartMenuFolder\Visit Pulse-Eight.url" "InternetShortcut" "URL" "http://www.pulse-eight.com/"
+  !insertmacro MUI_STARTMENU_WRITE_END  
+    
+  ;add entry to add/remove programs
+  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Pulse-Eight USB-CEC Adapter sofware" \
+                 "DisplayName" "Pulse-Eight USB-CEC Adapter software"
+  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Pulse-Eight USB-CEC Adapter sofware" \
+                 "UninstallString" "$INSTDIR\uninstall.exe"
+  WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Pulse-Eight USB-CEC Adapter sofware" \
+                 "NoModify" 1
+  WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Pulse-Eight USB-CEC Adapter sofware" \
+                 "NoRepair" 1
+  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Pulse-Eight USB-CEC Adapter sofware" \
+                 "InstallLocation" "$INSTDIR"
+  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Pulse-Eight USB-CEC Adapter sofware" \
+                 "DisplayIcon" "$INSTDIR\cec-client.exe,0"
+  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Pulse-Eight USB-CEC Adapter sofware" \
+                 "Publisher" "Pulse-Eight Limited"
+  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Pulse-Eight USB-CEC Adapter sofware" \
+                 "HelpLink" "http://www.pulse-eight.com/"
+  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Pulse-Eight USB-CEC Adapter sofware" \
+                 "URLInfoAbout" "http://www.pulse-eight.com"
+
+  ;install driver
+  ExecWait '"$INSTDIR\driver\p8-usbcec-driver-installer.exe" /S'
+  Delete "$INSTDIR\driver\p8-usbcec-driver-installer.exe"
+SectionEnd
+
+Section "libCEC" SecLibCec
+  SetShellVarContext current
+  SectionIn 1 3
+
+  ; Copy to the installation directory
+  SetOutPath "$INSTDIR"
+  File "..\ChangeLog"
   File "..\README"
   File "..\build\*.dll"
   SetOutPath "$INSTDIR\x64"
-  File /nonfatal "..\build\x64\*"
+  File /nonfatal "..\build\x64\*.dll"
 
   ; Copy to XBMC\system
   ReadRegStr $1 HKCU "Software\XBMC" ""
@@ -64,12 +129,6 @@ Section "libCEC" SecLibCEC
        File "..\build\libcec.dll"
   ${EndIf}
 
-  ; Copy the driver installer and .inf file
-  SetOutPath "$INSTDIR\driver"
-  File "..\build\dpinst-amd64.exe"
-  File "..\build\dpinst-x86.exe"
-  File "..\OEM001.inf"
-
   ; Copy the headers
   SetOutPath "$INSTDIR\include"
   File /r /x *.so "..\include\cec*.*"
@@ -80,12 +139,17 @@ Section "libCEC" SecLibCEC
   ${If} ${RunningX64}
     File /nonfatal "..\build\x64\libcec.x64.dll"
   ${EndIf}
+SectionEnd
 
-  ;Store installation folder
-  WriteRegStr HKCU "Software\libCEC" "" $INSTDIR
+Section "CEC debug client" SecCecClient
+  SetShellVarContext current
+  SectionIn 3
 
-  ;Create uninstaller
-  WriteUninstaller "$INSTDIR\Uninstall.exe"
+  ; Copy to the installation directory
+  SetOutPath "$INSTDIR"
+  File /x p8-usbcec-driver-installer.exe "..\build\*.exe"
+  SetOutPath "$INSTDIR\x64"
+  File /nonfatal "..\build\x64\*.exe"
 
   !insertmacro MUI_STARTMENU_WRITE_BEGIN Application
   SetOutPath "$INSTDIR"
@@ -99,40 +163,8 @@ Section "libCEC" SecLibCEC
       "" "$INSTDIR\cec-client.x64.exe" 0 SW_SHOWNORMAL \
       "" "Start the CEC Test client (x64)."
   ${EndIf}
-  CreateShortCut "$SMPROGRAMS\$StartMenuFolder\Uninstall libCEC.lnk" "$INSTDIR\Uninstall.exe" \
-    "" "$INSTDIR\Uninstall.exe" 0 SW_SHOWNORMAL \
-    "" "Uninstall libCEC."
-
-  WriteINIStr "$SMPROGRAMS\$StartMenuFolder\Visit Pulse-Eight.url" "InternetShortcut" "URL" "http://www.pulse-eight.com/"
   !insertmacro MUI_STARTMENU_WRITE_END  
-  
-  
-  ;add entry to add/remove programs
-  WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\libCEC" \
-                 "DisplayName" "libCEC"
-  WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\libCEC" \
-                 "UninstallString" "$INSTDIR\uninstall.exe"
-  WriteRegDWORD HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\libCEC" \
-                 "NoModify" 1
-  WriteRegDWORD HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\libCEC" \
-                 "NoRepair" 1
-  WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\libCEC" \
-                 "InstallLocation" "$INSTDIR"
-  WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\libCEC" \
-                 "DisplayIcon" "$INSTDIR\cec-client.exe,0"
-  WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\libCEC" \
-                 "Publisher" "Pulse-Eight Ltd."
-  WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\libCEC" \
-                 "HelpLink" "http://www.pulse-eight.com/"
-  WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\libCEC" \
-                 "URLInfoAbout" "http://www.pulse-eight.com"
-
-  ;install driver
-  ${If} ${RunningX64}
-       ExecWait '"$INSTDIR\driver\dpinst-amd64.exe" /lm /sa /sw /PATH "$INSTDIR\driver"'
-  ${Else}
-       ExecWait '"$INSTDIR\driver\dpinst-x86.exe" /lm /sa /sw /PATH "$INSTDIR\driver"'
-  ${EndIf}
+    
 SectionEnd
 
 ;--------------------------------
@@ -142,11 +174,6 @@ Section "Uninstall"
 
   SetShellVarContext current
 
-  ${If} ${RunningX64}
-       ExecWait '"$INSTDIR\driver\dpinst-amd64.exe" /u "$INSTDIR\driver\OEM001.inf"'
-  ${Else}
-       ExecWait '"$INSTDIR\driver\dpinst-x64.exe" /u "$INSTDIR\driver\OEM001.inf"'
-  ${EndIf}
   Delete "$INSTDIR\AUTHORS"
   Delete "$INSTDIR\cec*.exe"
   Delete "$INSTDIR\ChangeLog"
@@ -156,25 +183,29 @@ Section "Uninstall"
   Delete "$INSTDIR\x64\*.dll"
   Delete "$INSTDIR\x64\*.lib"
   Delete "$INSTDIR\README"
-  Delete "$INSTDIR\driver\OEM001.inf"
-  Delete "$INSTDIR\driver\dpinst-amd64.exe"
-  Delete "$INSTDIR\driver\dpinst-x86.exe"
+
+  ; Uninstall the driver
+  ReadRegStr $1 HKLM "Software\Pulse-Eight\USB-CEC Adapter driver" ""
+  ${If} $1 != ""
+    ExecWait '"$1\Uninstall.exe" /S _?=$1'
+  ${EndIf}
 
   RMDir /r "$INSTDIR\include"
   Delete "$INSTDIR\Uninstall.exe"
   RMDir /r "$INSTDIR"
+  RMDir "$PROGRAMFILES\Pulse-Eight"
   
   !insertmacro MUI_STARTMENU_GETFOLDER Application $StartMenuFolder
   Delete "$SMPROGRAMS\$StartMenuFolder\CEC Test client.lnk"
   ${If} ${RunningX64}
     Delete "$SMPROGRAMS\$StartMenuFolder\CEC Test client (x64).lnk"
   ${EndIf}
-  Delete "$SMPROGRAMS\$StartMenuFolder\Uninstall libCEC.lnk"
+  Delete "$SMPROGRAMS\$StartMenuFolder\Uninstall Pulse-Eight USB-CEC Adapter software.lnk"
   Delete "$SMPROGRAMS\$StartMenuFolder\Visit Pulse-Eight.url"
-  RMDir "$SMPROGRAMS\$StartMenuFolder"  
-
-  DeleteRegKey HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\libCEC"
-
-  DeleteRegKey /ifempty HKCU "Software\libCEC"
+  RMDir "$SMPROGRAMS\$StartMenuFolder"
 
+  DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Pulse-Eight USB-CEC Adapter sofware"
+  DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Pulse-Eight USB-CEC Adapter driver"
+  DeleteRegKey /ifempty HKLM "Software\Pulse-Eight\USB-CEC Adapter software"
+  DeleteRegKey /ifempty HKLM "Software\Pulse-Eight"
 SectionEnd
index b5e6969cb485588c99f670bfe8044afe8df724f6..da6bd00d95b28a3cf6b842f27da62b121d2c267f 100644 (file)
Binary files a/project/libcec.rc and b/project/libcec.rc differ
index 70231936e635ddb4fdff6cb64fa7d799f6416519..0ca4ccafb3ab20a0f107c9d12ab500fb0e46d127 100644 (file)
@@ -24,8 +24,9 @@
     <ClInclude Include="..\include\cecloader.h" />
     <ClInclude Include="..\include\cectypes.h" />
     <ClInclude Include="..\src\lib\adapter\AdapterCommunication.h" />
-    <ClInclude Include="..\src\lib\adapter\AdapterDetection.h" />
-    <ClInclude Include="..\src\lib\adapter\AdapterMessage.h" />
+    <ClInclude Include="..\src\lib\adapter\USBCECAdapterCommunication.h" />
+    <ClInclude Include="..\src\lib\adapter\USBCECAdapterDetection.h" />
+    <ClInclude Include="..\src\lib\adapter\USBCECAdapterMessage.h" />
     <ClInclude Include="..\src\lib\CECProcessor.h" />
     <ClInclude Include="..\src\lib\devices\CECAudioSystem.h" />
     <ClInclude Include="..\src\lib\devices\CECBusDevice.h" />
     <ClInclude Include="..\src\lib\implementations\SLCommandHandler.h" />
     <ClInclude Include="..\src\lib\implementations\VLCommandHandler.h" />
     <ClInclude Include="..\src\lib\LibCEC.h" />
-    <ClInclude Include="..\src\lib\platform\buffer.h" />
     <ClInclude Include="..\src\lib\platform\os.h" />
-    <ClInclude Include="..\src\lib\platform\serialport\baudrate.h" />
-    <ClInclude Include="..\src\lib\platform\serialport\serialport.h" />
-    <ClInclude Include="..\src\lib\platform\StdString.h" />
+    <ClInclude Include="..\src\lib\platform\sockets\serialport.h" />
+    <ClInclude Include="..\src\lib\platform\sockets\socket.h" />
+    <ClInclude Include="..\src\lib\platform\sockets\tcp.h" />
     <ClInclude Include="..\src\lib\platform\threads\mutex.h" />
     <ClInclude Include="..\src\lib\platform\threads\threads.h" />
-    <ClInclude Include="..\src\lib\platform\timeutils.h" />
+    <ClInclude Include="..\src\lib\platform\util\baudrate.h" />
+    <ClInclude Include="..\src\lib\platform\util\buffer.h" />
+    <ClInclude Include="..\src\lib\platform\util\StdString.h" />
+    <ClInclude Include="..\src\lib\platform\util\timeutils.h" />
+    <ClInclude Include="..\src\lib\platform\windows\os-socket.h" />
     <ClInclude Include="..\src\lib\platform\windows\os-threads.h" />
     <ClInclude Include="..\src\lib\platform\windows\os-types.h" />
+    <ClInclude Include="..\src\lib\platform\windows\stdint.h" />
   </ItemGroup>
   <ItemGroup>
-    <ClCompile Include="..\src\lib\adapter\AdapterCommunication.cpp" />
-    <ClCompile Include="..\src\lib\adapter\AdapterDetection.cpp" />
+    <ClCompile Include="..\src\lib\adapter\USBCECAdapterCommunication.cpp" />
+    <ClCompile Include="..\src\lib\adapter\USBCECAdapterDetection.cpp" />
     <ClCompile Include="..\src\lib\CECProcessor.cpp" />
     <ClCompile Include="..\src\lib\devices\CECAudioSystem.cpp" />
     <ClCompile Include="..\src\lib\devices\CECBusDevice.cpp" />
index 37a07ba87a43669e843baf5efa837f20562876b5..a85f501934f38b3a36245e205f3f472b60a3412b 100644 (file)
@@ -1,9 +1,6 @@
 ï»¿<?xml version="1.0" encoding="utf-8"?>
 <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup>
-    <Filter Include="platform">
-      <UniqueIdentifier>{cc48ddc0-be11-43ec-a805-3a9434f443ed}</UniqueIdentifier>
-    </Filter>
     <Filter Include="exports">
       <UniqueIdentifier>{01b9c84a-dcfe-4bdc-b983-69e3e3929b0f}</UniqueIdentifier>
     </Filter>
     <Filter Include="devices">
       <UniqueIdentifier>{bfc43a58-636d-4c1a-b191-486cb8509c7c}</UniqueIdentifier>
     </Filter>
-    <Filter Include="platform\windows">
-      <UniqueIdentifier>{fa3d5953-d288-45e9-93f4-8419e6b701c7}</UniqueIdentifier>
+    <Filter Include="adapter">
+      <UniqueIdentifier>{51614b77-8a0e-47a8-8500-5beb0fd12d49}</UniqueIdentifier>
     </Filter>
-    <Filter Include="platform\serialport">
-      <UniqueIdentifier>{e3945145-efa2-4393-b201-f50e1e775008}</UniqueIdentifier>
+    <Filter Include="platform">
+      <UniqueIdentifier>{7d05b1b5-e728-4f9e-b78f-d63cac4ded8e}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="platform\sockets">
+      <UniqueIdentifier>{6cfe4bad-ed3a-4a16-8c59-4489089f5fe5}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="platform\util">
+      <UniqueIdentifier>{39a56ebf-ba93-4e7b-bf72-2f57b99a1ee1}</UniqueIdentifier>
     </Filter>
     <Filter Include="platform\threads">
-      <UniqueIdentifier>{38a27e9e-86ad-46f6-a4fb-e1e524267b74}</UniqueIdentifier>
+      <UniqueIdentifier>{be183456-d61e-4283-b642-fe25ed71e9c5}</UniqueIdentifier>
     </Filter>
-    <Filter Include="adapter">
-      <UniqueIdentifier>{51614b77-8a0e-47a8-8500-5beb0fd12d49}</UniqueIdentifier>
+    <Filter Include="platform\windows">
+      <UniqueIdentifier>{65c4a590-4577-40e4-91ad-339e20b99ebe}</UniqueIdentifier>
     </Filter>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\src\lib\CECProcessor.h" />
     <ClInclude Include="..\src\lib\LibCEC.h" />
-    <ClInclude Include="..\src\lib\platform\timeutils.h">
-      <Filter>platform</Filter>
-    </ClInclude>
     <ClInclude Include="..\include\cec.h">
       <Filter>exports</Filter>
     </ClInclude>
     <ClInclude Include="..\src\lib\platform\os.h">
       <Filter>platform</Filter>
     </ClInclude>
-    <ClInclude Include="..\src\lib\platform\windows\os-threads.h">
-      <Filter>platform\windows</Filter>
+    <ClInclude Include="..\src\lib\platform\sockets\serialport.h">
+      <Filter>platform\sockets</Filter>
     </ClInclude>
-    <ClInclude Include="..\src\lib\platform\windows\os-types.h">
-      <Filter>platform\windows</Filter>
+    <ClInclude Include="..\src\lib\platform\sockets\socket.h">
+      <Filter>platform\sockets</Filter>
     </ClInclude>
-    <ClInclude Include="..\src\lib\platform\serialport\baudrate.h">
-      <Filter>platform\serialport</Filter>
+    <ClInclude Include="..\src\lib\platform\sockets\tcp.h">
+      <Filter>platform\sockets</Filter>
     </ClInclude>
-    <ClInclude Include="..\src\lib\platform\serialport\serialport.h">
-      <Filter>platform\serialport</Filter>
+    <ClInclude Include="..\src\lib\platform\util\baudrate.h">
+      <Filter>platform\util</Filter>
+    </ClInclude>
+    <ClInclude Include="..\src\lib\platform\util\buffer.h">
+      <Filter>platform\util</Filter>
+    </ClInclude>
+    <ClInclude Include="..\src\lib\platform\util\StdString.h">
+      <Filter>platform\util</Filter>
+    </ClInclude>
+    <ClInclude Include="..\src\lib\platform\util\timeutils.h">
+      <Filter>platform\util</Filter>
     </ClInclude>
     <ClInclude Include="..\src\lib\platform\threads\mutex.h">
       <Filter>platform\threads</Filter>
     <ClInclude Include="..\src\lib\platform\threads\threads.h">
       <Filter>platform\threads</Filter>
     </ClInclude>
-    <ClInclude Include="..\src\lib\platform\buffer.h">
-      <Filter>platform</Filter>
+    <ClInclude Include="..\src\lib\platform\windows\os-socket.h">
+      <Filter>platform\windows</Filter>
     </ClInclude>
-    <ClInclude Include="..\src\lib\platform\StdString.h">
-      <Filter>platform</Filter>
+    <ClInclude Include="..\src\lib\platform\windows\os-threads.h">
+      <Filter>platform\windows</Filter>
+    </ClInclude>
+    <ClInclude Include="..\src\lib\platform\windows\os-types.h">
+      <Filter>platform\windows</Filter>
+    </ClInclude>
+    <ClInclude Include="..\src\lib\platform\windows\stdint.h">
+      <Filter>platform\windows</Filter>
     </ClInclude>
     <ClInclude Include="..\src\lib\adapter\AdapterCommunication.h">
       <Filter>adapter</Filter>
     </ClInclude>
-    <ClInclude Include="..\src\lib\adapter\AdapterDetection.h">
+    <ClInclude Include="..\src\lib\adapter\USBCECAdapterCommunication.h">
+      <Filter>adapter</Filter>
+    </ClInclude>
+    <ClInclude Include="..\src\lib\adapter\USBCECAdapterDetection.h">
       <Filter>adapter</Filter>
     </ClInclude>
-    <ClInclude Include="..\src\lib\adapter\AdapterMessage.h">
+    <ClInclude Include="..\src\lib\adapter\USBCECAdapterMessage.h">
       <Filter>adapter</Filter>
     </ClInclude>
   </ItemGroup>
       <Filter>devices</Filter>
     </ClCompile>
     <ClCompile Include="..\src\lib\platform\windows\serialport.cpp">
-      <Filter>platform\serialport</Filter>
+      <Filter>platform\windows</Filter>
     </ClCompile>
-    <ClCompile Include="..\src\lib\adapter\AdapterCommunication.cpp">
+    <ClCompile Include="..\src\lib\adapter\USBCECAdapterCommunication.cpp">
       <Filter>adapter</Filter>
     </ClCompile>
-    <ClCompile Include="..\src\lib\adapter\AdapterDetection.cpp">
+    <ClCompile Include="..\src\lib\adapter\USBCECAdapterDetection.cpp">
       <Filter>adapter</Filter>
     </ClCompile>
   </ItemGroup>
diff --git a/project/p8-usbcec-driver.nsi b/project/p8-usbcec-driver.nsi
new file mode 100644 (file)
index 0000000..92ac3ac
--- /dev/null
@@ -0,0 +1,118 @@
+;p8-usbcec-driver installer
+;Copyright (C) 2012 Pulse-Eight Ltd.
+;http://www.pulse-eight.com/
+
+!include "MUI2.nsh"
+!include "nsDialogs.nsh"
+!include "LogicLib.nsh"
+!include "x64.nsh"
+
+Name "Pulse-Eight USB-CEC Adapter"
+OutFile "..\build\p8-usbcec-driver-installer.exe"
+
+XPStyle on
+InstallDir "$PROGRAMFILES\Pulse-Eight\USB-CEC Adapter\driver"
+InstallDirRegKey HKLM "Software\Pulse-Eight\USB-CEC Adapter driver" ""
+RequestExecutionLevel admin
+
+!define MUI_FINISHPAGE_LINK "Visit http://www.pulse-eight.com/ for more information."
+!define MUI_FINISHPAGE_LINK_LOCATION "http://www.pulse-eight.com/"
+!define MUI_ABORTWARNING  
+
+!insertmacro MUI_PAGE_WELCOME
+!insertmacro MUI_PAGE_LICENSE "..\COPYING"
+!insertmacro MUI_PAGE_DIRECTORY
+
+!define MUI_STARTMENUPAGE_REGISTRY_ROOT "HKLM" 
+!define MUI_STARTMENUPAGE_REGISTRY_KEY "Software\Pulse-Eight\USB-CEC Adapter driver" 
+
+!insertmacro MUI_PAGE_INSTFILES
+!insertmacro MUI_PAGE_FINISH
+
+!insertmacro MUI_UNPAGE_WELCOME
+!insertmacro MUI_UNPAGE_CONFIRM
+!insertmacro MUI_UNPAGE_INSTFILES
+!insertmacro MUI_UNPAGE_FINISH
+
+!insertmacro MUI_LANGUAGE "English"
+
+InstType "USB-CEC driver only"
+
+Section "USB-CEC driver" SecDriver
+  SetShellVarContext current
+  SectionIn RO
+  SectionIn 1
+
+  ; Copy to the installation directory
+  SetOutPath "$INSTDIR"
+  File "..\AUTHORS"
+  File "..\COPYING"
+
+  ; Copy the driver installer and .inf file
+  File "..\build\dpinst-amd64.exe"
+  File "..\build\dpinst-x86.exe"
+  File "..\driver\p8usb-cec.inf"
+  File "..\driver\p8usb-cec.cat"
+
+  ;Store installation folder
+  WriteRegStr HKLM "Software\Pulse-Eight\USB-CEC Adapter driver" "" $INSTDIR
+
+  ;Create uninstaller
+  WriteUninstaller "$INSTDIR\Uninstall.exe"
+    
+  ;add entry to add/remove programs
+  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Pulse-Eight USB-CEC Adapter driver" \
+                 "DisplayName" "Pulse-Eight USB-CEC Adapter driver"
+  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Pulse-Eight USB-CEC Adapter driver" \
+                 "UninstallString" "$INSTDIR\uninstall.exe"
+  WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Pulse-Eight USB-CEC Adapter driver" \
+                 "NoModify" 1
+  WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Pulse-Eight USB-CEC Adapter driver" \
+                 "NoRepair" 1
+  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Pulse-Eight USB-CEC Adapter driver" \
+                 "InstallLocation" "$INSTDIR"
+  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Pulse-Eight USB-CEC Adapter driver" \
+                 "Publisher" "Pulse-Eight Limited"
+  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Pulse-Eight USB-CEC Adapter driver" \
+                 "HelpLink" "http://www.pulse-eight.com/"
+  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Pulse-Eight USB-CEC Adapter driver" \
+                 "URLInfoAbout" "http://www.pulse-eight.com"
+
+  ;install driver
+  ${If} ${RunningX64}
+       ExecWait '"$INSTDIR\dpinst-amd64.exe" /lm /sa /sw /PATH "$INSTDIR"'
+  ${Else}
+       ExecWait '"$INSTDIR\dpinst-x86.exe" /lm /sa /sw /PATH "$INSTDIR"'
+  ${EndIf}
+SectionEnd
+
+;--------------------------------
+;Uninstaller Section
+
+Section "Uninstall"
+
+  SetShellVarContext current
+
+  ${If} ${RunningX64}
+       ExecWait '"$INSTDIR\dpinst-amd64.exe" /u "$INSTDIR\p8usb-cec.inf"'
+  ${Else}
+       ExecWait '"$INSTDIR\dpinst-x64.exe" /u "$INSTDIR\p8usb-cec.inf"'
+  ${EndIf}
+  Delete "$INSTDIR\AUTHORS"
+  Delete "$INSTDIR\COPYING"
+  Delete "$INSTDIR\p8usb-cec.inf"
+  Delete "$INSTDIR\p8usb-cec.cat"
+  Delete "$INSTDIR\dpinst-amd64.exe"
+  Delete "$INSTDIR\dpinst-x86.exe"
+
+  RMDir /r "$INSTDIR\include"
+  Delete "$INSTDIR\Uninstall.exe"
+  RMDir /r "$INSTDIR"
+  RMDir "$PROGRAMFILES\Pulse-Eight\USB-CEC Adapter"
+  RMDir "$PROGRAMFILES\Pulse-Eight"
+  
+  DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Pulse-Eight USB-CEC Adapter driver"
+  DeleteRegKey /ifempty HKLM "Software\Pulse-Eight\USB-CEC Adapter driver"
+  DeleteRegKey /ifempty HKLM "Software\Pulse-Eight"
+
+SectionEnd
index 24d3722cc5c2de80fc36d5a6b22846cc5eb44320..f09738fe58d5786494524d69129ca7fae063efd5 100644 (file)
Binary files a/project/testclient.rc and b/project/testclient.rc differ
index 0db6eb2e9d717dba33a74abaddb1ba1d81a6b133..fb1957290a362c2ea309f2c9388f09baa73f1292 100644 (file)
   <ItemGroup>
     <ClInclude Include="..\include\cec.h" />
     <ClInclude Include="..\include\cecloader.h" />
-    <ClInclude Include="..\src\lib\platform\os.h" />
-    <ClInclude Include="..\src\lib\platform\threads\mutex.h" />
-    <ClInclude Include="..\src\lib\platform\threads\threads.h" />
-    <ClInclude Include="..\src\lib\platform\timeutils.h" />
-    <ClInclude Include="..\src\lib\platform\windows\dlfcn-win32.h" />
-    <ClInclude Include="..\src\lib\platform\windows\os-threads.h" />
-    <ClInclude Include="..\src\lib\platform\windows\os-types.h" />
   </ItemGroup>
   <ItemGroup>
-    <ClCompile Include="..\src\lib\platform\windows\dlfcn-win32.cpp" />
     <ClCompile Include="..\src\testclient\main.cpp" />
   </ItemGroup>
   <ItemGroup>
index 45e1fe0ece70c9e6c66d01c962bc453cb0913a59..70acf3d3041ea6202fe042add81dbe2caf3622f8 100644 (file)
@@ -7,12 +7,6 @@
     <Filter Include="platform">
       <UniqueIdentifier>{f08c0a80-22d9-4bdd-90de-b9cf5fa88f99}</UniqueIdentifier>
     </Filter>
-    <Filter Include="platform\threads">
-      <UniqueIdentifier>{fb28e188-b2a5-48d3-9010-b56024b19850}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="platform\windows">
-      <UniqueIdentifier>{a8b22b54-3252-44fb-a499-e42f9bac0e15}</UniqueIdentifier>
-    </Filter>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\include\cec.h">
     <ClInclude Include="..\include\cecloader.h">
       <Filter>exports</Filter>
     </ClInclude>
-    <ClInclude Include="..\src\lib\platform\os.h">
-      <Filter>platform</Filter>
-    </ClInclude>
-    <ClInclude Include="..\src\lib\platform\timeutils.h">
-      <Filter>platform</Filter>
-    </ClInclude>
-    <ClInclude Include="..\src\lib\platform\windows\dlfcn-win32.h">
-      <Filter>platform\windows</Filter>
-    </ClInclude>
-    <ClInclude Include="..\src\lib\platform\windows\os-threads.h">
-      <Filter>platform\windows</Filter>
-    </ClInclude>
-    <ClInclude Include="..\src\lib\platform\windows\os-types.h">
-      <Filter>platform\windows</Filter>
-    </ClInclude>
-    <ClInclude Include="..\src\lib\platform\threads\mutex.h">
-      <Filter>platform\threads</Filter>
-    </ClInclude>
-    <ClInclude Include="..\src\lib\platform\threads\threads.h">
-      <Filter>platform\threads</Filter>
-    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\src\testclient\main.cpp" />
-    <ClCompile Include="..\src\lib\platform\windows\dlfcn-win32.cpp">
-      <Filter>platform\windows</Filter>
-    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="testclient.rc" />
index fb546d460bcaa7ba396094520e64c0cadd1fbeca..6075440fc7da8e10ad5daf2d035a549129e3d696 100644 (file)
@@ -10,7 +10,7 @@ using System.Runtime.InteropServices;
 [assembly: AssemblyConfiguration("")]
 [assembly: AssemblyCompany("Pulse-Eight Ltd.")]
 [assembly: AssemblyProduct("CecSharpClient")]
-[assembly: AssemblyCopyright("Copyright (c) Pulse-Eight Ltd. 2012")]
+[assembly: AssemblyCopyright("Copyright (c) Pulse-Eight Ltd. 2011-2012")]
 [assembly: AssemblyTrademark("")]
 [assembly: AssemblyCulture("")]
 
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
 // You can specify all the values or you can default the Build and Revision Numbers 
 // by using the '*' as shown below:
 // [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.4.2.0")]
-[assembly: AssemblyFileVersion("1.4.2.0")]
+[assembly: AssemblyVersion("1.4.3.0")]
+[assembly: AssemblyFileVersion("1.4.3.0")]
index c030509ae28d029e502f290532569988e1fe996b..0520cc759745090e425a9069b627a723b3c3cd78 100644 (file)
@@ -9,13 +9,12 @@ using namespace System::Security::Permissions;
 [assembly:AssemblyConfigurationAttribute("")];
 [assembly:AssemblyCompanyAttribute("Pulse-Eight Ltd.")];
 [assembly:AssemblyProductAttribute("LibCecSharp")];
-[assembly:AssemblyCopyrightAttribute("Copyright (c) Pulse-Eight Ltd. 2012")];
+[assembly:AssemblyCopyrightAttribute("Copyright (c) Pulse-Eight Ltd. 2011-2012")];
 [assembly:AssemblyTrademarkAttribute("")];
 [assembly:AssemblyCultureAttribute("")];
 
-[assembly:AssemblyVersionAttribute("1.4.2.0")];
+[assembly:AssemblyVersionAttribute("1.4.3.0")];
 
 [assembly:ComVisible(false)];
 [assembly:CLSCompliantAttribute(true)];
 [assembly:SecurityPermission(SecurityAction::RequestMinimum, UnmanagedCode = true)];
-[assembly:AssemblyKeyFile("LibCecSharp-dev.snk")];
index 6b1ba7a10dc7c881386fa34e2b129fb9b7e1a41f..06a98aaedda1fa16c96073da03a12a51d1971589 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the libCEC(R) library.
  *
- * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
  * libCEC(R) is an original work, containing original code.
  *
  * libCEC(R) is a trademark of Pulse-Eight Limited.
@@ -588,7 +588,7 @@ public:
    
    ~LibCecSharp(void)
    {
-     CECDestroy(m_libCec);
+     Close();
      DestroyDelegates();
      m_libCec = NULL;
    }
@@ -596,7 +596,7 @@ public:
 protected:
    !LibCecSharp(void)
    {
-     CECDestroy(m_libCec);
+     Close();
      DestroyDelegates();
      m_libCec = NULL;
    }
@@ -950,6 +950,8 @@ public:
 private:
   void DestroyDelegates()
   {
+    m_bHasCallbacks = false;
+    delete m_callbacks;
     m_logMessageGCHandle.Free();
     m_keypressGCHandle.Free();
     m_commandGCHandle.Free();
index 8c808ae8b390cb20e4461e466d20038d9944a1e3..78d24360b6da344ed7471379b9e7b96ee097c118 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the libCEC(R) library.
  *
- * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
  * libCEC(R) is an original work, containing original code.
  *
  * libCEC(R) is a trademark of Pulse-Eight Limited.
@@ -32,7 +32,7 @@
 
 #include "CECProcessor.h"
 
-#include "adapter/AdapterMessage.h"
+#include "adapter/USBCECAdapterCommunication.h"
 #include "devices/CECBusDevice.h"
 #include "devices/CECAudioSystem.h"
 #include "devices/CECPlaybackDevice.h"
 #include "devices/CECTV.h"
 #include "implementations/CECCommandHandler.h"
 #include "LibCEC.h"
+#include "platform/util/timeutils.h"
 
 using namespace CEC;
 using namespace std;
 using namespace PLATFORM;
 
 CCECProcessor::CCECProcessor(CLibCEC *controller, const char *strDeviceName, cec_logical_address iLogicalAddress /* = CECDEVICE_PLAYBACKDEVICE1 */, uint16_t iPhysicalAddress /* = CEC_DEFAULT_PHYSICAL_ADDRESS*/) :
-    m_bStarted(false),
     m_bInitialised(false),
     m_iHDMIPort(CEC_DEFAULT_HDMI_PORT),
     m_iBaseDevice((cec_logical_address)CEC_DEFAULT_BASE_DEVICE),
-    m_lastInitiator(CECDEVICE_UNKNOWN),
     m_strDeviceName(strDeviceName),
+    m_communication(NULL),
     m_controller(controller),
     m_bMonitor(false),
     m_iStandardLineTimeout(3),
     m_iRetryLineTimeout(3),
     m_iLastTransmission(0)
 {
-  m_communication = new CAdapterCommunication(this);
   m_logicalAddresses.Clear();
   m_logicalAddresses.Set(iLogicalAddress);
   m_types.clear();
@@ -68,19 +67,18 @@ CCECProcessor::CCECProcessor(CLibCEC *controller, const char *strDeviceName, cec
 }
 
 CCECProcessor::CCECProcessor(CLibCEC *controller, const char *strDeviceName, const cec_device_type_list &types) :
-    m_bStarted(false),
     m_bInitialised(false),
     m_iHDMIPort(CEC_DEFAULT_HDMI_PORT),
     m_iBaseDevice((cec_logical_address)CEC_DEFAULT_BASE_DEVICE),
     m_strDeviceName(strDeviceName),
     m_types(types),
+    m_communication(NULL),
     m_controller(controller),
     m_bMonitor(false),
     m_iStandardLineTimeout(3),
     m_iRetryLineTimeout(3),
     m_iLastTransmission(0)
 {
-  m_communication = new CAdapterCommunication(this);
   m_logicalAddresses.Clear();
   for (int iPtr = 0; iPtr < 16; iPtr++)
   {
@@ -117,8 +115,6 @@ CCECProcessor::CCECProcessor(CLibCEC *controller, const char *strDeviceName, con
 
 CCECProcessor::~CCECProcessor(void)
 {
-  m_bStarted = false;
-  m_startCondition.Broadcast();
   StopThread();
 
   delete m_communication;
@@ -132,12 +128,15 @@ bool CCECProcessor::OpenConnection(const char *strPort, uint16_t iBaudRate, uint
 {
   bool bReturn(false);
   CLockObject lock(m_mutex);
-  if (!m_communication)
+  if (m_communication)
   {
-    CLibCEC::AddLog(CEC_LOG_ERROR, "no connection handler found");
-    return bReturn;
+    CLibCEC::AddLog(CEC_LOG_WARNING, "existing connection handler found, deleting it");
+    m_communication->Close();
+    delete m_communication;
   }
 
+  m_communication = new CUSBCECAdapterCommunication(this, strPort, iBaudRate);
+
   /* check for an already opened connection */
   if (m_communication->IsOpen())
   {
@@ -149,44 +148,26 @@ bool CCECProcessor::OpenConnection(const char *strPort, uint16_t iBaudRate, uint
   uint64_t iTarget = iTimeoutMs > 0 ? iNow + iTimeoutMs : iNow + CEC_DEFAULT_TRANSMIT_WAIT;
 
   /* open a new connection */
-  if ((bReturn = m_communication->Open(strPort, iBaudRate, iTimeoutMs)) == false)
-    CLibCEC::AddLog(CEC_LOG_ERROR, "could not open a connection");
-
-  /* try to ping the adapter */
-  bool bPingOk(false);
-  unsigned iPingTry(0), iFwVersionTry(0);
-  uint16_t iFirmwareVersion(CEC_FW_VERSION_UNKNOWN);
-  while ((!bPingOk || iFirmwareVersion == CEC_FW_VERSION_UNKNOWN) && iTarget > iNow)
+  unsigned iConnectTry(0);
+  while (iNow < iTarget && (bReturn = m_communication->Open(this, iTimeoutMs)) == false)
   {
-    if (!bPingOk)
-    {
-      if ((bPingOk = m_communication->PingAdapter()) == false)
-      {
-        CLibCEC::AddLog(CEC_LOG_ERROR, "the adapter did not respond correctly to a ping (try %d)", ++iPingTry);
-        Sleep(500);
-      }
-    }
-
-    if (bPingOk)
-    {
-      if ((iFirmwareVersion = m_communication->GetFirmwareVersion()) == CEC_FW_VERSION_UNKNOWN)
-      {
-        CLibCEC::AddLog(CEC_LOG_ERROR, "the adapter did not respond with a correct firmware version (try %d)", ++iFwVersionTry);
-        Sleep(500);
-      }
-      else
-      {
-        CLibCEC::AddLog(CEC_LOG_NOTICE, "CEC Adapter firmware version: %d", iFirmwareVersion);
-        bReturn = true;
-      }
-    }
-
+    CLibCEC::AddLog(CEC_LOG_ERROR, "could not open a connection (try %d)", ++iConnectTry);
+    Sleep(500);
     iNow = GetTimeMs();
   }
 
+  if (bReturn)
+    CLibCEC::AddLog(CEC_LOG_NOTICE, "connected to the CEC adapter. firmware version = %d", m_communication->GetFirmwareVersion());
+
   return bReturn;
 }
 
+bool CCECProcessor::IsInitialised(void)
+{
+  CLockObject lock(m_mutex);
+  return m_bInitialised;
+}
+
 void CCECProcessor::SetInitialised(bool bSetTo /* = true */)
 {
   CLockObject lock(m_mutex);
@@ -233,7 +214,7 @@ bool CCECProcessor::Start(const char *strPort, uint16_t iBaudRate /* = 38400 */,
       return bReturn;
 
     /* create the processor thread */
-    if (!CreateThread() || !m_startCondition.Wait(m_mutex) || !m_bStarted)
+    if (!CreateThread())
     {
       CLibCEC::AddLog(CEC_LOG_ERROR, "could not create a processor thread");
       return bReturn;
@@ -329,7 +310,7 @@ bool CCECProcessor::ChangeDeviceType(cec_device_type from, cec_device_type to)
     if (previousDevice && newDevice)
     {
       newDevice->SetDeviceStatus(CEC_DEVICE_STATUS_HANDLED_BY_LIBCEC);
-      previousDevice->SetDeviceStatus(CEC_DEVICE_STATUS_UNKNOWN);
+      previousDevice->SetDeviceStatus(CEC_DEVICE_STATUS_NOT_PRESENT);
 
       newDevice->SetCecVersion(previousDevice->GetCecVersion(false));
       previousDevice->SetCecVersion(CEC_VERSION_UNKNOWN);
@@ -402,53 +383,40 @@ bool CCECProcessor::FindLogicalAddresses(void)
 
 void CCECProcessor::ReplaceHandlers(void)
 {
+  CLockObject lock(m_mutex);
+  if (!IsInitialised())
+    return;
   for (uint8_t iPtr = 0; iPtr <= CECDEVICE_PLAYBACKDEVICE3; iPtr++)
     m_busDevices[iPtr]->ReplaceHandler(m_bInitialised);
 }
 
-void *CCECProcessor::Process(void)
+bool CCECProcessor::OnCommandReceived(const cec_command &command)
 {
-  bool                  bParseFrame(false);
-  cec_command           command;
-  CCECAdapterMessage    msg;
+  m_commandBuffer.Push(command);
+  return true;
+}
 
-  {
-    CLockObject lock(m_mutex);
-    m_bStarted = true;
-    CLibCEC::AddLog(CEC_LOG_DEBUG, "processor thread started");
-    m_startCondition.Signal();
-  }
+void *CCECProcessor::Process(void)
+{
+  cec_command command;
+  CLibCEC::AddLog(CEC_LOG_DEBUG, "processor thread started");
 
-  while (!IsStopped())
+  while (!IsStopped() && m_communication->IsOpen())
   {
     ReplaceHandlers();
-    command.Clear();
-    msg.Clear();
-
-    {
-      CLockObject lock(m_mutex);
-      if (m_commandBuffer.Pop(command))
-      {
-        bParseFrame = true;
-      }
-      else if (m_communication->IsOpen() && m_communication->Read(msg, 50))
-      {
-        if ((bParseFrame = (ParseMessage(msg) && !IsStopped())) == true)
-          command = m_currentframe;
-      }
-    }
-
-    if (bParseFrame)
+    if (m_commandBuffer.Pop(command))
       ParseCommand(command);
-    bParseFrame = false;
-
-    Sleep(5);
 
     m_controller->CheckKeypressTimeout();
+    Sleep(5);
   }
 
   if (m_communication)
+  {
     m_communication->Close();
+    delete m_communication;
+    m_communication = NULL;
+  }
 
   return NULL;
 }
@@ -479,6 +447,12 @@ bool CCECProcessor::SetActiveSource(cec_device_type type /* = CEC_DEVICE_TYPE_RE
   {
     bReturn = m_busDevices[addr]->TransmitActiveSource();
 
+    if (bReturn)
+    {
+      m_busDevices[addr]->SetMenuState(CEC_MENU_STATE_ACTIVATED);
+      m_busDevices[addr]->TransmitMenuState(CECDEVICE_TV);
+    }
+
     if (bReturn && (m_busDevices[addr]->GetType() == CEC_DEVICE_TYPE_PLAYBACK_DEVICE ||
         m_busDevices[addr]->GetType() == CEC_DEVICE_TYPE_RECORDING_DEVICE) &&
         m_busDevices[addr]->GetHandler()->SendDeckStatusUpdateOnActiveSource())
@@ -560,7 +534,7 @@ bool CCECProcessor::SetHDMIPort(cec_logical_address iBaseDevice, uint8_t iPort,
 
   m_iBaseDevice = iBaseDevice;
   m_iHDMIPort = iPort;
-  if (!m_bStarted && !bForce)
+  if (!IsRunning() && !bForce)
     return true;
 
   CLibCEC::AddLog(CEC_LOG_DEBUG, "setting HDMI port to %d on device %s (%d)", iPort, ToString(iBaseDevice), (int)iBaseDevice);
@@ -663,6 +637,7 @@ bool CCECProcessor::SetPhysicalAddress(uint16_t iPhysicalAddress, bool bSendUpda
   bool bSendActiveView(false);
   bool bReturn(false);
   cec_logical_addresses sendUpdatesTo;
+  sendUpdatesTo.Clear();
 
   {
     CLockObject lock(m_mutex);
@@ -855,51 +830,23 @@ bool CCECProcessor::IsActiveSource(cec_logical_address iAddress)
 
 bool CCECProcessor::Transmit(const cec_command &data)
 {
-  bool bReturn(false);
-  LogOutput(data);
-
-  CCECAdapterMessage *output = new CCECAdapterMessage(data);
-
-  /* set the number of retries */
-  if (data.opcode == CEC_OPCODE_NONE)
-    output->maxTries = 1;
-  else if (data.initiator != CECDEVICE_BROADCAST)
-    output->maxTries = m_busDevices[data.initiator]->GetHandler()->GetTransmitRetries() + 1;
-
-  bReturn = Transmit(output);
-
-  /* set to "not present" on failed ack */
-  if (output->state == ADAPTER_MESSAGE_STATE_SENT_NOT_ACKED &&
-      output->Destination() != CECDEVICE_BROADCAST)
-    m_busDevices[output->Destination()]->SetDeviceStatus(CEC_DEVICE_STATUS_NOT_PRESENT);
-
-  delete output;
-  return bReturn;
-}
-
-bool CCECProcessor::Transmit(CCECAdapterMessage *output)
-{
-  bool bReturn(false);
-  CLockObject lock(m_mutex);
+  cec_adapter_message_state retVal(ADAPTER_MESSAGE_STATE_UNKNOWN);
   {
-    if (!m_communication)
-      return bReturn;
-
+    CLockObject lock(m_mutex);
+    LogOutput(data);
     m_iLastTransmission = GetTimeMs();
-    m_communication->SetLineTimeout(m_iStandardLineTimeout);
-    output->tries = 0;
-
-    do
-    {
-      if (output->tries > 0)
-        m_communication->SetLineTimeout(m_iRetryLineTimeout);
-      bReturn = m_communication->Write(output);
-    }while (!bReturn && output->transmit_timeout > 0 && output->NeedsRetry() && ++output->tries < output->maxTries);
+    if (!m_communication)
+      return false;
+    uint8_t iMaxTries = m_busDevices[data.initiator]->GetHandler()->GetTransmitRetries() + 1;
+    retVal = m_communication->Write(data, iMaxTries, m_iLineTimeout, m_iRetryLineTimeout);
   }
 
-  m_communication->SetLineTimeout(m_iStandardLineTimeout);
+  /* set to "not present" on failed ack */
+  if (retVal == ADAPTER_MESSAGE_STATE_SENT_NOT_ACKED &&
+      data.destination != CECDEVICE_BROADCAST)
+    m_busDevices[data.destination]->SetDeviceStatus(CEC_DEVICE_STATUS_NOT_PRESENT);
 
-  return bReturn;
+  return retVal == ADAPTER_MESSAGE_STATE_SENT_ACKED;
 }
 
 void CCECProcessor::TransmitAbort(cec_logical_address address, cec_opcode opcode, cec_abort_reason reason /* = CEC_ABORT_REASON_UNRECOGNIZED_OPCODE */)
@@ -915,58 +862,7 @@ void CCECProcessor::TransmitAbort(cec_logical_address address, cec_opcode opcode
   Transmit(command);
 }
 
-bool CCECProcessor::ParseMessage(const CCECAdapterMessage &msg)
-{
-  bool bEom(false);
-  bool bIsError(msg.IsError());
-
-  if (msg.IsEmpty())
-    return bEom;
-
-  switch(msg.Message())
-  {
-  case MSGCODE_FRAME_START:
-    {
-      m_currentframe.Clear();
-      if (msg.Size() >= 2)
-      {
-        m_currentframe.initiator   = msg.Initiator();
-        m_currentframe.destination = msg.Destination();
-        m_currentframe.ack         = msg.IsACK();
-        m_currentframe.eom         = msg.IsEOM();
-      }
-      if (m_currentframe.ack == 0x1)
-      {
-        m_lastInitiator = m_currentframe.initiator;
-        m_busDevices[m_lastInitiator]->GetHandler()->HandlePoll(m_currentframe.initiator, m_currentframe.destination);
-      }
-    }
-    break;
-  case MSGCODE_RECEIVE_FAILED:
-    {
-      if (m_lastInitiator != CECDEVICE_UNKNOWN)
-        bIsError = m_busDevices[m_lastInitiator]->GetHandler()->HandleReceiveFailed();
-    }
-    break;
-  case MSGCODE_FRAME_DATA:
-    {
-      if (msg.Size() >= 2)
-      {
-        m_currentframe.PushBack(msg[1]);
-        m_currentframe.eom = msg.IsEOM();
-      }
-      bEom = msg.IsEOM();
-    }
-    break;
-  default:
-    break;
-  }
-
-  CLibCEC::AddLog(bIsError ? CEC_LOG_WARNING : CEC_LOG_DEBUG, msg.ToString());
-  return bEom;
-}
-
-void CCECProcessor::ParseCommand(cec_command &command)
+void CCECProcessor::ParseCommand(const cec_command &command)
 {
   CStdString dataStr;
   dataStr.Format(">> %1x%1x:%02x", command.initiator, command.destination, command.opcode);
@@ -1429,12 +1325,16 @@ bool CCECProcessor::PingAdapter(void)
 
 void CCECProcessor::HandlePoll(cec_logical_address initiator, cec_logical_address destination)
 {
-  m_busDevices[initiator]->GetHandler()->HandlePoll(initiator, destination);
-  m_lastInitiator = initiator;
+  m_busDevices[initiator]->HandlePoll(destination);
+}
+
+bool CCECProcessor::HandleReceiveFailed(cec_logical_address initiator)
+{
+  return !m_busDevices[initiator]->HandleReceiveFailed();
 }
 
-bool CCECProcessor::HandleReceiveFailed(void)
+bool CCECProcessor::SetStreamPath(uint16_t iPhysicalAddress)
 {
-  return m_lastInitiator != CECDEVICE_UNKNOWN &&
-      !m_busDevices[m_lastInitiator]->GetHandler()->HandleReceiveFailed();
+  // stream path changes are sent by the TV
+  return m_busDevices[CECDEVICE_TV]->GetHandler()->TransmitSetStreamPath(iPhysicalAddress);
 }
index 140911a7022a828628171e67574febac6703706d..c21110d29568080039a5942c14c18147d973ccdb 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * This file is part of the libCEC(R) library.
  *
- * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
  * libCEC(R) is an original work, containing original code.
  *
  * libCEC(R) is a trademark of Pulse-Eight Limited.
 
 #include <string>
 #include <cectypes.h>
+#include "platform/threads/threads.h"
+#include "platform/util/buffer.h"
 #include "adapter/AdapterCommunication.h"
-#include "platform/os.h"
-
-class CSerialPort;
 
 namespace CEC
 {
   class CLibCEC;
-  class CAdapterCommunication;
+  struct IAdapterCommunication;
   class CCECBusDevice;
 
-  class CCECProcessor : public PLATFORM::CThread
+  class CCECProcessor : public PLATFORM::CThread, public IAdapterCommunicationCallback
   {
     public:
       CCECProcessor(CLibCEC *controller, const char *strDeviceName, cec_logical_address iLogicalAddress = CECDEVICE_PLAYBACKDEVICE1, uint16_t iPhysicalAddress = CEC_DEFAULT_PHYSICAL_ADDRESS);
@@ -54,6 +53,8 @@ namespace CEC
       virtual bool Start(const char *strPort, uint16_t iBaudRate = 38400, uint32_t iTimeoutMs = 10000);
       virtual void *Process(void);
 
+      virtual bool                  OnCommandReceived(const cec_command &command);
+
       virtual bool                  IsMonitoring(void) const { return m_bMonitor; }
       virtual CCECBusDevice *       GetDeviceByPhysicalAddress(uint16_t iPhysicalAddress, bool bRefresh = false) const;
       virtual CCECBusDevice *       GetDeviceByType(cec_device_type type) const;
@@ -73,10 +74,10 @@ namespace CEC
       virtual bool                  IsPresentDeviceType(cec_device_type type);
       virtual uint16_t              GetPhysicalAddress(void) const;
       virtual uint64_t              GetLastTransmission(void) const { return m_iLastTransmission; }
-      virtual bool                  IsStarted(void) const { return m_bStarted; }
       virtual cec_logical_address   GetActiveSource(void);
       virtual bool                  IsActiveSource(cec_logical_address iAddress);
-      virtual bool                  IsInitialised(void) const { return m_bInitialised; }
+      virtual bool                  IsInitialised(void);
+      virtual bool                  SetStreamPath(uint16_t iPhysicalAddress);
 
       virtual bool SetActiveView(void);
       virtual bool SetActiveSource(cec_device_type type = CEC_DEVICE_TYPE_RESERVED);
@@ -114,7 +115,6 @@ namespace CEC
       const char *ToString(const cec_vendor_id vendor);
 
       virtual bool Transmit(const cec_command &data);
-      virtual bool Transmit(CCECAdapterMessage *output);
       virtual void TransmitAbort(cec_logical_address address, cec_opcode opcode, cec_abort_reason reason = CEC_ABORT_REASON_UNRECOGNIZED_OPCODE);
 
       virtual bool ChangeDeviceType(cec_device_type from, cec_device_type to);
@@ -124,7 +124,7 @@ namespace CEC
       virtual bool StartBootloader(void);
       virtual bool PingAdapter(void);
       virtual void HandlePoll(cec_logical_address initiator, cec_logical_address destination);
-      virtual bool HandleReceiveFailed(void);
+      virtual bool HandleReceiveFailed(cec_logical_address initiator);
 
       CCECBusDevice *  m_busDevices[16];
       PLATFORM::CMutex m_transmitMutex;
@@ -144,21 +144,16 @@ namespace CEC
       bool FindLogicalAddressAudioSystem(void);
 
       void LogOutput(const cec_command &data);
-      bool ParseMessage(const CCECAdapterMessage &msg);
-      void ParseCommand(cec_command &command);
+      void ParseCommand(const cec_command &command);
 
-      bool                                m_bStarted;
       bool                                m_bInitialised;
       uint8_t                             m_iHDMIPort;
       cec_logical_address                 m_iBaseDevice;
-      cec_command                         m_currentframe;
       cec_logical_addresses               m_logicalAddresses;
-      cec_logical_address                 m_lastInitiator;
       std::string                         m_strDeviceName;
       cec_device_type_list                m_types;
       PLATFORM::CMutex                    m_mutex;
-      PLATFORM::CCondition                m_startCondition;
-      CAdapterCommunication*              m_communication;
+      IAdapterCommunication *             m_communication;
       CLibCEC*                            m_controller;
       bool                                m_bMonitor;
       PLATFORM::SyncedBuffer<cec_command> m_commandBuffer;
index 1dd336621ded1c6af8abc99ba8896feb8e87c2e6..7022def6242c824ea837af4cc3ddfcb77bd36eb1 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the libCEC(R) library.
  *
- * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
  * libCEC(R) is an original work, containing original code.
  *
  * libCEC(R) is a trademark of Pulse-Eight Limited.
 
 #include "LibCEC.h"
 
-#include "adapter/AdapterCommunication.h"
-#include "adapter/AdapterDetection.h"
+#include "adapter/USBCECAdapterDetection.h"
 #include "CECProcessor.h"
 #include "devices/CECBusDevice.h"
-#include "platform/timeutils.h"
+#include "platform/util/timeutils.h"
+#include "platform/util/StdString.h"
 
 using namespace std;
 using namespace CEC;
@@ -111,7 +111,7 @@ int8_t CLibCEC::FindAdapters(cec_adapter *deviceList, uint8_t iBufSize, const ch
     strDebug.Format("trying to autodetect all CEC adapters");
   AddLog(CEC_LOG_DEBUG, strDebug);
 
-  return CAdapterDetection::FindAdapters(deviceList, iBufSize, strDevicePath);
+  return CUSBCECAdapterDetection::FindAdapters(deviceList, iBufSize, strDevicePath);
 }
 
 bool CLibCEC::PingAdapter(void)
@@ -435,6 +435,19 @@ void CLibCEC::CheckKeypressTimeout(void)
   }
 }
 
+bool CLibCEC::SetStreamPath(cec_logical_address iAddress)
+{
+  uint16_t iPhysicalAddress = GetDevicePhysicalAddress(iAddress);
+  if (iPhysicalAddress != 0xFFFF)
+    return SetStreamPath(iPhysicalAddress);
+  return false;
+}
+
+bool CLibCEC::SetStreamPath(uint16_t iPhysicalAddress)
+{
+  return m_cec->SetStreamPath(iPhysicalAddress);
+}
+
 static CLibCEC *g_libCEC_instance(NULL);
 CLibCEC *CLibCEC::GetInstance(void)
 {
index 752bae6933f919957ceb2df060d3d0a02ede24ab..6cc2514d561b0df852ad9626c11733b39ab7b653 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * This file is part of the libCEC(R) library.
  *
- * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
  * libCEC(R) is an original work, containing original code.
  *
  * libCEC(R) is a trademark of Pulse-Eight Limited.
@@ -33,7 +33,7 @@
 
 #include <string>
 #include <cec.h>
-#include "platform/os.h"
+#include "platform/util/buffer.h"
 
 namespace CEC
 {
@@ -99,6 +99,8 @@ namespace CEC
       virtual bool EnablePhysicalAddressDetection(void);
       virtual cec_logical_address GetActiveSource(void);
       virtual bool IsActiveSource(cec_logical_address iAddress);
+      virtual bool SetStreamPath(cec_logical_address iAddress);
+      virtual bool SetStreamPath(uint16_t iPhysicalAddress);
 
       const char *ToString(const cec_menu_state state);
       const char *ToString(const cec_version version);
index 91ab395eca5fa61e30657bbede26abb8c4d2757e..3711686e3685e56f907699e1c974f14fde0bf177 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the libCEC(R) library.
  *
- * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
  * libCEC(R) is an original work, containing original code.
  *
  * libCEC(R) is a trademark of Pulse-Eight Limited.
@@ -371,4 +371,14 @@ int cec_enable_physical_address_detection(void)
   return cec_parser ? (cec_parser->EnablePhysicalAddressDetection() ? 1 : 0) : -1;
 }
 
+int cec_set_stream_path_logical(CEC::cec_logical_address iAddress)
+{
+  return cec_parser ? (cec_parser->SetStreamPath(iAddress) ? 1 : 0) : -1;
+}
+
+int cec_set_stream_path_physical(uint16_t iPhysicalAddress)
+{
+  return cec_parser ? (cec_parser->SetStreamPath(iPhysicalAddress) ? 1 : 0) : -1;
+}
+
 //@}
index c7cf9c4db5b3a658e1f46a97ba6428ca008e6db8..819d6093e281a3300ce217fb861b6a948739f41f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the libCEC(R) library.
  *
- * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
  * libCEC(R) is an original work, containing original code.
  *
  * libCEC(R) is a trademark of Pulse-Eight Limited.
index cd20766bbaa11b3fc27a9be65cfa0b2095514619..5df7c60021140b6a677ab0190956f5a8d93d172e 100644 (file)
@@ -11,8 +11,8 @@ pkgconfig_DATA = libcec.pc
 libcec_la_SOURCES = CECProcessor.cpp \
                     LibCEC.cpp \
                     LibCECC.cpp \
-                    adapter/AdapterCommunication.cpp \
-                    adapter/AdapterDetection.cpp \
+                    adapter/USBCECAdapterCommunication.cpp \
+                    adapter/USBCECAdapterDetection.cpp \
                     devices/CECAudioSystem.cpp \
                     devices/CECBusDevice.cpp \
                     devices/CECPlaybackDevice.cpp \
diff --git a/src/lib/adapter/AdapterCommunication.cpp b/src/lib/adapter/AdapterCommunication.cpp
deleted file mode 100644 (file)
index 2bbcb01..0000000
+++ /dev/null
@@ -1,494 +0,0 @@
-/*
- * This file is part of the libCEC(R) library.
- *
- * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
- * libCEC(R) is an original work, containing original code.
- *
- * libCEC(R) is a trademark of Pulse-Eight Limited.
- *
- * This program is dual-licensed; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- *
- * Alternatively, you can license this library under a commercial license,
- * please contact Pulse-Eight Licensing for more information.
- *
- * For more information contact:
- * Pulse-Eight Licensing       <license@pulse-eight.com>
- *     http://www.pulse-eight.com/
- *     http://www.pulse-eight.net/
- */
-
-#include "AdapterCommunication.h"
-
-#include "AdapterMessage.h"
-#include "../CECProcessor.h"
-#include "../platform/serialport/serialport.h"
-#include "../LibCEC.h"
-
-using namespace std;
-using namespace CEC;
-using namespace PLATFORM;
-
-CAdapterCommunication::CAdapterCommunication(CCECProcessor *processor) :
-    m_port(NULL),
-    m_processor(processor),
-    m_iLineTimeout(0),
-    m_iFirmwareVersion(CEC_FW_VERSION_UNKNOWN)
-{
-  m_port = new PLATFORM::CSerialPort;
-}
-
-CAdapterCommunication::~CAdapterCommunication(void)
-{
-  Close();
-
-  if (m_port)
-  {
-    delete m_port;
-    m_port = NULL;
-  }
-}
-
-bool CAdapterCommunication::Open(const char *strPort, uint16_t iBaudRate /* = 38400 */, uint32_t iTimeoutMs /* = 10000 */)
-{
-  uint64_t iNow = GetTimeMs();
-  uint64_t iTimeout = iNow + iTimeoutMs;
-
-  CLockObject lock(m_mutex);
-
-  if (!m_port)
-  {
-    CLibCEC::AddLog(CEC_LOG_ERROR, "port is NULL");
-    return false;
-  }
-
-  if (IsOpen())
-  {
-    CLibCEC::AddLog(CEC_LOG_ERROR, "port is already open");
-    return true;
-  }
-
-  CStdString strError;
-  bool bConnected(false);
-  while (!bConnected && iNow < iTimeout)
-  {
-    if ((bConnected = m_port->Open(strPort, iBaudRate)) == false)
-    {
-      strError.Format("error opening serial port '%s': %s", strPort, m_port->GetError().c_str());
-      Sleep(250);
-      iNow = GetTimeMs();
-    }
-  }
-
-  if (!bConnected)
-  {
-    CLibCEC::AddLog(CEC_LOG_ERROR, strError);
-    return false;
-  }
-
-  CLibCEC::AddLog(CEC_LOG_DEBUG, "connection opened, clearing any previous input and waiting for active transmissions to end before starting");
-
-  //clear any input bytes
-  uint8_t buff[1024];
-  while (m_port->Read(buff, 1024, 100) > 0)
-  {
-    CLibCEC::AddLog(CEC_LOG_DEBUG, "data received, clearing it");
-    Sleep(250);
-  }
-
-  if (CreateThread())
-  {
-    CLibCEC::AddLog(CEC_LOG_DEBUG, "communication thread started");
-    return true;
-  }
-  else
-  {
-    CLibCEC::AddLog(CEC_LOG_ERROR, "could not create a communication thread");
-  }
-
-  return false;
-}
-
-void CAdapterCommunication::Close(void)
-{
-  CLockObject lock(m_mutex);
-  m_rcvCondition.Broadcast();
-  StopThread();
-}
-
-void *CAdapterCommunication::Process(void)
-{
-  while (!IsStopped())
-  {
-    ReadFromDevice(50);
-    Sleep(5);
-    WriteNextCommand();
-  }
-
-  CCECAdapterMessage *msg(NULL);
-  if (m_outBuffer.Pop(msg))
-    msg->condition.Broadcast();
-
-  return NULL;
-}
-
-bool CAdapterCommunication::Write(CCECAdapterMessage *data)
-{
-  bool bReturn(false);
-
-  CLockObject lock(data->mutex);
-  data->state = ADAPTER_MESSAGE_STATE_WAITING_TO_BE_SENT;
-  m_outBuffer.Push(data);
-  data->condition.Wait(data->mutex);
-
-  if (data->state != ADAPTER_MESSAGE_STATE_SENT)
-  {
-    CLibCEC::AddLog(CEC_LOG_ERROR, "command was not sent");
-  }
-  else if (data->expectControllerAck)
-  {
-    bReturn = WaitForAck(*data);
-    if (bReturn)
-    {
-      if (data->isTransmission)
-        data->state = ADAPTER_MESSAGE_STATE_SENT_ACKED;
-    }
-    else
-    {
-      data->state = ADAPTER_MESSAGE_STATE_SENT_NOT_ACKED;
-      CLibCEC::AddLog(CEC_LOG_DEBUG, "did not receive ack");
-    }
-  }
-  else
-  {
-    bReturn = true;
-  }
-
-  return bReturn;
-}
-
-bool CAdapterCommunication::Read(CCECAdapterMessage &msg, uint32_t iTimeout)
-{
-  CLockObject lock(m_mutex);
-
-  msg.Clear();
-  uint64_t iNow = GetTimeMs();
-  uint64_t iTarget = iNow + iTimeout;
-  bool bGotFullMessage(false);
-  bool bNextIsEscaped(false);
-  bool bGotStart(false);
-
-  while(!bGotFullMessage && iNow < iTarget)
-  {
-    uint8_t buf = 0;
-    if (!m_inBuffer.Pop(buf))
-    {
-      if (!m_rcvCondition.Wait(m_mutex, (uint32_t) (iTarget - iNow)))
-        return false;
-    }
-
-    if (!bGotStart)
-    {
-      if (buf == MSGSTART)
-        bGotStart = true;
-      continue;
-    }
-    else if (buf == MSGSTART) //we found a msgstart before msgend, this is not right, remove
-    {
-      if (msg.Size() > 0)
-        CLibCEC::AddLog(CEC_LOG_WARNING, "received MSGSTART before MSGEND, removing previous buffer contents");
-      msg.Clear();
-      bGotStart = true;
-    }
-
-    if (buf == MSGEND)
-    {
-      bGotFullMessage = true;
-    }
-    else if (bNextIsEscaped)
-    {
-      msg.PushBack(buf + (uint8_t)ESCOFFSET);
-      bNextIsEscaped = false;
-    }
-    else if (buf == MSGESC)
-      bNextIsEscaped = true;
-    else
-      msg.PushBack(buf);
-  }
-
-  if (bGotFullMessage)
-    msg.state = ADAPTER_MESSAGE_STATE_INCOMING;
-
-  return bGotFullMessage;
-}
-
-std::string CAdapterCommunication::GetError(void) const
-{
-  return m_port->GetError();
-}
-
-bool CAdapterCommunication::StartBootloader(void)
-{
-  bool bReturn(false);
-  if (!IsRunning())
-    return bReturn;
-
-  CLibCEC::AddLog(CEC_LOG_DEBUG, "starting the bootloader");
-  CCECAdapterMessage *output = new CCECAdapterMessage;
-
-  output->PushBack(MSGSTART);
-  output->PushEscaped(MSGCODE_START_BOOTLOADER);
-  output->PushBack(MSGEND);
-  output->isTransmission = false;
-  output->expectControllerAck = false;
-
-  if ((bReturn = Write(output)) == false)
-    CLibCEC::AddLog(CEC_LOG_ERROR, "could not start the bootloader");
-  delete output;
-
-  return bReturn;
-}
-
-bool CAdapterCommunication::PingAdapter(void)
-{
-  bool bReturn(false);
-  if (!IsRunning())
-    return bReturn;
-
-  CLibCEC::AddLog(CEC_LOG_DEBUG, "sending ping");
-  CCECAdapterMessage *output = new CCECAdapterMessage;
-
-  output->PushBack(MSGSTART);
-  output->PushEscaped(MSGCODE_PING);
-  output->PushBack(MSGEND);
-  output->isTransmission = false;
-
-  if ((bReturn = Write(output)) == false)
-    CLibCEC::AddLog(CEC_LOG_ERROR, "could not ping the adapter");
-  delete output;
-
-  return bReturn;
-}
-
-uint16_t CAdapterCommunication::GetFirmwareVersion(void)
-{
-  uint16_t iReturn(m_iFirmwareVersion);
-  if (!IsRunning())
-    return iReturn;
-
-  if (iReturn == CEC_FW_VERSION_UNKNOWN)
-  {
-    CLibCEC::AddLog(CEC_LOG_DEBUG, "requesting the firmware version");
-    CCECAdapterMessage *output = new CCECAdapterMessage;
-
-    output->PushBack(MSGSTART);
-    output->PushEscaped(MSGCODE_FIRMWARE_VERSION);
-    output->PushBack(MSGEND);
-    output->isTransmission = false;
-    output->expectControllerAck = false;
-
-    SendMessageToAdapter(output);
-    delete output;
-
-    CCECAdapterMessage input;
-    if (!Read(input, CEC_DEFAULT_TRANSMIT_WAIT) || input.Message() != MSGCODE_FIRMWARE_VERSION || input.Size() != 3)
-      CLibCEC::AddLog(CEC_LOG_ERROR, "no or invalid firmware version (size = %d, message = %d)", input.Size(), input.Message());
-    else
-    {
-      m_iFirmwareVersion = (input[1] << 8 | input[2]);
-      iReturn = m_iFirmwareVersion;
-    }
-  }
-
-  return iReturn;
-}
-
-bool CAdapterCommunication::SetLineTimeout(uint8_t iTimeout)
-{
-  bool bReturn(m_iLineTimeout != iTimeout);
-
-  if (!bReturn)
-  {
-    CCECAdapterMessage *output = new CCECAdapterMessage;
-
-    output->PushBack(MSGSTART);
-    output->PushEscaped(MSGCODE_TRANSMIT_IDLETIME);
-    output->PushEscaped(iTimeout);
-    output->PushBack(MSGEND);
-    output->isTransmission = false;
-
-    if ((bReturn = Write(output)) == false)
-      CLibCEC::AddLog(CEC_LOG_ERROR, "could not set the idletime");
-    delete output;
-  }
-
-  return bReturn;
-}
-
-bool CAdapterCommunication::SetAckMask(uint16_t iMask)
-{
-  bool bReturn(false);
-  CStdString strLog;
-  strLog.Format("setting ackmask to %2x", iMask);
-  CLibCEC::AddLog(CEC_LOG_DEBUG, strLog.c_str());
-
-  CCECAdapterMessage *output = new CCECAdapterMessage;
-
-  output->PushBack(MSGSTART);
-  output->PushEscaped(MSGCODE_SET_ACK_MASK);
-  output->PushEscaped(iMask >> 8);
-  output->PushEscaped((uint8_t)iMask);
-  output->PushBack(MSGEND);
-  output->isTransmission = false;
-
-  if ((bReturn = Write(output)) == false)
-    CLibCEC::AddLog(CEC_LOG_ERROR, "could not set the ackmask");
-  delete output;
-
-  return bReturn;
-}
-
-bool CAdapterCommunication::IsOpen(void)
-{
-  return !IsStopped() && m_port->IsOpen() && IsRunning();
-}
-
-bool CAdapterCommunication::WaitForAck(CCECAdapterMessage &message)
-{
-  bool bError(false);
-  bool bTransmitSucceeded(false);
-  uint8_t iPacketsLeft(message.Size() / 4);
-
-  int64_t iNow = GetTimeMs();
-  int64_t iTargetTime = iNow + message.transmit_timeout;
-
-  while (!bTransmitSucceeded && !bError && (message.transmit_timeout == 0 || iNow < iTargetTime))
-  {
-    CCECAdapterMessage msg;
-    int32_t iWait = (int32_t)(iTargetTime - iNow);
-    if (iWait <= 5 || message.transmit_timeout <= 5)
-      iWait = CEC_DEFAULT_TRANSMIT_WAIT;
-
-    if (!Read(msg, iWait))
-    {
-      iNow = GetTimeMs();
-      continue;
-    }
-
-    if (msg.Message() == MSGCODE_FRAME_START && msg.IsACK())
-    {
-      m_processor->HandlePoll(msg.Initiator(), msg.Destination());
-      iNow = GetTimeMs();
-      continue;
-    }
-
-    if (msg.Message() == MSGCODE_RECEIVE_FAILED &&
-        m_processor->HandleReceiveFailed())
-    {
-      iNow = GetTimeMs();
-      continue;
-    }
-
-    bError = msg.IsError();
-    if (bError)
-    {
-      message.reply = msg.Message();
-      CLibCEC::AddLog(CEC_LOG_DEBUG, msg.ToString());
-    }
-    else
-    {
-      switch(msg.Message())
-      {
-      case MSGCODE_COMMAND_ACCEPTED:
-        CLibCEC::AddLog(CEC_LOG_DEBUG, msg.ToString());
-        if (iPacketsLeft > 0)
-          iPacketsLeft--;
-        if (!message.isTransmission && iPacketsLeft == 0)
-          bTransmitSucceeded = true;
-        break;
-      case MSGCODE_TRANSMIT_SUCCEEDED:
-        CLibCEC::AddLog(CEC_LOG_DEBUG, msg.ToString());
-        bTransmitSucceeded = (iPacketsLeft == 0);
-        bError = !bTransmitSucceeded;
-        message.reply = MSGCODE_TRANSMIT_SUCCEEDED;
-        break;
-      default:
-        // ignore other data while waiting
-        break;
-      }
-
-      iNow = GetTimeMs();
-    }
-  }
-
-  return bTransmitSucceeded && !bError;
-}
-
-void CAdapterCommunication::AddData(uint8_t *data, uint8_t iLen)
-{
-  CLockObject lock(m_mutex);
-  for (uint8_t iPtr = 0; iPtr < iLen; iPtr++)
-    m_inBuffer.Push(data[iPtr]);
-
-  m_rcvCondition.Signal();
-}
-
-bool CAdapterCommunication::ReadFromDevice(uint32_t iTimeout)
-{
-  int32_t iBytesRead;
-  uint8_t buff[1024];
-  if (!m_port)
-    return false;
-
-  CLockObject lock(m_mutex);
-  iBytesRead = m_port->Read(buff, sizeof(buff), iTimeout);
-  if (iBytesRead < 0 || iBytesRead > 256)
-  {
-    CStdString strError;
-    strError.Format("error reading from serial port: %s", m_port->GetError().c_str());
-    CLibCEC::AddLog(CEC_LOG_ERROR, strError);
-    return false;
-  }
-  else if (iBytesRead > 0)
-    AddData(buff, (uint8_t) iBytesRead);
-
-  return iBytesRead > 0;
-}
-
-void CAdapterCommunication::SendMessageToAdapter(CCECAdapterMessage *msg)
-{
-  CLockObject adapterLock(m_mutex);
-  CLockObject lock(msg->mutex);
-  if (m_port->Write(msg->packet.data, msg->Size()) != (int32_t) msg->Size())
-  {
-    CStdString strError;
-    strError.Format("error writing to serial port: %s", m_port->GetError().c_str());
-    CLibCEC::AddLog(CEC_LOG_ERROR, strError);
-    msg->state = ADAPTER_MESSAGE_STATE_ERROR;
-  }
-  else
-  {
-    CLibCEC::AddLog(CEC_LOG_DEBUG, "command sent");
-    msg->state = ADAPTER_MESSAGE_STATE_SENT;
-  }
-  msg->condition.Signal();
-}
-
-void CAdapterCommunication::WriteNextCommand(void)
-{
-  CCECAdapterMessage *msg(NULL);
-  if (m_outBuffer.Pop(msg))
-    SendMessageToAdapter(msg);
-}
index f7979548c6b41cdf4aadcffab64af7cd855320ab..9762926cc10a23e0561b96914c13b2ba4fac2aa8 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * This file is part of the libCEC(R) library.
  *
- * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
  * libCEC(R) is an original work, containing original code.
  *
  * libCEC(R) is a trademark of Pulse-Eight Limited.
  *     http://www.pulse-eight.net/
  */
 
-#include <cectypes.h>
-#include "../platform/os.h"
-
-namespace PLATFORM
-{
-  class CSerialPort;
-}
+#include "../platform/util/StdString.h"
 
 namespace CEC
 {
-  class CCECProcessor;
-  class CCECAdapterMessage;
+  typedef enum cec_adapter_message_state
+  {
+    ADAPTER_MESSAGE_STATE_UNKNOWN = 0,          /**< the initial state */
+    ADAPTER_MESSAGE_STATE_WAITING_TO_BE_SENT,   /**< waiting in the send queue of the adapter, or timed out */
+    ADAPTER_MESSAGE_STATE_SENT,                 /**< sent and waiting on an ACK */
+    ADAPTER_MESSAGE_STATE_SENT_NOT_ACKED,       /**< sent, but failed to ACK */
+    ADAPTER_MESSAGE_STATE_SENT_ACKED,           /**< sent, and ACK received */
+    ADAPTER_MESSAGE_STATE_INCOMING,             /**< received from another device */
+    ADAPTER_MESSAGE_STATE_ERROR                 /**< an error occured */
+  } cec_adapter_message_state;
+
+  struct IAdapterCommunicationCallback
+  {
+  public:
+    /*!
+     * @brief Callback method for IAdapterCommunication, called when a new cec_command is received
+     * @param command The command that has been received
+     * @return True when it was handled by this listener, false otherwise.
+     */
+    virtual bool OnCommandReceived(const cec_command &command) = 0;
+  };
 
-  class CAdapterCommunication : private PLATFORM::CThread
+  struct IAdapterCommunication
   {
   public:
-    CAdapterCommunication(CCECProcessor *processor);
-    virtual ~CAdapterCommunication();
+    /*!
+     * @brief Open a connection to the CEC adapter
+     * @param cb The callback struct. if set to NULL, the Read() method has to be used to read commands. if set, OnCommandReceived() will be called for each command that was received
+     * @param iTimeoutMs Connection timeout in ms
+     * @return True when connected, false otherwise
+     */
+    virtual bool Open(IAdapterCommunicationCallback *cb, uint32_t iTimeoutMs = 10000) = 0;
+
+    /*!
+     * @brief Close an open connection
+     */
+    virtual void Close(void) = 0;
+
+    /*!
+     * @return True when the connection is open, false otherwise
+     */
+    virtual bool IsOpen(void) = 0;
+
+    /*!
+     * @return The last error message, or an empty string if there was none
+     */
+    virtual CStdString GetError(void) const = 0;
+
+    /*!
+     * @brief Reads one cec_command from the adapter
+     * @param command The command that will be read (output)
+     * @param iTimeout The read timeout
+     * @return True when a command has been read, false otherwise.
+     */
+    virtual bool Read(cec_command &command, uint32_t iTimeout) = 0;
+
+    /*!
+     * @brief Write a cec_command to the adapter
+     * @param data The command to write
+     * @param iMaxTries The maximum number of tries
+     * @param iLineTimeout The line timeout for the first try
+     * @param iRetryLineTimeout The line timeout for each next try
+     * @return The last state of the transmitted command
+     */
+    virtual cec_adapter_message_state Write(const cec_command &data, uint8_t iMaxTries, uint8_t iLineTimeout = 3, uint8_t iRetryLineTimeout = 3) = 0;
 
-    bool Open(const char *strPort, uint16_t iBaudRate = 38400, uint32_t iTimeoutMs = 10000);
-    bool Read(CCECAdapterMessage &msg, uint32_t iTimeout = 1000);
-    bool Write(CCECAdapterMessage *data);
-    void Close(void);
-    bool IsOpen(void);
-    std::string GetError(void) const;
+    /*!
+     * @brief Change the current line timeout on the CEC bus
+     * @param iTimeout The new timeout
+     * @return True when set, false otherwise
+     */
+    virtual bool SetLineTimeout(uint8_t iTimeout) = 0;
 
-    void *Process(void);
+    /*!
+     * @brief Put the device in bootloader mode (which will disrupt CEC communication when it succeeds)
+     * @return True when the bootloader command has been sent, false otherwise.
+     */
+    virtual bool StartBootloader(void) = 0;
 
-    bool SetLineTimeout(uint8_t iTimeout);
-    bool StartBootloader(void);
-    bool SetAckMask(uint16_t iMask);
-    bool PingAdapter(void);
-    uint16_t GetFirmwareVersion(void);
+    /*!
+     * @brief Change the ACK-mask of the device, the mask for logical addresses to which the CEC device should ACK
+     * @param iMask The new mask
+     * @return True when set, false otherwise.
+     */
+    virtual bool SetAckMask(uint16_t iMask) = 0;
 
-    bool WaitForAck(CCECAdapterMessage &message);
+    /*!
+     * @brief Check whether the CEC adapter responds
+     * @return True when the ping was sent and acked, false otherwise.
+     */
+    virtual bool PingAdapter(void) = 0;
 
-  private:
-    void SendMessageToAdapter(CCECAdapterMessage *msg);
-    void WriteNextCommand(void);
-    void AddData(uint8_t *data, uint8_t iLen);
-    bool ReadFromDevice(uint32_t iTimeout);
+    /*!
+     * @return The firmware version of this CEC adapter.
+     */
+    virtual uint16_t GetFirmwareVersion(void) = 0;
 
-    PLATFORM::CSerialPort *                      m_port;
-    CCECProcessor *                              m_processor;
-    PLATFORM::SyncedBuffer<uint8_t>              m_inBuffer;
-    PLATFORM::SyncedBuffer<CCECAdapterMessage *> m_outBuffer;
-    PLATFORM::CMutex                             m_mutex;
-    PLATFORM::CCondition                         m_rcvCondition;
-    uint8_t                                      m_iLineTimeout;
-    uint16_t                                     m_iFirmwareVersion;
+    /*!
+     * @return True when the control mode has been set, false otherwise.
+     */
+    virtual bool SetControlledMode(bool controlled) = 0;
   };
 };
diff --git a/src/lib/adapter/USBCECAdapterCommunication.cpp b/src/lib/adapter/USBCECAdapterCommunication.cpp
new file mode 100644 (file)
index 0000000..01bf303
--- /dev/null
@@ -0,0 +1,698 @@
+/*
+ * This file is part of the libCEC(R) library.
+ *
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is an original work, containing original code.
+ *
+ * libCEC(R) is a trademark of Pulse-Eight Limited.
+ *
+ * This program is dual-licensed; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * Alternatively, you can license this library under a commercial license,
+ * please contact Pulse-Eight Licensing for more information.
+ *
+ * For more information contact:
+ * Pulse-Eight Licensing       <license@pulse-eight.com>
+ *     http://www.pulse-eight.com/
+ *     http://www.pulse-eight.net/
+ */
+
+#include "USBCECAdapterCommunication.h"
+#include "../platform/sockets/serialport.h"
+#include "../platform/util/timeutils.h"
+#include "../LibCEC.h"
+#include "../CECProcessor.h"
+
+using namespace std;
+using namespace CEC;
+using namespace PLATFORM;
+
+CUSBCECAdapterCommunication::CUSBCECAdapterCommunication(CCECProcessor *processor, const char *strPort, uint16_t iBaudRate /* = 38400 */) :
+    m_port(NULL),
+    m_processor(processor),
+    m_iLineTimeout(0),
+    m_iFirmwareVersion(CEC_FW_VERSION_UNKNOWN),
+    m_lastInitiator(CECDEVICE_UNKNOWN),
+    m_bNextIsEscaped(false),
+    m_bGotStart(false)
+{
+  m_port = new PLATFORM::CSerialPort(strPort, iBaudRate);
+}
+
+CUSBCECAdapterCommunication::~CUSBCECAdapterCommunication(void)
+{
+  Close();
+}
+
+bool CUSBCECAdapterCommunication::CheckAdapter(uint32_t iTimeoutMs /* = 10000 */)
+{
+  bool bReturn(false);
+  uint64_t iNow = GetTimeMs();
+  uint64_t iTarget = iTimeoutMs > 0 ? iNow + iTimeoutMs : iNow + CEC_DEFAULT_TRANSMIT_WAIT;
+
+  /* try to ping the adapter */
+  bool bPinged(false);
+  unsigned iPingTry(0);
+  while (iNow < iTarget && (bPinged = PingAdapter()) == false)
+  {
+    CLibCEC::AddLog(CEC_LOG_ERROR, "the adapter did not respond correctly to a ping (try %d)", ++iPingTry);
+    Sleep(500);
+    iNow = GetTimeMs();
+  }
+
+  /* try to read the firmware version */
+  m_iFirmwareVersion = CEC_FW_VERSION_UNKNOWN;
+  unsigned iFwVersionTry(0);
+  while (bPinged && iNow < iTarget && (m_iFirmwareVersion = GetFirmwareVersion()) == CEC_FW_VERSION_UNKNOWN)
+  {
+    CLibCEC::AddLog(CEC_LOG_ERROR, "the adapter did not respond with a correct firmware version (try %d)", ++iFwVersionTry);
+    Sleep(500);
+    iNow = GetTimeMs();
+  }
+
+  if (m_iFirmwareVersion >= 2)
+  {
+    /* try to set controlled mode */
+    unsigned iControlledTry(0);
+    bool bControlled(false);
+    while (iNow < iTarget && (bControlled = SetControlledMode(true)) == false)
+    {
+      CLibCEC::AddLog(CEC_LOG_ERROR, "the adapter did not respond correctly to setting controlled mode (try %d)", ++iControlledTry);
+      Sleep(500);
+      iNow = GetTimeMs();
+    }
+    bReturn = bControlled;
+  }
+  else
+    bReturn = true;
+
+  return bReturn;
+}
+
+bool CUSBCECAdapterCommunication::Open(IAdapterCommunicationCallback *cb, uint32_t iTimeoutMs /* = 10000 */)
+{
+  uint64_t iNow = GetTimeMs();
+  uint64_t iTimeout = iNow + iTimeoutMs;
+
+  {
+    CLockObject lock(m_mutex);
+
+    if (!m_port)
+    {
+      CLibCEC::AddLog(CEC_LOG_ERROR, "port is NULL");
+      return false;
+    }
+
+    if (IsOpen())
+    {
+      CLibCEC::AddLog(CEC_LOG_ERROR, "port is already open");
+      return true;
+    }
+
+    m_callback = cb;
+    CStdString strError;
+    bool bConnected(false);
+    while (!bConnected && iNow < iTimeout)
+    {
+      if ((bConnected = m_port->Open(iTimeout)) == false)
+      {
+        strError.Format("error opening serial port '%s': %s", m_port->GetName().c_str(), m_port->GetError().c_str());
+        Sleep(250);
+        iNow = GetTimeMs();
+      }
+    }
+
+    if (!bConnected)
+    {
+      CLibCEC::AddLog(CEC_LOG_ERROR, strError);
+      return false;
+    }
+
+    CLibCEC::AddLog(CEC_LOG_DEBUG, "connection opened, clearing any previous input and waiting for active transmissions to end before starting");
+
+    //clear any input bytes
+    uint8_t buff[1024];
+    while (m_port->Read(buff, 1024, 100) > 0)
+    {
+      CLibCEC::AddLog(CEC_LOG_DEBUG, "data received, clearing it");
+      Sleep(250);
+    }
+  }
+
+  if (CreateThread())
+  {
+    if (!CheckAdapter())
+    {
+      StopThread();
+      CLibCEC::AddLog(CEC_LOG_ERROR, "the adapter failed to pass basic checks");
+    }
+    else
+    {
+      CLibCEC::AddLog(CEC_LOG_DEBUG, "communication thread started");
+      return true;
+    }
+  }
+  CLibCEC::AddLog(CEC_LOG_ERROR, "could not create a communication thread");
+
+  return false;
+}
+
+void CUSBCECAdapterCommunication::Close(void)
+{
+  CLockObject lock(m_mutex);
+  m_rcvCondition.Broadcast();
+  StopThread();
+}
+
+void *CUSBCECAdapterCommunication::Process(void)
+{
+  cec_command command;
+  bool bCommandReceived(false);
+  while (!IsStopped())
+  {
+    {
+      CLockObject lock(m_mutex);
+      ReadFromDevice(50);
+      bCommandReceived = m_callback && Read(command, 0);
+    }
+
+    /* push the next command to the callback method if there is one */
+    if (!IsStopped() && bCommandReceived)
+      m_callback->OnCommandReceived(command);
+
+    if (!IsStopped())
+    {
+      Sleep(5);
+      WriteNextCommand();
+    }
+  }
+
+  CCECAdapterMessage *msg(NULL);
+  if (m_outBuffer.Pop(msg))
+    msg->condition.Broadcast();
+
+  if (m_port)
+  {
+    delete m_port;
+    m_port = NULL;
+  }
+
+  return NULL;
+}
+
+cec_adapter_message_state CUSBCECAdapterCommunication::Write(const cec_command &data, uint8_t iMaxTries, uint8_t iLineTimeout /* = 3 */, uint8_t iRetryLineTimeout /* = 3 */)
+{
+  cec_adapter_message_state retVal(ADAPTER_MESSAGE_STATE_UNKNOWN);
+
+  CCECAdapterMessage *output = new CCECAdapterMessage(data);
+
+  /* set the number of retries */
+  if (data.opcode == CEC_OPCODE_NONE) //TODO
+    output->maxTries = 1;
+  else if (data.initiator != CECDEVICE_BROADCAST)
+    output->maxTries = iMaxTries;
+
+  output->lineTimeout = iLineTimeout;
+  output->retryTimeout = iRetryLineTimeout;
+  output->tries = 0;
+
+  bool bRetry(true);
+  while (bRetry && ++output->tries < output->maxTries)
+  {
+    bRetry = (!Write(output) || output->NeedsRetry()) && output->transmit_timeout > 0;
+    if (bRetry)
+      Sleep(CEC_DEFAULT_TRANSMIT_RETRY_WAIT);
+  }
+  retVal = output->state;
+
+  delete output;
+  return retVal;
+}
+
+bool CUSBCECAdapterCommunication::Write(CCECAdapterMessage *data)
+{
+  CLockObject lock(data->mutex);
+  data->state = ADAPTER_MESSAGE_STATE_WAITING_TO_BE_SENT;
+  m_outBuffer.Push(data);
+  data->condition.Wait(data->mutex);
+
+  if ((data->expectControllerAck && data->state != ADAPTER_MESSAGE_STATE_SENT_ACKED) ||
+      (!data->expectControllerAck && data->state != ADAPTER_MESSAGE_STATE_SENT))
+  {
+    CLibCEC::AddLog(CEC_LOG_DEBUG, "command was not %s", data->state == ADAPTER_MESSAGE_STATE_SENT_NOT_ACKED ? "acked" : "sent");
+    return false;
+  }
+
+  return true;
+}
+
+bool CUSBCECAdapterCommunication::Read(cec_command &command, uint32_t iTimeout)
+{
+  CCECAdapterMessage msg;
+  if (Read(msg, iTimeout))
+  {
+    if (ParseMessage(msg))
+    {
+      command = m_currentframe;
+      m_currentframe.Clear();
+      return true;
+    }
+  }
+  return false;
+}
+
+bool CUSBCECAdapterCommunication::Read(CCECAdapterMessage &msg, uint32_t iTimeout)
+{
+  CLockObject lock(m_mutex);
+
+  msg.Clear();
+  CCECAdapterMessage *buf(NULL);
+
+  if (!m_inBuffer.Pop(buf))
+  {
+    if (iTimeout == 0 || !m_rcvCondition.Wait(m_mutex, iTimeout))
+      return false;
+    m_inBuffer.Pop(buf);
+  }
+
+  if (buf)
+  {
+    msg.packet = buf->packet;
+    msg.state = msg.state = ADAPTER_MESSAGE_STATE_INCOMING;
+    delete buf;
+    return true;
+  }
+  return false;
+}
+
+CStdString CUSBCECAdapterCommunication::GetError(void) const
+{
+  CStdString strError;
+  strError = m_port->GetError();
+  return strError;
+}
+
+bool CUSBCECAdapterCommunication::StartBootloader(void)
+{
+  bool bReturn(false);
+  if (!IsRunning())
+    return bReturn;
+
+  CLibCEC::AddLog(CEC_LOG_DEBUG, "starting the bootloader");
+  CCECAdapterMessage *output = new CCECAdapterMessage;
+
+  output->PushBack(MSGSTART);
+  output->PushEscaped(MSGCODE_START_BOOTLOADER);
+  output->PushBack(MSGEND);
+  output->isTransmission = false;
+  output->expectControllerAck = false;
+
+  if ((bReturn = Write(output)) == false)
+    CLibCEC::AddLog(CEC_LOG_ERROR, "could not start the bootloader");
+  delete output;
+
+  return bReturn;
+}
+
+bool CUSBCECAdapterCommunication::PingAdapter(void)
+{
+  bool bReturn(false);
+  if (!IsRunning())
+    return bReturn;
+
+  CLibCEC::AddLog(CEC_LOG_DEBUG, "sending ping");
+  CCECAdapterMessage *output = new CCECAdapterMessage;
+
+  output->PushBack(MSGSTART);
+  output->PushEscaped(MSGCODE_PING);
+  output->PushBack(MSGEND);
+  output->isTransmission = false;
+
+  if ((bReturn = Write(output)) == false)
+    CLibCEC::AddLog(CEC_LOG_ERROR, "could not ping the adapter");
+  delete output;
+
+  return bReturn;
+}
+
+bool CUSBCECAdapterCommunication::ParseMessage(const CCECAdapterMessage &msg)
+{
+  bool bEom(false);
+  bool bIsError(msg.IsError());
+
+  if (msg.IsEmpty())
+    return bEom;
+
+  switch(msg.Message())
+  {
+  case MSGCODE_FRAME_START:
+    {
+      m_currentframe.Clear();
+      if (msg.Size() >= 2)
+      {
+        m_currentframe.initiator   = msg.Initiator();
+        m_currentframe.destination = msg.Destination();
+        m_currentframe.ack         = msg.IsACK();
+        m_currentframe.eom         = msg.IsEOM();
+      }
+      if (m_currentframe.ack == 0x1)
+      {
+        m_lastInitiator = m_currentframe.initiator;
+        m_processor->HandlePoll(m_currentframe.initiator, m_currentframe.destination);
+      }
+    }
+    break;
+  case MSGCODE_RECEIVE_FAILED:
+    {
+      m_currentframe.Clear();
+      if (m_lastInitiator != CECDEVICE_UNKNOWN)
+        bIsError = m_processor->HandleReceiveFailed(m_lastInitiator);
+    }
+    break;
+  case MSGCODE_FRAME_DATA:
+    {
+      if (msg.Size() >= 2)
+      {
+        m_currentframe.PushBack(msg[1]);
+        m_currentframe.eom = msg.IsEOM();
+      }
+      bEom = msg.IsEOM();
+    }
+    break;
+  default:
+    break;
+  }
+
+  CLibCEC::AddLog(bIsError ? CEC_LOG_WARNING : CEC_LOG_DEBUG, msg.ToString());
+  return bEom;
+}
+
+uint16_t CUSBCECAdapterCommunication::GetFirmwareVersion(void)
+{
+  CLockObject lock(m_mutex);
+  uint16_t iReturn(m_iFirmwareVersion);
+  if (!IsRunning())
+    return iReturn;
+
+  if (iReturn == CEC_FW_VERSION_UNKNOWN)
+  {
+    CLibCEC::AddLog(CEC_LOG_DEBUG, "requesting the firmware version");
+    CCECAdapterMessage *output = new CCECAdapterMessage;
+
+    output->PushBack(MSGSTART);
+    output->PushEscaped(MSGCODE_FIRMWARE_VERSION);
+    output->PushBack(MSGEND);
+    output->isTransmission = false;
+    output->expectControllerAck = false;
+
+    SendMessageToAdapter(output);
+    bool bWriteOk = output->state == ADAPTER_MESSAGE_STATE_SENT;
+    delete output;
+    if (!bWriteOk)
+    {
+      CLibCEC::AddLog(CEC_LOG_ERROR, "could not request the firmware version");
+      return iReturn;
+    }
+
+    Sleep(250); // TODO ReadFromDevice() isn't waiting for the timeout to pass on win32
+    ReadFromDevice(CEC_DEFAULT_TRANSMIT_WAIT, 5 /* start + msgcode + 2 bytes for fw version + end */);
+    CCECAdapterMessage input;
+    if (Read(input, 0))
+    {
+      if (input.Message() != MSGCODE_FIRMWARE_VERSION || input.Size() != 3)
+        CLibCEC::AddLog(CEC_LOG_ERROR, "invalid firmware version (size = %d, message = %d)", input.Size(), input.Message());
+      else
+      {
+        m_iFirmwareVersion = (input[1] << 8 | input[2]);
+        iReturn = m_iFirmwareVersion;
+      }
+    }
+    else
+    {
+      CLibCEC::AddLog(CEC_LOG_ERROR, "no firmware version received");
+    }
+  }
+
+  return iReturn;
+}
+
+bool CUSBCECAdapterCommunication::SetLineTimeout(uint8_t iTimeout)
+{
+  m_iLineTimeout = iTimeout;
+  return true;
+  //TODO
+//  bool bReturn(m_iLineTimeout != iTimeout);
+//
+//  if (!bReturn)
+//  {
+//    CCECAdapterMessage *output = new CCECAdapterMessage;
+//
+//    output->PushBack(MSGSTART);
+//    output->PushEscaped(MSGCODE_TRANSMIT_IDLETIME);
+//    output->PushEscaped(iTimeout);
+//    output->PushBack(MSGEND);
+//    output->isTransmission = false;
+//
+//    if ((bReturn = Write(output)) == false)
+//      CLibCEC::AddLog(CEC_LOG_ERROR, "could not set the idletime");
+//    delete output;
+//  }
+//
+//  return bReturn;
+}
+
+bool CUSBCECAdapterCommunication::SetAckMask(uint16_t iMask)
+{
+  bool bReturn(false);
+  CLibCEC::AddLog(CEC_LOG_DEBUG, "setting ackmask to %2x", iMask);
+
+  CCECAdapterMessage *output = new CCECAdapterMessage;
+
+  output->PushBack(MSGSTART);
+  output->PushEscaped(MSGCODE_SET_ACK_MASK);
+  output->PushEscaped(iMask >> 8);
+  output->PushEscaped((uint8_t)iMask);
+  output->PushBack(MSGEND);
+  output->isTransmission = false;
+
+  if ((bReturn = Write(output)) == false)
+    CLibCEC::AddLog(CEC_LOG_ERROR, "could not set the ackmask");
+  delete output;
+
+  return bReturn;
+}
+
+
+bool CUSBCECAdapterCommunication::SetControlledMode(bool controlled)
+{
+  bool bReturn(false);
+  CLibCEC::AddLog(CEC_LOG_DEBUG, "turning controlled mode %s", controlled ? "on" : "off");
+
+  CCECAdapterMessage *output = new CCECAdapterMessage;
+
+  output->PushBack(MSGSTART);
+  output->PushEscaped(MSGCODE_SET_CONTROLLED);
+  output->PushEscaped(controlled);
+  output->PushBack(MSGEND);
+  output->isTransmission = false;
+
+  if ((bReturn = Write(output)) == false)
+    CLibCEC::AddLog(CEC_LOG_ERROR, "could not set controlled mode");
+  delete output;
+
+  return bReturn;
+}
+
+bool CUSBCECAdapterCommunication::IsOpen(void)
+{
+  return !IsStopped() && m_port->IsOpen() && IsRunning();
+}
+
+bool CUSBCECAdapterCommunication::WaitForAck(CCECAdapterMessage &message)
+{
+  bool bError(false);
+  bool bTransmitSucceeded(false);
+  uint8_t iPacketsLeft(message.Size() / 4);
+
+  int64_t iNow = GetTimeMs();
+  int64_t iTargetTime = iNow + (message.transmit_timeout <= 5 ? CEC_DEFAULT_TRANSMIT_WAIT : message.transmit_timeout);
+
+  while (!bTransmitSucceeded && !bError && iNow < iTargetTime)
+  {
+    ReadFromDevice(50);
+    CCECAdapterMessage msg;
+    if (!Read(msg, 0))
+    {
+      iNow = GetTimeMs();
+      continue;
+    }
+
+    if (msg.Message() == MSGCODE_FRAME_START && msg.IsACK())
+    {
+      m_processor->HandlePoll(msg.Initiator(), msg.Destination());
+      m_lastInitiator = msg.Initiator();
+      iNow = GetTimeMs();
+      continue;
+    }
+
+    if (msg.Message() == MSGCODE_RECEIVE_FAILED &&
+        m_lastInitiator != CECDEVICE_UNKNOWN &&
+        m_processor->HandleReceiveFailed(m_lastInitiator))
+    {
+      iNow = GetTimeMs();
+      continue;
+    }
+
+    bError = msg.IsError();
+    if (bError)
+    {
+      message.reply = msg.Message();
+      CLibCEC::AddLog(CEC_LOG_DEBUG, msg.ToString());
+    }
+    else
+    {
+      switch(msg.Message())
+      {
+      case MSGCODE_COMMAND_ACCEPTED:
+        CLibCEC::AddLog(CEC_LOG_DEBUG, msg.ToString());
+        if (iPacketsLeft > 0)
+          iPacketsLeft--;
+        if (!message.isTransmission && iPacketsLeft == 0)
+          bTransmitSucceeded = true;
+        break;
+      case MSGCODE_TRANSMIT_SUCCEEDED:
+        CLibCEC::AddLog(CEC_LOG_DEBUG, msg.ToString());
+        bTransmitSucceeded = (iPacketsLeft == 0);
+        bError = !bTransmitSucceeded;
+        message.reply = MSGCODE_TRANSMIT_SUCCEEDED;
+        break;
+      default:
+        // ignore other data while waiting
+        break;
+      }
+
+      iNow = GetTimeMs();
+    }
+  }
+
+  message.state = bTransmitSucceeded && !bError ?
+      ADAPTER_MESSAGE_STATE_SENT_ACKED :
+      ADAPTER_MESSAGE_STATE_SENT_NOT_ACKED;
+
+  return bTransmitSucceeded && !bError;
+}
+
+void CUSBCECAdapterCommunication::AddData(uint8_t *data, size_t iLen)
+{
+  CLockObject lock(m_mutex);
+  for (size_t iPtr = 0; iPtr < iLen; iPtr++)
+  {
+    if (!m_bGotStart)
+    {
+      if (data[iPtr] == MSGSTART)
+        m_bGotStart = true;
+    }
+    else if (data[iPtr] == MSGSTART) //we found a msgstart before msgend, this is not right, remove
+    {
+      if (m_currentAdapterMessage.Size() > 0)
+        CLibCEC::AddLog(CEC_LOG_WARNING, "received MSGSTART before MSGEND, removing previous buffer contents");
+      m_currentAdapterMessage.Clear();
+      m_bGotStart = true;
+    }
+    else if (data[iPtr] == MSGEND)
+    {
+      CCECAdapterMessage *newMessage = new CCECAdapterMessage;
+      newMessage->packet = m_currentAdapterMessage.packet;
+      m_inBuffer.Push(newMessage);
+      m_currentAdapterMessage.Clear();
+      m_bGotStart = false;
+      m_bNextIsEscaped = false;
+      m_rcvCondition.Signal();
+    }
+    else if (m_bNextIsEscaped)
+    {
+      m_currentAdapterMessage.PushBack(data[iPtr] + (uint8_t)ESCOFFSET);
+      m_bNextIsEscaped = false;
+    }
+    else if (data[iPtr] == MSGESC)
+    {
+      m_bNextIsEscaped = true;
+    }
+    else
+    {
+      m_currentAdapterMessage.PushBack(data[iPtr]);
+    }
+  }
+}
+
+bool CUSBCECAdapterCommunication::ReadFromDevice(uint32_t iTimeout, size_t iSize /* = 256 */)
+{
+  ssize_t iBytesRead;
+  uint8_t buff[256];
+  if (!m_port)
+    return false;
+  if (iSize > 256)
+    iSize = 256;
+
+  CLockObject lock(m_mutex);
+  iBytesRead = m_port->Read(buff, sizeof(uint8_t) * iSize, iTimeout);
+  if (iBytesRead < 0 || iBytesRead > 256)
+  {
+    CLibCEC::AddLog(CEC_LOG_ERROR, "error reading from serial port: %s", m_port->GetError().c_str());
+    return false;
+  }
+  else if (iBytesRead > 0)
+  {
+    AddData(buff, iBytesRead);
+  }
+
+  return iBytesRead > 0;
+}
+
+void CUSBCECAdapterCommunication::SendMessageToAdapter(CCECAdapterMessage *msg)
+{
+  CLockObject adapterLock(m_mutex);
+  CLockObject lock(msg->mutex);
+  if (msg->tries == 1)
+    SetLineTimeout(msg->lineTimeout);
+  else
+    SetLineTimeout(msg->retryTimeout);
+
+  if (m_port->Write(msg->packet.data, msg->Size()) != (ssize_t) msg->Size())
+  {
+    CLibCEC::AddLog(CEC_LOG_ERROR, "error writing to serial port: %s", m_port->GetError().c_str());
+    msg->state = ADAPTER_MESSAGE_STATE_ERROR;
+  }
+  else
+  {
+    CLibCEC::AddLog(CEC_LOG_DEBUG, "command sent");
+    msg->state = ADAPTER_MESSAGE_STATE_SENT;
+
+    if (msg->expectControllerAck)
+    {
+      if (!WaitForAck(*msg))
+        CLibCEC::AddLog(CEC_LOG_DEBUG, "did not receive ack");
+    }
+  }
+  msg->condition.Signal();
+}
+
+void CUSBCECAdapterCommunication::WriteNextCommand(void)
+{
+  CCECAdapterMessage *msg(NULL);
+  if (m_outBuffer.Pop(msg))
+    SendMessageToAdapter(msg);
+}
diff --git a/src/lib/adapter/USBCECAdapterCommunication.h b/src/lib/adapter/USBCECAdapterCommunication.h
new file mode 100644 (file)
index 0000000..f4fab4b
--- /dev/null
@@ -0,0 +1,97 @@
+#pragma once
+/*
+ * This file is part of the libCEC(R) library.
+ *
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is an original work, containing original code.
+ *
+ * libCEC(R) is a trademark of Pulse-Eight Limited.
+ *
+ * This program is dual-licensed; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * Alternatively, you can license this library under a commercial license,
+ * please contact Pulse-Eight Licensing for more information.
+ *
+ * For more information contact:
+ * Pulse-Eight Licensing       <license@pulse-eight.com>
+ *     http://www.pulse-eight.com/
+ *     http://www.pulse-eight.net/
+ */
+
+#include <cectypes.h>
+#include "../platform/threads/threads.h"
+#include "../platform/util/buffer.h"
+#include "AdapterCommunication.h"
+#include "USBCECAdapterMessage.h"
+
+namespace PLATFORM
+{
+  class ISocket;
+}
+
+namespace CEC
+{
+  class CCECProcessor;
+
+  class CUSBCECAdapterCommunication : public IAdapterCommunication, private PLATFORM::CThread
+  {
+  public:
+    CUSBCECAdapterCommunication(CCECProcessor *processor, const char *strPort, uint16_t iBaudRate = 38400);
+    virtual ~CUSBCECAdapterCommunication();
+
+    virtual bool Open(IAdapterCommunicationCallback *cb, uint32_t iTimeoutMs = 10000);
+    virtual void Close(void);
+    virtual bool IsOpen(void);
+    virtual CStdString GetError(void) const;
+
+    bool Read(cec_command &command, uint32_t iTimeout);
+    cec_adapter_message_state Write(const cec_command &data, uint8_t iMaxTries, uint8_t iLineTimeout = 3, uint8_t iRetryLineTimeout = 3);
+
+    virtual bool SetLineTimeout(uint8_t iTimeout);
+    virtual bool StartBootloader(void);
+    virtual bool SetAckMask(uint16_t iMask);
+    virtual bool PingAdapter(void);
+    virtual uint16_t GetFirmwareVersion(void);
+    virtual bool SetControlledMode(bool controlled);
+
+    void *Process(void);
+  private:
+    bool CheckAdapter(uint32_t iTimeoutMs = 10000);
+    bool Write(CCECAdapterMessage *data);
+    bool Read(CCECAdapterMessage &msg, uint32_t iTimeout = 1000);
+    bool ParseMessage(const CCECAdapterMessage &msg);
+    void SendMessageToAdapter(CCECAdapterMessage *msg);
+    void WriteNextCommand(void);
+    void AddData(uint8_t *data, size_t iLen);
+    bool ReadFromDevice(uint32_t iTimeout, size_t iSize = 256);
+    bool WaitForAck(CCECAdapterMessage &message);
+
+    PLATFORM::ISocket *                          m_port;
+    CCECProcessor *                              m_processor;
+    PLATFORM::SyncedBuffer<CCECAdapterMessage *> m_inBuffer;
+    PLATFORM::SyncedBuffer<CCECAdapterMessage *> m_outBuffer;
+    PLATFORM::CMutex                             m_mutex;
+    PLATFORM::CCondition                         m_rcvCondition;
+    uint8_t                                      m_iLineTimeout;
+    uint16_t                                     m_iFirmwareVersion;
+    cec_command                                  m_currentframe;
+    cec_logical_address                          m_lastInitiator;
+    CCECAdapterMessage                           m_currentAdapterMessage;
+    bool                                         m_bNextIsEscaped;
+    bool                                         m_bGotStart;
+    IAdapterCommunicationCallback *              m_callback;
+  };
+};
similarity index 97%
rename from src/lib/adapter/AdapterDetection.cpp
rename to src/lib/adapter/USBCECAdapterDetection.cpp
index 596bfd88d9e1328175dd45875c9991f14e0d645b..0d9f8b3d9c04b19738f560be47d1cb57ae43f95b 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the libCEC(R) library.
  *
- * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
  * libCEC(R) is an original work, containing original code.
  *
  * libCEC(R) is a trademark of Pulse-Eight Limited.
@@ -30,8 +30,8 @@
  *     http://www.pulse-eight.net/
  */
 
-#include "AdapterDetection.h"
-#include "../platform/os.h"
+#include "USBCECAdapterDetection.h"
+#include "../platform/util/StdString.h"
 
 #if defined(__APPLE__)
 #include <dirent.h>
@@ -112,7 +112,7 @@ bool FindComPort(CStdString &strLocation)
 }
 #endif
 
-uint8_t CAdapterDetection::FindAdapters(cec_adapter *deviceList, uint8_t iBufSize, const char *strDevicePath /* = NULL */)
+uint8_t CUSBCECAdapterDetection::FindAdapters(cec_adapter *deviceList, uint8_t iBufSize, const char *strDevicePath /* = NULL */)
 {
   uint8_t iFound(0);
 
similarity index 92%
rename from src/lib/adapter/AdapterDetection.h
rename to src/lib/adapter/USBCECAdapterDetection.h
index 359a515e9fcfd69024995ac7730e209ad53d925c..45b641b476a47593938bec590e0097243bd7ff63 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * This file is part of the libCEC(R) library.
  *
- * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
  * libCEC(R) is an original work, containing original code.
  *
  * libCEC(R) is a trademark of Pulse-Eight Limited.
@@ -35,7 +35,7 @@
 
 namespace CEC
 {
-  class CAdapterDetection
+  class CUSBCECAdapterDetection
   {
   public:
     static uint8_t FindAdapters(cec_adapter *deviceList, uint8_t iBufSize, const char *strDevicePath = NULL); 
similarity index 95%
rename from src/lib/adapter/AdapterMessage.h
rename to src/lib/adapter/USBCECAdapterMessage.h
index ad81878ece635fb178957bfae38c93bde196ff54..ae41177b4f7ef4109cebd403c179009c0c585b15 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * This file is part of the libCEC(R) library.
  *
- * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
  * libCEC(R) is an original work, containing original code.
  *
  * libCEC(R) is a trademark of Pulse-Eight Limited.
  *     http://www.pulse-eight.net/
  */
 
+#include "../platform/util/StdString.h"
+
 namespace CEC
 {
-  typedef enum cec_adapter_message_state
-  {
-    ADAPTER_MESSAGE_STATE_UNKNOWN = 0,
-    ADAPTER_MESSAGE_STATE_WAITING_TO_BE_SENT,
-    ADAPTER_MESSAGE_STATE_SENT,
-    ADAPTER_MESSAGE_STATE_SENT_NOT_ACKED,
-    ADAPTER_MESSAGE_STATE_SENT_ACKED,
-    ADAPTER_MESSAGE_STATE_INCOMING,
-    ADAPTER_MESSAGE_STATE_ERROR
-  } cec_adapter_message_state;
-
-
   class CCECAdapterMessage
   {
   public:
@@ -228,6 +218,12 @@ namespace CEC
       case MSGCODE_FRAME_ACK:
         strMsg = "FRAME_ACK";
         break;
+      case MSGCODE_SET_POWERSTATE:
+        strMsg = "SET_POWERSTATE";
+        break;
+      case MSGCODE_SET_CONTROLLED:
+        strMsg = "SET_CONTROLLED";
+        break;
       }
 
       return strMsg;
@@ -263,6 +259,8 @@ namespace CEC
       reply               = MSGCODE_NOTHING;
       isTransmission      = true;
       expectControllerAck = true;
+      lineTimeout         = 3;
+      retryTimeout        = 3;
     }
 
     void Shift(uint8_t iShiftBy)
@@ -356,6 +354,8 @@ namespace CEC
     int32_t                   transmit_timeout;
     bool                      isTransmission;
     bool                      expectControllerAck;
+    uint8_t                   lineTimeout;
+    uint8_t                   retryTimeout;
     PLATFORM::CMutex          mutex;
     PLATFORM::CCondition      condition;
   };
index e8fbf8c46fbe0865c910ffab58b3d953d4870405..6d1d94827a50972c02f1c45c380952d6ab099dea 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the libCEC(R) library.
  *
- * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
  * libCEC(R) is an original work, containing original code.
  *
  * libCEC(R) is a trademark of Pulse-Eight Limited.
index dc35ef0f4f436c8cdb6999f4d52f4e50afdfc6e6..de2a0cc07d14d8e08bab5b21db2633880ecbb8dd 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * This file is part of the libCEC(R) library.
  *
- * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
  * libCEC(R) is an original work, containing original code.
  *
  * libCEC(R) is a trademark of Pulse-Eight Limited.
index 46e618c8ad952398b7517ae01e02a4a345daf956..2aa29c1d31c2f09818a4833ab100280f2c71ece5 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the libCEC(R) library.
  *
- * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
  * libCEC(R) is an original work, containing original code.
  *
  * libCEC(R) is a trademark of Pulse-Eight Limited.
@@ -37,6 +37,7 @@
 #include "../implementations/SLCommandHandler.h"
 #include "../implementations/VLCommandHandler.h"
 #include "../LibCEC.h"
+#include "../platform/util/timeutils.h"
 
 using namespace CEC;
 using namespace PLATFORM;
@@ -496,7 +497,7 @@ bool CCECBusDevice::TryLogicalAddress(void)
 {
   CLibCEC::AddLog(CEC_LOG_DEBUG, "trying logical address '%s'", GetLogicalAddressName());
 
-  m_processor->SetAckMask(0x1 << m_iLogicalAddress);
+  m_processor->SetAckMask(0);
   if (!TransmitPoll(m_iLogicalAddress))
   {
     CLibCEC::AddLog(CEC_LOG_NOTICE, "using logical address '%s'", GetLogicalAddressName());
@@ -833,4 +834,19 @@ bool CCECBusDevice::ActivateSource(void)
   return m_handler->ActivateSource();
 }
 
+void CCECBusDevice::HandlePoll(cec_logical_address iDestination)
+{
+  CLockObject lock(m_mutex);
+  CLibCEC::AddLog(CEC_LOG_DEBUG, "<< POLL: %s (%x) -> %s (%x)", ToString(m_iLogicalAddress), m_iLogicalAddress, ToString(iDestination), iDestination);
+  m_bAwaitingReceiveFailed = true;
+}
+
+bool CCECBusDevice::HandleReceiveFailed(void)
+{
+  CLockObject lock(m_handlerMutex);
+  bool bReturn = m_bAwaitingReceiveFailed;
+  m_bAwaitingReceiveFailed = false;
+  return bReturn;
+}
+
 //@}
index ba686322ca3fe9dab6c87b3817b3afa1f1306477..79ae987b654b1a72399cd0a2dd08b521bea8b3ce 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * This file is part of the libCEC(R) library.
  *
- * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
  * libCEC(R) is an original work, containing original code.
  *
  * libCEC(R) is a trademark of Pulse-Eight Limited.
@@ -33,7 +33,8 @@
 
 #include <cectypes.h>
 #include <set>
-#include "../platform/os.h"
+#include "../platform/threads/mutex.h"
+#include "../platform/util/StdString.h"
 
 namespace CEC
 {
@@ -75,6 +76,8 @@ namespace CEC
     virtual bool                  IsActiveSource(void) const { return m_bActiveSource; }
     virtual bool                  IsUnsupportedFeature(cec_opcode opcode) const;
     virtual void                  SetUnsupportedFeature(cec_opcode opcode);
+    virtual void                  HandlePoll(cec_logical_address initiator);
+    virtual bool                  HandleReceiveFailed(void);
 
     virtual void SetInactiveSource(void);
     virtual void SetActiveSource(void);
@@ -136,5 +139,6 @@ namespace CEC
     std::set<cec_opcode>  m_unsupportedFeatures;
     PLATFORM::CMutex      m_mutex;
     PLATFORM::CMutex      m_handlerMutex;
+    bool                  m_bAwaitingReceiveFailed;
   };
 };
index 86c1679cabe9e5bbb26b725ade214047c3224122..6f0a8487a8c268a92005691cdd3f96eb2580f228 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the libCEC(R) library.
  *
- * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
  * libCEC(R) is an original work, containing original code.
  *
  * libCEC(R) is a trademark of Pulse-Eight Limited.
index a188489efc9ba1a53512ffdb7f2dbee5fda5ad0c..c6f26ec152b524662797654495dbce3eca817d5d 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * This file is part of the libCEC(R) library.
  *
- * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
  * libCEC(R) is an original work, containing original code.
  *
  * libCEC(R) is a trademark of Pulse-Eight Limited.
index 702f7a47b40175261c02c01ef6cb515898759cb0..5639bc8dc920d29c057b46b3f541d039b60b908b 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the libCEC(R) library.
  *
- * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
  * libCEC(R) is an original work, containing original code.
  *
  * libCEC(R) is a trademark of Pulse-Eight Limited.
index c19b2d16f5aa7ebf0099c8a984f639e26792d1d0..d453e9c22218c4b08539ad0fa5a375f6fada146e 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * This file is part of the libCEC(R) library.
  *
- * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
  * libCEC(R) is an original work, containing original code.
  *
  * libCEC(R) is a trademark of Pulse-Eight Limited.
index 105ac7b63d2644d0e0660eeab69a4685e8699fa6..27df9b600869b9b53294824c626bb61fb3f2fed1 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the libCEC(R) library.
  *
- * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
  * libCEC(R) is an original work, containing original code.
  *
  * libCEC(R) is a trademark of Pulse-Eight Limited.
index c14075c79f18e384803ad711374ea5cd25c9216f..a90169e43f165baba663133d25f173177ca410f1 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * This file is part of the libCEC(R) library.
  *
- * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
  * libCEC(R) is an original work, containing original code.
  *
  * libCEC(R) is a trademark of Pulse-Eight Limited.
index 41b6c5eebaa1793c501efa18090c00f6de3214c8..b5de867d9e8a968fe4aeb644ce572ac5ca2330c5 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the libCEC(R) library.
  *
- * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
  * libCEC(R) is an original work, containing original code.
  *
  * libCEC(R) is a trademark of Pulse-Eight Limited.
index e74b3e5944aba6384dcfb1c9c22720c0b6ec5cef..2cf2ed2f6cbae0774782707483811ea1ee3b24fa 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * This file is part of the libCEC(R) library.
  *
- * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
  * libCEC(R) is an original work, containing original code.
  *
  * libCEC(R) is a trademark of Pulse-Eight Limited.
index 75d0a8c23c89f12c29134d48f25d7779a6fbe868..d3318a18dff928d103c86da4b586f8bc4247dc1c 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the libCEC(R) library.
  *
- * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
  * libCEC(R) is an original work, containing original code.
  *
  * libCEC(R) is a trademark of Pulse-Eight Limited.
@@ -46,7 +46,7 @@ CANCommandHandler::CANCommandHandler(CCECBusDevice *busDevice) :
 
 bool CANCommandHandler::HandleVendorRemoteButtonDown(const cec_command &command)
 {
-  if (m_processor->IsStarted() && command.parameters.size > 0)
+  if (m_processor->IsRunning() && command.parameters.size > 0)
   {
     cec_keypress key;
     key.duration = CEC_BUTTON_TIMEOUT;
index 8966c1a13fb4c986cdcb1e109d3d6da0f1cf700e..23b9de930b9434984def115a0f920ccd12220b7b 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * This file is part of the libCEC(R) library.
  *
- * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
  * libCEC(R) is an original work, containing original code.
  *
  * libCEC(R) is a trademark of Pulse-Eight Limited.
index ebd2ec24a829e008dfa55a6aa2c1fc02d9f787f6..0f006272e2d2d45d1a426350013f114ecf60489c 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the libCEC(R) library.
  *
- * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
  * libCEC(R) is an original work, containing original code.
  *
  * libCEC(R) is a trademark of Pulse-Eight Limited.
@@ -239,7 +239,7 @@ bool CCECCommandHandler::HandleDeviceCecVersion(const cec_command &command)
 
 bool CCECCommandHandler::HandleDeviceVendorCommandWithId(const cec_command &command)
 {
-  if (m_processor->IsStarted() && m_busDevice->MyLogicalAddressContains(command.destination))
+  if (m_processor->IsRunning() && m_busDevice->MyLogicalAddressContains(command.destination))
     m_processor->TransmitAbort(command.initiator, command.opcode, CEC_ABORT_REASON_REFUSED);
 
   return true;
@@ -261,7 +261,7 @@ bool CCECCommandHandler::HandleFeatureAbort(const cec_command &command)
 
 bool CCECCommandHandler::HandleGetCecVersion(const cec_command &command)
 {
-  if (m_processor->IsStarted() && m_busDevice->MyLogicalAddressContains(command.destination))
+  if (m_processor->IsRunning() && m_busDevice->MyLogicalAddressContains(command.destination))
   {
     CCECBusDevice *device = GetDevice(command.destination);
     if (device)
@@ -273,7 +273,7 @@ bool CCECCommandHandler::HandleGetCecVersion(const cec_command &command)
 
 bool CCECCommandHandler::HandleGiveAudioStatus(const cec_command &command)
 {
-  if (m_processor->IsStarted() && m_busDevice->MyLogicalAddressContains(command.destination))
+  if (m_processor->IsRunning() && m_busDevice->MyLogicalAddressContains(command.destination))
   {
     CCECBusDevice *device = GetDevice(command.destination);
     if (device && device->GetType() == CEC_DEVICE_TYPE_AUDIO_SYSTEM)
@@ -285,7 +285,7 @@ bool CCECCommandHandler::HandleGiveAudioStatus(const cec_command &command)
 
 bool CCECCommandHandler::HandleGiveDeckStatus(const cec_command &command)
 {
-  if (m_processor->IsStarted() && m_busDevice->MyLogicalAddressContains(command.destination))
+  if (m_processor->IsRunning() && m_busDevice->MyLogicalAddressContains(command.destination))
   {
     CCECBusDevice *device = GetDevice(command.destination);
     if (device && (device->GetType() == CEC_DEVICE_TYPE_PLAYBACK_DEVICE || device->GetType() == CEC_DEVICE_TYPE_RECORDING_DEVICE))
@@ -297,7 +297,7 @@ bool CCECCommandHandler::HandleGiveDeckStatus(const cec_command &command)
 
 bool CCECCommandHandler::HandleGiveDevicePowerStatus(const cec_command &command)
 {
-  if (m_processor->IsStarted() && m_busDevice->MyLogicalAddressContains(command.destination))
+  if (m_processor->IsRunning() && m_busDevice->MyLogicalAddressContains(command.destination))
   {
     CCECBusDevice *device = GetDevice(command.destination);
     if (device)
@@ -309,7 +309,7 @@ bool CCECCommandHandler::HandleGiveDevicePowerStatus(const cec_command &command)
 
 bool CCECCommandHandler::HandleGiveDeviceVendorId(const cec_command &command)
 {
-  if (m_processor->IsStarted() && m_busDevice->MyLogicalAddressContains(command.destination))
+  if (m_processor->IsRunning() && m_busDevice->MyLogicalAddressContains(command.destination))
   {
     CCECBusDevice *device = GetDevice(command.destination);
     if (device)
@@ -321,7 +321,7 @@ bool CCECCommandHandler::HandleGiveDeviceVendorId(const cec_command &command)
 
 bool CCECCommandHandler::HandleGiveOSDName(const cec_command &command)
 {
-  if (m_processor->IsStarted() && m_busDevice->MyLogicalAddressContains(command.destination))
+  if (m_processor->IsRunning() && m_busDevice->MyLogicalAddressContains(command.destination))
   {
     CCECBusDevice *device = GetDevice(command.destination);
     if (device)
@@ -333,7 +333,7 @@ bool CCECCommandHandler::HandleGiveOSDName(const cec_command &command)
 
 bool CCECCommandHandler::HandleGivePhysicalAddress(const cec_command &command)
 {
-  if (m_processor->IsStarted() && m_busDevice->MyLogicalAddressContains(command.destination))
+  if (m_processor->IsRunning() && m_busDevice->MyLogicalAddressContains(command.destination))
   {
     CCECBusDevice *device = GetDevice(command.destination);
     if (device)
@@ -349,7 +349,7 @@ bool CCECCommandHandler::HandleGivePhysicalAddress(const cec_command &command)
 
 bool CCECCommandHandler::HandleGiveSystemAudioModeStatus(const cec_command &command)
 {
-  if (m_processor->IsStarted() && m_busDevice->MyLogicalAddressContains(command.destination))
+  if (m_processor->IsRunning() && m_busDevice->MyLogicalAddressContains(command.destination))
   {
     CCECBusDevice *device = GetDevice(command.destination);
     if (device && device->GetType() == CEC_DEVICE_TYPE_AUDIO_SYSTEM)
@@ -367,7 +367,7 @@ bool CCECCommandHandler::HandleImageViewOn(const cec_command &command)
 
 bool CCECCommandHandler::HandleMenuRequest(const cec_command &command)
 {
-  if (m_processor->IsStarted() && m_busDevice->MyLogicalAddressContains(command.destination))
+  if (m_processor->IsRunning() && m_busDevice->MyLogicalAddressContains(command.destination))
   {
     if (command.parameters[0] == CEC_MENU_REQUEST_TYPE_QUERY)
     {
@@ -417,7 +417,7 @@ bool CCECCommandHandler::HandleReportPowerStatus(const cec_command &command)
 
 bool CCECCommandHandler::HandleRequestActiveSource(const cec_command &command)
 {
-  if (m_processor->IsStarted())
+  if (m_processor->IsRunning())
   {
     CLibCEC::AddLog(CEC_LOG_DEBUG, ">> %i requests active source", (uint8_t) command.initiator);
 
@@ -497,7 +497,7 @@ bool CCECCommandHandler::HandleSetOSDName(const cec_command &command)
 
 bool CCECCommandHandler::HandleSetStreamPath(const cec_command &command)
 {
-  if (m_processor->IsStarted() && command.parameters.size >= 2)
+  if (m_processor->IsRunning() && command.parameters.size >= 2)
   {
     uint16_t iStreamAddress = ((uint16_t)command.parameters[0] << 8) | ((uint16_t)command.parameters[1]);
     CLibCEC::AddLog(CEC_LOG_DEBUG, ">> %i sets stream path to physical address %04x", command.initiator, iStreamAddress);
@@ -508,6 +508,9 @@ bool CCECCommandHandler::HandleSetStreamPath(const cec_command &command)
     {
       device->SetActiveSource();
       device->TransmitActiveSource();
+
+      device->SetMenuState(CEC_MENU_STATE_ACTIVATED);
+      device->TransmitMenuState(command.initiator);
     }
   }
   return false;
@@ -515,7 +518,7 @@ bool CCECCommandHandler::HandleSetStreamPath(const cec_command &command)
 
 bool CCECCommandHandler::HandleSystemAudioModeRequest(const cec_command &command)
 {
-  if (m_processor->IsStarted() && m_busDevice->MyLogicalAddressContains(command.destination))
+  if (m_processor->IsRunning() && m_busDevice->MyLogicalAddressContains(command.destination))
   {
     CCECBusDevice *device = GetDevice(command.destination);
     if (device && device->GetType() == CEC_DEVICE_TYPE_AUDIO_SYSTEM)
@@ -587,7 +590,7 @@ bool CCECCommandHandler::HandleTextViewOn(const cec_command &command)
 
 bool CCECCommandHandler::HandleUserControlPressed(const cec_command &command)
 {
-  if (m_processor->IsStarted() && m_busDevice->MyLogicalAddressContains(command.destination) && command.parameters.size > 0)
+  if (m_processor->IsRunning() && m_busDevice->MyLogicalAddressContains(command.destination) && command.parameters.size > 0)
   {
     CLibCEC::AddKey();
 
@@ -623,7 +626,7 @@ bool CCECCommandHandler::HandleUserControlPressed(const cec_command &command)
 
 bool CCECCommandHandler::HandleUserControlRelease(const cec_command &command)
 {
-  if (m_processor->IsStarted() && m_busDevice->MyLogicalAddressContains(command.destination))
+  if (m_processor->IsRunning() && m_busDevice->MyLogicalAddressContains(command.destination))
     CLibCEC::AddKey();
 
   return true;
@@ -711,17 +714,6 @@ void CCECCommandHandler::SetPhysicalAddress(cec_logical_address iAddress, uint16
   }
 }
 
-void CCECCommandHandler::HandlePoll(const cec_logical_address iInitiator, const cec_logical_address iDestination)
-{
-  CLibCEC::AddLog(CEC_LOG_DEBUG, "<< POLL: %s (%x) -> %s (%x)", m_processor->ToString(iInitiator), iInitiator, m_processor->ToString(iDestination), iDestination);
-}
-
-bool CCECCommandHandler::HandleReceiveFailed(void)
-{
-  /* default = error */
-  return true;
-}
-
 bool CCECCommandHandler::TransmitImageViewOn(const cec_logical_address iInitiator, const cec_logical_address iDestination)
 {
   cec_command command;
@@ -907,6 +899,16 @@ bool CCECCommandHandler::TransmitSetSystemAudioMode(const cec_logical_address iI
   return Transmit(command, false);
 }
 
+bool CCECCommandHandler::TransmitSetStreamPath(uint16_t iStreamPath)
+{
+  cec_command command;
+  cec_command::Format(command, m_busDevice->GetLogicalAddress(), CECDEVICE_BROADCAST, CEC_OPCODE_SET_STREAM_PATH);
+  command.parameters.PushBack((uint8_t) ((iStreamPath >> 8) & 0xFF));
+  command.parameters.PushBack((uint8_t) (iStreamPath        & 0xFF));
+
+  return Transmit(command, false);
+}
+
 bool CCECCommandHandler::TransmitSystemAudioModeStatus(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_system_audio_status state)
 {
   cec_command command;
@@ -956,12 +958,11 @@ bool CCECCommandHandler::Transmit(cec_command &command, bool bExpectResponse /*
     while (!bReturn && ++iTries <= iMaxTries)
     {
       m_expectedResponse = expectedResponse;
-      if (m_processor->Transmit(command))
+      if ((bReturn = m_processor->Transmit(command)) == true)
       {
         CLibCEC::AddLog(CEC_LOG_DEBUG, "command transmitted");
-        bReturn = bExpectResponse ?
-            m_condition.Wait(m_receiveMutex, m_iTransmitWait) :
-            true;
+        if (bExpectResponse)
+          bReturn = m_condition.Wait(m_receiveMutex, m_iTransmitWait);
       }
     }
     --m_iUseCounter;
index f1e0924e9db5ebd0caa7ee2a71e3f21f8c91633d..e26530214617e4d90165fe86202ac1d20de72edc 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * This file is part of the libCEC(R) library.
  *
- * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
  * libCEC(R) is an original work, containing original code.
  *
  * libCEC(R) is a trademark of Pulse-Eight Limited.
@@ -33,7 +33,8 @@
 
 #include <cectypes.h>
 #include <vector>
-#include "../platform/os.h"
+#include "../platform/threads/mutex.h"
+#include "../platform/util/StdString.h"
 
 namespace CEC
 {
@@ -49,8 +50,6 @@ namespace CEC
     virtual bool HandleCommand(const cec_command &command);
     virtual cec_vendor_id GetVendorId(void) { return m_vendorId; };
     virtual void SetVendorId(cec_vendor_id vendorId) { m_vendorId = vendorId; }
-    virtual void HandlePoll(const cec_logical_address iInitiator, const cec_logical_address iDestination);
-    virtual bool HandleReceiveFailed(void);
     static bool HasSpecificHandler(cec_vendor_id vendorId) { return vendorId == CEC_VENDOR_LG || vendorId == CEC_VENDOR_SAMSUNG || vendorId == CEC_VENDOR_PANASONIC;}
 
     virtual bool InitHandler(void) { return true; }
@@ -81,6 +80,7 @@ namespace CEC
     virtual bool TransmitDeckStatus(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_deck_info state);
     virtual bool TransmitKeypress(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_user_control_code key, bool bWait = true);
     virtual bool TransmitKeyRelease(const cec_logical_address iInitiator, const cec_logical_address iDestination, bool bWait = true);
+    virtual bool TransmitSetStreamPath(uint16_t iStreamPath);
 
     virtual void MarkBusy(void);
     virtual bool MarkReady(void);
index 67018a8e82b60a5ee27f812994d9d610e5f762ac..c9fd65d3a544a762ed0060ff2db1c810f77f82d9 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the libCEC(R) library.
  *
- * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
  * libCEC(R) is an original work, containing original code.
  *
  * libCEC(R) is a trademark of Pulse-Eight Limited.
@@ -48,7 +48,6 @@ using namespace CEC;
 
 CSLCommandHandler::CSLCommandHandler(CCECBusDevice *busDevice) :
     CCECCommandHandler(busDevice),
-    m_bAwaitingReceiveFailed(false),
     m_bSLEnabled(false),
     m_bPowerStateReset(false)
 {
@@ -56,7 +55,7 @@ CSLCommandHandler::CSLCommandHandler(CCECBusDevice *busDevice) :
   CCECBusDevice *primary = m_processor->GetPrimaryDevice();
 
   /* imitate LG devices */
-  if (m_busDevice->GetLogicalAddress() != primary->GetLogicalAddress())
+  if (primary && m_busDevice->GetLogicalAddress() != primary->GetLogicalAddress())
     primary->SetVendorId(CEC_VENDOR_LG);
   SetLGDeckStatus();
 
@@ -71,24 +70,6 @@ CSLCommandHandler::CSLCommandHandler(CCECBusDevice *busDevice) :
   m_busDevice->SetMenuLanguage(lang);
 }
 
-
-void CSLCommandHandler::HandlePoll(const cec_logical_address iInitiator, const cec_logical_address iDestination)
-{
-  CCECCommandHandler::HandlePoll(iInitiator, iDestination);
-  m_bAwaitingReceiveFailed = true;
-}
-
-bool CSLCommandHandler::HandleReceiveFailed(void)
-{
-  if (m_bAwaitingReceiveFailed)
-  {
-    m_bAwaitingReceiveFailed = false;
-    return false;
-  }
-
-  return true;
-}
-
 bool CSLCommandHandler::InitHandler(void)
 {
   if (m_bHandlerInited)
@@ -139,7 +120,7 @@ bool CSLCommandHandler::HandleFeatureAbort(const cec_command &command)
 
 bool CSLCommandHandler::HandleGivePhysicalAddress(const cec_command &command)
 {
-  if (m_processor->IsStarted() && m_busDevice->MyLogicalAddressContains(command.destination))
+  if (m_processor->IsRunning() && m_busDevice->MyLogicalAddressContains(command.destination))
   {
     CCECBusDevice *device = GetDevice(command.destination);
     if (device)
index e398dc878d84af2030526b715a3835abaca45221..dae426605758b1e03b7f42535db9be55b588dae9 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * This file is part of the libCEC(R) library.
  *
- * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
  * libCEC(R) is an original work, containing original code.
  *
  * libCEC(R) is a trademark of Pulse-Eight Limited.
@@ -41,9 +41,6 @@ namespace CEC
     CSLCommandHandler(CCECBusDevice *busDevice);
     virtual ~CSLCommandHandler(void) {};
 
-    virtual void HandlePoll(const cec_logical_address iInitiator, const cec_logical_address iDestination);
-    virtual bool HandleReceiveFailed(void);
-
     virtual bool InitHandler(void);
     virtual bool ActivateSource(void);
 
@@ -64,7 +61,6 @@ namespace CEC
 
     virtual void SetLGDeckStatus(void);
 
-    bool    m_bAwaitingReceiveFailed;
     bool    m_bSLEnabled;
     bool    m_bPowerStateReset;
   };
index f0d59dbb0644b2bb3cae4f86d0a4f7d9910f40e6..ad4cf1717fb68a7f0bd0186e5caa54c99ee1f12d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the libCEC(R) library.
  *
- * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
  * libCEC(R) is an original work, containing original code.
  *
  * libCEC(R) is a trademark of Pulse-Eight Limited.
index cff1da4dfcdf3eb4aaad5966713fbdea614698eb..c3b0fe0337b261e5caf978d23076e9b12f929835 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * This file is part of the libCEC(R) library.
  *
- * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
  * libCEC(R) is an original work, containing original code.
  *
  * libCEC(R) is a trademark of Pulse-Eight Limited.
index fbe090342986ce0e7bc67fd5ad3099ce33994df6..4913d7b066244848fdabad850d58b0e8bd26dd38 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * This file is part of the libCEC(R) library.
  *
- * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
  * libCEC(R) is an original work, containing original code.
  *
  * libCEC(R) is a trademark of Pulse-Eight Limited.
  *     http://www.pulse-eight.net/
  */
 
-#if defined(_WIN32) || defined(_WIN64)
-#ifndef __WINDOWS__
-#define __WINDOWS__
-#endif
+#if (defined(_WIN32) || defined(_WIN64))
 #include "windows/os-types.h"
-#include "windows/os-threads.h"
 #else
 #include "posix/os-types.h"
-#include "posix/os-threads.h"
 #endif
-
-#include "timeutils.h"
-#include "threads/threads.h"
-#include "buffer.h"
-#include "StdString.h"
diff --git a/src/lib/platform/posix/os-socket.h b/src/lib/platform/posix/os-socket.h
new file mode 100644 (file)
index 0000000..468cc3d
--- /dev/null
@@ -0,0 +1,321 @@
+#pragma once
+/*
+ * This file is part of the libCEC(R) library.
+ *
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is an original work, containing original code.
+ *
+ * libCEC(R) is a trademark of Pulse-Eight Limited.
+ *
+ * This program is dual-licensed; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * Alternatively, you can license this library under a commercial license,
+ * please contact Pulse-Eight Licensing for more information.
+ *
+ * For more information contact:
+ * Pulse-Eight Licensing       <license@pulse-eight.com>
+ *     http://www.pulse-eight.com/
+ *     http://www.pulse-eight.net/
+ */
+
+
+#include "../os.h"
+#include "../util/timeutils.h"
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <poll.h>
+
+namespace PLATFORM
+{
+  // Standard sockets
+  //@{
+  inline void SocketClose(socket_t socket)
+  {
+    if (socket != INVALID_SOCKET_VALUE)
+      close(socket);
+  }
+
+  inline void SocketSetBlocking(socket_t socket, bool bSetTo)
+  {
+    if (socket != INVALID_SOCKET_VALUE)
+    {
+      if (bSetTo)
+        fcntl(socket, F_SETFL, fcntl(socket, F_GETFL) & ~O_NONBLOCK);
+      else
+        fcntl(socket, F_SETFL, fcntl(socket, F_GETFL) | O_NONBLOCK);
+    }
+  }
+
+  inline ssize_t SocketWrite(socket_t socket, int *iError, void* data, size_t len)
+  {
+    fd_set port;
+
+    if (socket == INVALID_SOCKET_VALUE)
+    {
+      *iError = EINVAL;
+      return -1;
+    }
+
+    ssize_t iBytesWritten(0);
+    struct timeval *tv(NULL);
+
+    while (iBytesWritten < (ssize_t)len)
+    {
+      FD_ZERO(&port);
+      FD_SET(socket, &port);
+      int returnv = select(socket + 1, NULL, &port, NULL, tv);
+      if (returnv < 0)
+      {
+        *iError = errno;
+        return -1;
+      }
+      else if (returnv == 0)
+      {
+        *iError = ETIMEDOUT;
+        return -1;
+      }
+
+      returnv = write(socket, (char*)data + iBytesWritten, len - iBytesWritten);
+      if (returnv == -1)
+      {
+        *iError = errno;
+        return -1;
+      }
+      iBytesWritten += returnv;
+    }
+
+    return iBytesWritten;
+  }
+
+  inline ssize_t SocketRead(socket_t socket, int *iError, void* data, size_t len, uint64_t iTimeoutMs /*= 0*/)
+  {
+    fd_set port;
+    struct timeval timeout, *tv;
+    int64_t iNow(0), iTarget(0);
+    ssize_t iBytesRead(0);
+    *iError = 0;
+
+    if (socket == INVALID_SOCKET_VALUE)
+    {
+      *iError = EINVAL;
+      return -1;
+    }
+
+    if (iTimeoutMs > 0)
+    {
+      iNow    = GetTimeMs();
+      iTarget = iNow + (int64_t) iTimeoutMs;
+    }
+
+    while (iBytesRead >= 0 && iBytesRead < (ssize_t)len && (iTimeoutMs == 0 || iTarget > iNow))
+    {
+      if (iTimeoutMs == 0)
+      {
+        tv = NULL;
+      }
+      else
+      {
+        timeout.tv_sec  = ((long int)iTarget - (long int)iNow) / (long int)1000.;
+        timeout.tv_usec = ((long int)iTarget - (long int)iNow) % (long int)1000.;
+        tv = &timeout;
+      }
+
+      FD_ZERO(&port);
+      FD_SET(socket, &port);
+      int32_t returnv = select(socket + 1, &port, NULL, NULL, tv);
+
+      if (returnv == -1)
+      {
+        *iError = errno;
+        return -1;
+      }
+      else if (returnv == 0)
+      {
+        break; //nothing to read
+      }
+
+      returnv = read(socket, (char*)data + iBytesRead, len - iBytesRead);
+      if (returnv == -1)
+      {
+        *iError = errno;
+        return -1;
+      }
+
+      iBytesRead += returnv;
+
+      if (iTimeoutMs > 0)
+        iNow = GetTimeMs();
+    }
+
+    return iBytesRead;
+  }
+  //@}
+
+  // TCP
+  //@{
+  inline void TcpSocketClose(tcp_socket_t socket)
+  {
+    SocketClose(socket);
+  }
+
+  inline void TcpSocketShutdown(tcp_socket_t socket)
+  {
+    if (socket != INVALID_SOCKET_VALUE)
+      shutdown(socket, SHUT_RDWR);
+  }
+
+  inline ssize_t TcpSocketWrite(tcp_socket_t socket, int *iError, void* data, size_t len)
+  {
+    if (socket == INVALID_SOCKET_VALUE)
+    {
+      *iError = EINVAL;
+      return -1;
+    }
+
+    ssize_t iReturn = send(socket, data, len, 0);
+    if (iReturn < (ssize_t)len)
+      *iError = errno;
+    return iReturn;
+  }
+
+  inline ssize_t TcpSocketRead(tcp_socket_t socket, int *iError, void* data, size_t len, uint64_t iTimeoutMs /*= 0*/)
+  {
+    int64_t iNow(0), iTarget(0);
+    ssize_t iBytesRead(0);
+    *iError = 0;
+
+    if (socket == INVALID_SOCKET_VALUE)
+    {
+      *iError = EINVAL;
+      return -1;
+    }
+
+    if (iTimeoutMs > 0)
+    {
+      iNow    = GetTimeMs();
+      iTarget = iNow + (int64_t) iTimeoutMs;
+    }
+
+    struct pollfd fds;
+    fds.fd = socket;
+    fds.events = POLLIN;
+    fds.revents = 0;
+
+    while (iBytesRead >= 0 && iBytesRead < (ssize_t)len && (iTimeoutMs == 0 || iTarget > iNow))
+    {
+      if (iTimeoutMs > 0)
+      {
+        int iPollResult = poll(&fds, 1, iTarget - iNow);
+        if (iPollResult == 0)
+        {
+          *iError = ETIMEDOUT;
+          return -ETIMEDOUT;
+        }
+      }
+
+      ssize_t iReadResult = (iTimeoutMs > 0) ?
+          recv(socket, (char*)data + iBytesRead, len - iBytesRead, MSG_DONTWAIT) :
+          recv(socket, data, len, MSG_WAITALL);
+      if (iReadResult < 0)
+      {
+        if (errno == EAGAIN && iTimeoutMs > 0)
+          continue;
+        *iError = errno;
+        return -errno;
+      }
+      else if (iReadResult == 0 || (iReadResult != (ssize_t)len && iTimeoutMs == 0))
+      {
+        *iError = ECONNRESET;
+        return -ECONNRESET;
+      }
+
+      iBytesRead += iReadResult;
+
+      if (iTimeoutMs > 0)
+        iNow = GetTimeMs();
+    }
+
+    if (iBytesRead < (ssize_t)len)
+      *iError = ETIMEDOUT;
+    return iBytesRead;
+  }
+
+  inline bool TcpResolveAddress(const char *strHost, uint16_t iPort, int *iError, struct addrinfo **info)
+  {
+    struct   addrinfo hints;
+    char     service[33];
+    memset(&hints, 0, sizeof(hints));
+    hints.ai_family   = AF_UNSPEC;
+    hints.ai_socktype = SOCK_STREAM;
+    hints.ai_protocol = IPPROTO_TCP;
+    sprintf(service, "%d", iPort);
+
+    *iError = getaddrinfo(strHost, service, &hints, info);
+    return !(*iError);
+  }
+
+  inline int TcpGetSocketError(tcp_socket_t socket)
+  {
+    int iReturn(0);
+    socklen_t optLen = sizeof(socket_t);
+    getsockopt(socket, SOL_SOCKET, SO_ERROR, (void *)&iReturn, &optLen);
+    return iReturn;
+  }
+
+  inline bool TcpSetNoDelay(tcp_socket_t socket)
+  {
+    int iSetTo(1);
+    setsockopt(socket, SOL_TCP, TCP_NODELAY, &iSetTo, sizeof(iSetTo));
+    return true;
+  }
+
+  inline bool TcpConnectSocket(tcp_socket_t socket, struct addrinfo* addr, int *iError, uint64_t iTimeout = 0)
+  {
+    *iError = 0;
+    int iConnectResult = connect(socket, addr->ai_addr, addr->ai_addrlen);
+    if (iConnectResult == -1)
+    {
+      if (errno == EINPROGRESS)
+      {
+        struct pollfd pfd;
+        pfd.fd = socket;
+        pfd.events = POLLOUT;
+        pfd.revents = 0;
+
+        int iPollResult = poll(&pfd, 1, iTimeout);
+        if (iPollResult == 0)
+          *iError = ETIMEDOUT;
+        else if (iPollResult == -1)
+          *iError = errno;
+
+        socklen_t errlen = sizeof(int);
+        getsockopt(socket, SOL_SOCKET, SO_ERROR, (void *)iError, &errlen);
+      }
+      else
+      {
+        *iError = errno;
+      }
+    }
+
+    return *iError == 0;
+  }
+  //@}
+}
index 9f7a688f26fbde241734b03989fb42222f1da7bb..48e1e355ca16e8ee18965852cda41bfd48329c63 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * This file is part of the libCEC(R) library.
  *
- * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
  * libCEC(R) is an original work, containing original code.
  *
  * libCEC(R) is a trademark of Pulse-Eight Limited.
@@ -69,19 +69,40 @@ namespace PLATFORM
   #define MutexTryLock(mutex)                      (pthread_mutex_trylock(&mutex) == 0)
   #define MutexUnlock(mutex)                       pthread_mutex_unlock(&mutex)
 
-  typedef pthread_cond_t condition_t;
-  #define ConditionCreate(cond)                    pthread_cond_init(&cond, NULL)
-  #define ConditionDelete(cond)                    pthread_cond_destroy(&cond)
-  #define ConditionSignal(cond)                    pthread_cond_signal(&cond)
-  #define ConditionBroadcast(cond)                 pthread_cond_broadcast(&cond)
-  inline bool ConditionWait(condition_t &cond, mutex_t &mutex, uint32_t iTimeout)
+  class CConditionImpl
   {
-    sched_yield();
-    if (iTimeout > 0)
+  public:
+    CConditionImpl(void)
     {
-      struct timespec timeout = GetAbsTime(iTimeout);
-      return (pthread_cond_timedwait(&cond, &mutex, &timeout) == 0);
+      pthread_cond_init(&m_condition, NULL);
     }
-    return (pthread_cond_wait(&cond, &mutex) == 0);
-  }
+
+    virtual ~CConditionImpl(void)
+    {
+      pthread_cond_destroy(&m_condition);
+    }
+
+    void Signal(void)
+    {
+      pthread_cond_signal(&m_condition);
+    }
+
+    void Broadcast(void)
+    {
+      pthread_cond_broadcast(&m_condition);
+    }
+
+    bool Wait(mutex_t &mutex, uint32_t iTimeoutMs)
+    {
+      sched_yield();
+      if (iTimeoutMs > 0)
+      {
+        struct timespec timeout = GetAbsTime(iTimeoutMs);
+        return (pthread_cond_timedwait(&m_condition, &mutex, &timeout) == 0);
+      }
+      return (pthread_cond_wait(&m_condition, &mutex) == 0);
+    }
+
+    pthread_cond_t m_condition;
+  };
 }
index 99bacb3a0ee868683384ab5e72843824516037cb..631e96508e963a9cfb1b88184e463fc80527d837 100644 (file)
@@ -1,21 +1,34 @@
 #pragma once
 /*
- *      Copyright (C) 2005-2011 Team XBMC
- *      http://www.xbmc.org
+ * This file is part of the libCEC(R) library.
  *
- *  This Program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2, or (at your option)
- *  any later version.
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is an original work, containing original code.
  *
- *  This Program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- *  GNU General Public License for more details.
+ * libCEC(R) is a trademark of Pulse-Eight Limited.
  *
- *  You should have received a copy of the GNU General Public License
- *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * This program is dual-licensed; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
  *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * Alternatively, you can license this library under a commercial license,
+ * please contact Pulse-Eight Licensing for more information.
+ *
+ * For more information contact:
+ * Pulse-Eight Licensing       <license@pulse-eight.com>
+ *     http://www.pulse-eight.com/
+ *     http://www.pulse-eight.net/
  */
 
 #define _FILE_OFFSET_BITS 64
@@ -33,3 +46,8 @@
 #define LIBTYPE
 #define DECLSPEC
 
+typedef int socket_t;
+typedef socket_t tcp_socket_t;
+#define INVALID_SOCKET_VALUE        (-1)
+typedef socket_t serial_socket_t;
+#define INVALID_SERIAL_SOCKET_VALUE (-1)
index ec8a5c1d48e2f4ea14160ab5bd51719de318a81b..5557064555be90200cc2eeb7873522f6c1de9359 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the libCEC(R) library.
  *
- * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
  * libCEC(R) is an original work, containing original code.
  *
  * libCEC(R) is a trademark of Pulse-Eight Limited.
  *     http://www.pulse-eight.net/
  */
 
+#include "../os.h"
 #include <stdio.h>
 #include <fcntl.h>
-#include "../serialport/serialport.h"
-#include "../serialport/baudrate.h"
-#include "../timeutils.h"
+#include "../sockets/serialport.h"
+#include "../util/baudrate.h"
+#include "../posix/os-socket.h"
 
 #if defined(__APPLE__)
 #ifndef XCASE
 using namespace std;
 using namespace PLATFORM;
 
-CSerialPort::CSerialPort()
+void CSerialSocket::Close(void)
 {
-  m_fd = -1;
-  m_tostdout = false;
+  SocketClose(m_socket);
 }
 
-CSerialPort::~CSerialPort()
+void CSerialSocket::Shutdown(void)
 {
-  Close();
+  SocketClose(m_socket);
 }
 
-int64_t CSerialPort::Write(uint8_t* data, uint32_t len)
+ssize_t CSerialSocket::Write(void* data, size_t len)
 {
-  fd_set port;
-
-  CLockObject lock(m_mutex);
-  if (m_fd == -1)
-  {
-    m_error = "port closed";
-    return -1;
-  }
-
-  int64_t byteswritten = 0;
-  struct timeval *tv;
-//TODO
-//  struct timeval timeout, *tv;
-//  if (data->transmit_timeout <= 0)
-//  {
-    tv = NULL;
-//  }
-//  else
-//  {
-//    timeout.tv_sec  = (long int)data->transmit_timeout / (long int)1000.;
-//    timeout.tv_usec = (long int)data->transmit_timeout % (long int)1000.;
-//    tv = &timeout;
-//  }
-
-  while (byteswritten < len)
-  {
-    FD_ZERO(&port);
-    FD_SET(m_fd, &port);
-    int returnv = select(m_fd + 1, NULL, &port, NULL, tv);
-    if (returnv < 0)
-    {
-      m_error = strerror(errno);
-      return -1;
-    }
-    else if (returnv == 0)
-    {
-      m_error = "timeout";
-      return -1;
-    }
-
-    returnv = write(m_fd, data + byteswritten, len - byteswritten);
-    if (returnv == -1)
-    {
-      m_error = strerror(errno);
-      return -1;
-    }
-    byteswritten += returnv;
-  }
-
-  //print what's written to stdout for debugging
-  if (m_tostdout)
-  {
-    printf("%s write:", m_name.c_str());
-    for (int i = 0; i < byteswritten; i++)
-      printf(" %02x", data[i]);
-
-    printf("\n");
-  }
-
-  return byteswritten;
+  return SocketWrite(m_socket, &m_iError, data, len);
 }
 
-int32_t CSerialPort::Read(uint8_t* data, uint32_t len, uint64_t iTimeoutMs /*= 0*/)
+ssize_t CSerialSocket::Read(void* data, size_t len, uint64_t iTimeoutMs /* = 0 */)
 {
-  fd_set port;
-  struct timeval timeout, *tv;
-  int64_t now(0), target(0);
-  int32_t bytesread = 0;
-
-  CLockObject lock(m_mutex);
-  if (m_fd == -1)
-  {
-    m_error = "port closed";
-    return -1;
-  }
-
-  if (iTimeoutMs > 0)
-  {
-    now    = GetTimeMs();
-    target = now + (int64_t) iTimeoutMs;
-  }
-
-  while (bytesread < (int32_t) len && (iTimeoutMs == 0 || target > now))
-  {
-    if (iTimeoutMs == 0)
-    {
-      tv = NULL;
-    }
-    else
-    {
-      timeout.tv_sec  = ((long int)target - (long int)now) / (long int)1000.;
-      timeout.tv_usec = ((long int)target - (long int)now) % (long int)1000.;
-      tv = &timeout;
-    }
-
-    FD_ZERO(&port);
-    FD_SET(m_fd, &port);
-    int32_t returnv = select(m_fd + 1, &port, NULL, NULL, tv);
-
-    if (returnv == -1)
-    {
-      m_error = strerror(errno);
-      return -1;
-    }
-    else if (returnv == 0)
-    {
-      break; //nothing to read
-    }
-
-    returnv = read(m_fd, data + bytesread, len - bytesread);
-    if (returnv == -1)
-    {
-      m_error = strerror(errno);
-      return -1;
-    }
-
-    bytesread += returnv;
-
-    if (iTimeoutMs > 0)
-      now = GetTimeMs();
-  }
-
-  //print what's read to stdout for debugging
-  if (m_tostdout && bytesread > 0)
-  {
-    printf("%s read:", m_name.c_str());
-    for (int i = 0; i < bytesread; i++)
-      printf(" %02x", data[i]);
-
-    printf("\n");
-  }
-
-  return bytesread;
+  return SocketRead(m_socket, &m_iError, data, len, iTimeoutMs);
 }
 
 //setting all this stuff up is a pain in the ass
-bool CSerialPort::Open(string name, uint32_t baudrate, uint8_t databits /* = 8 */, uint8_t stopbits /* = 1 */, uint8_t parity /* = PAR_NONE */)
+bool CSerialSocket::Open(uint64_t iTimeoutMs /* = 0 */)
 {
-  m_name = name;
-  m_error = strerror(errno);
+  iTimeoutMs = 0;
   CLockObject lock(m_mutex);
 
-  if (databits < 5 || databits > 8)
+  if (m_iDatabits != SERIAL_DATA_BITS_FIVE && m_iDatabits != SERIAL_DATA_BITS_SIX &&
+      m_iDatabits != SERIAL_DATA_BITS_SEVEN && m_iDatabits != SERIAL_DATA_BITS_EIGHT)
   {
-    m_error = "Databits has to be between 5 and 8";
+    m_strError = "Databits has to be between 5 and 8";
     return false;
   }
 
-  if (stopbits != 1 && stopbits != 2)
+  if (m_iStopbits != SERIAL_STOP_BITS_ONE && m_iStopbits != SERIAL_STOP_BITS_TWO)
   {
-    m_error = "Stopbits has to be 1 or 2";
+    m_strError = "Stopbits has to be 1 or 2";
     return false;
   }
 
-  if (parity != PAR_NONE && parity != PAR_EVEN && parity != PAR_ODD)
+  if (m_iParity != SERIAL_PARITY_NONE && m_iParity != SERIAL_PARITY_EVEN && m_iParity != SERIAL_PARITY_ODD)
   {
-    m_error = "Parity has to be none, even or odd";
+    m_strError = "Parity has to be none, even or odd";
     return false;
   }
 
-  m_fd = open(name.c_str(), O_RDWR | O_NOCTTY | O_NDELAY);
+  m_socket = open(m_strName.c_str(), O_RDWR | O_NOCTTY | O_NDELAY);
 
-  if (m_fd == -1)
+  if (m_socket == INVALID_SERIAL_SOCKET_VALUE)
   {
-    m_error = strerror(errno);
+    m_strError = strerror(errno);
     return false;
   }
 
-  fcntl(m_fd, F_SETFL, 0);
+  SocketSetBlocking(m_socket, false);
 
-  if (!SetBaudRate(baudrate))
-  {
+  if (!SetBaudRate(m_iBaudrate))
     return false;
-  }
 
   m_options.c_cflag |= (CLOCAL | CREAD);
   m_options.c_cflag &= ~HUPCL;
 
   m_options.c_cflag &= ~CSIZE;
-  if (databits == 5) m_options.c_cflag |= CS5;
-  if (databits == 6) m_options.c_cflag |= CS6;
-  if (databits == 7) m_options.c_cflag |= CS7;
-  if (databits == 8) m_options.c_cflag |= CS8;
+  if (m_iDatabits == SERIAL_DATA_BITS_FIVE)  m_options.c_cflag |= CS5;
+  if (m_iDatabits == SERIAL_DATA_BITS_SIX)   m_options.c_cflag |= CS6;
+  if (m_iDatabits == SERIAL_DATA_BITS_SEVEN) m_options.c_cflag |= CS7;
+  if (m_iDatabits == SERIAL_DATA_BITS_EIGHT) m_options.c_cflag |= CS8;
 
   m_options.c_cflag &= ~PARENB;
-  if (parity == PAR_EVEN || parity == PAR_ODD)
+  if (m_iParity == SERIAL_PARITY_EVEN || m_iParity == SERIAL_PARITY_ODD)
     m_options.c_cflag |= PARENB;
-  if (parity == PAR_ODD)
+  if (m_iParity == SERIAL_PARITY_ODD)
     m_options.c_cflag |= PARODD;
 
 #ifdef CRTSCTS
@@ -259,83 +130,61 @@ bool CSerialPort::Open(string name, uint32_t baudrate, uint8_t databits /* = 8 *
   m_options.c_cflag &= ~CNEW_RTSCTS;
 #endif
 
-  if (stopbits == 1) m_options.c_cflag &= ~CSTOPB;
+  if (m_iStopbits == SERIAL_STOP_BITS_ONE) m_options.c_cflag &= ~CSTOPB;
   else m_options.c_cflag |= CSTOPB;
   
   //I guessed a little here
   m_options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG | XCASE | ECHOK | ECHONL | ECHOCTL | ECHOPRT | ECHOKE | TOSTOP);
 
-  if (parity == PAR_NONE)
-  {
+  if (m_iParity == SERIAL_PARITY_NONE)
     m_options.c_iflag &= ~INPCK;
-  }
   else
-  {
     m_options.c_iflag |= INPCK | ISTRIP;
-  }
 
   m_options.c_iflag &= ~(IXON | IXOFF | IXANY | BRKINT | INLCR | IGNCR | ICRNL | IUCLC | IMAXBEL);
   m_options.c_oflag &= ~(OPOST | ONLCR | OCRNL);
 
-  if (tcsetattr(m_fd, TCSANOW, &m_options) != 0)
+  if (tcsetattr(m_socket, TCSANOW, &m_options) != 0)
   {
-    m_error = strerror(errno);
+    m_strError = strerror(errno);
     return false;
   }
   
-  //non-blocking port
-  fcntl(m_fd, F_SETFL, FNDELAY);
+  SocketSetBlocking(m_socket, true);
+  m_bIsOpen = true;
 
   return true;
 }
 
-void CSerialPort::Close()
-{
-  CLockObject lock(m_mutex);
-  if (m_fd != -1)
-  {
-    close(m_fd);
-    m_fd = -1;
-    m_name = "";
-    m_error = "";
-  }
-}
-
-bool CSerialPort::SetBaudRate(uint32_t baudrate)
+bool CSerialSocket::SetBaudRate(uint32_t baudrate)
 {
   int rate = IntToBaudrate(baudrate);
   if (rate == -1)
   {
     char buff[255];
     sprintf(buff, "%i is not a valid baudrate", baudrate);
-    m_error = buff;
+    m_strError = buff;
     return false;
   }
-  
+
   //get the current port attributes
-  if (tcgetattr(m_fd, &m_options) != 0)
+  if (tcgetattr(m_socket, &m_options) != 0)
   {
-    m_error = strerror(errno);
+    m_strError = strerror(errno);
     return false;
   }
 
   if (cfsetispeed(&m_options, rate) != 0)
   {
-    m_error = strerror(errno);
+    m_strError = strerror(errno);
     return false;
   }
-  
+
   if (cfsetospeed(&m_options, rate) != 0)
   {
-    m_error = strerror(errno);
+    m_strError = strerror(errno);
     return false;
   }
 
   return true;
 }
-
-bool CSerialPort::IsOpen()
-{
-  CLockObject lock(m_mutex);
-  return m_fd != -1;
-}
diff --git a/src/lib/platform/serialport/serialport.h b/src/lib/platform/serialport/serialport.h
deleted file mode 100644 (file)
index 3710bfe..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-#pragma once
-/*
- * This file is part of the libCEC(R) library.
- *
- * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
- * libCEC(R) is an original work, containing original code.
- *
- * libCEC(R) is a trademark of Pulse-Eight Limited.
- *
- * This program is dual-licensed; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- *
- * Alternatively, you can license this library under a commercial license,
- * please contact Pulse-Eight Licensing for more information.
- *
- * For more information contact:
- * Pulse-Eight Licensing       <license@pulse-eight.com>
- *     http://www.pulse-eight.com/
- *     http://www.pulse-eight.net/
- */
-
-#include "../os.h"
-#include <string>
-#include <stdint.h>
-
-#ifndef __WINDOWS__
-#include <termios.h>
-#endif
-
-namespace PLATFORM
-{
-  #define PAR_NONE 0
-  #define PAR_EVEN 1
-  #define PAR_ODD  2
-
-  class CSerialPort
-  {
-    public:
-      CSerialPort();
-      virtual ~CSerialPort();
-
-      bool Open(std::string name, uint32_t baudrate, uint8_t databits = 8, uint8_t stopbits = 1, uint8_t parity = PAR_NONE);
-      bool IsOpen();
-      void Close();
-
-      int64_t Write(uint8_t* data, uint32_t len);
-      int32_t Read(uint8_t* data, uint32_t len, uint64_t iTimeoutMs = 0);
-
-      std::string GetError() { return m_error; }
-      std::string GetName() { return m_name; }
-
-  private:
-      bool SetBaudRate(uint32_t baudrate);
-
-      std::string  m_error;
-      std::string  m_name;
-      CMutex       m_mutex;
-      bool         m_tostdout;
-
-  #ifdef __WINDOWS__
-      bool SetTimeouts(bool bBlocking);
-
-      HANDLE                m_handle;
-      bool                  m_bIsOpen;
-      uint32_t              m_iBaudrate;
-      uint8_t               m_iDatabits;
-      uint8_t               m_iStopbits;
-      uint8_t               m_iParity;
-      int64_t               m_iTimeout;
-      SyncedBuffer<uint8_t> m_buffer;
-      HANDLE                m_ovHandle;
-  #else
-      struct termios     m_options;
-      int                m_fd;
-  #endif
-  };
-};
diff --git a/src/lib/platform/sockets/serialport.h b/src/lib/platform/sockets/serialport.h
new file mode 100644 (file)
index 0000000..c74cc05
--- /dev/null
@@ -0,0 +1,115 @@
+#pragma once
+/*
+ * This file is part of the libCEC(R) library.
+ *
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is an original work, containing original code.
+ *
+ * libCEC(R) is a trademark of Pulse-Eight Limited.
+ *
+ * This program is dual-licensed; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * Alternatively, you can license this library under a commercial license,
+ * please contact Pulse-Eight Licensing for more information.
+ *
+ * For more information contact:
+ * Pulse-Eight Licensing       <license@pulse-eight.com>
+ *     http://www.pulse-eight.com/
+ *     http://www.pulse-eight.net/
+ */
+
+#include "../os.h"
+#include "../util/buffer.h"
+
+#include <string>
+#include <stdint.h>
+
+#if !defined(__WINDOWS__)
+#include <termios.h>
+#endif
+
+#include "socket.h"
+
+namespace PLATFORM
+{
+  enum SerialParity
+  {
+    SERIAL_PARITY_NONE = 0,
+    SERIAL_PARITY_EVEN,
+    SERIAL_PARITY_ODD
+  };
+
+  enum SerialStopBits
+  {
+    SERIAL_STOP_BITS_ONE = 1,
+    SERIAL_STOP_BITS_TWO = 2
+  };
+
+  enum SerialDataBits
+  {
+    SERIAL_DATA_BITS_FIVE  = 5,
+    SERIAL_DATA_BITS_SIX   = 6,
+    SERIAL_DATA_BITS_SEVEN = 7,
+    SERIAL_DATA_BITS_EIGHT = 8
+  };
+
+  class CSerialSocket : public CCommonSocket<serial_socket_t>
+  {
+    public:
+      CSerialSocket(const CStdString &strName, uint32_t iBaudrate, SerialDataBits iDatabits = SERIAL_DATA_BITS_EIGHT, SerialStopBits iStopbits = SERIAL_STOP_BITS_ONE, SerialParity iParity = SERIAL_PARITY_NONE) :
+          CCommonSocket<serial_socket_t>(INVALID_SERIAL_SOCKET_VALUE, strName),
+          m_bIsOpen(false),
+          m_iBaudrate(iBaudrate),
+          m_iDatabits(iDatabits),
+          m_iStopbits(iStopbits),
+          m_iParity(iParity) {}
+
+      virtual ~CSerialSocket(void) {}
+
+      virtual bool Open(uint64_t iTimeoutMs = 0);
+      virtual void Close(void);
+      virtual void Shutdown(void);
+      virtual ssize_t Write(void* data, size_t len);
+      virtual ssize_t Read(void* data, size_t len, uint64_t iTimeoutMs = 0);
+
+      virtual bool IsOpen(void)
+      {
+        return m_socket != INVALID_SERIAL_SOCKET_VALUE &&
+            m_bIsOpen;
+      }
+
+      virtual bool SetBaudRate(uint32_t baudrate);
+
+    protected:
+  #ifndef __WINDOWS__
+      struct termios  m_options;
+  #endif
+
+      bool            m_bIsOpen;
+      uint32_t        m_iBaudrate;
+      SerialDataBits  m_iDatabits;
+      SerialStopBits  m_iStopbits;
+      SerialParity    m_iParity;
+  };
+
+  class CSerialPort : public CProtectedSocket<CSerialSocket>
+  {
+  public:
+    CSerialPort(const CStdString &strName, uint32_t iBaudrate, SerialDataBits iDatabits = SERIAL_DATA_BITS_EIGHT, SerialStopBits iStopbits = SERIAL_STOP_BITS_ONE, SerialParity iParity = SERIAL_PARITY_NONE) :
+      CProtectedSocket<CSerialSocket> (new CSerialSocket(strName, iBaudrate, iDatabits, iStopbits, iParity)) {}
+    virtual ~CSerialPort(void) {}
+  };
+};
diff --git a/src/lib/platform/sockets/socket.h b/src/lib/platform/sockets/socket.h
new file mode 100644 (file)
index 0000000..388bb2d
--- /dev/null
@@ -0,0 +1,234 @@
+#pragma once
+/*
+ * This file is part of the libCEC(R) library.
+ *
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is an original work, containing original code.
+ *
+ * libCEC(R) is a trademark of Pulse-Eight Limited.
+ *
+ * This program is dual-licensed; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * Alternatively, you can license this library under a commercial license,
+ * please contact Pulse-Eight Licensing for more information.
+ *
+ * For more information contact:
+ * Pulse-Eight Licensing       <license@pulse-eight.com>
+ *     http://www.pulse-eight.com/
+ *     http://www.pulse-eight.net/
+ */
+
+#include "../threads/mutex.h"
+#include "../util/StdString.h"
+
+#if defined(__WINDOWS__)
+#include "../windows/os-socket.h"
+#else
+#include "../posix/os-socket.h"
+#endif
+
+// Common socket operations
+
+namespace PLATFORM
+{
+  class ISocket : public PreventCopy
+  {
+  public:
+    ISocket(void) {};
+    virtual ~ISocket(void) {}
+
+    virtual bool Open(uint64_t iTimeoutMs = 0) = 0;
+    virtual void Close(void) = 0;
+    virtual void Shutdown(void) = 0;
+    virtual bool IsOpen(void) = 0;
+    virtual ssize_t Write(void* data, size_t len) = 0;
+    virtual ssize_t Read(void* data, size_t len, uint64_t iTimeoutMs = 0) = 0;
+    virtual CStdString GetError(void) = 0;
+    virtual int GetErrorNumber(void) = 0;
+    virtual CStdString GetName(void) = 0;
+  };
+
+  template <typename _SType>
+  class CCommonSocket : public ISocket
+  {
+  public:
+    CCommonSocket(_SType initialSocketValue, const CStdString &strName) :
+      m_socket(initialSocketValue),
+      m_strName(strName),
+      m_iError(0) {}
+
+    virtual ~CCommonSocket(void) {}
+
+    virtual CStdString GetError(void)
+    {
+      CStdString strError;
+      strError = m_strError.IsEmpty() && m_iError != 0 ? strerror(m_iError) : m_strError;
+      return strError;
+    }
+
+    virtual int GetErrorNumber(void)
+    {
+      return m_iError;
+    }
+
+    virtual CStdString GetName(void)
+    {
+      CStdString strName;
+      strName = m_strName;
+      return strName;
+    }
+
+  protected:
+    _SType     m_socket;
+    CStdString m_strError;
+    CStdString m_strName;
+    int        m_iError;
+    CMutex     m_mutex;
+  };
+
+  template <typename _Socket>
+  class CProtectedSocket : public ISocket
+  {
+  public:
+    CProtectedSocket(_Socket *socket) :
+      m_socket(socket),
+      m_iUseCount(0) {}
+
+    virtual ~CProtectedSocket(void)
+    {
+      Close();
+      delete m_socket;
+    }
+
+    virtual bool Open(uint64_t iTimeoutMs = 0)
+    {
+      bool bReturn(false);
+      if (m_socket && WaitReady())
+      {
+        bReturn = m_socket->Open(iTimeoutMs);
+        MarkReady();
+      }
+      return bReturn;
+    }
+
+    virtual void Close(void)
+    {
+      if (m_socket && WaitReady())
+      {
+        m_socket->Close();
+        MarkReady();
+      }
+    }
+
+    virtual void Shutdown(void)
+    {
+      if (m_socket && WaitReady())
+      {
+        m_socket->Shutdown();
+        MarkReady();
+      }
+    }
+
+    virtual bool IsOpen(void)
+    {
+      CLockObject lock(m_mutex);
+      return m_socket && m_socket->IsOpen();
+    }
+
+    virtual bool IsBusy(void)
+    {
+      CLockObject lock(m_mutex);
+      return m_socket && m_iUseCount > 0;
+    }
+
+    virtual int GetUseCount(void)
+    {
+      CLockObject lock(m_mutex);
+      return m_iUseCount;
+    }
+
+    virtual ssize_t Write(void* data, size_t len)
+    {
+      if (!m_socket || !WaitReady())
+        return EINVAL;
+
+      ssize_t iReturn = m_socket->Write(data, len);
+      MarkReady();
+
+      return iReturn;
+    }
+
+    virtual ssize_t Read(void* data, size_t len, uint64_t iTimeoutMs = 0)
+    {
+      if (!m_socket || !WaitReady())
+        return EINVAL;
+
+      ssize_t iReturn = m_socket->Read(data, len, iTimeoutMs);
+      MarkReady();
+
+      return iReturn;
+    }
+
+    virtual CStdString GetError(void)
+    {
+      CStdString strError;
+      CLockObject lock(m_mutex);
+      strError = m_socket ? m_socket->GetError() : "";
+      return strError;
+    }
+
+    virtual int GetErrorNumber(void)
+    {
+      CLockObject lock(m_mutex);
+      return m_socket ? m_socket->GetErrorNumber() : EINVAL;
+    }
+
+    virtual CStdString GetName(void)
+    {
+      CStdString strName;
+      CLockObject lock(m_mutex);
+      strName = m_socket ? m_socket->GetName() : "";
+      return strName;
+    }
+
+  private:
+    bool WaitReady(void)
+    {
+      CLockObject lock(m_mutex);
+      if (m_iUseCount > 0)
+        m_condition.Wait(m_mutex);
+
+      if (m_iUseCount > 0)
+        return false;
+
+      ++m_iUseCount;
+      return true;
+    }
+
+    void MarkReady(void)
+    {
+      CLockObject lock(m_mutex);
+      if (m_iUseCount > 0)
+        --m_iUseCount;
+      m_condition.Broadcast();
+    }
+
+    _Socket   *m_socket;
+    CMutex     m_mutex;
+    CCondition m_condition;
+    int        m_iUseCount;
+  };
+};
diff --git a/src/lib/platform/sockets/tcp.h b/src/lib/platform/sockets/tcp.h
new file mode 100644 (file)
index 0000000..ffc372c
--- /dev/null
@@ -0,0 +1,130 @@
+#pragma once
+/*
+ * This file is part of the libCEC(R) library.
+ *
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is an original work, containing original code.
+ *
+ * libCEC(R) is a trademark of Pulse-Eight Limited.
+ *
+ * This program is dual-licensed; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * Alternatively, you can license this library under a commercial license,
+ * please contact Pulse-Eight Licensing for more information.
+ *
+ * For more information contact:
+ * Pulse-Eight Licensing       <license@pulse-eight.com>
+ *     http://www.pulse-eight.com/
+ *     http://www.pulse-eight.net/
+ */
+
+#include "socket.h"
+
+using namespace std;
+
+namespace PLATFORM
+{
+  class CTcpSocket : public CCommonSocket<tcp_socket_t>
+  {
+    public:
+      CTcpSocket(const CStdString &strHostname, uint16_t iPort) :
+        CCommonSocket<tcp_socket_t>(INVALID_SOCKET_VALUE, strHostname),
+        m_iPort(iPort) {}
+
+      virtual ~CTcpSocket(void) {}
+
+      virtual bool Open(uint64_t iTimeoutMs = 0)
+      {
+        bool bReturn(false);
+        struct addrinfo *address(NULL), *addr(NULL);
+        if (!TcpResolveAddress(m_strName.c_str(), m_iPort, &m_iError, &address))
+        {
+          m_strError = strerror(m_iError);
+          return bReturn;
+        }
+
+        for(addr = address; !bReturn && addr; addr = addr->ai_next)
+        {
+          m_socket = TcpCreateSocket(addr, &m_iError, iTimeoutMs);
+          if (m_socket != INVALID_SOCKET_VALUE)
+            bReturn = true;
+          else
+            m_strError = strerror(m_iError);
+        }
+
+        freeaddrinfo(address);
+        return bReturn;
+      }
+
+      virtual void Close(void)
+      {
+        TcpSocketClose(m_socket);
+        m_socket = INVALID_SOCKET_VALUE;
+      }
+
+      virtual void Shutdown(void)
+      {
+        TcpSocketShutdown(m_socket);
+        m_socket = INVALID_SOCKET_VALUE;
+      }
+
+      virtual ssize_t Write(void* data, size_t len)
+      {
+        return TcpSocketWrite(m_socket, &m_iError, data, len);
+      }
+
+      virtual ssize_t Read(void* data, size_t len, uint64_t iTimeoutMs = 0)
+      {
+        return TcpSocketRead(m_socket, &m_iError, data, len, iTimeoutMs);
+      }
+
+      virtual bool IsOpen(void)
+      {
+        return m_socket != INVALID_SOCKET_VALUE;
+      }
+
+    protected:
+      virtual tcp_socket_t TcpCreateSocket(struct addrinfo* addr, int* iError, uint64_t iTimeout)
+      {
+        tcp_socket_t fdSock = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
+        if (fdSock == INVALID_SOCKET_VALUE)
+        {
+          *iError = errno;
+          return (tcp_socket_t)INVALID_SOCKET_VALUE;
+        }
+
+        if (!TcpConnectSocket(fdSock, addr, iError, iTimeout))
+        {
+          TcpSocketClose(fdSock);
+          return (tcp_socket_t)INVALID_SOCKET_VALUE;
+        }
+
+        TcpSetNoDelay(fdSock);
+
+        return fdSock;
+      }
+
+      uint16_t   m_iPort;
+  };
+
+  class CTcpConnection : public CProtectedSocket<CTcpSocket>
+  {
+  public:
+    CTcpConnection(const CStdString &strHostname, uint16_t iPort) :
+      CProtectedSocket<CTcpSocket> (new CTcpSocket(strHostname, iPort)) {}
+    virtual ~CTcpConnection(void) {}
+  };
+};
index 2c2b5c569819a669353712c1968cfa14bab9cbae..d44c0f1953b532da1cfd81a22eaac01bf0fe4048 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * This file is part of the libCEC(R) library.
  *
- * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
  * libCEC(R) is an original work, containing original code.
  *
  * libCEC(R) is a trademark of Pulse-Eight Limited.
  *     http://www.pulse-eight.net/
  */
 
+#include "../os.h"
+
+#if defined(__WINDOWS__)
+#include "../windows/os-threads.h"
+#else
+#include "../posix/os-threads.h"
+#endif
+
 namespace PLATFORM
 {
   class PreventCopy
@@ -158,30 +166,25 @@ namespace PLATFORM
   class CCondition : public PreventCopy
   {
   public:
-    inline CCondition(void)
-    {
-      ConditionCreate(m_condition);
-    }
-
+    inline CCondition(void) {}
     inline ~CCondition(void)
     {
-      Broadcast();
-      ConditionDelete(m_condition);
+      m_condition.Broadcast();
     }
 
     inline void Broadcast(void)
     {
-      ConditionBroadcast(m_condition);
+      m_condition.Broadcast();
     }
 
     inline void Signal(void)
     {
-      ConditionSignal(m_condition);
+      m_condition.Signal();
     }
 
     inline bool Wait(CMutex &mutex, uint32_t iTimeout = 0)
     {
-      return ConditionWait(m_condition, mutex.m_mutex, iTimeout);
+      return m_condition.Wait(mutex.m_mutex, iTimeout);
     }
 
     static void Sleep(uint32_t iTimeout)
@@ -192,6 +195,7 @@ namespace PLATFORM
       w.Wait(m, iTimeout);
     }
 
-    condition_t m_condition;
+  private:
+    CConditionImpl m_condition;
   };
 }
index 7fea6026a228ede1ecd43023d2d6d5433ac12562..8fb71fce2b2158382168379054d30750b1e0c4dc 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * This file is part of the libCEC(R) library.
  *
- * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
  * libCEC(R) is an original work, containing original code.
  *
  * libCEC(R) is a trademark of Pulse-Eight Limited.
@@ -69,19 +69,19 @@ namespace PLATFORM
       return retVal;
     }
 
-    inline bool IsRunning(void)
+    virtual bool IsRunning(void)
     {
       CLockObject lock(m_threadMutex);
       return m_bRunning;
     }
 
-    inline bool IsStopped(void)
+    virtual bool IsStopped(void)
     {
       CLockObject lock(m_threadMutex);
       return m_bStop;
     }
 
-    inline bool CreateThread(bool bWait = true)
+    virtual bool CreateThread(bool bWait = true)
     {
         bool bReturn(false);
         CLockObject lock(m_threadMutex);
@@ -98,7 +98,7 @@ namespace PLATFORM
       return bReturn;
     }
 
-    inline bool StopThread(bool bWaitForExit = true)
+    virtual bool StopThread(bool bWaitForExit = true)
     {
       bool bReturn(true);
       bool bRunning(false);
@@ -117,7 +117,7 @@ namespace PLATFORM
       return true;
     }
 
-    inline bool Sleep(uint32_t iTimeout)
+    virtual bool Sleep(uint32_t iTimeout)
     {
       CLockObject lock(m_threadMutex);
       return m_bStop ? false : m_threadCondition.Wait(m_threadMutex, iTimeout);
similarity index 99%
rename from src/lib/platform/StdString.h
rename to src/lib/platform/util/StdString.h
index 9800f946b2b0dac71ebbc5bdc7eb4e9727acae33..496dae7382213e5d7941071bb64381e27cdac94d 100644 (file)
@@ -1,4 +1,5 @@
 #pragma once
+#include "../os.h"
 #include <string>
 #include <stdint.h>
 #include <vector>
similarity index 98%
rename from src/lib/platform/serialport/baudrate.h
rename to src/lib/platform/util/baudrate.h
index bfdb2d73e87e386621cc34694f521d54cea03e20..1411452cffda4c6cdc9521bb3e375daf37bba260 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * This file is part of the libCEC(R) library.
  *
- * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
  * libCEC(R) is an original work, containing original code.
  *
  * libCEC(R) is a trademark of Pulse-Eight Limited.
similarity index 95%
rename from src/lib/platform/buffer.h
rename to src/lib/platform/util/buffer.h
index 227b7565edcd7a438991d12b6355301336df65f9..ce6029c622cda793261f8de667e1cdc2af5c2ebc 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * This file is part of the libCEC(R) library.
  *
- * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
  * libCEC(R) is an original work, containing original code.
  *
  * libCEC(R) is a trademark of Pulse-Eight Limited.
@@ -31,7 +31,7 @@
  *     http://www.pulse-eight.net/
  */
 
-#include "os.h"
+#include "../threads/mutex.h"
 #include <queue>
 
 namespace PLATFORM
similarity index 95%
rename from src/lib/platform/timeutils.h
rename to src/lib/platform/util/timeutils.h
index b2f613add0d85657015a72ab667f46360c9699a4..d2992e75d0d46bebefe4e50741cae358ecbe1865 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * This file is part of the libCEC(R) library.
  *
- * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
  * libCEC(R) is an original work, containing original code.
  *
  * libCEC(R) is a trademark of Pulse-Eight Limited.
@@ -31,7 +31,8 @@
  *     http://www.pulse-eight.net/
  */
 
-#include <stdint.h>
+#include "../os.h"
+
 #if defined(__APPLE__)
 #include <mach/mach_time.h>
 #include <CoreVideo/CVHostTime.h>
@@ -41,8 +42,6 @@
 #include <sys/time.h>
 #endif
 
-#include "os.h"
-
 namespace PLATFORM
 {
   #if defined(__WINDOWS__)
diff --git a/src/lib/platform/windows/os-socket.h b/src/lib/platform/windows/os-socket.h
new file mode 100644 (file)
index 0000000..60badd7
--- /dev/null
@@ -0,0 +1,290 @@
+#pragma once
+/*
+ * This file is part of the libCEC(R) library.
+ *
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is an original work, containing original code.
+ *
+ * libCEC(R) is a trademark of Pulse-Eight Limited.
+ *
+ * This program is dual-licensed; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * Alternatively, you can license this library under a commercial license,
+ * please contact Pulse-Eight Licensing for more information.
+ *
+ * For more information contact:
+ * Pulse-Eight Licensing       <license@pulse-eight.com>
+ *     http://www.pulse-eight.com/
+ *     http://www.pulse-eight.net/
+ */
+
+#include "../os.h"
+#include "../util/timeutils.h"
+
+#include <ws2spi.h>
+#include <ws2ipdef.h>
+#include <ws2tcpip.h>
+
+#define SHUT_RDWR SD_BOTH
+
+#ifndef ETIMEDOUT
+#define ETIMEDOUT 138
+#endif
+
+namespace PLATFORM
+{
+  #ifndef MSG_WAITALL
+  #define MSG_WAITALL 0x8
+  #endif
+
+  inline int GetSocketError(void)
+  {
+    int error = WSAGetLastError();
+    switch(error)
+    {
+      case WSAEINPROGRESS: return EINPROGRESS;
+      case WSAECONNRESET : return ECONNRESET;
+      case WSAETIMEDOUT  : return ETIMEDOUT;
+      case WSAEWOULDBLOCK: return EAGAIN;
+      default            : return error;
+    }
+  }
+
+  // Serial port
+  //@{
+  inline void SerialSocketClose(serial_socket_t socket)
+  {
+    if (socket != INVALID_HANDLE_VALUE)
+      CloseHandle(socket);
+  }
+
+  inline ssize_t SerialSocketWrite(serial_socket_t socket, int *iError, void* data, size_t len)
+  {
+    if (len != (DWORD)len)
+    {
+      *iError = EINVAL;
+      return -1;
+    }
+
+    DWORD iBytesWritten(0);
+    if (socket != INVALID_HANDLE_VALUE)
+    {
+      if (!WriteFile(socket, data, (DWORD)len, &iBytesWritten, NULL))
+      {
+        *iError = GetLastError();
+        return -1;
+      }
+      return (ssize_t)iBytesWritten;
+    }
+
+    return -1;
+  }
+
+  inline ssize_t SerialSocketRead(serial_socket_t socket, int *iError, void* data, size_t len, uint64_t iTimeoutMs /*= 0*/)
+  {
+    if (len != (DWORD)len)
+    {
+      *iError = EINVAL;
+      return -1;
+    }
+
+    DWORD iBytesRead(0);
+    if (socket != INVALID_HANDLE_VALUE)
+    {
+      if(!ReadFile(socket, data, (DWORD)len, &iBytesRead, NULL) != 0)
+      {
+        *iError = GetLastError();
+        return -1;
+      }
+      return (ssize_t)iBytesRead;
+    }
+    return -1;
+  }
+  //@}
+
+  // TCP
+  //@{
+  inline void TcpSocketSetBlocking(tcp_socket_t socket, bool bSetTo)
+  {
+    u_long iSetTo = bSetTo ? 0 : 1;
+    ioctlsocket(socket, FIONBIO, &iSetTo);
+  }
+
+  inline void TcpSocketClose(tcp_socket_t socket)
+  {
+    closesocket(socket);
+  }
+
+  inline void TcpSocketShutdown(tcp_socket_t socket)
+  {
+    if (socket != INVALID_SOCKET &&
+        socket != SOCKET_ERROR)
+      shutdown(socket, SHUT_RDWR);
+  }
+
+  inline ssize_t TcpSocketWrite(tcp_socket_t socket, int *iError, void* data, size_t len)
+  {
+    if (socket == INVALID_SOCKET ||
+        socket == SOCKET_ERROR ||
+        len != (int)len)
+    {
+      *iError = EINVAL;
+      return -1;
+    }
+
+    ssize_t iReturn = send(socket, (char*)data, (int)len, 0);
+    if (iReturn < (ssize_t)len)
+      *iError = errno;
+    return iReturn;
+  }
+
+  inline ssize_t TcpSocketRead(tcp_socket_t socket, int *iError, void* data, size_t len, uint64_t iTimeoutMs /*= 0*/)
+  {
+    int64_t iNow(0), iTarget(0);
+    ssize_t iBytesRead(0);
+    *iError = 0;
+
+    if (socket == INVALID_SOCKET ||
+        socket == SOCKET_ERROR ||
+        len != (int)len)
+    {
+      *iError = EINVAL;
+      return -1;
+    }
+
+    if (iTimeoutMs > 0)
+    {
+      iNow    = GetTimeMs();
+      iTarget = iNow + (int64_t) iTimeoutMs;
+    }
+
+    fd_set fd_read;
+    struct timeval tv;
+    while (iBytesRead >= 0 && iBytesRead < (ssize_t)len && (iTimeoutMs == 0 || iTarget > iNow))
+    {
+      if (iTimeoutMs > 0)
+      {
+        tv.tv_sec  =        (long)(iTimeoutMs / 1000);
+        tv.tv_usec = 1000 * (long)(iTimeoutMs % 1000);
+
+        FD_ZERO(&fd_read);
+        FD_SET(socket, &fd_read);
+
+        if (select((int)socket + 1, &fd_read, NULL, NULL, &tv) == 0)
+          return ETIMEDOUT;
+        TcpSocketSetBlocking(socket, false);
+      }
+
+      ssize_t iReadResult = (iTimeoutMs > 0) ?
+          recv(socket, (char*)data + iBytesRead, (int)(len - iBytesRead), MSG_WAITALL) :
+          recv(socket, (char*)data, (int)len, MSG_WAITALL);
+      *iError = GetSocketError();
+      if (iReadResult < 0)
+      {
+        if (errno == EAGAIN && iTimeoutMs > 0)
+          continue;
+        *iError = errno;
+        return -1;
+      }
+      else if (iReadResult == 0 || (iReadResult != (ssize_t)len && iTimeoutMs == 0))
+      {
+        *iError = ECONNRESET;
+        return -1;
+      }
+
+      iBytesRead += iReadResult;
+
+      if (iTimeoutMs > 0)
+      {
+        TcpSocketSetBlocking(socket, true);
+        iNow = GetTimeMs();
+      }
+    }
+    return 0;
+  }
+
+  inline bool TcpResolveAddress(const char *strHost, uint16_t iPort, int *iError, struct addrinfo **info)
+  {
+    struct   addrinfo hints;
+    char     service[33];
+    memset(&hints, 0, sizeof(hints));
+    hints.ai_family   = AF_UNSPEC;
+    hints.ai_socktype = SOCK_STREAM;
+    hints.ai_protocol = IPPROTO_TCP;
+    sprintf(service, "%d", iPort);
+
+    *iError = getaddrinfo(strHost, service, &hints, info);
+    return !(*iError);
+  }
+
+  inline int TcpGetSocketError(tcp_socket_t socket)
+  {
+    int iReturn(0);
+    socklen_t optLen = sizeof(tcp_socket_t);
+    getsockopt(socket, SOL_SOCKET, SO_ERROR, (char *)&iReturn, &optLen);
+    return iReturn;
+  }
+
+  inline bool TcpSetNoDelay(tcp_socket_t socket)
+  {
+    int iSetTo(1);
+    setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (const char*)&iSetTo, sizeof(iSetTo));
+    return true;
+  }
+
+  inline bool TcpConnectSocket(tcp_socket_t socket, struct addrinfo* addr, int *iError, uint64_t iTimeout = 0)
+  {
+    TcpSocketSetBlocking(socket, false);
+
+    *iError = 0;
+    int iConnectResult = connect(socket, addr->ai_addr, (int)addr->ai_addrlen);
+    if (iConnectResult == -1)
+    {
+      if (GetSocketError() == EINPROGRESS ||
+          GetSocketError() == EAGAIN)
+      {
+        fd_set fd_write, fd_except;
+        struct timeval tv;
+        tv.tv_sec  =        (long)(iTimeout / 1000);
+        tv.tv_usec = 1000 * (long)(iTimeout % 1000);
+
+        FD_ZERO(&fd_write);
+        FD_ZERO(&fd_except);
+        FD_SET(socket, &fd_write);
+        FD_SET(socket, &fd_except);
+
+        int iPollResult = select(sizeof(socket)*8, NULL, &fd_write, &fd_except, &tv);
+        if (iPollResult == 0)
+          *iError = ETIMEDOUT;
+        else if (iPollResult == -1)
+          *iError = GetSocketError();
+        else
+        {
+          socklen_t errlen = sizeof(int);
+          getsockopt(socket, SOL_SOCKET, SO_ERROR, (char *)iError, &errlen);
+        }
+      }
+      else
+      {
+        *iError = errno;
+      }
+    }
+
+    TcpSocketSetBlocking(socket, true);
+
+    return *iError == 0;
+  }
+}
index 0e738684a1f599dca64e567ed60c731acb87ee0b..52bd4bc11ab946b3018bd522b01b64b0ace7cd9b 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * This file is part of the libCEC(R) library.
  *
- * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
  * libCEC(R) is an original work, containing original code.
  *
  * libCEC(R) is a trademark of Pulse-Eight Limited.
@@ -44,22 +44,96 @@ namespace PLATFORM
   #define MutexTryLock(mutex)                      (::TryEnterCriticalSection(mutex) != 0)
   #define MutexUnlock(mutex)                       ::LeaveCriticalSection(mutex)
 
-  #if (_WIN32_WINNT >= _WIN32_WINNT_VISTA)
-  typedef CONDITION_VARIABLE* condition_t;
-  #define ConditionCreate(cond)                    ::InitializeConditionVariable(cond = new CONDITION_VARIABLE)
-  #define ConditionDelete(cond)                    delete cond
-  #define ConditionSignal(cond)                    ::WakeConditionVariable(cond)
-  #define ConditionBroadcast(cond)                 ::WakeAllConditionVariable(cond)
-  #define ConditionWait(cond, mutex, timeout)      (::SleepConditionVariableCS(cond, mutex, timeout <= 0 ? INFINITE : timeout) ? true : false)
-  #else
-  typedef HANDLE condition_t;
-  #define ConditionCreate(cond)                    (cond = ::CreateEvent(NULL, TRUE, FALSE, NULL))
-  #define ConditionDelete(cond)                    ::CloseHandle(cond)
-  #define ConditionSignal(cond)                    ::SetEvent(cond)
-  #define ConditionBroadcast(cond)                 ::SetEvent(cond)
-  #define ConditionWait(cond, mutex, timeout)      ::ResetEvent(cond); \
-                                                   MutexUnlock(mutex); \
-                                                   ::WaitForSingleObject(cond, timeout <= 0 ? 1000 : timeout); \
-                                                   MutexLock(mutex)
-  #endif
+  // windows vista+ conditions
+  typedef VOID (WINAPI *ConditionArg)     (CONDITION_VARIABLE*);
+  typedef BOOL (WINAPI *ConditionMutexArg)(CONDITION_VARIABLE*, CRITICAL_SECTION*, DWORD);
+  static ConditionArg                     g_InitializeConditionVariable;
+  static ConditionArg                     g_WakeConditionVariable;
+  static ConditionArg                     g_WakeAllConditionVariable;
+  static ConditionMutexArg                g_SleepConditionVariableCS;
+
+  // check whether vista+ conditions are available at runtime  
+  static bool CheckVistaConditionFunctions(void)
+  {
+    static int iHasVistaConditionFunctions(-1);
+    if (iHasVistaConditionFunctions == -1)
+    {
+      HMODULE handle = GetModuleHandle("Kernel32");
+      if (handle == NULL)
+      {
+        iHasVistaConditionFunctions = 0;
+      }
+      else
+      {
+        g_InitializeConditionVariable = (ConditionArg)     GetProcAddress(handle,"InitializeConditionVariable");
+        g_WakeConditionVariable       = (ConditionArg)     GetProcAddress(handle,"WakeConditionVariable");
+        g_WakeAllConditionVariable    = (ConditionArg)     GetProcAddress(handle,"WakeAllConditionVariable");
+        g_SleepConditionVariableCS    = (ConditionMutexArg)GetProcAddress(handle,"SleepConditionVariableCS");
+
+        // 1 when everything is resolved, 0 otherwise
+        iHasVistaConditionFunctions = g_InitializeConditionVariable &&
+                                      g_WakeConditionVariable &&
+                                      g_WakeAllConditionVariable &&
+                                      g_SleepConditionVariableCS ? 1 : 0;
+      }
+    }
+    return iHasVistaConditionFunctions == 1;
+  }
+
+  class CConditionImpl
+  {
+  public:
+    CConditionImpl(void)
+    {
+      m_bOnVista = CheckVistaConditionFunctions();
+      if (m_bOnVista)
+        (*g_InitializeConditionVariable)(m_conditionVista = new CONDITION_VARIABLE);
+      else
+        m_conditionPreVista = ::CreateEvent(NULL, TRUE, FALSE, NULL);
+    }
+
+    virtual ~CConditionImpl(void)
+    {
+      if (m_bOnVista)
+        delete m_conditionVista;
+      else
+        ::CloseHandle(m_conditionPreVista);
+    }
+
+    void Signal(void)
+    {
+      if (m_bOnVista)
+        (*g_WakeConditionVariable)(m_conditionVista);
+      else
+        ::SetEvent(m_conditionPreVista);
+    }
+
+    void Broadcast(void)
+    {
+      if (m_bOnVista)
+        (*g_WakeAllConditionVariable)(m_conditionVista);
+      else
+        ::SetEvent(m_conditionPreVista);
+    }
+
+    bool Wait(mutex_t &mutex, uint32_t iTimeoutMs)
+    {
+      if (m_bOnVista)
+      {
+        return ((*g_SleepConditionVariableCS)(m_conditionVista, mutex, iTimeoutMs <= 0 ? INFINITE : iTimeoutMs) ? true : false);
+      }
+      else
+      {
+        ::ResetEvent(m_conditionPreVista);
+        MutexUnlock(mutex);
+        DWORD iWaitReturn = ::WaitForSingleObject(m_conditionPreVista, iTimeoutMs <= 0 ? 1000 : iTimeoutMs);
+        MutexLock(mutex);
+        return (iWaitReturn == 0);
+      }
+    }
+
+    bool                m_bOnVista;
+    CONDITION_VARIABLE *m_conditionVista;
+    HANDLE              m_conditionPreVista;
+  };
 }
index 3943510fbad76ec8e55097d411d770b88044a331..84edac9e414244c65b51d7535d92d38add4f3bb6 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * This file is part of the libCEC(R) library.
  *
- * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
  * libCEC(R) is an original work, containing original code.
  *
  * libCEC(R) is a trademark of Pulse-Eight Limited.
  *     http://www.pulse-eight.net/
  */
 
+#if !defined(__WINDOWS__)
+#define __WINDOWS__
+#endif
+
+#ifndef _WINSOCKAPI_
+#define _WINSOCKAPI_
+#endif
+
 #pragma warning(disable:4005) // Disable "warning C4005: '_WINSOCKAPI_' : macro redefinition"
 #include <winsock2.h>
 #pragma warning(default:4005)
 #include <stddef.h>
 #include <process.h>
 
+typedef SOCKET tcp_socket_t;
+#define INVALID_SOCKET_VALUE        INVALID_SOCKET
+typedef HANDLE serial_socket_t;
+#define INVALID_SERIAL_SOCKET_VALUE INVALID_HANDLE_VALUE
+
 typedef signed __int8    int8_t;
 typedef signed __int16   int16_t;
 typedef signed __int32   int32_t;
@@ -51,6 +64,15 @@ typedef unsigned __int16 uint16_t;
 typedef unsigned __int32 uint32_t;
 typedef unsigned __int64 uint64_t;
 
+#ifndef _SSIZE_T_DEFINED
+#ifdef  _WIN64
+typedef __int64    ssize_t;
+#else
+typedef _W64 int   ssize_t;
+#endif
+#define _SSIZE_T_DEFINED
+#endif
+
 #define snprintf _snprintf
 
 #if defined(_MSC_VER)
index 8e513fc7f1c6c87f607603786a16ddbf79552090..680b1f0426174729827e1b85c1ca4e75e136922f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the libCEC(R) library.
  *
- * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
  * libCEC(R) is an original work, containing original code.
  *
  * libCEC(R) is a trademark of Pulse-Eight Limited.
  *     http://www.pulse-eight.net/
  */
 
-#include "../serialport/serialport.h"
-#include "../serialport/baudrate.h"
-#include "../timeutils.h"
+#include "../sockets/serialport.h"
+#include "../util/baudrate.h"
+#include "../util/timeutils.h"
 
 using namespace std;
 using namespace PLATFORM;
 
-void FormatWindowsError(int iErrorCode, string &strMessage)
+void FormatWindowsError(int iErrorCode, CStdString &strMessage)
 {
   if (iErrorCode != ERROR_SUCCESS)
   {
@@ -48,89 +48,15 @@ void FormatWindowsError(int iErrorCode, string &strMessage)
   }
 }
 
-CSerialPort::CSerialPort(void) :
-  m_handle(INVALID_HANDLE_VALUE),
-  m_bIsOpen(false),
-  m_iBaudrate(0),
-  m_iDatabits(0),
-  m_iStopbits(0),
-  m_iParity(0)
+bool SetTimeouts(serial_socket_t socket, int* iError, bool bBlocking)
 {
-}
-
-CSerialPort::~CSerialPort(void)
-{
-  Close();
-}
-
-bool CSerialPort::Open(string name, uint32_t baudrate, uint8_t databits, uint8_t stopbits, uint8_t parity)
-{
-  CStdString strComPath = "\\\\.\\" + name;
-  CLockObject lock(m_mutex);
-  m_handle = CreateFile(strComPath.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
-  if (m_handle == INVALID_HANDLE_VALUE)
-  {
-    m_error = "Unable to open COM port";
-    FormatWindowsError(GetLastError(), m_error);
-    return false;
-  }
-
-  COMMCONFIG commConfig = {0};
-  DWORD dwSize = sizeof(commConfig);
-  commConfig.dwSize = dwSize;
-  if (GetDefaultCommConfig(strComPath.c_str(), &commConfig,&dwSize))
-  {
-    if (!SetCommConfig(m_handle, &commConfig,dwSize))
-    {
-      m_error = "unable to set default config";
-      FormatWindowsError(GetLastError(), m_error);
-    }
-  }
-  else
-  {
-    m_error = "unable to get default config";
-    FormatWindowsError(GetLastError(), m_error);
-  }
-
-  if (!SetupComm(m_handle, 64, 64))
-  {
-    m_error = "unable to set up the com port";
-    FormatWindowsError(GetLastError(), m_error);
-  }
-
-  m_iDatabits = databits;
-  m_iStopbits = stopbits;
-  m_iParity   = parity;
-  if (!SetBaudRate(baudrate))
-  {
-    m_error = "unable to set baud rate";
-    FormatWindowsError(GetLastError(), m_error);
-    Close();
-    return false;
-  }
-
-  if (!SetTimeouts(false))
-  {
-    m_error = "unable to set timeouts";
-    FormatWindowsError(GetLastError(), m_error);
-    Close();
-    return false;
-  }
-
-  m_bIsOpen = true;
-  return m_bIsOpen;
-}
-
-bool CSerialPort::SetTimeouts(bool bBlocking)
-{
-  if (m_handle == INVALID_HANDLE_VALUE)
+  if (socket == INVALID_HANDLE_VALUE)
          return false;
 
   COMMTIMEOUTS cto;
-  if (!GetCommTimeouts(m_handle, &cto))
+  if (!GetCommTimeouts(socket, &cto))
   {
-    m_error = "GetCommTimeouts failed";
-    FormatWindowsError(GetLastError(), m_error);
+    *iError = GetLastError();
     return false;
   }
 
@@ -147,69 +73,92 @@ bool CSerialPort::SetTimeouts(bool bBlocking)
     cto.ReadTotalTimeoutMultiplier  = 0;
   }
 
-  if (!SetCommTimeouts(m_handle, &cto))
+  if (!SetCommTimeouts(socket, &cto))
   {
-    m_error = "SetCommTimeouts failed";
-    FormatWindowsError(GetLastError(), m_error);
+    *iError = GetLastError();
     return false;
   }
 
   return true;
 }
 
-void CSerialPort::Close(void)
+void CSerialSocket::Close(void)
 {
-  CLockObject lock(m_mutex);
-  if (m_bIsOpen)
-  {
-    CloseHandle(m_handle);
-    m_bIsOpen = false;
-  }
+  SerialSocketClose(m_socket);
 }
 
-int64_t CSerialPort::Write(uint8_t* data, uint32_t len)
+void CSerialSocket::Shutdown(void)
 {
-  CLockObject lock(m_mutex);
-  DWORD iBytesWritten = 0;
-  if (!m_bIsOpen)
-    return -1;
+  SerialSocketClose(m_socket);
+}
 
-  if (!WriteFile(m_handle, data, len, &iBytesWritten, NULL))
-  {
-    m_error = "Error while writing to COM port";
-    FormatWindowsError(GetLastError(), m_error);
-    return -1;
-  }
+ssize_t CSerialSocket::Write(void* data, size_t len)
+{
+  return SerialSocketWrite(m_socket, &m_iError, data, len);
+}
 
-  return (int64_t)iBytesWritten;
+ssize_t CSerialSocket::Read(void* data, size_t len, uint64_t iTimeoutMs /* = 0 */)
+{
+  return SerialSocketRead(m_socket, &m_iError, data, len, iTimeoutMs);
 }
 
-int32_t CSerialPort::Read(uint8_t* data, uint32_t len, uint64_t iTimeoutMs /* = 0 */)
+bool CSerialSocket::Open(uint64_t iTimeoutMs /* = 0 */)
 {
+  iTimeoutMs = 0;
+  CStdString strComPath = "\\\\.\\" + m_strName;
   CLockObject lock(m_mutex);
-  int32_t iReturn(-1);
-  DWORD iBytesRead = 0;
-  if (m_handle == 0)
+  m_socket = CreateFile(strComPath.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
+  if (m_socket == INVALID_HANDLE_VALUE)
   {
-    m_error = "Error while reading from COM port: invalid handle";
-    return iReturn;
+    m_strError = "Unable to open COM port";
+    FormatWindowsError(GetLastError(), m_strError);
+    return false;
   }
 
-  if(!ReadFile(m_handle, data, len, &iBytesRead, NULL) != 0)
+  COMMCONFIG commConfig = {0};
+  DWORD dwSize = sizeof(commConfig);
+  commConfig.dwSize = dwSize;
+  if (GetDefaultCommConfig(strComPath.c_str(), &commConfig,&dwSize))
   {
-    m_error = "unable to read from device";
-    FormatWindowsError(GetLastError(), m_error);
-    iReturn = -1;
+    if (!SetCommConfig(m_socket, &commConfig,dwSize))
+    {
+      m_strError = "unable to set default config";
+      FormatWindowsError(GetLastError(), m_strError);
+    }
   }
   else
   {
-    iReturn = (int32_t) iBytesRead;
+    m_strError = "unable to get default config";
+    FormatWindowsError(GetLastError(), m_strError);
   }
 
-  return iReturn;
+  if (!SetupComm(m_socket, 64, 64))
+  {
+    m_strError = "unable to set up the com port";
+    FormatWindowsError(GetLastError(), m_strError);
+  }
+
+  if (!SetBaudRate(m_iBaudrate))
+  {
+    m_strError = "unable to set baud rate";
+    FormatWindowsError(GetLastError(), m_strError);
+    Close();
+    return false;
+  }
+
+  if (!SetTimeouts(m_socket, &m_iError, false))
+  {
+    m_strError = "unable to set timeouts";
+    FormatWindowsError(GetLastError(), m_strError);
+    Close();
+    return false;
+  }
+
+  m_bIsOpen = true;
+  return m_bIsOpen;
 }
 
-bool CSerialPort::SetBaudRate(uint32_t baudrate)
+bool CSerialSocket::SetBaudRate(uint32_t baudrate)
 {
   int32_t rate = IntToBaudrate(baudrate);
   if (rate < 0)
@@ -230,32 +179,26 @@ bool CSerialPort::SetBaudRate(uint32_t baudrate)
        dcb.fInX          = false;
   dcb.fAbortOnError = true;
 
-  if (m_iParity == PAR_NONE)
+  if (m_iParity == SERIAL_PARITY_NONE)
     dcb.Parity = NOPARITY;
-  else if (m_iParity == PAR_EVEN)
+  else if (m_iParity == SERIAL_PARITY_EVEN)
     dcb.Parity = EVENPARITY;
   else
     dcb.Parity = ODDPARITY;
 
-  if (m_iStopbits == 2)
+  if (m_iStopbits == SERIAL_STOP_BITS_TWO)
     dcb.StopBits = TWOSTOPBITS;
   else
     dcb.StopBits = ONESTOPBIT;
 
-  dcb.ByteSize = m_iDatabits;
+  dcb.ByteSize = (BYTE)m_iDatabits;
 
-  if(!SetCommState(m_handle,&dcb))
+  if(!SetCommState(m_socket,&dcb))
   {
-    m_error = "SetCommState failed";
-    FormatWindowsError(GetLastError(), m_error);
+    m_strError = "SetCommState failed";
+    FormatWindowsError(GetLastError(), m_strError);
     return false;
   }
 
   return true;
 }
-
-bool CSerialPort::IsOpen()
-{
-  CLockObject lock(m_mutex);
-  return m_bIsOpen;
-}
index 4b13f3a78311d6af929064213b347f14774c5fb8..c8e6819f091ba6741d06e9e685ee41fd5e7d406f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the libCEC(R) library.
  *
- * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
  * libCEC(R) is an original work, containing original code.
  *
  * libCEC(R) is a trademark of Pulse-Eight Limited.
@@ -62,15 +62,17 @@ bool                 g_bHardExit(false);
 CMutex               g_outputMutex;
 ICECCallbacks        g_callbacks;
 
-inline void PrintToStdOut(const char *strOut)
+inline void PrintToStdOut(const char *strFormat, ...)
 {
-  CLockObject lock(g_outputMutex);
-  cout << strOut << endl;
-}
+  CStdString strLog;
 
-inline void PrintToStdOut(const CStdString &strOut)
-{
-  PrintToStdOut(strOut.c_str());
+  va_list argList;
+  va_start(argList, strFormat);
+  strLog.FormatV(strFormat, argList);
+  va_end(argList);
+
+  CLockObject lock(g_outputMutex);
+  cout << strLog << endl;
 }
 
 inline bool HexStrToInt(const std::string& data, uint8_t& value)
@@ -153,7 +155,7 @@ int CecLogMessage(void *UNUSED(cbParam), const cec_log_message &message)
 
     CStdString strFullLog;
     strFullLog.Format("%s[%16lld]\t%s", strLevel.c_str(), message.time, message.message);
-    PrintToStdOut(strFullLog);
+    PrintToStdOut(strFullLog.c_str());
 
     if (g_logOutput.is_open())
     {
@@ -188,22 +190,16 @@ void EnableCallbacks(ICECAdapter *adapter)
 void ListDevices(ICECAdapter *parser)
 {
   cec_adapter *devices = new cec_adapter[10];
-  uint8_t iDevicesFound = parser->FindAdapters(devices, 10, NULL);
+  int8_t iDevicesFound = parser->FindAdapters(devices, 10, NULL);
   if (iDevicesFound <= 0)
   {
     PrintToStdOut("Found devices: NONE");
   }
   else
   {
-    CStdString strLog;
-    strLog.Format("Found devices: %d", iDevicesFound);
-    PrintToStdOut(strLog);
-    for (unsigned int iDevicePtr = 0; iDevicePtr < iDevicesFound; iDevicePtr++)
-    {
-      CStdString strDevice;
-      strDevice.Format("device:        %d\npath:          %s\ncom port:      %s", iDevicePtr + 1, devices[iDevicePtr].path, devices[iDevicePtr].comm);
-      PrintToStdOut(strDevice);
-    }
+    PrintToStdOut("Found devices: %d\n", iDevicesFound);
+    for (int8_t iDevicePtr = 0; iDevicePtr < iDevicesFound; iDevicePtr++)
+      PrintToStdOut("device:        %d\npath:          %s\ncom port:      %s\n", iDevicePtr + 1, devices[iDevicePtr].path, devices[iDevicePtr].comm);
   }
 }
 
@@ -247,9 +243,7 @@ ICECAdapter *CreateParser(cec_device_type_list typeList)
     return NULL;
   }
 
-  CStdString strLog;
-  strLog.Format("CEC Parser created - libcec version %d.%d", parser->GetLibVersionMajor(), parser->GetLibVersionMinor());
-  PrintToStdOut(strLog.c_str());
+  PrintToStdOut("CEC Parser created - libcec version %d.%d", parser->GetLibVersionMajor(), parser->GetLibVersionMinor());
 
   return parser;
 }
@@ -279,6 +273,8 @@ void ShowHelpConsole(void)
   "[lad]                     lists active devices on the bus" << endl <<
   "[ad] {addr}               checks whether the specified device is active." << endl <<
   "[at] {type}               checks whether the specified device type is active." << endl <<
+  "[sp] {addr}               makes the specified physical address active." << endl <<
+  "[spl] {addr}              makes the specified logical address active." << endl <<
   "[volup]                   send a volume up command to the amp if present" << endl <<
   "[voldown]                 send a volume down command to the amp if present" << endl <<
   "[mute]                    send a mute/unmute command to the amp if present" << endl <<
@@ -295,6 +291,42 @@ void ShowHelpConsole(void)
   "================================================================================" << endl;
 }
 
+bool ProcessCommandSP(ICECAdapter *parser, const string &command, string &arguments)
+{
+  if (command == "sp")
+  {
+    string strAddress;
+    int iAddress;
+    if (GetWord(arguments, strAddress))
+    {
+      sscanf(strAddress.c_str(), "%x", &iAddress);
+      if (iAddress >= 0 && iAddress <= 0xFFFF)
+        parser->SetStreamPath((uint16_t)iAddress);
+      return true;
+    }
+  }
+
+  return false;
+}
+
+bool ProcessCommandSPL(ICECAdapter *parser, const string &command, string &arguments)
+{
+  if (command == "spl")
+  {
+    string strAddress;
+    cec_logical_address iAddress;
+    if (GetWord(arguments, strAddress))
+    {
+      iAddress = (cec_logical_address)atoi(strAddress.c_str());
+      if (iAddress >= CECDEVICE_TV && iAddress < CECDEVICE_BROADCAST)
+        parser->SetStreamPath(iAddress);
+      return true;
+    }
+  }
+
+  return false;
+}
+
 bool ProcessCommandTX(ICECAdapter *parser, const string &command, string &arguments)
 {
   if (command == "tx" || command == "txn")
@@ -482,9 +514,7 @@ bool ProcessCommandVOLUP(ICECAdapter *parser, const string &command, string & UN
 {
   if (command == "volup")
   {
-    CStdString strLog;
-    strLog.Format("volume up: %2X", parser->VolumeUp());
-    PrintToStdOut(strLog);
+    PrintToStdOut("volume up: %2X", parser->VolumeUp());
     return true;
   }
 
@@ -495,9 +525,7 @@ bool ProcessCommandVOLDOWN(ICECAdapter *parser, const string &command, string &
 {
   if (command == "voldown")
   {
-    CStdString strLog;
-    strLog.Format("volume down: %2X", parser->VolumeDown());
-    PrintToStdOut(strLog);
+    PrintToStdOut("volume down: %2X", parser->VolumeDown());
     return true;
   }
 
@@ -508,9 +536,7 @@ bool ProcessCommandMUTE(ICECAdapter *parser, const string &command, string & UNU
 {
   if (command == "mute")
   {
-    CStdString strLog;
-    strLog.Format("mute: %2X", parser->MuteAudio());
-    PrintToStdOut(strLog);
+    PrintToStdOut("mute: %2X", parser->MuteAudio());
     return true;
   }
 
@@ -584,9 +610,7 @@ bool ProcessCommandVEN(ICECAdapter *parser, const string &command, string &argum
       if (iDev >= 0 && iDev < 15)
       {
         uint64_t iVendor = parser->GetDeviceVendorId((cec_logical_address) iDev);
-        CStdString strLog;
-        strLog.Format("vendor id: %06x", iVendor);
-        PrintToStdOut(strLog);
+        PrintToStdOut("vendor id: %06x", iVendor);
         return true;
       }
     }
@@ -606,9 +630,7 @@ bool ProcessCommandVER(ICECAdapter *parser, const string &command, string &argum
       if (iDev >= 0 && iDev < 15)
       {
         cec_version iVersion = parser->GetDeviceCecVersion((cec_logical_address) iDev);
-        CStdString strLog;
-        strLog.Format("CEC version %s", parser->ToString(iVersion));
-        PrintToStdOut(strLog);
+        PrintToStdOut("CEC version %s", parser->ToString(iVersion));
         return true;
       }
     }
@@ -628,9 +650,7 @@ bool ProcessCommandPOW(ICECAdapter *parser, const string &command, string &argum
       if (iDev >= 0 && iDev < 15)
       {
         cec_power_status iPower = parser->GetDevicePowerStatus((cec_logical_address) iDev);
-        CStdString strLog;
-        strLog.Format("power status: %s", parser->ToString(iPower));
-        PrintToStdOut(strLog);
+        PrintToStdOut("power status: %s", parser->ToString(iPower));
         return true;
       }
     }
@@ -650,9 +670,7 @@ bool ProcessCommandNAME(ICECAdapter *parser, const string &command, string &argu
       if (iDev >= 0 && iDev < 15)
       {
         cec_osd_name name = parser->GetDeviceOSDName((cec_logical_address)iDev);
-        CStdString strLog;
-        strLog.Format("OSD name of device %d is '%s'", iDev, name.name);
-        PrintToStdOut(strLog);
+        PrintToStdOut("OSD name of device %d is '%s'", iDev, name.name);
       }
       return true;
     }
@@ -665,14 +683,12 @@ bool ProcessCommandLAD(ICECAdapter *parser, const string &command, string & UNUS
 {
   if (command == "lad")
   {
-    CStdString strLog;
     PrintToStdOut("listing active devices:");
     cec_logical_addresses addresses = parser->GetActiveDevices();
     for (uint8_t iPtr = 0; iPtr <= 11; iPtr++)
       if (addresses[iPtr])
       {
-        strLog.Format("logical address %X", (int)iPtr);
-        PrintToStdOut(strLog);
+        PrintToStdOut("logical address %X", (int)iPtr);
       }
     return true;
   }
@@ -689,11 +705,7 @@ bool ProcessCommandAD(ICECAdapter *parser, const string &command, string &argume
     {
       int iDev = atoi(strDev);
       if (iDev >= 0 && iDev < 15)
-      {
-        CStdString strLog;
-        strLog.Format("logical address %X is %s", iDev, (parser->IsActiveDevice((cec_logical_address)iDev) ? "active" : "not active"));
-        PrintToStdOut(strLog);
-      }
+        PrintToStdOut("logical address %X is %s", iDev, (parser->IsActiveDevice((cec_logical_address)iDev) ? "active" : "not active"));
     }
   }
 
@@ -716,9 +728,8 @@ bool ProcessCommandAT(ICECAdapter *parser, const string &command, string &argume
         type = CEC_DEVICE_TYPE_RECORDING_DEVICE;
       else if (strType.Equals("t"))
         type = CEC_DEVICE_TYPE_TUNER;
-      CStdString strLog;
-      strLog.Format("device %d is %s", type, (parser->IsActiveDeviceType(type) ? "active" : "not active"));
-      PrintToStdOut(strLog);
+
+      PrintToStdOut("device %d is %s", type, (parser->IsActiveDeviceType(type) ? "active" : "not active"));
       return true;
     }
   }
@@ -766,9 +777,8 @@ bool ProcessCommandLOG(ICECAdapter * UNUSED(parser), const string &command, stri
       if (iNewLevel >= CEC_LOG_ERROR && iNewLevel <= CEC_LOG_ALL)
       {
         g_cecLogLevel = iNewLevel;
-        CStdString strLog;
-        strLog.Format("log level changed to %s", strLevel.c_str());
-        PrintToStdOut(strLog);
+
+        PrintToStdOut("log level changed to %s", strLevel.c_str());
         return true;
       }
     }
@@ -856,7 +866,9 @@ bool ProcessConsoleCommand(ICECAdapter *parser, string &input)
       ProcessCommandR(parser, command, input) ||
       ProcessCommandH(parser, command, input) ||
       ProcessCommandLOG(parser, command, input) ||
-      ProcessCommandSCAN(parser, command, input);
+      ProcessCommandSCAN(parser, command, input) ||
+      ProcessCommandSP(parser, command, input) ||
+      ProcessCommandSPL(parser, command, input);
     }
   }
   return true;
@@ -1079,9 +1091,7 @@ int main (int argc, char *argv[])
 
   if (!parser->Open(g_strPort.c_str()))
   {
-    CStdString strLog;
-    strLog.Format("unable to open the device on port %s", g_strPort.c_str());
-    PrintToStdOut(strLog);
+    PrintToStdOut("unable to open the device on port %s", g_strPort.c_str());
     UnloadLibCec(parser);
     return 1;
   }
diff --git a/support/create-driver-installer.cmd b/support/create-driver-installer.cmd
new file mode 100644 (file)
index 0000000..6b6b5d3
--- /dev/null
@@ -0,0 +1,53 @@
+@echo off
+
+rem Check for NSIS
+IF EXIST "%ProgramFiles%\NSIS\makensis.exe" (
+  set NSIS="%ProgramFiles%\NSIS\makensis.exe"
+) ELSE IF EXIST "%ProgramFiles(x86)%\NSIS\makensis.exe" (
+  set NSIS="%ProgramFiles(x86)%\NSIS\makensis.exe"
+) ELSE GOTO NONSIS
+
+rem Check for the Windows DDK
+IF NOT EXIST "C:\WinDDK\7600.16385.1" GOTO NODDK
+set DDK="C:\WinDDK\7600.16385.1"
+
+cd ..\project
+
+del /s /f /q ..\build
+mkdir ..\build
+
+echo. Copying driver installer
+copy "%DDK%\redist\DIFx\dpinst\MultiLin\amd64\dpinst.exe" ..\build\dpinst-amd64.exe
+copy "%DDK%\redist\DIFx\dpinst\MultiLin\x86\dpinst.exe" ..\build\dpinst-x86.exe
+
+:CREATEINSTALLER
+echo. Creating the installer
+%NSIS% /V1 /X"SetCompressor /FINAL lzma" "p8-usbcec-driver.nsi"
+
+IF NOT EXIST "..\build\p8-usbcec-driver-installer.exe" GOTO :ERRORCREATINGINSTALLER
+
+rem Sign the installer if sign-binary.cmd exists
+IF EXIST "..\support\sign-binary.cmd" (
+  echo. Signing the installer binaries
+  CALL ..\support\sign-binary.cmd ..\build\p8-usbcec-driver-installer.exe
+)
+
+echo. The installer can be found here: ..\build\p8-usbcec-driver-installer.exe
+
+GOTO EXIT
+
+:NOSIS
+echo. NSIS could not be found on your system.
+GOTO EXIT
+
+:NODDK
+echo. Windows DDK could not be found on your system
+GOTO EXIT
+
+:ERRORCREATINGINSTALLER
+echo. The installer could not be created.
+
+:EXIT
+del /q /f ..\build\dpinst-amd64.exe
+del /q /f ..\build\dpinst-x86.exe
+cd ..\support
\ No newline at end of file
index cd5227c564488eb7c65d43130ce1bfb4d1705807..5023ddc3696b83bd36636bf3917f308ef0300afa 100644 (file)
@@ -20,12 +20,15 @@ IF "%VS100COMNTOOLS%"=="" (
   set COMPILER10="%VS100COMNTOOLS%\..\IDE\devenv.exe"
 ) ELSE GOTO NOSDK10
 
-cd ..\project
-
 del /s /f /q ..\build
 mkdir ..\build
+
+call create-driver-installer.cmd
+
 mkdir ..\build\x64
 
+cd ..\project
+
 rem Skip to libCEC/x86 when we're running on win32
 if "%PROCESSOR_ARCHITECTURE%"=="x86" if "%PROCESSOR_ARCHITEW6432%"=="" goto libcecx86
 
@@ -77,24 +80,41 @@ echo. Compiling LibCecSharp (x86)
 %COMPILER9% LibCecSharp.sln /build "Release|x86" /project CecSharpTester
 
 :NOSDK9
-:CREATEINSTALLER
-echo. Copying driver installer
-copy "%DDK%\redist\DIFx\dpinst\MultiLin\amd64\dpinst.exe" ..\build\dpinst-amd64.exe
-copy "%DDK%\redist\DIFx\dpinst\MultiLin\x86\dpinst.exe" ..\build\dpinst-x86.exe
-
 rem Clean things up before creating the installer
-del ..\build\LibCecSharp.pdb
-del ..\build\CecSharpTester.pdb
+del /q /f ..\build\LibCecSharp.pdb
+del /q /f ..\build\CecSharpTester.pdb
 copy ..\build\cec-client.x64.exe ..\build\x64\cec-client.x64.exe
-del ..\build\cec-client.x64.exe
+del /q /f ..\build\cec-client.x64.exe
 copy ..\build\libcec.x64.dll ..\build\x64\libcec.x64.dll
-del ..\build\libcec.x64.dll
+del /q /f ..\build\libcec.x64.dll
 copy ..\build\libcec.x64.lib ..\build\x64\libcec.x64.lib
-del ..\build\libcec.x64.lib
+del /q /f ..\build\libcec.x64.lib
+
+rem Check for sign-binary.cmd, only present on the Pulse-Eight production build system
+rem Calls signtool.exe and signs the DLLs with Pulse-Eight's code signing key
+IF NOT EXIST "..\support\sign-binary.cmd" GOTO CREATEINSTALLER
+echo. Signing all binaries
+CALL ..\support\sign-binary.cmd ..\build\cec-client.exe
+CALL ..\support\sign-binary.cmd ..\build\CecSharpTester.exe
+CALL ..\support\sign-binary.cmd ..\build\libcec.dll
+CALL ..\support\sign-binary.cmd ..\build\LibCecSharp.dll
+CALL ..\support\sign-binary.cmd ..\build\x64\cec-client.x64.exe
+CALL ..\support\sign-binary.cmd ..\build\x64\CecSharpTester.exe
+CALL ..\support\sign-binary.cmd ..\build\x64\libcec.x64.dll
+CALL ..\support\sign-binary.cmd ..\build\x64\LibCecSharp.dll
 
+:CREATEINSTALLER
 echo. Creating the installer
 %NSIS% /V1 /X"SetCompressor /FINAL lzma" "libCEC.nsi"
 
+IF NOT EXIST "..\build\libCEC-installer.exe" GOTO :ERRORCREATINGINSTALLER
+
+rem Sign the installer if sign-binary.cmd exists
+IF EXIST "..\support\sign-binary.cmd" (
+  echo. Signing the installer binaries
+  CALL ..\support\sign-binary.cmd ..\build\libCEC-installer.exe
+)
+
 echo. The installer can be found here: ..\build\libCEC-installer.exe
 
 GOTO EXIT
@@ -109,5 +129,17 @@ GOTO EXIT
 
 :NODDK
 echo. Windows DDK could not be found on your system
+GOTO EXIT
+
+:ERRORCREATINGINSTALLER
+echo. The installer could not be created. The most likely cause is that something went wrong while compiling.
 
 :EXIT
+del /q /f ..\build\cec-client.exe
+del /q /f ..\build\CecSharpTester.exe
+del /q /f ..\build\*.dll
+del /q /f ..\build\*.lib
+del /q /f ..\build\*.exp
+del /s /f /q ..\build\x64
+rmdir ..\build\x64
+cd ..\support
\ No newline at end of file