Merge branch 'master' into release
authorLars Op den Kamp <lars@opdenkamp.eu>
Tue, 11 Sep 2012 12:54:14 +0000 (14:54 +0200)
committerLars Op den Kamp <lars@opdenkamp.eu>
Tue, 11 Sep 2012 12:54:14 +0000 (14:54 +0200)
40 files changed:
ChangeLog
configure.ac
debian/changelog
driver/p8usb-cec.inf
include/cec.h
include/cectypes.h
project/cec-config.rc
project/libcec.rc
project/libcec.vcxproj
project/testclient.rc
src/CecSharpTester/CecSharpClient.cs
src/CecSharpTester/Properties/AssemblyInfo.cs
src/LibCecSharp/AssemblyInfo.cpp
src/LibCecSharp/CecSharpTypes.h
src/cec-config-gui/CecConfigGUI.cs
src/cec-config-gui/Properties/AssemblyInfo.cs
src/cec-config/cec-config.cpp
src/lib/CECClient.cpp
src/lib/CECProcessor.cpp
src/lib/CECProcessor.h
src/lib/CECTypeUtils.h
src/lib/LibCEC.cpp
src/lib/LibCEC.h
src/lib/adapter/AdapterCommunication.h
src/lib/adapter/Pulse-Eight/USBCECAdapterCommands.cpp
src/lib/adapter/Pulse-Eight/USBCECAdapterCommands.h
src/lib/adapter/Pulse-Eight/USBCECAdapterCommunication.cpp
src/lib/adapter/Pulse-Eight/USBCECAdapterCommunication.h
src/lib/adapter/Pulse-Eight/USBCECAdapterDetection.cpp
src/lib/adapter/Pulse-Eight/USBCECAdapterMessage.cpp
src/lib/adapter/Pulse-Eight/USBCECAdapterMessage.h
src/lib/adapter/Pulse-Eight/USBCECAdapterMessageQueue.h
src/lib/adapter/RPi/RPiCECAdapterCommunication.cpp
src/lib/adapter/RPi/RPiCECAdapterCommunication.h
src/lib/devices/CECBusDevice.cpp
src/lib/implementations/VLCommandHandler.cpp
src/lib/platform/windows/serialport.cpp
src/testclient/main.cpp
support/cec-flash-device.sh [deleted file]
support/p8-usbcec-driver-installer.exe

index 5c43fc20b5dd1b370c7b40a907e21901832f9a4b..b2e908e16beb5b25974d24fc2442e7b5faca1f91 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,32 @@
+libcec (1.9.1-1) unstable; urgency=low
+
+  * changed/added:
+    * added the type of adapter to libcec_configuration,
+      and display the type in cec-client -l
+    * added device detection support for composite usb devices on windows.
+      needs the windows ddk, and it's expected to be found in
+      C:\WinDDK\7600.16385.1
+
+  * interface changes:
+    * adapter type was added to libcec_configuration
+    * moved cec_adapter_messagecode from cectypes.h to USBCECAdapterMessage.h
+
+  * fixed:
+    * retry m_port->Read(..) if an EINTR errror occurs instead of closing the
+      connection. credits @Obruni. closes #38
+    * make cec-client include cecloader.h from our project, not from system
+    * fixed duplicate entries check in CUSBCECAdapterDetection
+    * fixed missing cec_version updates in libcec_configuration
+    * transmit an active source message after <set stream path> to a device
+      that's handled by libCEC. closes #43
+    * rpi: handle vendor specific remote control presses. closes #42
+    * rpi: handle VC_CEC_LOGICAL_ADDR_LOST, sent by the Pi's firmware when
+      the logical address was taken while CEC was being reinitialised
+    * panasonic: send out an active source message when the tv started up
+      because it sometimes doesn't request this
+
+ -- Pulse-Eight Packaging <packaging@pulse-eight.com>  Wed, 5 Sep 2012 16:54:00 +0100
+
 libcec (1.8.2-1) unstable; urgency=low
 
   * changed/added:
index ae1b5a545515ace259e374a75b0bc079c7dffbb4..0d09d42144c5c47dd7ce635f4319617d14b8c396 100644 (file)
@@ -1,5 +1,5 @@
 AC_PREREQ(2.59)
-AC_INIT([libcec], [1:8:0], [http://libcec.pulse-eight.com/])
+AC_INIT([libcec], [1:9:0], [http://libcec.pulse-eight.com/])
 AC_CONFIG_HEADERS([config.h])
 AH_TOP([#pragma once])
 
index 5c43fc20b5dd1b370c7b40a907e21901832f9a4b..b2e908e16beb5b25974d24fc2442e7b5faca1f91 100644 (file)
@@ -1,3 +1,32 @@
+libcec (1.9.1-1) unstable; urgency=low
+
+  * changed/added:
+    * added the type of adapter to libcec_configuration,
+      and display the type in cec-client -l
+    * added device detection support for composite usb devices on windows.
+      needs the windows ddk, and it's expected to be found in
+      C:\WinDDK\7600.16385.1
+
+  * interface changes:
+    * adapter type was added to libcec_configuration
+    * moved cec_adapter_messagecode from cectypes.h to USBCECAdapterMessage.h
+
+  * fixed:
+    * retry m_port->Read(..) if an EINTR errror occurs instead of closing the
+      connection. credits @Obruni. closes #38
+    * make cec-client include cecloader.h from our project, not from system
+    * fixed duplicate entries check in CUSBCECAdapterDetection
+    * fixed missing cec_version updates in libcec_configuration
+    * transmit an active source message after <set stream path> to a device
+      that's handled by libCEC. closes #43
+    * rpi: handle vendor specific remote control presses. closes #42
+    * rpi: handle VC_CEC_LOGICAL_ADDR_LOST, sent by the Pi's firmware when
+      the logical address was taken while CEC was being reinitialised
+    * panasonic: send out an active source message when the tv started up
+      because it sometimes doesn't request this
+
+ -- Pulse-Eight Packaging <packaging@pulse-eight.com>  Wed, 5 Sep 2012 16:54:00 +0100
+
 libcec (1.8.2-1) unstable; urgency=low
 
   * changed/added:
index 9c8962622f3a78498a90b646522bbafecc800b36..f196ddf8c7f7c94bf7d5347de6a57318d4b9480a 100644 (file)
@@ -1,4 +1,4 @@
-; Copyright (c) 2011 Pulse-Eight Limited
+; Copyright (c) 2012 Pulse-Eight Limited
 
 [Version]
 Signature="$Windows NT$"
@@ -7,7 +7,7 @@ ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318}
 Provider=%MFGNAME%
 LayoutFile=layout.inf
 CatalogFile=%MFGFILENAME%.cat
-DriverVer=07/04/2011,1.0.0.0
+DriverVer=08/29/2012,1.1.0.0
 
 [Manufacturer]
 %MFGNAME%=DeviceList, NTamd64
@@ -22,61 +22,68 @@ DefaultDestDir=12
 ;------------------------------------------------------------------------------
 
 [DriverInstall.nt]
-include=mdmcpq.inf
-CopyFiles=FakeModemCopyFileSection
-AddReg=DriverInstall.nt.AddReg
+include   = mdmcpq.inf
+CopyFiles = FakeModemCopyFileSection
+AddReg    = DriverInstall.nt.AddReg
 
 [DriverInstall.nt.AddReg]
 HKR,,DevLoader,,*ntkern
 HKR,,NTMPDriver,,%DRIVERFILENAME%.sys
 HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider"
+HKR,,PortSubClass,1,01
 
 [DriverInstall.nt.Services]
-AddService=usbser, 0x00000002, DriverService.nt
+AddService = usbser, 0x00000002, DriverService.nt
 
 [DriverService.nt]
-DisplayName=%SERVICE%
-ServiceType=1
-StartType=3
-ErrorControl=1
-ServiceBinary=%12%\%DRIVERFILENAME%.sys
+DisplayName   = %SERVICE%
+ServiceType   = 1 ; SERVICE_KERNEL_DRIVER
+StartType     = 3 ; SERVICE_DEMAND_START
+ErrorControl  = 1 ; SERVICE_ERROR_NORMAL
+ServiceBinary = %12%\%DRIVERFILENAME%.sys
+LoadOrderGroup = Base
 
 ;------------------------------------------------------------------------------
 ;  Vista-64bit Sections
 ;------------------------------------------------------------------------------
 
 [DriverInstall.NTamd64]
-include=mdmcpq.inf
-CopyFiles=FakeModemCopyFileSection
-AddReg=DriverInstall.NTamd64.AddReg
+include   = mdmcpq.inf
+CopyFiles = FakeModemCopyFileSection
+AddReg    = DriverInstall.NTamd64.AddReg
 
 [DriverInstall.NTamd64.AddReg]
 HKR,,DevLoader,,*ntkern
 HKR,,NTMPDriver,,%DRIVERFILENAME%.sys
 HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider"
+HKR,,PortSubClass,1,01
 
 [DriverInstall.NTamd64.Services]
-AddService=usbser, 0x00000002, DriverService.NTamd64
+AddService = usbser, 0x00000002, DriverService.NTamd64
 
 [DriverService.NTamd64]
-DisplayName=%SERVICE%
-ServiceType=1
-StartType=3
-ErrorControl=1
-ServiceBinary=%12%\%DRIVERFILENAME%.sys
+DisplayName    = %SERVICE%
+ServiceType    = 1 ; SERVICE_KERNEL_DRIVER
+StartType      = 3 ; SERVICE_DEMAND_START
+ErrorControl   = 1 ; SERVICE_ERROR_NORMAL
+ServiceBinary  = %12%\%DRIVERFILENAME%.sys
+LoadOrderGroup = Base
 
 [SourceDisksFiles]
 [SourceDisksNames]
 [DeviceList]
-%DESCRIPTION%=DriverInstall, USB\VID_2548&PID_1001
+%DESCRIPTION2% = DriverInstall, USB\VID_2548&PID_1002&MI_00
+%DESCRIPTION%  = DriverInstall, USB\VID_2548&PID_1001
 
 [DeviceList.NTamd64]
-%DESCRIPTION%=DriverInstall, USB\VID_2548&PID_1001
+%DESCRIPTION2% = DriverInstall, USB\VID_2548&PID_1002&MI_00
+%DESCRIPTION%  = DriverInstall, USB\VID_2548&PID_1001
 
 [Strings]
-MFGFILENAME="p8usb-cec"
-DRIVERFILENAME ="usbser"
-MFGNAME="Pulse-Eight Limited"
-INSTDISK="Pulse-Eight USB-CEC Installation Disc"
-DESCRIPTION="Pulse-Eight USB to HDMI CEC Adapter"
-SERVICE="USB to HDMI-CEC"
+MFGFILENAME    = "p8usb-cec"
+DRIVERFILENAME = "usbser"
+MFGNAME        = "Pulse-Eight Limited"
+INSTDISK       = "Pulse-Eight USB-CEC Installation Disc"
+DESCRIPTION    = "Pulse-Eight USB to HDMI CEC Adapter"
+DESCRIPTION2   = "Pulse-Eight USB to HDMI CEC Adapter (rev.2)"
+SERVICE        = "USB to HDMI-CEC"
index bd56fff29161739ff9a4ada0efb44e1c6a647cd9..f5e75903149cdc91aa87a5a23aeebeb06bdb3b90 100644 (file)
@@ -36,7 +36,7 @@
 
 #include "cectypes.h"
 
-#define LIBCEC_VERSION_CURRENT CEC_SERVER_VERSION_1_8_1
+#define LIBCEC_VERSION_CURRENT CEC_SERVER_VERSION_1_9_0
 
 namespace CEC
 {
@@ -500,6 +500,8 @@ namespace CEC
      * Should be called as first call to libCEC, directly after CECInitialise() and before using Open()
      */
     virtual void InitVideoStandalone(void) = 0;
+
+    virtual const char *ToString(const cec_adapter_type type) = 0;
   };
 };
 
index 4656141d9619c3007e6c2adff31c22976e8c2144..291190ce31671abc9c47ea00d5a48fbaced0372a 100644 (file)
@@ -120,7 +120,7 @@ namespace CEC {
 #define CEC_MIN_LIB_VERSION          1
 #define CEC_LIB_VERSION_MAJOR        1
 #define CEC_LIB_VERSION_MAJOR_STR    "1"
-#define CEC_LIB_VERSION_MINOR        8
+#define CEC_LIB_VERSION_MINOR        9
 
 typedef enum cec_abort_reason
 {
@@ -615,52 +615,6 @@ typedef enum cec_log_level
   CEC_LOG_ALL     = 31
 } cec_log_level;
 
-typedef enum cec_adapter_messagecode
-{
-  MSGCODE_NOTHING = 0,
-  MSGCODE_PING,
-  MSGCODE_TIMEOUT_ERROR,
-  MSGCODE_HIGH_ERROR,
-  MSGCODE_LOW_ERROR,
-  MSGCODE_FRAME_START,
-  MSGCODE_FRAME_DATA,
-  MSGCODE_RECEIVE_FAILED,
-  MSGCODE_COMMAND_ACCEPTED,
-  MSGCODE_COMMAND_REJECTED,
-  MSGCODE_SET_ACK_MASK,
-  MSGCODE_TRANSMIT,
-  MSGCODE_TRANSMIT_EOM,
-  MSGCODE_TRANSMIT_IDLETIME,
-  MSGCODE_TRANSMIT_ACK_POLARITY,
-  MSGCODE_TRANSMIT_LINE_TIMEOUT,
-  MSGCODE_TRANSMIT_SUCCEEDED,
-  MSGCODE_TRANSMIT_FAILED_LINE,
-  MSGCODE_TRANSMIT_FAILED_ACK,
-  MSGCODE_TRANSMIT_FAILED_TIMEOUT_DATA,
-  MSGCODE_TRANSMIT_FAILED_TIMEOUT_LINE,
-  MSGCODE_FIRMWARE_VERSION,
-  MSGCODE_START_BOOTLOADER,
-  MSGCODE_GET_BUILDDATE,
-  MSGCODE_SET_CONTROLLED,
-  MSGCODE_GET_AUTO_ENABLED,
-  MSGCODE_SET_AUTO_ENABLED,
-  MSGCODE_GET_DEFAULT_LOGICAL_ADDRESS,
-  MSGCODE_SET_DEFAULT_LOGICAL_ADDRESS,
-  MSGCODE_GET_LOGICAL_ADDRESS_MASK,
-  MSGCODE_SET_LOGICAL_ADDRESS_MASK,
-  MSGCODE_GET_PHYSICAL_ADDRESS,
-  MSGCODE_SET_PHYSICAL_ADDRESS,
-  MSGCODE_GET_DEVICE_TYPE,
-  MSGCODE_SET_DEVICE_TYPE,
-  MSGCODE_GET_HDMI_VERSION,
-  MSGCODE_SET_HDMI_VERSION,
-  MSGCODE_GET_OSD_NAME,
-  MSGCODE_SET_OSD_NAME,
-  MSGCODE_WRITE_EEPROM,
-  MSGCODE_FRAME_EOM = 0x80,
-  MSGCODE_FRAME_ACK = 0x40,
-} cec_adapter_messagecode;
-
 typedef enum cec_bus_device_status
 {
   CEC_DEVICE_STATUS_UNKNOWN,
@@ -693,6 +647,14 @@ typedef enum cec_vendor_id
   CEC_VENDOR_UNKNOWN   = 0
 } cec_vendor_id;
 
+typedef enum cec_adapter_type
+{
+  ADAPTERTYPE_UNKNOWN          = 0,
+  ADAPTERTYPE_P8_EXTERNAL      = 0x1,
+  ADAPTERTYPE_P8_DAUGHTERBOARD = 0x2,
+  ADAPTERTYPE_RPI              = 0x100
+} cec_adapter_type;
+
 typedef struct cec_menu_language
 {
   char                language[4]; /**< the iso language code. @bug the language code is only 3 chars long, not 4. will be changed in v2.0, because changing it now would break backwards compat */
@@ -1231,7 +1193,9 @@ typedef enum cec_client_version
   CEC_CLIENT_VERSION_1_7_1   = 0x1701,
   CEC_CLIENT_VERSION_1_7_2   = 0x1702,
   CEC_CLIENT_VERSION_1_8_0   = 0x1800,
-  CEC_CLIENT_VERSION_1_8_1   = 0x1801
+  CEC_CLIENT_VERSION_1_8_1   = 0x1801,
+  CEC_CLIENT_VERSION_1_8_2   = 0x1802,
+  CEC_CLIENT_VERSION_1_9_0   = 0x1900
 } cec_client_version;
 
 typedef enum cec_server_version
@@ -1249,7 +1213,9 @@ typedef enum cec_server_version
   CEC_SERVER_VERSION_1_7_1   = 0x1701,
   CEC_SERVER_VERSION_1_7_2   = 0x1702,
   CEC_SERVER_VERSION_1_8_0   = 0x1800,
-  CEC_SERVER_VERSION_1_8_1   = 0x1801
+  CEC_SERVER_VERSION_1_8_1   = 0x1801,
+  CEC_SERVER_VERSION_1_8_2   = 0x1802,
+  CEC_SERVER_VERSION_1_9_0   = 0x1900
 } cec_server_version;
 
 typedef struct libcec_configuration
@@ -1286,6 +1252,7 @@ typedef struct libcec_configuration
   uint32_t              iFirmwareBuildDate;   /*!< (read-only) the build date of the firmware, in seconds since epoch. if not available, this value will be set to 0. added in 1.6.2 */
   uint8_t               bMonitorOnly;         /*!< won't allocate a CCECClient when starting the connection when set (same as monitor mode). added in 1.6.3 */
   cec_version           cecVersion;           /*!< CEC spec version to use by libCEC. defaults to v1.4. added in 1.8.0 */
+  cec_adapter_type      adapterType;          /*!< type of the CEC adapter that we're connected to. added in 1.8.2 */
 
 #ifdef __cplusplus
   // @todo re-add in v2.0 (breaks ABI)
@@ -1323,7 +1290,9 @@ typedef struct libcec_configuration
         /* libcec 1.6.3+ */
         (other.clientVersion < CEC_CLIENT_VERSION_1_6_3 || bMonitorOnly              == other.bMonitorOnly) &&
         /* libcec 1.8.0+ */
-        (other.clientVersion < CEC_CLIENT_VERSION_1_8_0 || cecVersion                == other.cecVersion));
+        (other.clientVersion < CEC_CLIENT_VERSION_1_8_0 || cecVersion                == other.cecVersion) &&
+        /* libcec 1.8.2+ */
+        (other.clientVersion < CEC_CLIENT_VERSION_1_8_2 || adapterType               == other.adapterType));
   }
 
   bool operator!=(const libcec_configuration &other) const
@@ -1356,6 +1325,7 @@ typedef struct libcec_configuration
     iFirmwareBuildDate =              CEC_FW_BUILD_UNKNOWN;
     bMonitorOnly =                    0;
     cecVersion =         (cec_version)CEC_DEFAULT_SETTING_CEC_VERSION;
+    adapterType =                     ADAPTERTYPE_UNKNOWN;
 
     memset(strDeviceName, 0, 13);
     deviceTypes.clear();
index 93552147730f07000451dd895b4e3bc0c5b50d2d..794082517e725c368e0775be77d891de7be39725 100644 (file)
Binary files a/project/cec-config.rc and b/project/cec-config.rc differ
index 05e40fe31ef9c30d5372107d28f53e0159c9968b..7b488df50750ddabfc055c8d25f3895293552703 100644 (file)
Binary files a/project/libcec.rc and b/project/libcec.rc differ
index 3c26ad7d65c1e54fd1ef81472560be7f529324b7..dd529e1b454008fd7d1f9a387eba321f68c503ea 100644 (file)
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
     <IncludePath>$(SolutionDir)..\include;$(IncludePath)</IncludePath>
+    <LibraryPath>C:\WinDDK\7600.16385.1\lib\win7\i386;$(LibraryPath)</LibraryPath>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
     <IncludePath>$(SolutionDir)..\include;$(IncludePath)</IncludePath>
+    <LibraryPath>C:\WinDDK\7600.16385.1\lib\win7\amd64;$(LibraryPath)</LibraryPath>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
     <OutDir>$(SolutionDir)..\build\</OutDir>
     <TargetName>libcec</TargetName>
     <IncludePath>$(SolutionDir)..\include;$(IncludePath)</IncludePath>
+    <LibraryPath>C:\WinDDK\7600.16385.1\lib\win7\i386;$(LibraryPath)</LibraryPath>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
     <OutDir>$(SolutionDir)..\build\</OutDir>
     <TargetName>$(ProjectName).x64</TargetName>
     <IncludePath>$(SolutionDir)..\include;$(IncludePath)</IncludePath>
+    <LibraryPath>C:\WinDDK\7600.16385.1\lib\win7\amd64;$(LibraryPath)</LibraryPath>
   </PropertyGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
     <ClCompile>
index 8d5a34be7089d9cc62ff08fc277b04e49e4f1d37..c227b7ee4dbeb2394564b646f19f930bd3591900 100644 (file)
Binary files a/project/testclient.rc and b/project/testclient.rc differ
index 0d58134693610ff78b6a2a99e2a13515b50817b9..dca7ce0ff8d84b18098453370e3ee913f79304e2 100644 (file)
@@ -43,7 +43,7 @@ namespace CecSharpClient
       Config = new LibCECConfiguration();
       Config.DeviceTypes.Types[0] = CecDeviceType.RecordingDevice;
       Config.DeviceName = "CEC Tester";
-      Config.ClientVersion = CecClientVersion.Version1_8_1;
+      Config.ClientVersion = CecClientVersion.Version1_9_0;
       Config.SetCallbacks(this);
       LogLevel = (int)CecLogLevel.All;
 
index 7161761c0869fc97ac696ff60b24aa05751f1e5f..53d167cea85425497d257c96ce72d1425af3a2bd 100644 (file)
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
 // You can specify all the values or you can default the Build and Revision Numbers 
 // by using the '*' as shown below:
 // [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.8.1.0")]
-[assembly: AssemblyFileVersion("1.8.1.0")]
+[assembly: AssemblyVersion("1.9.0.0")]
+[assembly: AssemblyFileVersion("1.9.0.0")]
index 8cfa0ad8f26918bd420ce9028cceb7f313dac2ab..9f633ca2274f6fe0cda6bf2224be4c6fed22935a 100644 (file)
@@ -13,7 +13,7 @@ using namespace System::Security::Permissions;
 [assembly:AssemblyTrademarkAttribute("")];
 [assembly:AssemblyCultureAttribute("")];
 
-[assembly:AssemblyVersionAttribute("1.8.1.0")];
+[assembly:AssemblyVersionAttribute("1.9.0.0")];
 
 [assembly:ComVisible(false)];
 [assembly:CLSCompliantAttribute(true)];
index 7b02c0d09098f5533cc06105286762ed901f9d16..52c0b2020797bfd702ddbc4aa293395f49947f27 100644 (file)
@@ -371,7 +371,9 @@ namespace CecSharp
                Version1_7_1  = 0x1701,
                Version1_7_2  = 0x1702,
                Version1_8_0  = 0x1800,
-               Version1_8_1  = 0x1801
+               Version1_8_1  = 0x1801,
+               Version1_8_2  = 0x1802,
+               Version1_9_0  = 0x1900
        };
 
        public enum class CecServerVersion
@@ -389,7 +391,9 @@ namespace CecSharp
                Version1_7_1  = 0x1701,
                Version1_7_2  = 0x1702,
                Version1_8_0  = 0x1800,
-               Version1_8_1  = 0x1801
+               Version1_8_1  = 0x1801,
+               Version1_8_2  = 0x1802,
+               Version1_9_0  = 0x1900
        };
 
        public ref class CecAdapter
index 7521b0950b33cbd43a18e568caa6f51caf99e798..0e83c6a449fd727218ab0acf75d3efd7b474c620 100644 (file)
@@ -28,7 +28,7 @@ namespace CecConfigGui
       Config.DeviceTypes.Types[0] = CecDeviceType.RecordingDevice;
       Config.DeviceName = "CEC Config";
       Config.GetSettingsFromROM = true;
-      Config.ClientVersion = CecClientVersion.Version1_8_1;
+      Config.ClientVersion = CecClientVersion.Version1_9_0;
       Callbacks = new CecCallbackWrapper(this);
       Config.SetCallbacks(Callbacks);
       LoadXMLConfiguration(ref Config);
index 91c17636d9595ffca0699528ec762b888dde5294..891de3eaa0f3b242a3797f26ec833fcbf6d20697 100644 (file)
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
 // You can specify all the values or you can default the Build and Revision Numbers 
 // by using the '*' as shown below:
 // [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.8.1.0")]
-[assembly: AssemblyFileVersion("1.8.1.0")]
+[assembly: AssemblyVersion("1.9.0.0")]
+[assembly: AssemblyFileVersion("1.9.0.0")]
index d7775e990718bb37ee4118b9e18b1f5aa7e965a6..a3d2b77f5666a592ba6b21d72a5307becf68e913 100644 (file)
@@ -159,7 +159,7 @@ bool OpenConnection(cec_device_type type = CEC_DEVICE_TYPE_RECORDING_DEVICE)
   g_config.Clear();
   snprintf(g_config.strDeviceName, 13, "CEC-config");
   g_config.callbackParam      = NULL;
-  g_config.clientVersion      = (uint32_t)CEC_CLIENT_VERSION_1_8_1;
+  g_config.clientVersion      = (uint32_t)CEC_CLIENT_VERSION_1_9_0;
   g_callbacks.CBCecLogMessage = &CecLogMessage;
   g_callbacks.CBCecKeyPress   = &CecKeyPress;
   g_callbacks.CBCecCommand    = &CecCommand;
index e7ac9556349601af73230fbc73904c918ed8777d..c9525af15ace48fd132a3c78771d65873fdf79ee 100644 (file)
@@ -802,6 +802,14 @@ bool CCECClient::GetCurrentConfiguration(libcec_configuration &configuration)
     configuration.bMonitorOnly            = m_configuration.bMonitorOnly;
   }
 
+  // client version 1.8.0
+  if (configuration.clientVersion >= CEC_CLIENT_VERSION_1_8_0)
+    configuration.cecVersion              = m_configuration.cecVersion;
+
+  // client version 1.8.2
+  if (configuration.clientVersion >= CEC_CLIENT_VERSION_1_8_2)
+    configuration.adapterType             = m_configuration.adapterType;
+
   return true;
 }
 
@@ -859,6 +867,14 @@ bool CCECClient::SetConfiguration(const libcec_configuration &configuration)
       m_configuration.bMonitorOnly = configuration.bMonitorOnly;
     }
 
+    // client version 1.8.0
+    if (configuration.clientVersion >= CEC_CLIENT_VERSION_1_8_0)
+      m_configuration.cecVersion   = configuration.cecVersion;
+
+    // client version 1.8.2
+    if (configuration.clientVersion >= CEC_CLIENT_VERSION_1_8_2)
+      m_configuration.adapterType  = configuration.adapterType;
+
     // ensure that there is at least 1 device type set
     if (m_configuration.deviceTypes.IsEmpty())
       m_configuration.deviceTypes.Add(CEC_DEVICE_TYPE_RECORDING_DEVICE);
index 88795e92b9dde65123abe66f6b4de546371b9759..9d496404d30a338b61a9acbb43ef70f3c2b34c06 100644 (file)
@@ -63,13 +63,17 @@ CCECProcessor::CCECProcessor(CLibCEC *libcec) :
     m_iStandardLineTimeout(3),
     m_iRetryLineTimeout(3),
     m_iLastTransmission(0),
-    m_bMonitor(true)
+    m_bMonitor(true),
+    m_addrAllocator(NULL),
+    m_bStallCommunication(false)
 {
   m_busDevices = new CCECDeviceMap(this);
 }
 
 CCECProcessor::~CCECProcessor(void)
 {
+  m_bStallCommunication = false;
+  DELETE_AND_NULL(m_addrAllocator);
   Close();
   DELETE_AND_NULL(m_busDevices);
 }
@@ -410,6 +414,9 @@ bool CCECProcessor::Transmit(const cec_command &data, bool bIsReply)
     }
   }
 
+  // wait until we finished allocating a new LA if it got lost
+  while (m_bStallCommunication) Sleep(5);
+
   {
     CLockObject lock(m_mutex);
     m_iLastTransmission = GetTimeMs();
@@ -604,6 +611,7 @@ bool CCECProcessor::GetDeviceInformation(const char *strPort, libcec_configurati
   config->iFirmwareVersion   = m_communication->GetFirmwareVersion();
   config->iPhysicalAddress   = m_communication->GetPhysicalAddress();
   config->iFirmwareBuildDate = m_communication->GetFirmwareBuildDate();
+  config->adapterType        = m_communication->GetAdapterType();
 
   return true;
 }
@@ -641,6 +649,54 @@ CCECTuner *CCECProcessor::GetTuner(cec_logical_address address) const
   return CCECBusDevice::AsTuner(m_busDevices->At(address));
 }
 
+bool CCECProcessor::AllocateLogicalAddresses(CCECClient* client)
+{
+  libcec_configuration &configuration = *client->GetConfiguration();
+
+  // mark as unregistered
+  client->SetRegistered(false);
+
+  // unregister this client from the old addresses
+  CECDEVICEVEC devices;
+  m_busDevices->GetByLogicalAddresses(devices, configuration.logicalAddresses);
+  for (CECDEVICEVEC::const_iterator it = devices.begin(); it != devices.end(); it++)
+  {
+    // remove client entry
+    CLockObject lock(m_mutex);
+    m_clients.erase((*it)->GetLogicalAddress());
+  }
+
+  // find logical addresses for this client
+  if (!client->AllocateLogicalAddresses())
+  {
+    m_libcec->AddLog(CEC_LOG_ERROR, "failed to find a free logical address for the client");
+    return false;
+  }
+
+  // register this client on the new addresses
+  devices.clear();
+  m_busDevices->GetByLogicalAddresses(devices, configuration.logicalAddresses);
+  for (CECDEVICEVEC::const_iterator it = devices.begin(); it != devices.end(); it++)
+  {
+    // set the physical address of the device at this LA
+    if (CLibCEC::IsValidPhysicalAddress(configuration.iPhysicalAddress))
+      (*it)->SetPhysicalAddress(configuration.iPhysicalAddress);
+
+    // replace a previous client
+    CLockObject lock(m_mutex);
+    m_clients.erase((*it)->GetLogicalAddress());
+    m_clients.insert(make_pair<cec_logical_address, CCECClient *>((*it)->GetLogicalAddress(), client));
+  }
+
+  // set the new ackmask
+  SetLogicalAddresses(GetLogicalAddresses());
+
+  // resume outgoing communication
+  m_bStallCommunication = false;
+
+  return true;
+}
+
 bool CCECProcessor::RegisterClient(CCECClient *client)
 {
   if (!client)
@@ -683,36 +739,20 @@ bool CCECProcessor::RegisterClient(CCECClient *client)
   // get the configuration from the client
   m_libcec->AddLog(CEC_LOG_NOTICE, "registering new CEC client - v%s", ToString((cec_client_version)configuration.clientVersion));
 
-  // mark as uninitialised and unregistered
-  client->SetRegistered(false);
-  client->SetInitialised(false);
-
   // get the current ackmask, so we can restore it if polling fails
   cec_logical_addresses previousMask = GetLogicalAddresses();
 
+  // mark as uninitialised
+  client->SetInitialised(false);
+
   // find logical addresses for this client
-  if (!client->AllocateLogicalAddresses())
+  if (!AllocateLogicalAddresses(client))
   {
     m_libcec->AddLog(CEC_LOG_ERROR, "failed to register the new CEC client - cannot allocate the requested device types");
     SetLogicalAddresses(previousMask);
     return false;
   }
 
-  // register this client on the new addresses
-  CECDEVICEVEC devices;
-  m_busDevices->GetByLogicalAddresses(devices, configuration.logicalAddresses);
-  for (CECDEVICEVEC::const_iterator it = devices.begin(); it != devices.end(); it++)
-  {
-               // set the physical address of the device at this LA
-    if (CLibCEC::IsValidPhysicalAddress(configuration.iPhysicalAddress))
-      (*it)->SetPhysicalAddress(configuration.iPhysicalAddress);
-
-    // replace a previous client
-    CLockObject lock(m_mutex);
-    m_clients.erase((*it)->GetLogicalAddress());
-    m_clients.insert(make_pair<cec_logical_address, CCECClient *>((*it)->GetLogicalAddress(), client));
-  }
-
   // get the settings from the rom
   if (configuration.bGetSettingsFromROM == 1)
   {
@@ -731,14 +771,13 @@ bool CCECProcessor::RegisterClient(CCECClient *client)
   configuration.serverVersion      = LIBCEC_VERSION_CURRENT;
   configuration.iFirmwareVersion   = m_communication->GetFirmwareVersion();
   configuration.iFirmwareBuildDate = m_communication->GetFirmwareBuildDate();
+  configuration.adapterType        = m_communication->GetAdapterType();
 
   // mark the client as registered
   client->SetRegistered(true);
 
-  // set the new ack mask
-  bool bReturn = SetLogicalAddresses(GetLogicalAddresses()) &&
-      // and initialise the client
-      client->OnRegister();
+  // initialise the client
+  bool bReturn = client->OnRegister();
 
   // log the new registration
   CStdString strLog;
@@ -884,3 +923,31 @@ void CCECProcessor::SwitchMonitoring(bool bSwitchTo)
   if (bSwitchTo)
     UnregisterClients();
 }
+
+void CCECProcessor::HandleLogicalAddressLost(cec_logical_address oldAddress)
+{
+  // stall outgoing messages until we know our new LA
+  m_bStallCommunication = true;
+
+  m_libcec->AddLog(CEC_LOG_NOTICE, "logical address %x was taken by another device, allocating a new address", oldAddress);
+  CCECClient* client = GetClient(oldAddress);
+  if (client)
+  {
+    if (m_addrAllocator)
+      while (m_addrAllocator->IsRunning()) Sleep(5);
+    delete m_addrAllocator;
+
+    m_addrAllocator = new CCECAllocateLogicalAddress(this, client);
+    m_addrAllocator->CreateThread();
+  }
+}
+
+CCECAllocateLogicalAddress::CCECAllocateLogicalAddress(CCECProcessor* processor, CCECClient* client) :
+    m_processor(processor),
+    m_client(client) { }
+
+void* CCECAllocateLogicalAddress::Process(void)
+{
+  m_processor->AllocateLogicalAddresses(m_client);
+  return NULL;
+}
index dc8e9f557d1c476b6a16029a11239fc3f380b56a..e1f6d68517eee2908cc7f1b6906e72db0f29240b 100644 (file)
@@ -51,6 +51,18 @@ namespace CEC
   class CCECTuner;
   class CCECTV;
   class CCECClient;
+  class CCECProcessor;
+
+  class CCECAllocateLogicalAddress : public PLATFORM::CThread
+  {
+  public:
+    CCECAllocateLogicalAddress(CCECProcessor* processor, CCECClient* client);
+    void* Process(void);
+
+  private:
+    CCECProcessor* m_processor;
+    CCECClient*    m_client;
+  };
 
   class CCECProcessor : public PLATFORM::CThread, public IAdapterCommunicationCallback
   {
@@ -69,6 +81,7 @@ namespace CEC
       CCECClient *GetClient(const cec_logical_address address);
 
       bool                  OnCommandReceived(const cec_command &command);
+      void                  HandleLogicalAddressLost(cec_logical_address oldAddress);
 
       CCECBusDevice *       GetDevice(cec_logical_address address) const;
       CCECAudioSystem *     GetAudioSystem(void) const;
@@ -129,6 +142,7 @@ namespace CEC
       bool IsRunningLatestFirmware(void);
       void SwitchMonitoring(bool bSwitchTo);
 
+      bool AllocateLogicalAddresses(CCECClient* client);
     private:
       bool OpenConnection(const char *strPort, uint16_t iBaudRate, uint32_t iTimeoutMs, bool bStartListening = true);
       void SetCECInitialised(bool bSetTo = true);
@@ -155,5 +169,7 @@ namespace CEC
       CCECDeviceMap *                             m_busDevices;
       std::map<cec_logical_address, CCECClient *> m_clients;
       bool                                        m_bMonitor;
+      CCECAllocateLogicalAddress*                 m_addrAllocator;
+      bool                                        m_bStallCommunication;
   };
 };
index 7a50d9e743fc0fcb43b30403b773054bee457add..a79163473c6fdac5ad312b66b29e582d91628569 100644 (file)
@@ -547,6 +547,10 @@ namespace CEC
         return "1.8.0";
       case CEC_CLIENT_VERSION_1_8_1:
         return "1.8.1";
+      case CEC_CLIENT_VERSION_1_8_2:
+        return "1.8.2";
+      case CEC_CLIENT_VERSION_1_9_0:
+        return "1.9.0";
       default:
         return "Unknown";
       }
@@ -584,6 +588,10 @@ namespace CEC
         return "1.8.0";
       case CEC_SERVER_VERSION_1_8_1:
         return "1.8.1";
+      case CEC_SERVER_VERSION_1_8_2:
+        return "1.8.2";
+      case CEC_SERVER_VERSION_1_9_0:
+        return "1.9.0";
       default:
         return "Unknown";
       }
@@ -776,5 +784,20 @@ namespace CEC
         return "unknown";
       }
     }
+
+    static const char *ToString(const cec_adapter_type type)
+    {
+      switch (type)
+      {
+      case ADAPTERTYPE_P8_EXTERNAL:
+        return "Pulse-Eight USB-CEC Adapter";
+      case ADAPTERTYPE_P8_DAUGHTERBOARD:
+        return "Pulse-Eight USB-CEC Daughterboard";
+      case ADAPTERTYPE_RPI:
+        return "Raspberry Pi";
+      default:
+        return "unknown";
+      }
+    }
   };
 }
index ad4ce66625873f156c7f037b0d9445228c3e0e28..252e1dcfe9f48545f183b82698b87cb325d029a3 100644 (file)
@@ -649,6 +649,11 @@ void CLibCEC::InitVideoStandalone(void)
   CAdapterFactory::InitVideoStandalone();
 }
 
+const char *CLibCEC::ToString(const cec_adapter_type type)
+{
+  return CCECTypeUtils::ToString(type);
+}
+
 // no longer being used
 void CLibCEC::AddKey(const cec_keypress &UNUSED(key)) {}
 void CLibCEC::ConfigurationChanged(const libcec_configuration &UNUSED(config)) {}
index 76d29191e9619ee66555bd9fad2c81d5d048176d..fa4e6321bf92b9d1b347af2b9d40da3bf8d7036b 100644 (file)
@@ -149,6 +149,7 @@ namespace CEC
       const char *GetLibInfo(void);
       const char *ToString(const cec_user_control_code key);
       void InitVideoStandalone(void);
+      const char *ToString(const cec_adapter_type type);
 
       CCECProcessor *           m_cec;
 
index 03880b6ef921dafaa46657aa6069c2c56456c47b..07026713042a19e934bc84af18d4060de42788cb 100644 (file)
@@ -75,6 +75,12 @@ namespace CEC
      */
     virtual bool HandleReceiveFailed(cec_logical_address initiator) = 0;
 
+    /*!
+     * @brief Callback method for IAdapterCommunication, called when a logical address that libCEC uses was taken by another device.
+     * @param oldAddress The logical address that was taken by another device.
+     */
+    virtual void HandleLogicalAddressLost(cec_logical_address oldAddress) = 0;
+
     virtual CLibCEC *GetLib(void) const = 0;
   };
 
@@ -200,6 +206,11 @@ namespace CEC
      */
     virtual bool SupportsSourceLogicalAddress(const cec_logical_address address) = 0;
 
+    /*!
+     * @return The type of adapter that this instance is connected to.
+     */
+    virtual cec_adapter_type GetAdapterType(void) = 0;
+
     IAdapterCommunicationCallback *m_callback;
   };
 };
index 457889cf3b555d9baffba9ed786ad2e813880ed0..ab0fa392e12633c54a0c237861bbae481b1fbfcb 100644 (file)
@@ -54,7 +54,8 @@ CUSBCECAdapterCommands::CUSBCECAdapterCommands(CUSBCECAdapterCommunication *comm
     m_iSettingLAMask(0),
     m_bNeedsWrite(false),
     m_iBuildDate(CEC_FW_BUILD_UNKNOWN),
-    m_bControlledMode(false)
+    m_bControlledMode(false),
+    m_adapterType(P8_ADAPTERTYPE_UNKNOWN)
 {
   m_persistedConfiguration.Clear();
 }
@@ -132,6 +133,19 @@ bool CUSBCECAdapterCommands::RequestSettingCECVersion(void)
   return false;
 }
 
+p8_cec_adapter_type CUSBCECAdapterCommands::RequestAdapterType(void)
+{
+  if (m_adapterType == P8_ADAPTERTYPE_UNKNOWN)
+  {
+    LIB_CEC->AddLog(CEC_LOG_DEBUG, "requesting adapter type");
+
+    cec_datapacket response = RequestSetting(MSGCODE_GET_ADAPTER_TYPE);
+    if (response.size == 1)
+      m_adapterType = (p8_cec_adapter_type)response[0];
+  }
+  return m_adapterType;
+}
+
 uint32_t CUSBCECAdapterCommands::RequestBuildDate(void)
 {
   if (m_iBuildDate == CEC_FW_BUILD_UNKNOWN)
index 897ed1cb417239784cd78e7914f9ef5c06357023..fa7f543261ef8e8c6aee8a9b0dc5c4c81f5fdad7 100644 (file)
@@ -32,6 +32,7 @@
  */
 
 #include "lib/platform/threads/mutex.h"
+#include "USBCECAdapterMessage.h"
 
 namespace CEC
 {
@@ -113,6 +114,17 @@ namespace CEC
      */
     uint32_t GetPersistedBuildDate(void) const { return m_iBuildDate; };
 
+    /*!
+     * @brief Request the adapter type.
+     * @return The type
+     */
+    p8_cec_adapter_type RequestAdapterType(void);
+
+    /*!
+     * @return The persisted build date.
+     */
+    p8_cec_adapter_type GetPersistedAdapterType(void) const { return m_adapterType; };
+
     /*!
      * @brief Persist the current settings in the EEPROM
      * @return True when persisted, false otherwise.
@@ -233,6 +245,7 @@ namespace CEC
     libcec_configuration         m_persistedConfiguration; /**< the configuration that is persisted in the eeprom */
     uint32_t                     m_iBuildDate;             /**< the build date of the firmware */
     bool                         m_bControlledMode;        /**< current value of the controlled mode feature */
+    p8_cec_adapter_type          m_adapterType;            /**< the type of the adapter that we're connected to */
     PLATFORM::CMutex             m_mutex;
   };
 }
index 70e45ac6c30e00e06987cf9c001f67cf55c68028..ae4c8ac60ebdc210e7706af77d55fac74dcf0bd5 100644 (file)
@@ -393,7 +393,11 @@ bool CUSBCECAdapterCommunication::ReadFromDevice(uint32_t iTimeout, size_t iSize
     if (!IsOpen())
       return false;
 
-    iBytesRead = m_port->Read(buff, sizeof(uint8_t) * iSize, iTimeout);
+    do {
+      /* retry Read() if it was interrupted */
+      iBytesRead = m_port->Read(buff, sizeof(uint8_t) * iSize, iTimeout);
+    } while(m_port->GetErrorNumber() == EINTR);
+
 
     if (m_port->GetErrorNumber())
     {
@@ -482,8 +486,14 @@ bool CUSBCECAdapterCommunication::CheckAdapter(uint32_t iTimeoutMs /* = CEC_DEFA
   else
     bReturn = true;
 
-  /* try to read the build date */
-  m_commands->RequestBuildDate();
+  if (m_commands->GetFirmwareVersion() >= 2)
+  {
+    /* try to read the build date */
+    m_commands->RequestBuildDate();
+
+    /* try to read the adapter type */
+    m_commands->RequestAdapterType();
+  }
 
   SetInitialised(bReturn);
   return bReturn;
@@ -570,6 +580,17 @@ uint32_t CUSBCECAdapterCommunication::GetFirmwareBuildDate(void)
   return iBuildDate;
 }
 
+cec_adapter_type CUSBCECAdapterCommunication::GetAdapterType(void)
+{
+  cec_adapter_type type(ADAPTERTYPE_UNKNOWN);
+  if (m_commands)
+    type = (cec_adapter_type)m_commands->GetPersistedAdapterType();
+  if (type == ADAPTERTYPE_UNKNOWN && IsOpen())
+    type = (cec_adapter_type)m_commands->RequestAdapterType();
+
+  return type;
+}
+
 bool CUSBCECAdapterCommunication::ProvidesExtendedResponse(void)
 {
   uint32_t iBuildDate(0);
index 1144d0e1be2c46fdbe63c7594971839bcdf1d4d3..2192456010ca99c7dae30f42285a8ed387d79dd3 100644 (file)
@@ -33,6 +33,7 @@
 
 #include "lib/platform/threads/threads.h"
 #include "lib/adapter/AdapterCommunication.h"
+#include "USBCECAdapterMessage.h"
 
 namespace PLATFORM
 {
@@ -86,6 +87,7 @@ namespace CEC
     bool SetControlledMode(bool controlled);
     cec_vendor_id GetVendorId(void) { return CEC_VENDOR_UNKNOWN; }
     bool SupportsSourceLogicalAddress(const cec_logical_address UNUSED(address)) { return true; }
+    cec_adapter_type GetAdapterType(void);
     ///}
 
     bool ProvidesExtendedResponse(void);
index f9969d83c08c16955250c5e867641751a4eb4cad..5d72b5efbbb7ab9a1916e487d00cb9e62259d8cf 100644 (file)
 #elif defined(__WINDOWS__)
 #pragma comment(lib, "advapi32.lib")
 #pragma comment(lib, "setupapi.lib")
+#pragma comment(lib, "cfgmgr32.lib")
 #include <setupapi.h>
+#include <cfgmgr32.h>
 
 // the virtual COM port only shows up when requesting devices with the raw device guid!
-static GUID USB_RAW_GUID =  { 0xA5DCBF10, 0x6530, 0x11D2, { 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED } };
+static GUID USB_RAW_GUID = { 0xA5DCBF10, 0x6530, 0x11D2, { 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED } };
+static GUID USB_CDC_GUID = { 0x4D36E978, 0xE325, 0x11CE, { 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18 } };
+
 #elif defined(HAVE_LIBUDEV)
 #include <dirent.h>
 #include <poll.h>
@@ -61,8 +65,9 @@ extern "C" {
 #include <unistd.h>
 #endif
 
-#define CEC_VID 0x2548
-#define CEC_PID 0x1001
+#define CEC_VID  0x2548
+#define CEC_PID  0x1001
+#define CEC_PID2 0x1002
 
 using namespace CEC;
 using namespace std;
@@ -125,6 +130,78 @@ bool CUSBCECAdapterDetection::CanAutodetect(void)
 #endif
 }
 
+#if defined(__WINDOWS__)
+static bool GetComPortFromHandle(HDEVINFO hDevHandle, PSP_DEVINFO_DATA devInfoData, char* strPortName, unsigned int iSize)
+{
+  bool bReturn(false);
+  TCHAR strRegPortName[256];
+  strRegPortName[0] = _T('\0');
+  DWORD dwSize = sizeof(strRegPortName);
+  DWORD dwType = 0;
+
+  HKEY hDeviceKey = SetupDiOpenDevRegKey(hDevHandle, devInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE);
+  if (!hDeviceKey)
+    return bReturn;
+
+  // locate the PortName
+  if ((RegQueryValueEx(hDeviceKey, _T("PortName"), NULL, &dwType, reinterpret_cast<LPBYTE>(strRegPortName), &dwSize) == ERROR_SUCCESS) &&
+      (dwType == REG_SZ) &&
+      _tcslen(strRegPortName) > 3 &&
+      _tcsnicmp(strRegPortName, _T("COM"), 3) == 0 &&
+      _ttoi(&(strRegPortName[3])) > 0)
+  {
+    // return the port name
+    snprintf(strPortName, iSize, "%s", strRegPortName);
+    bReturn = true;
+  }
+
+  RegCloseKey(hDeviceKey);
+
+  return bReturn;
+}
+
+static bool FindComPortForComposite(const char* strLocation, char* strPortName, unsigned int iSize)
+{
+  bool bReturn(false);
+
+  // find all devices of the CDC class
+  HDEVINFO hDevHandle = SetupDiGetClassDevs(&USB_CDC_GUID, NULL, NULL, DIGCF_PRESENT);
+  if (hDevHandle == INVALID_HANDLE_VALUE)
+    return bReturn;
+
+  // check all devices, whether they match the location or not
+  char strId[512];
+  bool bGetNext(true);
+  for (int iPtr = 0; !bReturn && bGetNext && iPtr < 1024 ; iPtr++)
+  {
+    strId[0] = 0;
+
+    SP_DEVINFO_DATA devInfoData;
+    devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
+
+    // no more devices
+    if (!SetupDiEnumDeviceInfo(hDevHandle, iPtr, &devInfoData))
+      bGetNext = false;
+    else
+    {
+      // check if the location of the _parent_ device matches
+      DEVINST parentDevInst;
+      if (CM_Get_Parent(&parentDevInst, devInfoData.DevInst, 0) == CR_SUCCESS)
+      {
+        CM_Get_Device_ID(parentDevInst, strId, 512, 0);
+
+        // match
+        if (!strncmp(strId, strLocation, strlen(strLocation)))
+          bReturn = GetComPortFromHandle(hDevHandle, &devInfoData, strPortName, iSize);
+      }
+    }
+  }
+
+  SetupDiDestroyDeviceInfoList(hDevHandle);
+  return bReturn;
+}
+#endif
+
 uint8_t CUSBCECAdapterDetection::FindAdapters(cec_adapter *deviceList, uint8_t iBufSize, const char *strDevicePath /* = NULL */)
 {
   uint8_t iFound(0);
@@ -180,17 +257,21 @@ uint8_t CUSBCECAdapterDetection::FindAdapters(cec_adapter *deviceList, uint8_t i
             kresult = IORegistryEntryGetParentEntry(parent, kIOServicePlane, &parent);
             IOObjectRelease(oldparent);
           }
-          if (strlen(bsdPath) && iVendor == CEC_VID && iProduct == CEC_PID)
+          if (strlen(bsdPath) && iVendor == CEC_VID && (iProduct == CEC_PID || iProduct == CEC_PID2))
           {
             if (!strDevicePath || !strcmp(bsdPath, strDevicePath))
             {
               // on darwin, the device path is the same as the comm path.
-              snprintf(deviceList[iFound  ].path, sizeof(deviceList[iFound].path), "%s", bsdPath);
-              snprintf(deviceList[iFound++].comm, sizeof(deviceList[iFound].path), "%s", bsdPath);
+              if (iFound == 0 || strcmp(deviceList[iFound-1].comm, bsdPath))
+              {
+                snprintf(deviceList[iFound].path, sizeof(deviceList[iFound].path), "%s", bsdPath);
+                snprintf(deviceList[iFound].comm, sizeof(deviceList[iFound].path), "%s", bsdPath);
+                iFound++;
+              }
             }
           }
         }
-             IOObjectRelease(serialService);
+        IOObjectRelease(serialService);
       }
     }
     IOObjectRelease(serialPortIterator);
@@ -225,16 +306,17 @@ uint8_t CUSBCECAdapterDetection::FindAdapters(cec_adapter *deviceList, uint8_t i
     int iVendor, iProduct;
     sscanf(udev_device_get_sysattr_value(pdev, "idVendor"), "%x", &iVendor);
     sscanf(udev_device_get_sysattr_value(pdev, "idProduct"), "%x", &iProduct);
-    if (iVendor == CEC_VID && iProduct == CEC_PID)
+    if (iVendor == CEC_VID && (iProduct == CEC_PID || iProduct == CEC_PID2))
     {
       CStdString strPath(udev_device_get_syspath(pdev));
       if (!strDevicePath || !strcmp(strPath.c_str(), strDevicePath))
       {
         CStdString strComm(strPath);
-        if (FindComPort(strComm))
+        if (FindComPort(strComm) && (iFound == 0 || strcmp(deviceList[iFound-1].comm, strComm.c_str())))
         {
-          snprintf(deviceList[iFound  ].path, sizeof(deviceList[iFound].path), "%s", strPath.c_str());
-          snprintf(deviceList[iFound++].comm, sizeof(deviceList[iFound].path), "%s", strComm.c_str());
+          snprintf(deviceList[iFound].path, sizeof(deviceList[iFound].path), "%s", strPath.c_str());
+          snprintf(deviceList[iFound].comm, sizeof(deviceList[iFound].path), "%s", strComm.c_str());
+          iFound++;
         }
       }
     }
@@ -254,6 +336,7 @@ uint8_t CUSBCECAdapterDetection::FindAdapters(cec_adapter *deviceList, uint8_t i
   SP_DEVINFO_DATA devInfoData;
   devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
 
+  // find all devices
   if ((hDevHandle = SetupDiGetClassDevs(&USB_RAW_GUID, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE)) == INVALID_HANDLE_VALUE)
     return iFound;
 
@@ -269,6 +352,7 @@ uint8_t CUSBCECAdapterDetection::FindAdapters(cec_adapter *deviceList, uint8_t i
 
     if(!bResult)
     {
+      // no (more) results
       SetupDiDestroyDeviceInfoList(hDevHandle);
       delete []buffer;
       buffer = NULL;
@@ -297,9 +381,11 @@ uint8_t CUSBCECAdapterDetection::FindAdapters(cec_adapter *deviceList, uint8_t i
     if(!bDetailResult)
       continue;
 
+    // check whether the path matches, if a path was given
     if (strDevicePath && strcmp(strDevicePath, devicedetailData->DevicePath) != 0)
       continue;
 
+    // get the vid and pid
     CStdString strVendorId;
     CStdString strProductId;
     CStdString strTmp(devicedetailData->DevicePath);
@@ -311,30 +397,28 @@ uint8_t CUSBCECAdapterDetection::FindAdapters(cec_adapter *deviceList, uint8_t i
     int iVendor, iProduct;
     sscanf(strVendorId, "%x", &iVendor);
     sscanf(strProductId, "%x", &iProduct);
-    if (iVendor != CEC_VID || iProduct != CEC_PID)
-      continue;
 
-    HKEY hDeviceKey = SetupDiOpenDevRegKey(hDevHandle, &devInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE);
-    if (!hDeviceKey)
+    // no match
+    if (iVendor != CEC_VID || (iProduct != CEC_PID && iProduct != CEC_PID2))
       continue;
 
-    TCHAR strPortName[256];
-    strPortName[0] = _T('\0');
-    DWORD dwSize = sizeof(strPortName);
-    DWORD dwType = 0;
 
-    /* search the registry */
-    if ((RegQueryValueEx(hDeviceKey, _T("PortName"), NULL, &dwType, reinterpret_cast<LPBYTE>(strPortName), &dwSize) == ERROR_SUCCESS) && (dwType == REG_SZ))
+    if (iProduct == CEC_PID2)
     {
-      if (_tcslen(strPortName) > 3 && _tcsnicmp(strPortName, _T("COM"), 3) == 0 &&
-        _ttoi(&(strPortName[3])) > 0)
+      // the 1002 pid indicates a composite device, that needs special treatment
+      char strId[512];
+      CM_Get_Device_ID(devInfoData.DevInst, strId, 512, 0);
+      if (FindComPortForComposite(strId, deviceList[iFound].comm, sizeof(deviceList[iFound].comm)))
       {
-        snprintf(deviceList[iFound  ].path, sizeof(deviceList[iFound].path), "%s", devicedetailData->DevicePath);
-        snprintf(deviceList[iFound++].comm, sizeof(deviceList[iFound].path), "%s", strPortName);
+        snprintf(deviceList[iFound].path, sizeof(deviceList[iFound].path), "%s", devicedetailData->DevicePath);
+        iFound++;
       }
     }
-
-    RegCloseKey(hDeviceKey);
+    else if (GetComPortFromHandle(hDevHandle, &devInfoData, deviceList[iFound].comm, sizeof(deviceList[iFound].comm)))
+    {
+      snprintf(deviceList[iFound].path, sizeof(deviceList[iFound].path), "%s", devicedetailData->DevicePath);
+      iFound++;
+    }
   }
 #elif defined(__FreeBSD__)
   char devicePath[PATH_MAX + 1];
@@ -345,8 +429,9 @@ uint8_t CUSBCECAdapterDetection::FindAdapters(cec_adapter *deviceList, uint8_t i
     (void)snprintf(devicePath, sizeof(devicePath), "/dev/ttyU%d", i);
     if (!access(devicePath, 0))
     {
-      snprintf(deviceList[iFound  ].path, sizeof(deviceList[iFound].path), "%s", devicePath);
-      snprintf(deviceList[iFound++].comm, sizeof(deviceList[iFound].path), "%s", devicePath);
+      snprintf(deviceList[iFound].path, sizeof(deviceList[iFound].path), "%s", devicePath);
+      snprintf(deviceList[iFound].comm, sizeof(deviceList[iFound].path), "%s", devicePath);
+      iFound++;
     }
   }
 #else
index 08e6c358243c70b6ecf2eb7ef8591c32692d297c..64efd062f5f58ab60a2666e4c6c82bab673cabb3 100644 (file)
@@ -229,6 +229,8 @@ const char *CCECAdapterMessage::ToString(cec_adapter_messagecode msgCode)
     return "SET_OSD_NAME";
   case MSGCODE_WRITE_EEPROM:
     return "WRITE_EEPROM";
+  case MSGCODE_GET_ADAPTER_TYPE:
+    return "GET_ADAPTER_TYPE";
   default:
     break;
   }
index 40ee1a435a920567ac2f7e4ce4ac64aad5eaa26f..f8ae4135362167378a5e4e61257484eeb1c87781 100644 (file)
 
 namespace CEC
 {
+  typedef enum cec_adapter_messagecode
+  {
+    MSGCODE_NOTHING = 0,
+    MSGCODE_PING,
+    MSGCODE_TIMEOUT_ERROR,
+    MSGCODE_HIGH_ERROR,
+    MSGCODE_LOW_ERROR,
+    MSGCODE_FRAME_START,
+    MSGCODE_FRAME_DATA,
+    MSGCODE_RECEIVE_FAILED,
+    MSGCODE_COMMAND_ACCEPTED,
+    MSGCODE_COMMAND_REJECTED,
+    MSGCODE_SET_ACK_MASK,
+    MSGCODE_TRANSMIT,
+    MSGCODE_TRANSMIT_EOM,
+    MSGCODE_TRANSMIT_IDLETIME,
+    MSGCODE_TRANSMIT_ACK_POLARITY,
+    MSGCODE_TRANSMIT_LINE_TIMEOUT,
+    MSGCODE_TRANSMIT_SUCCEEDED,
+    MSGCODE_TRANSMIT_FAILED_LINE,
+    MSGCODE_TRANSMIT_FAILED_ACK,
+    MSGCODE_TRANSMIT_FAILED_TIMEOUT_DATA,
+    MSGCODE_TRANSMIT_FAILED_TIMEOUT_LINE,
+    MSGCODE_FIRMWARE_VERSION,
+    MSGCODE_START_BOOTLOADER,
+    MSGCODE_GET_BUILDDATE,
+    MSGCODE_SET_CONTROLLED,
+    MSGCODE_GET_AUTO_ENABLED,
+    MSGCODE_SET_AUTO_ENABLED,
+    MSGCODE_GET_DEFAULT_LOGICAL_ADDRESS,
+    MSGCODE_SET_DEFAULT_LOGICAL_ADDRESS,
+    MSGCODE_GET_LOGICAL_ADDRESS_MASK,
+    MSGCODE_SET_LOGICAL_ADDRESS_MASK,
+    MSGCODE_GET_PHYSICAL_ADDRESS,
+    MSGCODE_SET_PHYSICAL_ADDRESS,
+    MSGCODE_GET_DEVICE_TYPE,
+    MSGCODE_SET_DEVICE_TYPE,
+    MSGCODE_GET_HDMI_VERSION,
+    MSGCODE_SET_HDMI_VERSION,
+    MSGCODE_GET_OSD_NAME,
+    MSGCODE_SET_OSD_NAME,
+    MSGCODE_WRITE_EEPROM,
+    MSGCODE_GET_ADAPTER_TYPE,
+    MSGCODE_FRAME_EOM = 0x80,
+    MSGCODE_FRAME_ACK = 0x40,
+  } cec_adapter_messagecode;
+
+  typedef enum p8_cec_adapter_type
+  {
+    P8_ADAPTERTYPE_UNKNOWN = 0,
+    P8_ADAPTERTYPE_EXTERNAL,
+    P8_ADAPTERTYPE_DAUGHTERBOARD,
+  } p8_cec_adapter_type;
+
   class CCECAdapterMessage
   {
   public:
index edd34be9ae964c2deb80ee5874d1b3de6d86ae2f..b81c908fafb6bf2b4ed5a7ba84df0b1b90441ffb 100644 (file)
@@ -34,6 +34,7 @@
 #include "lib/platform/threads/threads.h"
 #include "lib/platform/util/buffer.h"
 #include <map>
+#include "USBCECAdapterMessage.h"
 
 namespace CEC
 {
index 5e1efd493f4a8117018816616870219974d5d3fe..5d13368e50a3c569667ab0b812ed3d824b534c50 100644 (file)
@@ -142,10 +142,14 @@ void CRPiCECAdapterCommunication::OnDataReceived(uint32_t header, uint32_t p0, u
     }
     break;
   case VC_CEC_BUTTON_PRESSED:
+  case VC_CEC_REMOTE_PRESSED:
     {
       // translate into a cec_command
       cec_command command;
-      cec_command::Format(command, (cec_logical_address)CEC_CB_INITIATOR(p0), (cec_logical_address)CEC_CB_FOLLOWER(p0), CEC_OPCODE_USER_CONTROL_PRESSED);
+      cec_command::Format(command,
+                          (cec_logical_address)CEC_CB_INITIATOR(p0),
+                          (cec_logical_address)CEC_CB_FOLLOWER(p0),
+                          reason == VC_CEC_BUTTON_PRESSED ? CEC_OPCODE_USER_CONTROL_PRESSED : CEC_OPCODE_VENDOR_REMOTE_BUTTON_DOWN);
       command.parameters.PushBack((uint8_t)CEC_CB_OPERAND1(p0));
 
       // send to libCEC
@@ -153,10 +157,14 @@ void CRPiCECAdapterCommunication::OnDataReceived(uint32_t header, uint32_t p0, u
     }
     break;
   case VC_CEC_BUTTON_RELEASE:
+  case VC_CEC_REMOTE_RELEASE:
     {
       // translate into a cec_command
       cec_command command;
-      cec_command::Format(command, (cec_logical_address)CEC_CB_INITIATOR(p0), (cec_logical_address)CEC_CB_FOLLOWER(p0), CEC_OPCODE_USER_CONTROL_RELEASE);
+      cec_command::Format(command,
+                          (cec_logical_address)CEC_CB_INITIATOR(p0),
+                          (cec_logical_address)CEC_CB_FOLLOWER(p0),
+                          reason == VC_CEC_BUTTON_PRESSED ? CEC_OPCODE_USER_CONTROL_RELEASE : CEC_OPCODE_VENDOR_REMOTE_BUTTON_UP);
       command.parameters.PushBack((uint8_t)CEC_CB_OPERAND1(p0));
 
       // send to libCEC
@@ -180,9 +188,18 @@ void CRPiCECAdapterCommunication::OnDataReceived(uint32_t header, uint32_t p0, u
       m_logicalAddressCondition.Signal();
     }
     break;
+  case VC_CEC_LOGICAL_ADDR_LOST:
+    {
+      // the logical address was taken by another device
+      cec_logical_address previousAddress = m_logicalAddress;
+      m_logicalAddress = CECDEVICE_UNKNOWN;
+
+      // notify libCEC that we lost our LA when the connection was initialised
+      if (m_bInitialised)
+        m_callback->HandleLogicalAddressLost(previousAddress);
+    }
+    break;
   case VC_CEC_TOPOLOGY:
-  case VC_CEC_REMOTE_PRESSED:
-  case VC_CEC_REMOTE_RELEASE:
     break;
   default:
     LIB_CEC->AddLog(CEC_LOG_DEBUG, "ignoring unknown reason %x", reason);
index 530aec105b8a1923afd317891258c7b577443d24..7f815450c27b60a87e28cc4256d7b4ed80880acf 100644 (file)
@@ -34,7 +34,7 @@
 #if defined(HAVE_RPI_API)
 
 #include "lib/adapter/AdapterCommunication.h"
-#include "lib/platform/threads/mutex.h"
+#include "lib/platform/threads/threads.h"
 
 extern "C" {
 #include <interface/vmcs_host/vc_cecservice.h>
@@ -78,6 +78,7 @@ namespace CEC
     bool SetControlledMode(bool UNUSED(controlled)) { return true; };
     cec_vendor_id GetVendorId(void) { return CEC_VENDOR_BROADCOM; }
     bool SupportsSourceLogicalAddress(const cec_logical_address address) { return address > CECDEVICE_TV && address < CECDEVICE_BROADCAST; }
+    cec_adapter_type GetAdapterType(void) { return ADAPTERTYPE_RPI; };
     ///}
 
     bool IsInitialised(void);
index 466e977249159f740cbe32a53765dc1716929476..2998a622021786c7e3e9ba162870f1b92aa45373 100644 (file)
@@ -1087,6 +1087,10 @@ void CCECBusDevice::SetStreamPath(uint16_t iNewAddress, uint16_t iOldAddress /*
   {
     // if a device is found with the new physical address, mark it as active, which will automatically mark all other devices as inactive
     device->MarkAsActiveSource();
+
+    // respond with an active source message if this device is handled by libCEC
+    if (device->IsHandledByLibCEC())
+      device->TransmitActiveSource(true);
   }
   else
   {
index e74daac4d463f23fe8cc5143fef93d2420e2a5a2..072d71182ec2c92ca7c780ab68b41ecb0330c249 100644 (file)
@@ -128,6 +128,10 @@ int CVLCommandHandler::HandleDeviceVendorCommandWithId(const cec_command &comman
 
       // send capabilties
       SendVendorCommandCapabilities(m_processor->GetLogicalAddress(), command.initiator);
+
+      // reactivate the source, so the tv switches channels
+      if (m_processor->IsActiveSource(m_processor->GetLogicalAddress()))
+        m_processor->GetDevice(m_processor->GetLogicalAddress())->TransmitActiveSource(false);
     }
     else if (command.parameters.At(4) == VL_POWERED_DOWN)
     {
index c595468cf0b5621d3efc7de3a39bd521a03138f2..00ba7bb80e0ce3530182cb95542176bb75ee89be 100644 (file)
@@ -103,7 +103,7 @@ ssize_t CSerialSocket::Write(void* data, size_t len)
   if (IsOpen())
   {
     ssize_t iReturn = SerialSocketWrite(m_socket, &m_iError, data, len);
-    if (iReturn != len)
+    if (iReturn != (ssize_t)len)
     {
       m_strError = "unable to write to the serial port";
       FormatWindowsError(GetLastError(), m_strError);
index e594eaf16aa2b132e700ff4deceb92e87b8f2644..84133a931c5b7ceca64591ecdfe85ed646123bd0 100644 (file)
@@ -47,9 +47,9 @@ using namespace CEC;
 using namespace std;
 using namespace PLATFORM;
 
-#define CEC_CONFIG_VERSION CEC_CLIENT_VERSION_1_8_1;
+#define CEC_CONFIG_VERSION CEC_CLIENT_VERSION_1_9_0;
 
-#include <cecloader.h>
+#include "../../include/cecloader.h"
 
 ICECCallbacks        g_callbacks;
 libcec_configuration g_config;
@@ -224,7 +224,12 @@ void ListDevices(ICECAdapter *parser)
           time_t buildTime = (time_t)config.iFirmwareBuildDate;
           strDeviceInfo.AppendFormat("firmware build date: %s", asctime(gmtime(&buildTime)));
           strDeviceInfo = strDeviceInfo.Left(strDeviceInfo.length() > 1 ? (unsigned)(strDeviceInfo.length() - 1) : 0); // strip \n added by asctime
-          strDeviceInfo.append(" +0000");
+          strDeviceInfo.append(" +0000\n");
+        }
+
+        if (config.adapterType != ADAPTERTYPE_UNKNOWN)
+        {
+          strDeviceInfo.AppendFormat("type:                %s\n", parser->ToString(config.adapterType));
         }
       }
       strDeviceInfo.append("\n");
diff --git a/support/cec-flash-device.sh b/support/cec-flash-device.sh
deleted file mode 100755 (executable)
index 10715cb..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-#!/bin/bash
-
-_usage()
-{
-  echo "Usage: $0 /path/to/firmware.hex"
-}
-
-_check_bootloader_device()
-{
-  cec_adapter=`lsusb  | grep "03eb:2ffa" | wc -l`
-  if [ $cec_adapter -eq 0 ]; then
-    _enter_bootloader
-    cec_adapter=`lsusb  | grep "03eb:2ffa" | wc -l`
-  fi
-
-  if [ $cec_adapter -eq 0 ]; then
-    echo "ERROR: failed to find any CEC adapter in bootloader mode"
-    return 1
-  fi
-
-  return 0
-}
-
-_enter_bootloader()
-{
-  echo "Instructing the CEC adapter to enter bootloader mode"
-  cec_adapter=`lsusb  | grep "2548:1001" | wc -l`
-  if [ $cec_adapter -gt 0 ]; then
-    echo "bl" | cec-client --bootloader
-    echo "Waiting for the device to reinitialise"
-    sleep 5
-  fi
-}
-
-_flash()
-{
-  file=$1
-
-  if [ ! -f "$file" ]; then
-    echo "ERROR: firmware file '$file' does not exist"
-    exit 1
-  fi
-
-  cat << EOB
-Flash '$file' onto the CEC adapter
-
-DISCONNECT THE HDMI CABLES BEFORE STARTING AND
-DO NOT POWER OFF OR DISCONNECT THE DEVICE WHILE THIS OPERATION IS IN PROGRESS!
-
-
-Are you sure you want to flash '$file' onto the CEC adapter?
-Type 'do it!' if you're sure. Anything else will cancel the operation.
-
-EOB
-  read confirmation
-  if [ ! "$confirmation" == "do it!" ]; then
-    echo "Exiting"
-    exit 0
-  fi
-
-  _prereq
-  if [ $? -eq 1 ]; then
-    exit 1
-  fi
-
-  _check_bootloader_device
-  if [ $? -eq 1 ]; then
-    exit 1
-  fi
-
-
-  echo "Erasing the previous firmware"
-  sudo dfu-programmer at90usb162 erase
-
-  echo "Flashing the new firmware"
-  sudo dfu-programmer at90usb162 flash "$file"
-
-  cat << EOB
-
-===============================================================================
-
-Done!
-
-Remove the USB cable from the device and reconnect it to use the new firmware.
-
-EOB
-  exit 0
-}
-
-_prereq()
-{
-  programmer=`which dfu-programmer`
-  if [ -z "$programmer" ]; then
-    echo "dfu-programmer was not found in your path, installing"
-    sudo apt-get install -y dfu-programmer
-  fi
-
-  programmer=`which dfu-programmer`
-  if [ -z "$programmer" ]; then
-    echo "ERROR: failed to find dfu-programmer"
-    return 1
-  fi
-  return 0
-}
-
-
-cat << EOB
-===============================================================================
-              Pulse-Eight CEC Adapter firmware flash tool
-===============================================================================
-
-EOB
-
-if [ -z "$1" ]; then
-  _usage
-else
-  _flash $1
-fi
-
-exit 0
index 13596e7f6a14b7e6f00aafc824d99dbfc28e0049..310a1f8ac31179f910fac7fad50d2dfd003b66a4 100644 (file)
Binary files a/support/p8-usbcec-driver-installer.exe and b/support/p8-usbcec-driver-installer.exe differ