*.suo
*.user
+/support/sign-binary.cmd
+
aclocal.m4
autom4te.cache
config.guess
/*
* 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.
+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:
+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:
/*
* 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.
*/
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;
/*
* 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.
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
/*
* 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.
/*
* 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.
#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
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;
#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
{
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"
;libCEC installer
-;Copyright (C) 2011 Pulse-Eight Ltd.
+;Copyright (C) 2012 Pulse-Eight Ltd.
;http://www.pulse-eight.com/
!include "MUI2.nsh"
!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
!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
!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" ""
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*.*"
${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"
"" "$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
;--------------------------------
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"
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
<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" />
<?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>
--- /dev/null
+;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
<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>
<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" />
[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("")]
// 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")]
[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")];
/*
* 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.
~LibCecSharp(void)
{
- CECDestroy(m_libCec);
+ Close();
DestroyDelegates();
m_libCec = NULL;
}
protected:
!LibCecSharp(void)
{
- CECDestroy(m_libCec);
+ Close();
DestroyDelegates();
m_libCec = NULL;
}
private:
void DestroyDelegates()
{
+ m_bHasCallbacks = false;
+ delete m_callbacks;
m_logMessageGCHandle.Free();
m_keypressGCHandle.Free();
m_commandGCHandle.Free();
/*
* 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 "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();
}
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++)
{
CCECProcessor::~CCECProcessor(void)
{
- m_bStarted = false;
- m_startCondition.Broadcast();
StopThread();
delete m_communication;
{
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())
{
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);
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;
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);
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;
}
{
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())
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);
bool bSendActiveView(false);
bool bReturn(false);
cec_logical_addresses sendUpdatesTo;
+ sendUpdatesTo.Clear();
{
CLockObject lock(m_mutex);
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 */)
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);
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);
}
/*
* 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);
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;
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);
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);
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;
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;
/*
* 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;
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)
}
}
+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)
{
/*
* 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 <cec.h>
-#include "platform/os.h"
+#include "platform/util/buffer.h"
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);
/*
* 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.
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;
+}
+
//@}
/*
* 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.
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 \
+++ /dev/null
-/*
- * 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);
-}
/*
* 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;
};
};
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+#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;
+ };
+};
/*
* 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 "AdapterDetection.h"
-#include "../platform/os.h"
+#include "USBCECAdapterDetection.h"
+#include "../platform/util/StdString.h"
#if defined(__APPLE__)
#include <dirent.h>
}
#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);
/*
* 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.
namespace CEC
{
- class CAdapterDetection
+ class CUSBCECAdapterDetection
{
public:
static uint8_t FindAdapters(cec_adapter *deviceList, uint8_t iBufSize, const char *strDevicePath = NULL);
/*
* 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:
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;
reply = MSGCODE_NOTHING;
isTransmission = true;
expectControllerAck = true;
+ lineTimeout = 3;
+ retryTimeout = 3;
}
void Shift(uint8_t iShiftBy)
int32_t transmit_timeout;
bool isTransmission;
bool expectControllerAck;
+ uint8_t lineTimeout;
+ uint8_t retryTimeout;
PLATFORM::CMutex mutex;
PLATFORM::CCondition condition;
};
/*
* 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.
/*
* 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.
/*
* 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 "../implementations/SLCommandHandler.h"
#include "../implementations/VLCommandHandler.h"
#include "../LibCEC.h"
+#include "../platform/util/timeutils.h"
using namespace CEC;
using namespace PLATFORM;
{
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());
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;
+}
+
//@}
/*
* 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 <cectypes.h>
#include <set>
-#include "../platform/os.h"
+#include "../platform/threads/mutex.h"
+#include "../platform/util/StdString.h"
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);
std::set<cec_opcode> m_unsupportedFeatures;
PLATFORM::CMutex m_mutex;
PLATFORM::CMutex m_handlerMutex;
+ bool m_bAwaitingReceiveFailed;
};
};
/*
* 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.
/*
* 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.
/*
* 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.
/*
* 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.
/*
* 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.
/*
* 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.
/*
* 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.
/*
* 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.
/*
* 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.
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;
/*
* 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.
/*
* 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.
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;
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)
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)
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))
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)
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)
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)
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)
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)
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)
{
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);
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);
{
device->SetActiveSource();
device->TransmitActiveSource();
+
+ device->SetMenuState(CEC_MENU_STATE_ACTIVATED);
+ device->TransmitMenuState(command.initiator);
}
}
return false;
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)
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();
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;
}
}
-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;
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;
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;
/*
* 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 <cectypes.h>
#include <vector>
-#include "../platform/os.h"
+#include "../platform/threads/mutex.h"
+#include "../platform/util/StdString.h"
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; }
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);
/*
* 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.
CSLCommandHandler::CSLCommandHandler(CCECBusDevice *busDevice) :
CCECCommandHandler(busDevice),
- m_bAwaitingReceiveFailed(false),
m_bSLEnabled(false),
m_bPowerStateReset(false)
{
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();
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)
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)
/*
* 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.
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);
virtual void SetLGDeckStatus(void);
- bool m_bAwaitingReceiveFailed;
bool m_bSLEnabled;
bool m_bPowerStateReset;
};
/*
* 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.
/*
* 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.
/*
* 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"
--- /dev/null
+#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;
+ }
+ //@}
+}
/*
* 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.
#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;
+ };
}
#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
#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)
/*
* 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
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;
-}
+++ /dev/null
-#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
- };
-};
--- /dev/null
+#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) {}
+ };
+};
--- /dev/null
+#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;
+ };
+};
--- /dev/null
+#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) {}
+ };
+};
/*
* 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
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)
w.Wait(m, iTimeout);
}
- condition_t m_condition;
+ private:
+ CConditionImpl m_condition;
};
}
/*
* 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.
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);
return bReturn;
}
- inline bool StopThread(bool bWaitForExit = true)
+ virtual bool StopThread(bool bWaitForExit = true)
{
bool bReturn(true);
bool bRunning(false);
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);
#pragma once
+#include "../os.h"
#include <string>
#include <stdint.h>
#include <vector>
/*
* 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.
/*
* 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 "../threads/mutex.h"
#include <queue>
namespace PLATFORM
/*
* 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 <stdint.h>
+#include "../os.h"
+
#if defined(__APPLE__)
#include <mach/mach_time.h>
#include <CoreVideo/CVHostTime.h>
#include <sys/time.h>
#endif
-#include "os.h"
-
namespace PLATFORM
{
#if defined(__WINDOWS__)
--- /dev/null
+#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;
+ }
+}
/*
* 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.
#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;
+ };
}
/*
* 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;
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)
/*
* 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)
{
}
}
-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;
}
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)
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;
-}
/*
* 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.
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)
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())
{
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);
}
}
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;
}
"[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 <<
"================================================================================" << 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")
{
if (command == "volup")
{
- CStdString strLog;
- strLog.Format("volume up: %2X", parser->VolumeUp());
- PrintToStdOut(strLog);
+ PrintToStdOut("volume up: %2X", parser->VolumeUp());
return true;
}
{
if (command == "voldown")
{
- CStdString strLog;
- strLog.Format("volume down: %2X", parser->VolumeDown());
- PrintToStdOut(strLog);
+ PrintToStdOut("volume down: %2X", parser->VolumeDown());
return true;
}
{
if (command == "mute")
{
- CStdString strLog;
- strLog.Format("mute: %2X", parser->MuteAudio());
- PrintToStdOut(strLog);
+ PrintToStdOut("mute: %2X", parser->MuteAudio());
return true;
}
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;
}
}
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;
}
}
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;
}
}
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;
}
{
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;
}
{
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"));
}
}
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;
}
}
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;
}
}
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;
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;
}
--- /dev/null
+@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
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
%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
: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