.project
.cproject
+*.manifest
aclocal.m4
autom4te.cache
cec-client.exe
cec-client.ilk
cec-client.pdb
+CecSharpClient.exe
+CecSharpClient.pdb
+CecSharpClient.vshost.exe
+CecSharpClient.vshost.exe.manifest
+
+LibCecSharp.dll
+LibCecSharp.ilk
+LibCecSharp.pdb
build
include/boost
-project/boost-1_46_1-xbmc-win32
+project/bin
project/Debug/
+project/Release/
project/ipch/
project/libcec.sdf
project/libcec.suo
-project/libcec.vcxproj.user
-project/testclient.vcxproj.user
+project/obj
+project/Properties
+project/*.user
src/lib/.deps
src/lib/.libs
src/testclient/cec-client
src/testclient/*.o
+src/CecSharpTester/obj
/dpinst-x86.exe
/dpinst-amd64.exe
+libcec (1.3-1) unstable; urgency=low
+
+ * changed/added:
+ * make libudev optional. if libudev is not available on linux, adapter
+ autodetection will also not be available. fixes compilation on Hardy/ATV1
+ * added a C++ CLR wrapper for libCEC, so libCEC can be used by any .NET
+ language
+ * added vendor support for LG
+ * added vendor support for Philips
+ * added vendor support for Yamaha
+ * added vendor support for Onkyo
+ * added 'scan' command to cec-client, that displays info about devices on
+ the bus. made all ToString() methods available on the interface.
+ * added '-s' or '--single-command' to cec-client. starting cec-client with
+ this parameter executes a single command in cec-client and does not power
+ on devices on startup and power them off on exit. this way, you can use
+ cec-client in a shell script. since there's some handshaking involved at
+ startup, this is not very fast. to execute a command and only display the
+ result and any error/warning, execute it with
+ RESULT=`echo command | cec-client -s -d 3` (on linux/osx, win32 batch
+ files are a bit different)
+ * added HDMI port ('-p' or '--port') and base device ('-b' or '--base') to
+ cec-client's parameters
+ * handle image view on and text view on
+ * handle routing information and report physical address opcodes
+ * handle audio status updates
+ * send ping and bootloader commands via the output queue
+ * scan the CEC bus for devices when starting libcec
+ * pass all commands that are directed at libcec to listeners
+ * interface changes:
+ * added GetActiveSource()/cec_get_active_source()
+ * added IsActiveSource()/cec_is_active_source()
+ * added GetDevicePhysicalAddress()/cec_get_device_physical_address()
+ * added GetDeviceOSDName()/cec_get_osd_name()
+ * added SendKeypress()/cec_send_keypress() and SendKeyRelease()/
+ cec_send_key_release()
+ * added VolumeUp()/cec_volume_up(), VolumeDown()/cec_volume_down(),
+ MuteAudio()/cec_mute_audio()
+ * added GetActiveDevices()/cec_get_active_devices(), IsActiveDevice()/
+ cec_is_active_device(), IsActiveDeviceType()/cec_is_active_device_type().
+ * added SetHDMIPort()/cec_set_hdmi_port(). devices are now detected on load
+ and when a device with the same physical address is detected, libcec will
+ use the selected hdmi port on that device. should fix source selection on
+ other devices, like an amplifier
+ * added a hook in libcec for physical address autodetection
+ * fixed:
+ * don't request the physical address from the tv (it's always 0x0000)
+ * set the proper ackmask before doing anything else
+ * don't unlock the transmit mutex in CCECProcessor while waiting for an
+ answer
+ * fix device polling
+ * refactor CEC read/write. keep a single lock for all writes, not one per
+ device
+ * ignore other data while waiting for a response
+ * retry failed tranmissions
+ * don't delete a message before it's been sent when starting the bootloader
+ * or when sending a ping
+ * fixed possible segfault when switching the command handler after a vendor
+ * id changed
+ * handle audio opcodes correctly
+ * inactive source should be directly addressed at the TV
+ * don't report a changed physical address when it hasn't changed
+ * routing information sets the stream path, not the physical address
+ * don't scan the whole bus in CCECProcessor::IsActiveDeviceType()
+ * don't request the vendor id from devices that are handled by libcec
+ * mark device status as present when a command was received from a device
+ * always send a power on command in CCECBusDevice::PowerOn()
+ * don't request updates statusses unless needed
+ * report physical address sends 3 parameters, not 2. check whether the
+ device type is correct
+ * devices can send vendor commands from other vendors, so don't assume the
+ device is of a certain vendor when it sends commands with a vendor id
+ * thread safety fixes. bugzid: 19
+ * clear any previous input when opening a connection to the adapter.
+ bugzid: 54
+ * use the correct source address in CSLCommandHandler::HandleVendorCommand()
+ * uncorrected CEC_OPCODE_DEVICE_VENDOR_ID. closes #5
+ * renamed enum methods. fixes potential macro collision with isset().
+ thanks davilla
+ * don't change the active device when receiving stream path changed
+ messages. fixes wrong source selection when powering after the TV.
+
+ -- Pulse-Eight Packaging <packaging@pulse-eight.com> Fri, 09 Dec 2011 12:16:00 +0100
+
libcec (1.2-1) unstable; urgency=low
* bugfixes:
For developers:
* see /include/cec.h for the C++ API and /include/cecc.h for the C version.
+* see src/testclient/main.cpp for an example
+
+For .NET developers:
+* build project/libcec.sln first
+* add a reference to LibCecSharp.dll
+* see src\CecSharpTester\CecSharpClient.cs for an example
If you wish to contribute to this project, you must first sign our contributors agreement
Please see http://www.pulse-eight.net/contributors for more information
\ No newline at end of file
-AC_INIT([libcec], 1:2:0)
+AC_INIT([libcec], 1:3:0)
AM_INIT_AUTOMAKE(AC_PACKAGE_NAME, AC_PACKAGE_VERSION)
AC_PROG_CXX
AC_PROG_LIBTOOL
+has_libudev="yes"
case "${host}" in
*-*-linux*)
- AC_SEARCH_LIBS([udev_new], [udev],, AC_MSG_ERROR("required library 'udev' is missing"))
- REQUIRES="udev"
+ PKG_CHECK_MODULES([UDEV],[libudev],,[has_libudev="no";AC_MSG_WARN("library 'udev' is missing - adapter detection will not be available")])
;;
*-apple-darwin*)
+ has_libudev="no";
LIBS+="-framework CoreVideo -framework IOKit"
;;
esac
+if test "x$has_libudev" != "xno"; then
+ INCLUDES="$INCLUDES $UDEV_CFLAGS";LIBS="$LIBS $UDEV_LIBS"
+ AC_DEFINE([HAVE_LIBUDEV],[1],["Define to 1 if libudev is installed"])
+ REQUIRES="udev"
+fi
+
AC_SEARCH_LIBS([pthread_create],[pthread],, AC_MSG_ERROR("required library 'pthread' is missing"))
libs_pre_dl=$LIBS
+libcec (1.3-1) unstable; urgency=low
+
+ * changed/added:
+ * make libudev optional. if libudev is not available on linux, adapter
+ autodetection will also not be available. fixes compilation on Hardy/ATV1
+ * added a C++ CLR wrapper for libCEC, so libCEC can be used by any .NET
+ language
+ * added vendor support for LG
+ * added vendor support for Philips
+ * added vendor support for Yamaha
+ * added vendor support for Onkyo
+ * added 'scan' command to cec-client, that displays info about devices on
+ the bus. made all ToString() methods available on the interface.
+ * added '-s' or '--single-command' to cec-client. starting cec-client with
+ this parameter executes a single command in cec-client and does not power
+ on devices on startup and power them off on exit. this way, you can use
+ cec-client in a shell script. since there's some handshaking involved at
+ startup, this is not very fast. to execute a command and only display the
+ result and any error/warning, execute it with
+ RESULT=`echo command | cec-client -s -d 3` (on linux/osx, win32 batch
+ files are a bit different)
+ * added HDMI port ('-p' or '--port') and base device ('-b' or '--base') to
+ cec-client's parameters
+ * handle image view on and text view on
+ * handle routing information and report physical address opcodes
+ * handle audio status updates
+ * send ping and bootloader commands via the output queue
+ * scan the CEC bus for devices when starting libcec
+ * pass all commands that are directed at libcec to listeners
+ * interface changes:
+ * added GetActiveSource()/cec_get_active_source()
+ * added IsActiveSource()/cec_is_active_source()
+ * added GetDevicePhysicalAddress()/cec_get_device_physical_address()
+ * added GetDeviceOSDName()/cec_get_osd_name()
+ * added SendKeypress()/cec_send_keypress() and SendKeyRelease()/
+ cec_send_key_release()
+ * added VolumeUp()/cec_volume_up(), VolumeDown()/cec_volume_down(),
+ MuteAudio()/cec_mute_audio()
+ * added GetActiveDevices()/cec_get_active_devices(), IsActiveDevice()/
+ cec_is_active_device(), IsActiveDeviceType()/cec_is_active_device_type().
+ * added SetHDMIPort()/cec_set_hdmi_port(). devices are now detected on load
+ and when a device with the same physical address is detected, libcec will
+ use the selected hdmi port on that device. should fix source selection on
+ other devices, like an amplifier
+ * added a hook in libcec for physical address autodetection
+ * fixed:
+ * don't request the physical address from the tv (it's always 0x0000)
+ * set the proper ackmask before doing anything else
+ * don't unlock the transmit mutex in CCECProcessor while waiting for an
+ answer
+ * fix device polling
+ * refactor CEC read/write. keep a single lock for all writes, not one per
+ device
+ * ignore other data while waiting for a response
+ * retry failed tranmissions
+ * don't delete a message before it's been sent when starting the bootloader
+ * or when sending a ping
+ * fixed possible segfault when switching the command handler after a vendor
+ * id changed
+ * handle audio opcodes correctly
+ * inactive source should be directly addressed at the TV
+ * don't report a changed physical address when it hasn't changed
+ * routing information sets the stream path, not the physical address
+ * don't scan the whole bus in CCECProcessor::IsActiveDeviceType()
+ * don't request the vendor id from devices that are handled by libcec
+ * mark device status as present when a command was received from a device
+ * always send a power on command in CCECBusDevice::PowerOn()
+ * don't request updates statusses unless needed
+ * report physical address sends 3 parameters, not 2. check whether the
+ device type is correct
+ * devices can send vendor commands from other vendors, so don't assume the
+ device is of a certain vendor when it sends commands with a vendor id
+ * thread safety fixes. bugzid: 19
+ * clear any previous input when opening a connection to the adapter.
+ bugzid: 54
+ * use the correct source address in CSLCommandHandler::HandleVendorCommand()
+ * uncorrected CEC_OPCODE_DEVICE_VENDOR_ID. closes #5
+ * renamed enum methods. fixes potential macro collision with isset().
+ thanks davilla
+ * don't change the active device when receiving stream path changed
+ messages. fixes wrong source selection when powering after the TV.
+
+ -- Pulse-Eight Packaging <packaging@pulse-eight.com> Fri, 09 Dec 2011 12:16:00 +0100
+
libcec (1.2-1) unstable; urgency=low
* bugfixes:
*/
virtual bool SetPhysicalAddress(uint16_t iPhysicalAddress = CEC_DEFAULT_PHYSICAL_ADDRESS) = 0;
+ /*!
+ * @brief Enable physical address detection (if the connected adapter supports this).
+ * @return True when physical address detection was enabled, false otherwise.
+ */
+ virtual bool EnablePhysicalAddressDetection(void) = 0;
+
+ /*!
+ * @brief Changes the active HDMI port.
+ * @param iBaseDevice The device to which this libcec is connected.
+ * @param iPort The new port number.
+ * @return True when changed, false otherwise.
+ */
+ virtual bool SetHDMIPort(cec_logical_address iBaseDevice, uint8_t iPort) = 0;
+
/*!
* @brief Power on the connected CEC capable devices.
* @param address The logical address to power on.
*/
virtual cec_power_status GetDevicePowerStatus(cec_logical_address iAddress) = 0;
+ /*!
+ * @brief Get the physical address of the device with the given logical address.
+ * @param iLogicalAddress The device to get the vendor id for.
+ * @return The physical address or 0 if it wasn't found.
+ */
+ virtual uint16_t GetDevicePhysicalAddress(cec_logical_address iAddress) = 0;
+
/*!
* @brief Sends a POLL message to a device.
* @param iAddress The device to send the message to.
* @return True if the POLL was acked, false otherwise.
*/
virtual bool PollDevice(cec_logical_address iAddress) = 0;
+
+ /*!
+ * @return The devices that are active on the bus and not handled by libcec.
+ */
+ virtual cec_logical_addresses GetActiveDevices(void) = 0;
+
+ /*!
+ * @brief Check whether a device is active on the bus.
+ * @param iAddress The address to check.
+ * @return True when active, false otherwise.
+ */
+ virtual bool IsActiveDevice(cec_logical_address iAddress) = 0;
+
+ /*!
+ * @brief Check whether a device of the given type is active on the bus.
+ * @param type The type to check.
+ * @return True when active, false otherwise.
+ */
+ virtual bool IsActiveDeviceType(cec_device_type type) = 0;
+
+ /*!
+ * @brief Sends a volume up keypress to an audiosystem if it's present.
+ * @param bWait Wait for the response of the audiosystem when true.
+ * @return The new audio status.
+ */
+ virtual uint8_t VolumeUp(bool bWait = true) = 0;
+
+ /*!
+ * @brief Sends a volume down keypress to an audiosystem if it's present.
+ * @param bWait Wait for the response of the audiosystem when true.
+ * @return The new audio status.
+ */
+ virtual uint8_t VolumeDown(bool bWait = true) = 0;
+
+ /*!
+ * @brief Sends a mute keypress to an audiosystem if it's present.
+ * @param bWait Wait for the response of the audiosystem when true.
+ * @return The new audio status.
+ */
+ virtual uint8_t MuteAudio(bool bWait = true) = 0;
+
+ /*!
+ * @brief Send a keypress to a device on the CEC bus.
+ * @param iDestination The address to send the message to.
+ * @param key The key to send.
+ * @param bWait True to wait for a response, false otherwise.
+ * @return True when the keypress was acked, false otherwise.
+ */
+ virtual bool SendKeypress(cec_logical_address iDestination, cec_user_control_code key, bool bWait = false) = 0;
+
+ /*!
+ * @brief Send a key release to a device on the CEC bus.
+ * @param iDestination The address to send the message to.
+ * @param bWait True to wait for a response, false otherwise.
+ * @return True when the keypress was acked, false otherwise.
+ */
+ virtual bool SendKeyRelease(cec_logical_address iDestination, bool bWait = false) = 0;
+
+ /*!
+ * @brief Get the OSD name of a device on the CEC bus.
+ * @param iAddress The device to get the OSD name for.
+ * @return The OSD name.
+ */
+ virtual cec_osd_name GetDeviceOSDName(cec_logical_address iAddress) = 0;
+
+ /*!
+ * @brief Get the logical address of the device that is currently the active source on the CEC bus.
+ * @return The active source or CECDEVICE_UNKNOWN when unknown.
+ */
+ virtual cec_logical_address GetActiveSource(void) = 0;
+
+ /*!
+ * @brief Check whether a device is currently the active source on the CEC bus.
+ * @param iAddress The address to check.
+ * @return True when it is the active source, false otherwise.
+ */
+ virtual bool IsActiveSource(cec_logical_address iAddress) = 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;
+ virtual const char *ToString(const cec_logical_address address) = 0;
+ virtual const char *ToString(const cec_deck_control_mode mode) = 0;
+ virtual const char *ToString(const cec_deck_info status) = 0;
+ virtual const char *ToString(const cec_opcode opcode) = 0;
+ virtual const char *ToString(const cec_system_audio_status mode) = 0;
+ virtual const char *ToString(const cec_audio_status status) = 0;
+ virtual const char *ToString(const cec_vendor_id vendor) = 0;
+
};
};
extern DECLSPEC int cec_set_active_source(cec_device_type type);
#endif
+#ifdef __cplusplus
+extern DECLSPEC int cec_set_deck_control_mode(CEC::cec_deck_control_mode mode, int bSendUpdate);
+#else
+extern DECLSPEC int cec_set_deck_control_mode(cec_deck_control_mode mode, int bSendUpdate);
+#endif
+
+#ifdef __cplusplus
+extern DECLSPEC int cec_set_deck_info(CEC::cec_deck_info info, int bSendUpdate);
+#else
+extern DECLSPEC int cec_set_deck_info(cec_deck_info info, int bSendUpdate);
+#endif
+
extern DECLSPEC int cec_set_inactive_view(void);
+#ifdef __cplusplus
+extern DECLSPEC int cec_set_menu_state(CEC::cec_menu_state state, int bSendUpdate);
+#else
+extern DECLSPEC int cec_set_menu_state(cec_menu_state state, int bSendUpdate);
+#endif
+
#ifdef __cplusplus
extern DECLSPEC int cec_get_next_log_message(CEC::cec_log_message *message);
#else
extern DECLSPEC uint64_t cec_get_device_vendor_id(cec_logical_address iLogicalAddress);
#endif
+#ifdef __cplusplus
+extern DECLSPEC uint16_t cec_get_device_physical_address(CEC::cec_logical_address iLogicalAddress);
+#else
+extern DECLSPEC uint16_t cec_get_device_physical_address(cec_logical_address iLogicalAddress);
+#endif
+
+#ifdef __cplusplus
+extern DECLSPEC CEC::cec_logical_address cec_get_active_source(void);
+#else
+extern DECLSPEC cec_logical_address cec_get_active_source(void);
+#endif
+
+#ifdef __cplusplus
+extern DECLSPEC int cec_is_active_source(CEC::cec_logical_address iAddress);
+#else
+extern DECLSPEC int cec_is_active_source(cec_logical_address iAddress);
+#endif
+
#ifdef __cplusplus
extern DECLSPEC CEC::cec_power_status cec_get_device_power_status(CEC::cec_logical_address iLogicalAddress);
#else
extern DECLSPEC int cec_poll_device(cec_logical_address iLogicalAddress);
#endif
+#ifdef __cplusplus
+extern DECLSPEC CEC::cec_logical_addresses cec_get_active_devices(void);
+#else
+extern DECLSPEC cec_logical_addresses cec_get_active_devices(void);
+#endif
+
+#ifdef __cplusplus
+extern DECLSPEC int cec_is_active_device(CEC::cec_logical_address iAddress);
+#else
+extern DECLSPEC int cec_is_active_device(cec_logical_address iAddress);
+#endif
+
+#ifdef __cplusplus
+extern DECLSPEC int cec_is_active_device_type(CEC::cec_device_type type);
+#else
+extern DECLSPEC int cec_is_active_device_type(cec_device_type type);
+#endif
+
+#ifdef __cplusplus
+extern DECLSPEC int cec_set_hdmi_port(CEC::cec_logical_address iBaseDevice, uint8_t iPort);
+#else
+extern DECLSPEC int cec_set_hdmi_port(cec_logical_address iBaseDevice, uint8_t iPort);
+#endif
+
+extern DECLSPEC int cec_volume_up(int bWait);
+
+extern DECLSPEC int cec_volume_down(int bWait);
+
+extern DECLSPEC int cec_mute_audio(int bWait);
+
+#ifdef __cplusplus
+extern DECLSPEC int cec_send_keypress(CEC::cec_logical_address iDestination, CEC::cec_user_control_code key, int bWait);
+#else
+extern DECLSPEC int cec_send_keypress(cec_logical_address iDestination, cec_user_control_code key, int bWait);
+#endif
+
+#ifdef __cplusplus
+extern DECLSPEC int cec_send_key_release(CEC::cec_logical_address iDestination, int bWait);
+#else
+extern DECLSPEC int cec_send_key_release(cec_logical_address iDestination, int bWait);
+#endif
+
+#ifdef __cplusplus
+extern DECLSPEC CEC::cec_osd_name cec_get_device_osd_name(CEC::cec_logical_address iAddress);
+#else
+extern DECLSPEC cec_osd_name cec_get_device_osd_name(cec_logical_address iAddress);
+#endif
+
+extern DECLSPEC int cec_enable_physical_address_detection(void);
+
#ifdef __cplusplus
};
#endif
namespace CEC {
#endif
+//default physical address 1.0.0.0, HDMI port 1
+#define CEC_DEFAULT_PHYSICAL_ADDRESS 0x1000
+#define CEC_DEFAULT_HDMI_PORT 1
+#define CEC_DEFAULT_BASE_DEVICE 0
+#define MSGSTART 0xFF
+#define MSGEND 0xFE
+#define MSGESC 0xFD
+#define ESCOFFSET 3
+#define CEC_BUTTON_TIMEOUT 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
+#define CEC_LIB_VERSION_MINOR 3
+
typedef enum cec_abort_reason
{
- CEC_ABORT_REASON_UNRECOGNIZED_OPCODE = 0,
+ CEC_ABORT_REASON_UNRECOGNIZED_OPCODE = 0,
CEC_ABORT_REASON_NOT_IN_CORRECT_MODE_TO_RESPOND = 1,
- CEC_ABORT_REASON_CANNOT_PROVIDE_SOURCE = 2,
- CEC_ABORT_REASON_INVALID_OPERAND = 3,
- CEC_ABORT_REASON_REFUSED = 4
+ CEC_ABORT_REASON_CANNOT_PROVIDE_SOURCE = 2,
+ CEC_ABORT_REASON_INVALID_OPERAND = 3,
+ CEC_ABORT_REASON_REFUSED = 4
} cec_abort_reason;
typedef enum cec_analogue_broadcast_type
{
- CEC_ANALOGUE_BROADCAST_TYPE_CABLE = 0x00,
- CEC_ANALOGUE_BROADCAST_TYPE_SATELLITE = 0x01,
+ CEC_ANALOGUE_BROADCAST_TYPE_CABLE = 0x00,
+ CEC_ANALOGUE_BROADCAST_TYPE_SATELLITE = 0x01,
CEC_ANALOGUE_BROADCAST_TYPE_TERRESTIAL = 0x02
} cec_analogue_broadcast_type;
typedef enum cec_audio_rate
{
- CEC_AUDIO_RATE_RATE_CONTROL_OFF = 0,
- CEC_AUDIO_RATE_STANDARD_RATE_100 = 1,
- CEC_AUDIO_RATE_FAST_RATE_MAX_101 = 2,
- CEC_AUDIO_RATE_SLOW_RATE_MIN_99 = 3,
+ CEC_AUDIO_RATE_RATE_CONTROL_OFF = 0,
+ CEC_AUDIO_RATE_STANDARD_RATE_100 = 1,
+ CEC_AUDIO_RATE_FAST_RATE_MAX_101 = 2,
+ CEC_AUDIO_RATE_SLOW_RATE_MIN_99 = 3,
CEC_AUDIO_RATE_STANDARD_RATE_100_0 = 4,
CEC_AUDIO_RATE_FAST_RATE_MAX_100_1 = 5,
- CEC_AUDIO_RATE_SLOW_RATE_MIN_99_9 = 6
+ CEC_AUDIO_RATE_SLOW_RATE_MIN_99_9 = 6
} cec_audio_rate;
typedef enum cec_audio_status
{
- CEC_AUDIO_MUTE_STATUS_MASK = 0x80,
- CEC_AUDIO_VOLUME_STATUS_MASK = 0x7F,
- CEC_AUDIO_VOLUME_MIN = 0x00,
- CEC_AUDIO_VOLUME_MAX = 0x64,
+ CEC_AUDIO_MUTE_STATUS_MASK = 0x80,
+ CEC_AUDIO_VOLUME_STATUS_MASK = 0x7F,
+ CEC_AUDIO_VOLUME_MIN = 0x00,
+ CEC_AUDIO_VOLUME_MAX = 0x64,
CEC_AUDIO_VOLUME_STATUS_UNKNOWN = 0x7F
} cec_audio_status;
typedef enum cec_boolean
{
CEC_FALSE = 0,
- CEC_TRUE = 1
+ CEC_TRUE = 1
} cec_boolean;
typedef enum cec_version
typedef enum cec_channel_identifier
{
CEC_CHANNEL_NUMBER_FORMAT_MASK = 0xFC000000,
- CEC_1_PART_CHANNEL_NUMBER = 0x04000000,
- CEC_2_PART_CHANNEL_NUMBER = 0x08000000,
- CEC_MAJOR_CHANNEL_NUMBER_MASK = 0x3FF0000,
- CEC_MINOR_CHANNEL_NUMBER_MASK = 0xFFFF
+ CEC_1_PART_CHANNEL_NUMBER = 0x04000000,
+ CEC_2_PART_CHANNEL_NUMBER = 0x08000000,
+ CEC_MAJOR_CHANNEL_NUMBER_MASK = 0x3FF0000,
+ CEC_MINOR_CHANNEL_NUMBER_MASK = 0xFFFF
} cec_channel_identifier;
typedef enum cec_deck_control_mode
{
- CEC_DECK_CONTROL_MODE_SKIP_FORWARD_WIND = 1,
+ CEC_DECK_CONTROL_MODE_SKIP_FORWARD_WIND = 1,
CEC_DECK_CONTROL_MODE_SKIP_REVERSE_REWIND = 2,
- CEC_DECK_CONTROL_MODE_STOP = 3,
- CEC_DECK_CONTROL_MODE_EJECT = 4
+ CEC_DECK_CONTROL_MODE_STOP = 3,
+ CEC_DECK_CONTROL_MODE_EJECT = 4
} cec_deck_control_mode;
typedef enum cec_deck_info
{
- CEC_DECK_INFO_PLAY = 0x11,
- CEC_DECK_INFO_RECORD = 0x12,
- CEC_DECK_INFO_PLAY_REVERSE = 0x13,
- CEC_DECK_INFO_STILL = 0x14,
- CEC_DECK_INFO_SLOW = 0x15,
- CEC_DECK_INFO_SLOW_REVERSE = 0x16,
- CEC_DECK_INFO_FAST_FORWARD = 0x17,
- CEC_DECK_INFO_FAST_REVERSE = 0x18,
- CEC_DECK_INFO_NO_MEDIA = 0x19,
- CEC_DECK_INFO_STOP = 0x1A,
- CEC_DECK_INFO_SKIP_FORWARD_WIND = 0x1B,
- CEC_DECK_INFO_SKIP_REVERSE_REWIND = 0x1C,
+ CEC_DECK_INFO_PLAY = 0x11,
+ CEC_DECK_INFO_RECORD = 0x12,
+ CEC_DECK_INFO_PLAY_REVERSE = 0x13,
+ CEC_DECK_INFO_STILL = 0x14,
+ CEC_DECK_INFO_SLOW = 0x15,
+ CEC_DECK_INFO_SLOW_REVERSE = 0x16,
+ CEC_DECK_INFO_FAST_FORWARD = 0x17,
+ CEC_DECK_INFO_FAST_REVERSE = 0x18,
+ CEC_DECK_INFO_NO_MEDIA = 0x19,
+ CEC_DECK_INFO_STOP = 0x1A,
+ CEC_DECK_INFO_SKIP_FORWARD_WIND = 0x1B,
+ CEC_DECK_INFO_SKIP_REVERSE_REWIND = 0x1C,
CEC_DECK_INFO_INDEX_SEARCH_FORWARD = 0x1D,
CEC_DECK_INFO_INDEX_SEARCH_REVERSE = 0x1E,
- CEC_DECK_INFO_OTHER_STATUS = 0x1F
+ CEC_DECK_INFO_OTHER_STATUS = 0x1F,
+ CEC_DECK_INFO_OTHER_STATUS_LG = 0x20
} cec_deck_info;
typedef enum cec_device_type
{
- CEC_DEVICE_TYPE_TV = 0,
+ CEC_DEVICE_TYPE_TV = 0,
CEC_DEVICE_TYPE_RECORDING_DEVICE = 1,
- CEC_DEVICE_TYPE_RESERVED = 2,
- CEC_DEVICE_TYPE_TUNER = 3,
- CEC_DEVICE_TYPE_PLAYBACK_DEVICE = 4,
- CEC_DEVICE_TYPE_AUDIO_SYSTEM = 5
+ CEC_DEVICE_TYPE_RESERVED = 2,
+ CEC_DEVICE_TYPE_TUNER = 3,
+ CEC_DEVICE_TYPE_PLAYBACK_DEVICE = 4,
+ CEC_DEVICE_TYPE_AUDIO_SYSTEM = 5
} cec_device_type;
-typedef struct cec_device_type_list
-{
- cec_device_type types[5];
-
-#ifdef __cplusplus
- void clear(void)
- {
- for (unsigned int iPtr = 0; iPtr < 5; iPtr++)
- types[iPtr] = CEC_DEVICE_TYPE_RESERVED;
- }
-
- void add(const cec_device_type type)
- {
- for (unsigned int iPtr = 0; iPtr < 5; iPtr++)
- {
- if (types[iPtr] == CEC_DEVICE_TYPE_RESERVED)
- {
- types[iPtr] = type;
- break;
- }
- }
- }
-
- bool isset(cec_device_type type)
- {
- bool bReturn(false);
- for (unsigned int iPtr = 0; !bReturn && iPtr < 5; iPtr++)
- {
- if (types[iPtr] == type)
- bReturn = true;
- }
- return bReturn;
- }
-
- bool empty()
- {
- bool bReturn(true);
- for (unsigned int iPtr = 0; bReturn && iPtr < 5; iPtr++)
- {
- if (types[iPtr] != CEC_DEVICE_TYPE_RESERVED)
- bReturn = false;
- }
- return bReturn;
- }
-
- cec_device_type operator[](uint8_t pos) const { return pos < 5 ? types[pos] : CEC_DEVICE_TYPE_RESERVED; }
-#endif
-} cec_device_type_list;
-
typedef enum cec_display_control
{
CEC_DISPLAY_CONTROL_DISPLAY_FOR_DEFAULT_TIME = 0x00,
- CEC_DISPLAY_CONTROL_DISPLAY_UNTIL_CLEARED = 0x40,
- CEC_DISPLAY_CONTROL_CLEAR_PREVIOUS_MESSAGE = 0x80,
- CEC_DISPLAY_CONTROL_RESERVED_FOR_FUTURE_USE = 0xC0
+ CEC_DISPLAY_CONTROL_DISPLAY_UNTIL_CLEARED = 0x40,
+ CEC_DISPLAY_CONTROL_CLEAR_PREVIOUS_MESSAGE = 0x80,
+ CEC_DISPLAY_CONTROL_RESERVED_FOR_FUTURE_USE = 0xC0
} cec_display_control;
typedef enum cec_external_source_specifier
{
- CEC_EXTERNAL_SOURCE_SPECIFIER_EXTERNAL_PLUG = 4,
+ CEC_EXTERNAL_SOURCE_SPECIFIER_EXTERNAL_PLUG = 4,
CEC_EXTERNAL_SOURCE_SPECIFIER_EXTERNAL_PHYSICAL_ADDRESS = 5
} cec_external_source_specifier;
typedef enum cec_menu_request_type
{
- CEC_MENU_REQUEST_TYPE_ACTIVATE = 0,
+ CEC_MENU_REQUEST_TYPE_ACTIVATE = 0,
CEC_MENU_REQUEST_TYPE_DEACTIVATE = 1,
- CEC_MENU_REQUEST_TYPE_QUERY = 2
+ CEC_MENU_REQUEST_TYPE_QUERY = 2
} cec_menu_request_type;
typedef enum cec_menu_state
{
- CEC_MENU_STATE_ACTIVATED = 0,
+ CEC_MENU_STATE_ACTIVATED = 0,
CEC_MENU_STATE_DEACTIVATED = 1
} cec_menu_state;
typedef enum cec_play_mode
{
- CEC_PLAY_MODE_PLAY_FORWARD = 0x24,
- CEC_PLAY_MODE_PLAY_REVERSE = 0x20,
- CEC_PLAY_MODE_PLAY_STILL = 0x25,
- CEC_PLAY_MODE_FAST_FORWARD_MIN_SPEED = 0x05,
+ CEC_PLAY_MODE_PLAY_FORWARD = 0x24,
+ CEC_PLAY_MODE_PLAY_REVERSE = 0x20,
+ CEC_PLAY_MODE_PLAY_STILL = 0x25,
+ CEC_PLAY_MODE_FAST_FORWARD_MIN_SPEED = 0x05,
CEC_PLAY_MODE_FAST_FORWARD_MEDIUM_SPEED = 0x06,
- CEC_PLAY_MODE_FAST_FORWARD_MAX_SPEED = 0x07,
- CEC_PLAY_MODE_FAST_REVERSE_MIN_SPEED = 0x09,
+ CEC_PLAY_MODE_FAST_FORWARD_MAX_SPEED = 0x07,
+ CEC_PLAY_MODE_FAST_REVERSE_MIN_SPEED = 0x09,
CEC_PLAY_MODE_FAST_REVERSE_MEDIUM_SPEED = 0x0A,
- CEC_PLAY_MODE_FAST_REVERSE_MAX_SPEED = 0x0B,
- CEC_PLAY_MODE_SLOW_FORWARD_MIN_SPEED = 0x15,
+ CEC_PLAY_MODE_FAST_REVERSE_MAX_SPEED = 0x0B,
+ CEC_PLAY_MODE_SLOW_FORWARD_MIN_SPEED = 0x15,
CEC_PLAY_MODE_SLOW_FORWARD_MEDIUM_SPEED = 0x16,
- CEC_PLAY_MODE_SLOW_FORWARD_MAX_SPEED = 0x17,
- CEC_PLAY_MODE_SLOW_REVERSE_MIN_SPEED = 0x19,
+ CEC_PLAY_MODE_SLOW_FORWARD_MAX_SPEED = 0x17,
+ CEC_PLAY_MODE_SLOW_REVERSE_MIN_SPEED = 0x19,
CEC_PLAY_MODE_SLOW_REVERSE_MEDIUM_SPEED = 0x1A,
- CEC_PLAY_MODE_SLOW_REVERSE_MAX_SPEED = 0x1B
+ CEC_PLAY_MODE_SLOW_REVERSE_MAX_SPEED = 0x1B
} cec_play_mode;
typedef enum cec_power_status
{
- CEC_POWER_STATUS_ON = 0x00,
- CEC_POWER_STATUS_STANDBY = 0x01,
+ CEC_POWER_STATUS_ON = 0x00,
+ CEC_POWER_STATUS_STANDBY = 0x01,
CEC_POWER_STATUS_IN_TRANSITION_STANDBY_TO_ON = 0x02,
CEC_POWER_STATUS_IN_TRANSITION_ON_TO_STANDBY = 0x03,
- CEC_POWER_STATUS_UNKNOWN = 0x99
+ CEC_POWER_STATUS_UNKNOWN = 0x99
} cec_power_status;
typedef enum cec_record_source_type
{
- CEC_RECORD_SOURCE_TYPE_OWN_SOURCE = 1,
- CEC_RECORD_SOURCE_TYPE_DIGITAL_SERVICE = 2,
- CEC_RECORD_SOURCE_TYPE_ANALOGUE_SERVICE = 3,
- CEC_RECORD_SOURCE_TYPE_EXTERNAL_PLUS = 4,
+ CEC_RECORD_SOURCE_TYPE_OWN_SOURCE = 1,
+ CEC_RECORD_SOURCE_TYPE_DIGITAL_SERVICE = 2,
+ CEC_RECORD_SOURCE_TYPE_ANALOGUE_SERVICE = 3,
+ CEC_RECORD_SOURCE_TYPE_EXTERNAL_PLUS = 4,
CEC_RECORD_SOURCE_TYPE_EXTERNAL_PHYSICAL_ADDRESS = 5
} cec_record_source_type;
typedef enum cec_record_status_info
{
- CEC_RECORD_STATUS_INFO_RECORDING_CURRENTLY_SELECTED_SOURCE = 0x01,
- CEC_RECORD_STATUS_INFO_RECORDING_DIGITAL_SERVICE = 0x02,
- CEC_RECORD_STATUS_INFO_RECORDING_ANALOGUE_SERVICE = 0x03,
- CEC_RECORD_STATUS_INFO_RECORDING_EXTERNAL_INPUT = 0x04,
- CEC_RECORD_STATUS_INFO_NO_RECORDING_UNABLE_TO_RECORD_DIGITAL_SERVICE = 0x05,
+ CEC_RECORD_STATUS_INFO_RECORDING_CURRENTLY_SELECTED_SOURCE = 0x01,
+ CEC_RECORD_STATUS_INFO_RECORDING_DIGITAL_SERVICE = 0x02,
+ CEC_RECORD_STATUS_INFO_RECORDING_ANALOGUE_SERVICE = 0x03,
+ CEC_RECORD_STATUS_INFO_RECORDING_EXTERNAL_INPUT = 0x04,
+ CEC_RECORD_STATUS_INFO_NO_RECORDING_UNABLE_TO_RECORD_DIGITAL_SERVICE = 0x05,
CEC_RECORD_STATUS_INFO_NO_RECORDING_UNABLE_TO_RECORD_ANALOGUE_SERVICE = 0x06,
CEC_RECORD_STATUS_INFO_NO_RECORDING_UNABLE_TO_SELECT_REQUIRED_SERVICE = 0x07,
- CEC_RECORD_STATUS_INFO_NO_RECORDING_INVALID_EXTERNAL_PLUG_NUMBER = 0x09,
- CEC_RECORD_STATUS_INFO_NO_RECORDING_INVALID_EXTERNAL_ADDRESS = 0x0A,
- CEC_RECORD_STATUS_INFO_NO_RECORDING_CA_SYSTEM_NOT_SUPPORTED = 0x0B,
- CEC_RECORD_STATUS_INFO_NO_RECORDING_NO_OR_INSUFFICIENT_ENTITLEMENTS = 0x0C,
- CEC_RECORD_STATUS_INFO_NO_RECORDING_NOT_ALLOWED_TO_COPY_SOURCE = 0x0D,
- CEC_RECORD_STATUS_INFO_NO_RECORDING_NO_FURTHER_COPIES_ALLOWED = 0x0E,
- CEC_RECORD_STATUS_INFO_NO_RECORDING_NO_MEDIA = 0x10,
- CEC_RECORD_STATUS_INFO_NO_RECORDING_PLAYING = 0x11,
- CEC_RECORD_STATUS_INFO_NO_RECORDING_ALREADY_RECORDING = 0x12,
- CEC_RECORD_STATUS_INFO_NO_RECORDING_MEDIA_PROTECTED = 0x13,
- CEC_RECORD_STATUS_INFO_NO_RECORDING_NO_SOURCE_SIGNAL = 0x14,
- CEC_RECORD_STATUS_INFO_NO_RECORDING_MEDIA_PROBLEM = 0x15,
- CEC_RECORD_STATUS_INFO_NO_RECORDING_NOT_ENOUGH_SPACE_AVAILABLE = 0x16,
- CEC_RECORD_STATUS_INFO_NO_RECORDING_PARENTAL_LOCK_ON = 0x17,
- CEC_RECORD_STATUS_INFO_RECORDING_TERMINATED_NORMALLY = 0x1A,
- CEC_RECORD_STATUS_INFO_RECORDING_HAS_ALREADY_TERMINATED = 0x1B,
- CEC_RECORD_STATUS_INFO_NO_RECORDING_OTHER_REASON = 0x1F
+ CEC_RECORD_STATUS_INFO_NO_RECORDING_INVALID_EXTERNAL_PLUG_NUMBER = 0x09,
+ CEC_RECORD_STATUS_INFO_NO_RECORDING_INVALID_EXTERNAL_ADDRESS = 0x0A,
+ CEC_RECORD_STATUS_INFO_NO_RECORDING_CA_SYSTEM_NOT_SUPPORTED = 0x0B,
+ CEC_RECORD_STATUS_INFO_NO_RECORDING_NO_OR_INSUFFICIENT_ENTITLEMENTS = 0x0C,
+ CEC_RECORD_STATUS_INFO_NO_RECORDING_NOT_ALLOWED_TO_COPY_SOURCE = 0x0D,
+ CEC_RECORD_STATUS_INFO_NO_RECORDING_NO_FURTHER_COPIES_ALLOWED = 0x0E,
+ CEC_RECORD_STATUS_INFO_NO_RECORDING_NO_MEDIA = 0x10,
+ CEC_RECORD_STATUS_INFO_NO_RECORDING_PLAYING = 0x11,
+ CEC_RECORD_STATUS_INFO_NO_RECORDING_ALREADY_RECORDING = 0x12,
+ CEC_RECORD_STATUS_INFO_NO_RECORDING_MEDIA_PROTECTED = 0x13,
+ CEC_RECORD_STATUS_INFO_NO_RECORDING_NO_SOURCE_SIGNAL = 0x14,
+ CEC_RECORD_STATUS_INFO_NO_RECORDING_MEDIA_PROBLEM = 0x15,
+ CEC_RECORD_STATUS_INFO_NO_RECORDING_NOT_ENOUGH_SPACE_AVAILABLE = 0x16,
+ CEC_RECORD_STATUS_INFO_NO_RECORDING_PARENTAL_LOCK_ON = 0x17,
+ CEC_RECORD_STATUS_INFO_RECORDING_TERMINATED_NORMALLY = 0x1A,
+ CEC_RECORD_STATUS_INFO_RECORDING_HAS_ALREADY_TERMINATED = 0x1B,
+ CEC_RECORD_STATUS_INFO_NO_RECORDING_OTHER_REASON = 0x1F
} cec_record_status_info;
typedef enum cec_recording_sequence
{
- CEC_RECORDING_SEQUENCE_SUNDAY = 0x01,
- CEC_RECORDING_SEQUENCE_MONDAY = 0x02,
- CEC_RECORDING_SEQUENCE_TUESDAY = 0x04,
+ CEC_RECORDING_SEQUENCE_SUNDAY = 0x01,
+ CEC_RECORDING_SEQUENCE_MONDAY = 0x02,
+ CEC_RECORDING_SEQUENCE_TUESDAY = 0x04,
CEC_RECORDING_SEQUENCE_WEDNESDAY = 0x08,
- CEC_RECORDING_SEQUENCE_THURSDAY = 0x10,
- CEC_RECORDING_SEQUENCE_FRIDAY = 0x20,
- CEC_RECORDING_SEQUENCE_SATURDAY = 0x40,
+ CEC_RECORDING_SEQUENCE_THURSDAY = 0x10,
+ CEC_RECORDING_SEQUENCE_FRIDAY = 0x20,
+ CEC_RECORDING_SEQUENCE_SATURDAY = 0x40,
CEC_RECORDING_SEQUENCE_ONCE_ONLY = 0x00
} cec_recording_sequence;
typedef enum cec_status_request
{
- CEC_STATUS_REQUEST_ON = 1,
- CEC_STATUS_REQUEST_OFF = 2,
+ CEC_STATUS_REQUEST_ON = 1,
+ CEC_STATUS_REQUEST_OFF = 2,
CEC_STATUS_REQUEST_ONCE = 3
} cec_status_request;
typedef enum cec_system_audio_status
{
CEC_SYSTEM_AUDIO_STATUS_OFF = 0,
- CEC_SYSTEM_AUDIO_STATUS_ON = 1
+ CEC_SYSTEM_AUDIO_STATUS_ON = 1
} cec_system_audio_status;
typedef enum cec_timer_cleared_status_data
{
- CEC_TIMER_CLEARED_STATUS_DATA_TIMER_NOT_CLEARED_RECORDING = 0x00,
- CEC_TIMER_CLEARED_STATUS_DATA_TIMER_NOT_CLEARED_NO_MATCHING = 0x01,
+ CEC_TIMER_CLEARED_STATUS_DATA_TIMER_NOT_CLEARED_RECORDING = 0x00,
+ CEC_TIMER_CLEARED_STATUS_DATA_TIMER_NOT_CLEARED_NO_MATCHING = 0x01,
CEC_TIMER_CLEARED_STATUS_DATA_TIMER_NOT_CLEARED_NO_INF0_AVAILABLE = 0x02,
- CEC_TIMER_CLEARED_STATUS_DATA_TIMER_CLEARED = 0x80
+ CEC_TIMER_CLEARED_STATUS_DATA_TIMER_CLEARED = 0x80
} cec_timer_cleared_status_data;
typedef enum cec_timer_overlap_warning
{
- CEC_TIMER_OVERLAP_WARNING_NO_OVERLAP = 0,
+ CEC_TIMER_OVERLAP_WARNING_NO_OVERLAP = 0,
CEC_TIMER_OVERLAP_WARNING_TIMER_BLOCKS_OVERLAP = 1
} cec_timer_overlap_warning;
typedef enum cec_media_info
{
CEC_MEDIA_INFO_MEDIA_PRESENT_AND_NOT_PROTECTED = 0x00,
- CEC_MEDIA_INFO_MEDIA_PRESENT_BUT_PROTECTED = 0x01,
- CEC_MEDIA_INFO_MEDIA_NOT_PRESENT = 0x02,
- CEC_MEDIA_INFO_FUTURE_USE = 0x03
+ CEC_MEDIA_INFO_MEDIA_PRESENT_BUT_PROTECTED = 0x01,
+ CEC_MEDIA_INFO_MEDIA_NOT_PRESENT = 0x02,
+ CEC_MEDIA_INFO_FUTURE_USE = 0x03
} cec_media_info;
typedef enum cec_programmed_indicator
{
CEC_PROGRAMMED_INDICATOR_NOT_PROGRAMMED = 0,
- CEC_PROGRAMMED_INDICATOR_PROGRAMMED = 1
+ CEC_PROGRAMMED_INDICATOR_PROGRAMMED = 1
} cec_programmed_indicator;
typedef enum cec_programmed_info
{
- CEC_PROGRAMMED_INFO_FUTURE_USE = 0x0,
- CEC_PROGRAMMED_INFO_ENOUGH_SPACE_AVAILABLE_FOR_RECORDING = 0x08,
+ CEC_PROGRAMMED_INFO_FUTURE_USE = 0x0,
+ CEC_PROGRAMMED_INFO_ENOUGH_SPACE_AVAILABLE_FOR_RECORDING = 0x08,
CEC_PROGRAMMED_INFO_NOT_ENOUGH_SPACE_AVAILABLE_FOR_RECORDING = 0x09,
- CEC_PROGRAMMED_INFO_MAY_NOT_BE_ENOUGH_SPACE_AVAILABLE = 0x0B,
- CEC_PROGRAMMED_INFO_NO_MEDIA_INFO_AVAILABLE = 0x0A
+ CEC_PROGRAMMED_INFO_MAY_NOT_BE_ENOUGH_SPACE_AVAILABLE = 0x0B,
+ CEC_PROGRAMMED_INFO_NO_MEDIA_INFO_AVAILABLE = 0x0A
} cec_programmed_info;
typedef enum cec_not_programmed_error_info
{
- CEC_NOT_PROGRAMMED_ERROR_INFO_FUTURE_USE = 0x0,
- CEC_NOT_PROGRAMMED_ERROR_INFO_NO_FREE_TIMER_AVAILABLE = 0x01,
- CEC_NOT_PROGRAMMED_ERROR_INFO_DATE_OUT_OF_RANGE = 0x02,
- CEC_NOT_PROGRAMMED_ERROR_INFO_RECORDING_SEQUENCE_ERROR = 0x03,
- CEC_NOT_PROGRAMMED_ERROR_INFO_INVALID_EXTERNAL_PLUG_NUMBER = 0x04,
- CEC_NOT_PROGRAMMED_ERROR_INFO_INVALID_EXTERNAL_PHYSICAL_ADDRESS = 0x05,
- CEC_NOT_PROGRAMMED_ERROR_INFO_CA_SYSTEM_NOT_SUPPORTED = 0x06,
+ CEC_NOT_PROGRAMMED_ERROR_INFO_FUTURE_USE = 0x0,
+ CEC_NOT_PROGRAMMED_ERROR_INFO_NO_FREE_TIMER_AVAILABLE = 0x01,
+ CEC_NOT_PROGRAMMED_ERROR_INFO_DATE_OUT_OF_RANGE = 0x02,
+ CEC_NOT_PROGRAMMED_ERROR_INFO_RECORDING_SEQUENCE_ERROR = 0x03,
+ CEC_NOT_PROGRAMMED_ERROR_INFO_INVALID_EXTERNAL_PLUG_NUMBER = 0x04,
+ CEC_NOT_PROGRAMMED_ERROR_INFO_INVALID_EXTERNAL_PHYSICAL_ADDRESS = 0x05,
+ CEC_NOT_PROGRAMMED_ERROR_INFO_CA_SYSTEM_NOT_SUPPORTED = 0x06,
CEC_NOT_PROGRAMMED_ERROR_INFO_NO_OR_INSUFFICIENT_CA_ENTITLEMENTS = 0x07,
- CEC_NOT_PROGRAMMED_ERROR_INFO_DOES_NOT_SUPPORT_RESOLUTION = 0x08,
- CEC_NOT_PROGRAMMED_ERROR_INFO_PARENTAL_LOCK_ON = 0x09,
- CEC_NOT_PROGRAMMED_ERROR_INFO_CLOCK_FAILURE = 0x0A,
- CEC_NOT_PROGRAMMED_ERROR_INFO_RESERVED_FOR_FUTURE_USE_START = 0x0B,
- CEC_NOT_PROGRAMMED_ERROR_INFO_RESERVED_FOR_FUTURE_USE_END = 0x0D,
- CEC_NOT_PROGRAMMED_ERROR_INFO_DUPLICATE_ALREADY_PROGRAMMED = 0x0E
+ CEC_NOT_PROGRAMMED_ERROR_INFO_DOES_NOT_SUPPORT_RESOLUTION = 0x08,
+ CEC_NOT_PROGRAMMED_ERROR_INFO_PARENTAL_LOCK_ON = 0x09,
+ CEC_NOT_PROGRAMMED_ERROR_INFO_CLOCK_FAILURE = 0x0A,
+ CEC_NOT_PROGRAMMED_ERROR_INFO_RESERVED_FOR_FUTURE_USE_START = 0x0B,
+ CEC_NOT_PROGRAMMED_ERROR_INFO_RESERVED_FOR_FUTURE_USE_END = 0x0D,
+ CEC_NOT_PROGRAMMED_ERROR_INFO_DUPLICATE_ALREADY_PROGRAMMED = 0x0E
} cec_not_programmed_error_info;
typedef enum cec_recording_flag
{
CEC_RECORDING_FLAG_NOT_BEING_USED_FOR_RECORDING = 0,
- CEC_RECORDING_FLAG_BEING_USED_FOR_RECORDING = 1
+ CEC_RECORDING_FLAG_BEING_USED_FOR_RECORDING = 1
} cec_recording_flag;
typedef enum cec_tuner_display_info
{
- CEC_TUNER_DISPLAY_INFO_DISPLAYING_DIGITAL_TUNER = 0,
- CEC_TUNER_DISPLAY_INFO_NOT_DISPLAYING_TUNER = 1,
+ CEC_TUNER_DISPLAY_INFO_DISPLAYING_DIGITAL_TUNER = 0,
+ CEC_TUNER_DISPLAY_INFO_NOT_DISPLAYING_TUNER = 1,
CEC_TUNER_DISPLAY_INFO_DISPLAYING_ANALOGUE_TUNER = 2
} cec_tuner_display_info;
typedef enum cec_broadcast_system
{
- CEC_BROADCAST_SYSTEM_PAL_B_G = 0,
- CEC_BROADCAST_SYSTEM_SECAM_L1 = 1,
- CEC_BROADCAST_SYSTEM_PAL_M = 2,
- CEC_BROADCAST_SYSTEM_NTSC_M = 3,
- CEC_BROADCAST_SYSTEM_PAL_I = 4,
- CEC_BROADCAST_SYSTEM_SECAM_DK = 5,
- CEC_BROADCAST_SYSTEM_SECAM_B_G = 6,
- CEC_BROADCAST_SYSTEM_SECAM_L2 = 7,
- CEC_BROADCAST_SYSTEM_PAL_DK = 8,
+ CEC_BROADCAST_SYSTEM_PAL_B_G = 0,
+ CEC_BROADCAST_SYSTEM_SECAM_L1 = 1,
+ CEC_BROADCAST_SYSTEM_PAL_M = 2,
+ CEC_BROADCAST_SYSTEM_NTSC_M = 3,
+ CEC_BROADCAST_SYSTEM_PAL_I = 4,
+ CEC_BROADCAST_SYSTEM_SECAM_DK = 5,
+ CEC_BROADCAST_SYSTEM_SECAM_B_G = 6,
+ CEC_BROADCAST_SYSTEM_SECAM_L2 = 7,
+ CEC_BROADCAST_SYSTEM_PAL_DK = 8,
CEC_BROADCAST_SYSTEM_OTHER_SYSTEM = 30
} cec_broadcast_system;
typedef enum cec_user_control_code
{
- CEC_USER_CONTROL_CODE_SELECT = 0x00,
- CEC_USER_CONTROL_CODE_UP = 0x01,
- CEC_USER_CONTROL_CODE_DOWN = 0x02,
- CEC_USER_CONTROL_CODE_LEFT = 0x03,
- CEC_USER_CONTROL_CODE_RIGHT = 0x04,
- CEC_USER_CONTROL_CODE_RIGHT_UP = 0x05,
- CEC_USER_CONTROL_CODE_RIGHT_DOWN = 0x06,
- CEC_USER_CONTROL_CODE_LEFT_UP = 0x07,
- CEC_USER_CONTROL_CODE_LEFT_DOWN = 0x08,
- CEC_USER_CONTROL_CODE_ROOT_MENU = 0x09,
- CEC_USER_CONTROL_CODE_SETUP_MENU = 0x0A,
- CEC_USER_CONTROL_CODE_CONTENTS_MENU = 0x0B,
- CEC_USER_CONTROL_CODE_FAVORITE_MENU = 0x0C,
- CEC_USER_CONTROL_CODE_EXIT = 0x0D,
- CEC_USER_CONTROL_CODE_NUMBER0 = 0x20,
- CEC_USER_CONTROL_CODE_NUMBER1 = 0x21,
- CEC_USER_CONTROL_CODE_NUMBER2 = 0x22,
- CEC_USER_CONTROL_CODE_NUMBER3 = 0x23,
- CEC_USER_CONTROL_CODE_NUMBER4 = 0x24,
- CEC_USER_CONTROL_CODE_NUMBER5 = 0x25,
- CEC_USER_CONTROL_CODE_NUMBER6 = 0x26,
- CEC_USER_CONTROL_CODE_NUMBER7 = 0x27,
- CEC_USER_CONTROL_CODE_NUMBER8 = 0x28,
- CEC_USER_CONTROL_CODE_NUMBER9 = 0x29,
- CEC_USER_CONTROL_CODE_DOT = 0x2A,
- CEC_USER_CONTROL_CODE_ENTER = 0x2B,
- CEC_USER_CONTROL_CODE_CLEAR = 0x2C,
- CEC_USER_CONTROL_CODE_NEXT_FAVORITE = 0x2F,
- CEC_USER_CONTROL_CODE_CHANNEL_UP = 0x30,
- CEC_USER_CONTROL_CODE_CHANNEL_DOWN = 0x31,
- CEC_USER_CONTROL_CODE_PREVIOUS_CHANNEL = 0x32,
- CEC_USER_CONTROL_CODE_SOUND_SELECT = 0x33,
- CEC_USER_CONTROL_CODE_INPUT_SELECT = 0x34,
- CEC_USER_CONTROL_CODE_DISPLAY_INFORMATION = 0x35,
- CEC_USER_CONTROL_CODE_HELP = 0x36,
- CEC_USER_CONTROL_CODE_PAGE_UP = 0x37,
- CEC_USER_CONTROL_CODE_PAGE_DOWN = 0x38,
- CEC_USER_CONTROL_CODE_POWER = 0x40,
- CEC_USER_CONTROL_CODE_VOLUME_UP = 0x41,
- CEC_USER_CONTROL_CODE_VOLUME_DOWN = 0x42,
- CEC_USER_CONTROL_CODE_MUTE = 0x43,
- CEC_USER_CONTROL_CODE_PLAY = 0x44,
- CEC_USER_CONTROL_CODE_STOP = 0x45,
- CEC_USER_CONTROL_CODE_PAUSE = 0x46,
- CEC_USER_CONTROL_CODE_RECORD = 0x47,
- CEC_USER_CONTROL_CODE_REWIND = 0x48,
- CEC_USER_CONTROL_CODE_FAST_FORWARD = 0x49,
- CEC_USER_CONTROL_CODE_EJECT = 0x4A,
- CEC_USER_CONTROL_CODE_FORWARD = 0x4B,
- CEC_USER_CONTROL_CODE_BACKWARD = 0x4C,
- CEC_USER_CONTROL_CODE_STOP_RECORD = 0x4D,
- CEC_USER_CONTROL_CODE_PAUSE_RECORD = 0x4E,
- CEC_USER_CONTROL_CODE_ANGLE = 0x50,
- CEC_USER_CONTROL_CODE_SUB_PICTURE = 0x51,
- CEC_USER_CONTROL_CODE_VIDEO_ON_DEMAND = 0x52,
- CEC_USER_CONTROL_CODE_ELECTRONIC_PROGRAM_GUIDE = 0x53,
- CEC_USER_CONTROL_CODE_TIMER_PROGRAMMING = 0x54,
- CEC_USER_CONTROL_CODE_INITIAL_CONFIGURATION = 0x55,
- CEC_USER_CONTROL_CODE_PLAY_FUNCTION = 0x60,
- CEC_USER_CONTROL_CODE_PAUSE_PLAY_FUNCTION = 0x61,
- CEC_USER_CONTROL_CODE_RECORD_FUNCTION = 0x62,
- CEC_USER_CONTROL_CODE_PAUSE_RECORD_FUNCTION = 0x63,
- CEC_USER_CONTROL_CODE_STOP_FUNCTION = 0x64,
- CEC_USER_CONTROL_CODE_MUTE_FUNCTION = 0x65,
- CEC_USER_CONTROL_CODE_RESTORE_VOLUME_FUNCTION = 0x66,
- CEC_USER_CONTROL_CODE_TUNE_FUNCTION = 0x67,
- CEC_USER_CONTROL_CODE_SELECT_MEDIA_FUNCTION = 0x68,
- CEC_USER_CONTROL_CODE_SELECT_AV_INPUT_FUNCTION = 0x69,
+ CEC_USER_CONTROL_CODE_SELECT = 0x00,
+ CEC_USER_CONTROL_CODE_UP = 0x01,
+ CEC_USER_CONTROL_CODE_DOWN = 0x02,
+ CEC_USER_CONTROL_CODE_LEFT = 0x03,
+ CEC_USER_CONTROL_CODE_RIGHT = 0x04,
+ CEC_USER_CONTROL_CODE_RIGHT_UP = 0x05,
+ CEC_USER_CONTROL_CODE_RIGHT_DOWN = 0x06,
+ CEC_USER_CONTROL_CODE_LEFT_UP = 0x07,
+ CEC_USER_CONTROL_CODE_LEFT_DOWN = 0x08,
+ CEC_USER_CONTROL_CODE_ROOT_MENU = 0x09,
+ CEC_USER_CONTROL_CODE_SETUP_MENU = 0x0A,
+ CEC_USER_CONTROL_CODE_CONTENTS_MENU = 0x0B,
+ CEC_USER_CONTROL_CODE_FAVORITE_MENU = 0x0C,
+ CEC_USER_CONTROL_CODE_EXIT = 0x0D,
+ CEC_USER_CONTROL_CODE_NUMBER0 = 0x20,
+ CEC_USER_CONTROL_CODE_NUMBER1 = 0x21,
+ CEC_USER_CONTROL_CODE_NUMBER2 = 0x22,
+ CEC_USER_CONTROL_CODE_NUMBER3 = 0x23,
+ CEC_USER_CONTROL_CODE_NUMBER4 = 0x24,
+ CEC_USER_CONTROL_CODE_NUMBER5 = 0x25,
+ CEC_USER_CONTROL_CODE_NUMBER6 = 0x26,
+ CEC_USER_CONTROL_CODE_NUMBER7 = 0x27,
+ CEC_USER_CONTROL_CODE_NUMBER8 = 0x28,
+ CEC_USER_CONTROL_CODE_NUMBER9 = 0x29,
+ CEC_USER_CONTROL_CODE_DOT = 0x2A,
+ CEC_USER_CONTROL_CODE_ENTER = 0x2B,
+ CEC_USER_CONTROL_CODE_CLEAR = 0x2C,
+ CEC_USER_CONTROL_CODE_NEXT_FAVORITE = 0x2F,
+ CEC_USER_CONTROL_CODE_CHANNEL_UP = 0x30,
+ CEC_USER_CONTROL_CODE_CHANNEL_DOWN = 0x31,
+ CEC_USER_CONTROL_CODE_PREVIOUS_CHANNEL = 0x32,
+ CEC_USER_CONTROL_CODE_SOUND_SELECT = 0x33,
+ CEC_USER_CONTROL_CODE_INPUT_SELECT = 0x34,
+ CEC_USER_CONTROL_CODE_DISPLAY_INFORMATION = 0x35,
+ CEC_USER_CONTROL_CODE_HELP = 0x36,
+ CEC_USER_CONTROL_CODE_PAGE_UP = 0x37,
+ CEC_USER_CONTROL_CODE_PAGE_DOWN = 0x38,
+ CEC_USER_CONTROL_CODE_POWER = 0x40,
+ CEC_USER_CONTROL_CODE_VOLUME_UP = 0x41,
+ CEC_USER_CONTROL_CODE_VOLUME_DOWN = 0x42,
+ CEC_USER_CONTROL_CODE_MUTE = 0x43,
+ CEC_USER_CONTROL_CODE_PLAY = 0x44,
+ CEC_USER_CONTROL_CODE_STOP = 0x45,
+ CEC_USER_CONTROL_CODE_PAUSE = 0x46,
+ CEC_USER_CONTROL_CODE_RECORD = 0x47,
+ CEC_USER_CONTROL_CODE_REWIND = 0x48,
+ CEC_USER_CONTROL_CODE_FAST_FORWARD = 0x49,
+ CEC_USER_CONTROL_CODE_EJECT = 0x4A,
+ CEC_USER_CONTROL_CODE_FORWARD = 0x4B,
+ CEC_USER_CONTROL_CODE_BACKWARD = 0x4C,
+ CEC_USER_CONTROL_CODE_STOP_RECORD = 0x4D,
+ CEC_USER_CONTROL_CODE_PAUSE_RECORD = 0x4E,
+ CEC_USER_CONTROL_CODE_ANGLE = 0x50,
+ CEC_USER_CONTROL_CODE_SUB_PICTURE = 0x51,
+ CEC_USER_CONTROL_CODE_VIDEO_ON_DEMAND = 0x52,
+ CEC_USER_CONTROL_CODE_ELECTRONIC_PROGRAM_GUIDE = 0x53,
+ CEC_USER_CONTROL_CODE_TIMER_PROGRAMMING = 0x54,
+ CEC_USER_CONTROL_CODE_INITIAL_CONFIGURATION = 0x55,
+ CEC_USER_CONTROL_CODE_PLAY_FUNCTION = 0x60,
+ CEC_USER_CONTROL_CODE_PAUSE_PLAY_FUNCTION = 0x61,
+ CEC_USER_CONTROL_CODE_RECORD_FUNCTION = 0x62,
+ CEC_USER_CONTROL_CODE_PAUSE_RECORD_FUNCTION = 0x63,
+ CEC_USER_CONTROL_CODE_STOP_FUNCTION = 0x64,
+ CEC_USER_CONTROL_CODE_MUTE_FUNCTION = 0x65,
+ CEC_USER_CONTROL_CODE_RESTORE_VOLUME_FUNCTION = 0x66,
+ CEC_USER_CONTROL_CODE_TUNE_FUNCTION = 0x67,
+ CEC_USER_CONTROL_CODE_SELECT_MEDIA_FUNCTION = 0x68,
+ CEC_USER_CONTROL_CODE_SELECT_AV_INPUT_FUNCTION = 0x69,
CEC_USER_CONTROL_CODE_SELECT_AUDIO_INPUT_FUNCTION = 0x6A,
- CEC_USER_CONTROL_CODE_POWER_TOGGLE_FUNCTION = 0x6B,
- CEC_USER_CONTROL_CODE_POWER_OFF_FUNCTION = 0x6C,
- CEC_USER_CONTROL_CODE_POWER_ON_FUNCTION = 0x6D,
- CEC_USER_CONTROL_CODE_F1_BLUE = 0x71,
- CEC_USER_CONTROL_CODE_F2_RED = 0X72,
- CEC_USER_CONTROL_CODE_F3_GREEN = 0x73,
- CEC_USER_CONTROL_CODE_F4_YELLOW = 0x74,
- CEC_USER_CONTROL_CODE_F5 = 0x75,
- CEC_USER_CONTROL_CODE_DATA = 0x76,
- CEC_USER_CONTROL_CODE_MAX = 0x76,
+ CEC_USER_CONTROL_CODE_POWER_TOGGLE_FUNCTION = 0x6B,
+ CEC_USER_CONTROL_CODE_POWER_OFF_FUNCTION = 0x6C,
+ CEC_USER_CONTROL_CODE_POWER_ON_FUNCTION = 0x6D,
+ CEC_USER_CONTROL_CODE_F1_BLUE = 0x71,
+ CEC_USER_CONTROL_CODE_F2_RED = 0X72,
+ CEC_USER_CONTROL_CODE_F3_GREEN = 0x73,
+ CEC_USER_CONTROL_CODE_F4_YELLOW = 0x74,
+ CEC_USER_CONTROL_CODE_F5 = 0x75,
+ CEC_USER_CONTROL_CODE_DATA = 0x76,
+ CEC_USER_CONTROL_CODE_MAX = 0x76,
CEC_USER_CONTROL_CODE_UNKNOWN
} cec_user_control_code;
typedef enum cec_logical_address
{
- CECDEVICE_UNKNOWN = -1, //not a valid logical address
- CECDEVICE_TV,
- CECDEVICE_RECORDINGDEVICE1,
- CECDEVICE_RECORDINGDEVICE2,
- CECDEVICE_TUNER1,
- CECDEVICE_PLAYBACKDEVICE1,
- CECDEVICE_AUDIOSYSTEM,
- CECDEVICE_TUNER2,
- CECDEVICE_TUNER3,
- CECDEVICE_PLAYBACKDEVICE2,
- CECDEVICE_RECORDINGDEVICE3,
- CECDEVICE_TUNER4,
- CECDEVICE_PLAYBACKDEVICE3,
- CECDEVICE_RESERVED1,
- CECDEVICE_RESERVED2,
- CECDEVICE_FREEUSE,
- CECDEVICE_UNREGISTERED = 15,
- CECDEVICE_BROADCAST = 15
+ CECDEVICE_UNKNOWN = -1, //not a valid logical address
+ CECDEVICE_TV = 0,
+ CECDEVICE_RECORDINGDEVICE1 = 1,
+ CECDEVICE_RECORDINGDEVICE2 = 2,
+ CECDEVICE_TUNER1 = 3,
+ CECDEVICE_PLAYBACKDEVICE1 = 4,
+ CECDEVICE_AUDIOSYSTEM = 5,
+ CECDEVICE_TUNER2 = 6,
+ CECDEVICE_TUNER3 = 7,
+ CECDEVICE_PLAYBACKDEVICE2 = 8,
+ CECDEVICE_RECORDINGDEVICE3 = 9,
+ CECDEVICE_TUNER4 = 10,
+ CECDEVICE_PLAYBACKDEVICE3 = 11,
+ CECDEVICE_RESERVED1 = 12,
+ CECDEVICE_RESERVED2 = 13,
+ CECDEVICE_FREEUSE = 14,
+ CECDEVICE_UNREGISTERED = 15,
+ CECDEVICE_BROADCAST = 15
} cec_logical_address;
-typedef struct cec_logical_addresses
-{
- cec_logical_address primary;
- int addresses[16];
-
-#ifdef __cplusplus
- void clear(void)
- {
- primary = CECDEVICE_UNKNOWN;
- for (unsigned int iPtr = 0; iPtr < 16; iPtr++)
- addresses[iPtr] = 0;
- }
-
- bool empty(void) const
- {
- return primary == CECDEVICE_UNKNOWN;
- }
-
- uint16_t ackmask(void) const
- {
- uint16_t mask = 0;
- for (unsigned int iPtr = 0; iPtr < 16; iPtr++)
- if (addresses[iPtr] == 1)
- mask |= 0x1 << iPtr;
- return mask;
- }
-
- void set(cec_logical_address address)
- {
- if (primary == CECDEVICE_UNKNOWN)
- primary = address;
-
- addresses[(int) address] = 1;
- }
-
- void unset(cec_logical_address address)
- {
- if (primary == address)
- primary = CECDEVICE_UNKNOWN;
-
- addresses[(int) address] = 0;
- }
-
- bool isset(cec_logical_address address) const { return addresses[(int) address] == 1; }
- bool operator[](uint8_t pos) const { return pos < 16 ? isset((cec_logical_address) pos) : false; }
-#endif
-} cec_logical_addresses;
-
typedef enum cec_opcode
{
- CEC_OPCODE_ACTIVE_SOURCE = 0x82,
- CEC_OPCODE_IMAGE_VIEW_ON = 0x04,
- CEC_OPCODE_TEXT_VIEW_ON = 0x0D,
- CEC_OPCODE_INACTIVE_SOURCE = 0x9D,
- CEC_OPCODE_REQUEST_ACTIVE_SOURCE = 0x85,
- CEC_OPCODE_ROUTING_CHANGE = 0x80,
- CEC_OPCODE_ROUTING_INFORMATION = 0x81,
- CEC_OPCODE_SET_STREAM_PATH = 0x86,
- CEC_OPCODE_STANDBY = 0x36,
- CEC_OPCODE_RECORD_OFF = 0x0B,
- CEC_OPCODE_RECORD_ON = 0x09,
- CEC_OPCODE_RECORD_STATUS = 0x0A,
- CEC_OPCODE_RECORD_TV_SCREEN = 0x0F,
- CEC_OPCODE_CLEAR_ANALOGUE_TIMER = 0x33,
- CEC_OPCODE_CLEAR_DIGITAL_TIMER = 0x99,
- CEC_OPCODE_CLEAR_EXTERNAL_TIMER = 0xA1,
- CEC_OPCODE_SET_ANALOGUE_TIMER = 0x34,
- CEC_OPCODE_SET_DIGITAL_TIMER = 0x97,
- CEC_OPCODE_SET_EXTERNAL_TIMER = 0xA2,
- CEC_OPCODE_SET_TIMER_PROGRAM_TITLE = 0x67,
- CEC_OPCODE_TIMER_CLEARED_STATUS = 0x43,
- CEC_OPCODE_TIMER_STATUS = 0x35,
- CEC_OPCODE_CEC_VERSION = 0x9E,
- CEC_OPCODE_GET_CEC_VERSION = 0x9F,
- CEC_OPCODE_GIVE_PHYSICAL_ADDRESS = 0x83,
- CEC_OPCODE_GET_MENU_LANGUAGE = 0x91,
- CEC_OPCODE_REPORT_PHYSICAL_ADDRESS = 0x84,
- CEC_OPCODE_SET_MENU_LANGUAGE = 0x32,
- CEC_OPCODE_DECK_CONTROL = 0x42,
- CEC_OPCODE_DECK_STATUS = 0x1B,
- CEC_OPCODE_GIVE_DECK_STATUS = 0x1A,
- CEC_OPCODE_PLAY = 0x41,
- CEC_OPCODE_GIVE_TUNER_DEVICE_STATUS = 0x08,
- CEC_OPCODE_SELECT_ANALOGUE_SERVICE = 0x92,
- CEC_OPCODE_SELECT_DIGITAL_SERVICE = 0x93,
- CEC_OPCODE_TUNER_DEVICE_STATUS = 0x07,
- CEC_OPCODE_TUNER_STEP_DECREMENT = 0x06,
- CEC_OPCODE_TUNER_STEP_INCREMENT = 0x05,
- CEC_OPCODE_DEVICE_VENDOR_ID = 0x87,
- CEC_OPCODE_GIVE_DEVICE_VENDOR_ID = 0x8C,
- CEC_OPCODE_VENDOR_COMMAND = 0x89,
- CEC_OPCODE_VENDOR_COMMAND_WITH_ID = 0xA0,
- CEC_OPCODE_VENDOR_REMOTE_BUTTON_DOWN = 0x8A,
- CEC_OPCODE_VENDOR_REMOTE_BUTTON_UP = 0x8B,
- CEC_OPCODE_SET_OSD_STRING = 0x64,
- CEC_OPCODE_GIVE_OSD_NAME = 0x46,
- CEC_OPCODE_SET_OSD_NAME = 0x47,
- CEC_OPCODE_MENU_REQUEST = 0x8D,
- CEC_OPCODE_MENU_STATUS = 0x8E,
- CEC_OPCODE_USER_CONTROL_PRESSED = 0x44,
- CEC_OPCODE_USER_CONTROL_RELEASE = 0x45,
- CEC_OPCODE_GIVE_DEVICE_POWER_STATUS = 0x8F,
- CEC_OPCODE_REPORT_POWER_STATUS = 0x90,
- CEC_OPCODE_FEATURE_ABORT = 0x00,
- CEC_OPCODE_ABORT = 0xFF,
- CEC_OPCODE_GIVE_AUDIO_STATUS = 0x71,
+ CEC_OPCODE_ACTIVE_SOURCE = 0x82,
+ CEC_OPCODE_IMAGE_VIEW_ON = 0x04,
+ CEC_OPCODE_TEXT_VIEW_ON = 0x0D,
+ CEC_OPCODE_INACTIVE_SOURCE = 0x9D,
+ CEC_OPCODE_REQUEST_ACTIVE_SOURCE = 0x85,
+ CEC_OPCODE_ROUTING_CHANGE = 0x80,
+ CEC_OPCODE_ROUTING_INFORMATION = 0x81,
+ CEC_OPCODE_SET_STREAM_PATH = 0x86,
+ CEC_OPCODE_STANDBY = 0x36,
+ CEC_OPCODE_RECORD_OFF = 0x0B,
+ CEC_OPCODE_RECORD_ON = 0x09,
+ CEC_OPCODE_RECORD_STATUS = 0x0A,
+ CEC_OPCODE_RECORD_TV_SCREEN = 0x0F,
+ CEC_OPCODE_CLEAR_ANALOGUE_TIMER = 0x33,
+ CEC_OPCODE_CLEAR_DIGITAL_TIMER = 0x99,
+ CEC_OPCODE_CLEAR_EXTERNAL_TIMER = 0xA1,
+ CEC_OPCODE_SET_ANALOGUE_TIMER = 0x34,
+ CEC_OPCODE_SET_DIGITAL_TIMER = 0x97,
+ CEC_OPCODE_SET_EXTERNAL_TIMER = 0xA2,
+ CEC_OPCODE_SET_TIMER_PROGRAM_TITLE = 0x67,
+ CEC_OPCODE_TIMER_CLEARED_STATUS = 0x43,
+ CEC_OPCODE_TIMER_STATUS = 0x35,
+ CEC_OPCODE_CEC_VERSION = 0x9E,
+ CEC_OPCODE_GET_CEC_VERSION = 0x9F,
+ CEC_OPCODE_GIVE_PHYSICAL_ADDRESS = 0x83,
+ CEC_OPCODE_GET_MENU_LANGUAGE = 0x91,
+ CEC_OPCODE_REPORT_PHYSICAL_ADDRESS = 0x84,
+ CEC_OPCODE_SET_MENU_LANGUAGE = 0x32,
+ CEC_OPCODE_DECK_CONTROL = 0x42,
+ CEC_OPCODE_DECK_STATUS = 0x1B,
+ CEC_OPCODE_GIVE_DECK_STATUS = 0x1A,
+ CEC_OPCODE_PLAY = 0x41,
+ CEC_OPCODE_GIVE_TUNER_DEVICE_STATUS = 0x08,
+ CEC_OPCODE_SELECT_ANALOGUE_SERVICE = 0x92,
+ CEC_OPCODE_SELECT_DIGITAL_SERVICE = 0x93,
+ CEC_OPCODE_TUNER_DEVICE_STATUS = 0x07,
+ CEC_OPCODE_TUNER_STEP_DECREMENT = 0x06,
+ CEC_OPCODE_TUNER_STEP_INCREMENT = 0x05,
+ CEC_OPCODE_DEVICE_VENDOR_ID = 0x87,
+ CEC_OPCODE_GIVE_DEVICE_VENDOR_ID = 0x8C,
+ CEC_OPCODE_VENDOR_COMMAND = 0x89,
+ CEC_OPCODE_VENDOR_COMMAND_WITH_ID = 0xA0,
+ CEC_OPCODE_VENDOR_REMOTE_BUTTON_DOWN = 0x8A,
+ CEC_OPCODE_VENDOR_REMOTE_BUTTON_UP = 0x8B,
+ CEC_OPCODE_SET_OSD_STRING = 0x64,
+ CEC_OPCODE_GIVE_OSD_NAME = 0x46,
+ CEC_OPCODE_SET_OSD_NAME = 0x47,
+ CEC_OPCODE_MENU_REQUEST = 0x8D,
+ CEC_OPCODE_MENU_STATUS = 0x8E,
+ CEC_OPCODE_USER_CONTROL_PRESSED = 0x44,
+ CEC_OPCODE_USER_CONTROL_RELEASE = 0x45,
+ CEC_OPCODE_GIVE_DEVICE_POWER_STATUS = 0x8F,
+ CEC_OPCODE_REPORT_POWER_STATUS = 0x90,
+ CEC_OPCODE_FEATURE_ABORT = 0x00,
+ CEC_OPCODE_ABORT = 0xFF,
+ CEC_OPCODE_GIVE_AUDIO_STATUS = 0x71,
CEC_OPCODE_GIVE_SYSTEM_AUDIO_MODE_STATUS = 0x7D,
- CEC_OPCODE_REPORT_AUDIO_STATUS = 0x7A,
- CEC_OPCODE_SET_SYSTEM_AUDIO_MODE = 0x72,
- CEC_OPCODE_SYSTEM_AUDIO_MODE_REQUEST = 0x70,
- CEC_OPCODE_SYSTEM_AUDIO_MODE_STATUS = 0x7E,
- CEC_OPCODE_SET_AUDIO_RATE = 0x9A,
- CEC_OPCODE_NONE = 0xFD /* when this opcode is set, no opcode will be sent to the device. this is one of the reserved numbers */
+ CEC_OPCODE_REPORT_AUDIO_STATUS = 0x7A,
+ CEC_OPCODE_SET_SYSTEM_AUDIO_MODE = 0x72,
+ CEC_OPCODE_SYSTEM_AUDIO_MODE_REQUEST = 0x70,
+ CEC_OPCODE_SYSTEM_AUDIO_MODE_STATUS = 0x7E,
+ CEC_OPCODE_SET_AUDIO_RATE = 0x9A,
+ /* when this opcode is set, no opcode will be sent to the device. this is one of the reserved numbers */
+ CEC_OPCODE_NONE = 0xFD
} cec_opcode;
typedef enum cec_log_level
CEC_LOG_ALL = 31
} cec_log_level;
-typedef struct cec_menu_language
-{
- char language[4];
- cec_logical_address device;
-} cec_menu_language;
-
-typedef struct cec_log_message
-{
- char message[1024];
- cec_log_level level;
- int64_t time;
-} cec_log_message;
-
-typedef struct cec_keypress
-{
- cec_user_control_code keycode;
- unsigned int duration;
-} cec_keypress;
-
-typedef struct cec_adapter
-{
- char path[1024];
- char comm[1024];
-} cec_adapter;
-
typedef enum cec_adapter_messagecode
{
MSGCODE_NOTHING = 0,
MSGCODE_FRAME_ACK = 0x40,
} cec_adapter_messagecode;
+typedef enum cec_bus_device_status
+{
+ CEC_DEVICE_STATUS_UNKNOWN,
+ CEC_DEVICE_STATUS_PRESENT,
+ CEC_DEVICE_STATUS_NOT_PRESENT,
+ CEC_DEVICE_STATUS_HANDLED_BY_LIBCEC
+} cec_bus_device_status;
+
+typedef enum cec_vendor_id
+{
+ CEC_VENDOR_SAMSUNG = 0x00F0,
+ CEC_VENDOR_LG = 0xE091,
+ CEC_VENDOR_PANASONIC = 0x8045,
+ CEC_VENDOR_PIONEER = 0xE036,
+ CEC_VENDOR_ONKYO = 0x09B0,
+ CEC_VENDOR_YAMAHA = 0xA0DE,
+ CEC_VENDOR_PHILIPS = 0x903E,
+ CEC_VENDOR_UNKNOWN = 0
+} cec_vendor_id;
+
+typedef struct cec_menu_language
+{
+ char language[4];
+ cec_logical_address device;
+} cec_menu_language;
+
+typedef struct cec_osd_name
+{
+ char name[14];
+ cec_logical_address device;
+} cec_osd_name;
+
+typedef struct cec_log_message
+{
+ char message[1024];
+ cec_log_level level;
+ int64_t time;
+} cec_log_message;
+
+typedef struct cec_keypress
+{
+ cec_user_control_code keycode;
+ unsigned int duration;
+} cec_keypress;
+
+typedef struct cec_adapter
+{
+ char path[1024];
+ char comm[1024];
+} cec_adapter;
+
typedef struct cec_datapacket
{
uint8_t data[100];
#ifdef __cplusplus
cec_datapacket &operator =(const struct cec_datapacket &packet)
{
- clear();
+ Clear();
for (uint8_t iPtr = 0; iPtr < packet.size; iPtr++)
- push_back(packet[iPtr]);
+ PushBack(packet[iPtr]);
return *this;
}
- bool empty(void) const { return size == 0; }
- bool full(void) const { return size == 100; }
+ bool IsEmpty(void) const { return size == 0; }
+ bool IsFull(void) const { return size == 100; }
uint8_t operator[](uint8_t pos) const { return pos < size ? data[pos] : 0; }
- uint8_t at(uint8_t pos) const { return pos < size ? data[pos] : 0; }
+ uint8_t At(uint8_t pos) const { return pos < size ? data[pos] : 0; }
- void shift(uint8_t iShiftBy)
+ void Shift(uint8_t iShiftBy)
{
if (iShiftBy >= size)
{
- clear();
+ Clear();
}
else
{
}
}
- void push_back(uint8_t add)
+ void PushBack(uint8_t add)
{
if (size < 100)
data[size++] = add;
}
- void clear(void)
+ void Clear(void)
{
memset(data, 0, sizeof(data));
size = 0;
return *this;
}
- static void format(cec_command &command, cec_logical_address initiator, cec_logical_address destination, cec_opcode opcode)
+ static void Format(cec_command &command, cec_logical_address initiator, cec_logical_address destination, cec_opcode opcode, int32_t timeout = CEC_DEFAULT_TRANSMIT_TIMEOUT)
{
- command.clear();
- command.initiator = initiator;
- command.destination = destination;
+ command.Clear();
+ command.initiator = initiator;
+ command.destination = destination;
+ command.transmit_timeout = timeout;
if (opcode != CEC_OPCODE_NONE)
{
command.opcode = opcode;
}
}
- void push_back(uint8_t data)
+ void PushBack(uint8_t data)
{
if (initiator == CECDEVICE_UNKNOWN && destination == CECDEVICE_UNKNOWN)
{
opcode = (cec_opcode) data;
}
else
- parameters.push_back(data);
+ parameters.PushBack(data);
}
- void clear(void)
+ void Clear(void)
{
initiator = CECDEVICE_UNKNOWN;
destination = CECDEVICE_UNKNOWN;
eom = 0;
opcode_set = 0;
opcode = CEC_OPCODE_FEATURE_ABORT;
- transmit_timeout = 1000;
- parameters.clear();
+ transmit_timeout = CEC_DEFAULT_TRANSMIT_TIMEOUT;
+ parameters.Clear();
};
#endif
} cec_command;
-typedef enum cec_vendor_id
+typedef struct cec_device_type_list
{
- CEC_VENDOR_SAMSUNG = 0x00F0,
- CEC_VENDOR_LG = 0xE091,
- CEC_VENDOR_PANASONIC = 0x8045,
- CEC_VENDOR_PIONEER = 0xE036,
- CEC_VENDOR_UNKNOWN = 0
-} cec_vendor_id;
+ cec_device_type types[5];
-//default physical address 1.0.0.0, HDMI port 1
-#define CEC_DEFAULT_PHYSICAL_ADDRESS 0x1000
-#define MSGSTART 0xFF
-#define MSGEND 0xFE
-#define MSGESC 0xFD
-#define ESCOFFSET 3
-#define CEC_BUTTON_TIMEOUT 500
+#ifdef __cplusplus
+ /*!
+ * @deprecated
+ */
+ void clear(void) { Clear(); }
+ /*!
+ * @deprecated
+ */
+ void add(const cec_device_type type) { Add(type); }
+
+ void Clear(void)
+ {
+ for (unsigned int iPtr = 0; iPtr < 5; iPtr++)
+ types[iPtr] = CEC_DEVICE_TYPE_RESERVED;
+ }
-#define CEC_MIN_LIB_VERSION 1
-#define CEC_LIB_VERSION_MAJOR 1
-#define CEC_LIB_VERSION_MINOR 2
+ void Add(const cec_device_type type)
+ {
+ for (unsigned int iPtr = 0; iPtr < 5; iPtr++)
+ {
+ if (types[iPtr] == CEC_DEVICE_TYPE_RESERVED)
+ {
+ types[iPtr] = type;
+ break;
+ }
+ }
+ }
+
+ bool IsSet(cec_device_type type)
+ {
+ bool bReturn(false);
+ for (unsigned int iPtr = 0; !bReturn && iPtr < 5; iPtr++)
+ {
+ if (types[iPtr] == type)
+ bReturn = true;
+ }
+ return bReturn;
+ }
+
+ bool IsEmpty()
+ {
+ bool bReturn(true);
+ for (unsigned int iPtr = 0; bReturn && iPtr < 5; iPtr++)
+ {
+ if (types[iPtr] != CEC_DEVICE_TYPE_RESERVED)
+ bReturn = false;
+ }
+ return bReturn;
+ }
+
+ cec_device_type operator[](uint8_t pos) const { return pos < 5 ? types[pos] : CEC_DEVICE_TYPE_RESERVED; }
+#endif
+} cec_device_type_list;
+
+typedef struct cec_logical_addresses
+{
+ cec_logical_address primary;
+ int addresses[16];
+
+#ifdef __cplusplus
+ void Clear(void)
+ {
+ primary = CECDEVICE_UNKNOWN;
+ for (unsigned int iPtr = 0; iPtr < 16; iPtr++)
+ addresses[iPtr] = 0;
+ }
+
+ bool IsEmpty(void) const
+ {
+ return primary == CECDEVICE_UNKNOWN;
+ }
+
+ uint16_t AckMask(void) const
+ {
+ uint16_t mask = 0;
+ for (unsigned int iPtr = 0; iPtr < 16; iPtr++)
+ if (addresses[iPtr] == 1)
+ mask |= 0x1 << iPtr;
+ return mask;
+ }
+
+ void Set(cec_logical_address address)
+ {
+ if (primary == CECDEVICE_UNKNOWN)
+ primary = address;
+
+ addresses[(int) address] = 1;
+ }
+
+ void Unset(cec_logical_address address)
+ {
+ if (primary == address)
+ primary = CECDEVICE_UNKNOWN;
+
+ addresses[(int) address] = 0;
+ }
+
+ bool IsSet(cec_logical_address address) const { return addresses[(int) address] == 1; }
+ bool operator[](uint8_t pos) const { return pos < 16 ? IsSet((cec_logical_address) pos) : false; }
+#endif
+} cec_logical_addresses;
#ifdef __cplusplus
};
--- /dev/null
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CecSharpClient", "..\src\CecSharpTester\CecSharpClient.csproj", "{47EF8EFE-5758-4E82-B9BA-F9B002F9C0D4}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x86 = Debug|x86
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {47EF8EFE-5758-4E82-B9BA-F9B002F9C0D4}.Debug|x86.ActiveCfg = Debug|x86
+ {47EF8EFE-5758-4E82-B9BA-F9B002F9C0D4}.Debug|x86.Build.0 = Debug|x86
+ {47EF8EFE-5758-4E82-B9BA-F9B002F9C0D4}.Release|x86.ActiveCfg = Release|x86
+ {47EF8EFE-5758-4E82-B9BA-F9B002F9C0D4}.Release|x86.Build.0 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{1AC27FBD-653A-4F5F-ADBC-2A8FD074EEB7}</ProjectGuid>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <Keyword>ManagedCProj</Keyword>
+ <RootNamespace>LibCecSharp</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CLRSupport>true</CLRSupport>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <CLRSupport>true</CLRSupport>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>true</LinkIncremental>
+ <IncludePath>$(SolutionDir)\..\include;$(IncludePath)</IncludePath>
+ <TargetName>$(ProjectName)</TargetName>
+ <OutDir>$(SolutionDir)..\</OutDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ <IncludePath>$(SolutionDir)\..\include;$(IncludePath)</IncludePath>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalDependencies>
+ </AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalDependencies>
+ </AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\include\cec.h" />
+ <ClInclude Include="..\include\cectypes.h" />
+ <ClInclude Include="..\src\LibCecSharp\resource.h" />
+ <ClInclude Include="..\src\LibCecSharp\Stdafx.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\src\LibCecSharp\AssemblyInfo.cpp" />
+ <ClCompile Include="..\src\LibCecSharp\LibCecSharp.cpp" />
+ <ClCompile Include="..\src\LibCecSharp\Stdafx.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="libcec.vcxproj">
+ <Project>{c04b0fb1-667d-4f1c-bdae-a07cdffaaaa0}</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\src\LibCecSharp\resource.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\LibCecSharp\Stdafx.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\cec.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\cectypes.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\src\LibCecSharp\AssemblyInfo.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\LibCecSharp\LibCecSharp.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\LibCecSharp\Stdafx.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project>
\ No newline at end of file
%COMPILER% libcec.sln /clean Release
echo Compiling libCEC
-%COMPILER% libcec.sln /clean Release
-%COMPILER% libcec.sln /build Release
+%COMPILER% libcec.sln /build Release /project libcec
+echo Compiling cec-client
+%COMPILER% libcec.sln /build Release /project testclient
+echo Compiling LibCecSharp
+%COMPILER% libcec.sln /build Release /project LibCecSharp
rem Copy driver installer
echo Copying driver installer
RequestExecutionLevel admin
Var StartMenuFolder
-!define MUI_FINISHPAGE_LINK "Please visit http://www.pulse-eight.com/ for more information."
+!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
File "..\COPYING"
File "..\libcec.dll"
File "..\libcec.lib"
+ File "Release\LibCecSharp.dll"
File "..\pthreadVC2.dll"
File "..\README"
Delete "$INSTDIR\libcec.dll"
Delete "$INSTDIR\libcec.lib"
Delete "$INSTDIR\libcec.pdb"
+ Delete "$INSTDIR\LibCecSharp.dll"
Delete "$INSTDIR\pthreadVC2.dll"
Delete "$INSTDIR\README"
Delete "$INSTDIR\driver\OEM001.inf"
{C04B0FB1-667D-4F1C-BDAE-A07CDFFAAAA0} = {C04B0FB1-667D-4F1C-BDAE-A07CDFFAAAA0}
EndProjectSection
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibCecSharp", "LibCecSharp.vcxproj", "{1AC27FBD-653A-4F5F-ADBC-2A8FD074EEB7}"
+ ProjectSection(ProjectDependencies) = postProject
+ {C04B0FB1-667D-4F1C-BDAE-A07CDFFAAAA0} = {C04B0FB1-667D-4F1C-BDAE-A07CDFFAAAA0}
+ EndProjectSection
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|Mixed Platforms = Debug|Mixed Platforms
Debug|Win32 = Debug|Win32
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|Mixed Platforms = Release|Mixed Platforms
Release|Win32 = Release|Win32
+ Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {C04B0FB1-667D-4F1C-BDAE-A07CDFFAAAA0}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {C04B0FB1-667D-4F1C-BDAE-A07CDFFAAAA0}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
+ {C04B0FB1-667D-4F1C-BDAE-A07CDFFAAAA0}.Debug|Mixed Platforms.Build.0 = Debug|Win32
{C04B0FB1-667D-4F1C-BDAE-A07CDFFAAAA0}.Debug|Win32.ActiveCfg = Debug|Win32
{C04B0FB1-667D-4F1C-BDAE-A07CDFFAAAA0}.Debug|Win32.Build.0 = Debug|Win32
+ {C04B0FB1-667D-4F1C-BDAE-A07CDFFAAAA0}.Debug|x86.ActiveCfg = Debug|Win32
+ {C04B0FB1-667D-4F1C-BDAE-A07CDFFAAAA0}.Release|Any CPU.ActiveCfg = Release|Win32
+ {C04B0FB1-667D-4F1C-BDAE-A07CDFFAAAA0}.Release|Mixed Platforms.ActiveCfg = Release|Win32
+ {C04B0FB1-667D-4F1C-BDAE-A07CDFFAAAA0}.Release|Mixed Platforms.Build.0 = Release|Win32
{C04B0FB1-667D-4F1C-BDAE-A07CDFFAAAA0}.Release|Win32.ActiveCfg = Release|Win32
{C04B0FB1-667D-4F1C-BDAE-A07CDFFAAAA0}.Release|Win32.Build.0 = Release|Win32
+ {C04B0FB1-667D-4F1C-BDAE-A07CDFFAAAA0}.Release|x86.ActiveCfg = Release|Win32
+ {F01222BF-6B3D-43BD-B254-434031CB9887}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {F01222BF-6B3D-43BD-B254-434031CB9887}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
+ {F01222BF-6B3D-43BD-B254-434031CB9887}.Debug|Mixed Platforms.Build.0 = Debug|Win32
{F01222BF-6B3D-43BD-B254-434031CB9887}.Debug|Win32.ActiveCfg = Debug|Win32
{F01222BF-6B3D-43BD-B254-434031CB9887}.Debug|Win32.Build.0 = Debug|Win32
+ {F01222BF-6B3D-43BD-B254-434031CB9887}.Debug|x86.ActiveCfg = Debug|Win32
+ {F01222BF-6B3D-43BD-B254-434031CB9887}.Release|Any CPU.ActiveCfg = Release|Win32
+ {F01222BF-6B3D-43BD-B254-434031CB9887}.Release|Mixed Platforms.ActiveCfg = Release|Win32
+ {F01222BF-6B3D-43BD-B254-434031CB9887}.Release|Mixed Platforms.Build.0 = Release|Win32
{F01222BF-6B3D-43BD-B254-434031CB9887}.Release|Win32.ActiveCfg = Release|Win32
{F01222BF-6B3D-43BD-B254-434031CB9887}.Release|Win32.Build.0 = Release|Win32
+ {F01222BF-6B3D-43BD-B254-434031CB9887}.Release|x86.ActiveCfg = Release|Win32
+ {1AC27FBD-653A-4F5F-ADBC-2A8FD074EEB7}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {1AC27FBD-653A-4F5F-ADBC-2A8FD074EEB7}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
+ {1AC27FBD-653A-4F5F-ADBC-2A8FD074EEB7}.Debug|Mixed Platforms.Build.0 = Debug|Win32
+ {1AC27FBD-653A-4F5F-ADBC-2A8FD074EEB7}.Debug|Win32.ActiveCfg = Debug|Win32
+ {1AC27FBD-653A-4F5F-ADBC-2A8FD074EEB7}.Debug|Win32.Build.0 = Debug|Win32
+ {1AC27FBD-653A-4F5F-ADBC-2A8FD074EEB7}.Debug|x86.ActiveCfg = Debug|Win32
+ {1AC27FBD-653A-4F5F-ADBC-2A8FD074EEB7}.Release|Any CPU.ActiveCfg = Release|Win32
+ {1AC27FBD-653A-4F5F-ADBC-2A8FD074EEB7}.Release|Mixed Platforms.ActiveCfg = Release|Win32
+ {1AC27FBD-653A-4F5F-ADBC-2A8FD074EEB7}.Release|Mixed Platforms.Build.0 = Release|Win32
+ {1AC27FBD-653A-4F5F-ADBC-2A8FD074EEB7}.Release|Win32.ActiveCfg = Release|Win32
+ {1AC27FBD-653A-4F5F-ADBC-2A8FD074EEB7}.Release|Win32.Build.0 = Release|Win32
+ {1AC27FBD-653A-4F5F-ADBC-2A8FD074EEB7}.Release|x86.ActiveCfg = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
--- /dev/null
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("CecSharpClient")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Pulse-Eight Ltd.")]
+[assembly: AssemblyProduct("CecSharpClient")]
+[assembly: AssemblyCopyright("Copyright © Pulse-Eight Ltd. 2011")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("fb8d5961-9ba9-4e56-8706-ac150183706f")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// 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.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
--- /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/
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace CecSharpClient
+{
+ class CecSharpClient
+ {
+ public CecSharpClient()
+ {
+ CecDeviceTypeList types = new CecDeviceTypeList();
+ types.Types[0] = CecDeviceType.RecordingDevice;
+
+ Lib = new LibCecSharp("CEC Tester", types);
+ LogLevel = (int) CecLogLevel.All;
+
+ Console.WriteLine("CEC Parser created - libcec version " + Lib.GetLibVersionMajor() + "." + Lib.GetLibVersionMinor());
+ }
+
+ void FlushLog()
+ {
+ CecLogMessage message = Lib.GetNextLogMessage();
+ bool bGotMessage = !message.Empty;
+ while (bGotMessage)
+ {
+ if (((int)message.Level & LogLevel) == (int)message.Level)
+ {
+ string strLevel = "";
+ switch (message.Level)
+ {
+ case CecLogLevel.Error:
+ strLevel = "ERROR: ";
+ break;
+ case CecLogLevel.Warning:
+ strLevel = "WARNING: ";
+ break;
+ case CecLogLevel.Notice:
+ strLevel = "NOTICE: ";
+ break;
+ case CecLogLevel.Traffic:
+ strLevel = "TRAFFIC: ";
+ break;
+ case CecLogLevel.Debug:
+ strLevel = "DEBUG: ";
+ break;
+ default:
+ break;
+ }
+ string strLog = string.Format("{0} {1,16} {2}", strLevel, message.Time, message.Message);
+ Console.WriteLine(strLog);
+ }
+
+ message = Lib.GetNextLogMessage();
+ bGotMessage = !message.Empty;
+ }
+ }
+
+ public bool Connect(int timeout)
+ {
+ CecAdapter[] adapters = Lib.FindAdapters(string.Empty);
+ if (adapters.Length > 0)
+ return Connect(adapters[0].ComPort, timeout);
+ else
+ {
+ Console.WriteLine("Did not find any CEC adapters");
+ return false;
+ }
+ }
+
+ public bool Connect(string port, int timeout)
+ {
+ return Lib.Open(port, timeout);
+ }
+
+ public void Close()
+ {
+ Lib.Close();
+ }
+
+ public void ListDevices()
+ {
+ int iAdapter = 0;
+ foreach (CecAdapter adapter in Lib.FindAdapters(string.Empty))
+ {
+ Console.WriteLine("Adapter: " + iAdapter++);
+ Console.WriteLine("Path: " + adapter.Path);
+ Console.WriteLine("Com port: " + adapter.ComPort);
+ }
+ }
+
+ void ShowConsoleHelp()
+ {
+ Console.WriteLine(
+ "================================================================================" + System.Environment.NewLine +
+ "Available commands:" + System.Environment.NewLine +
+ System.Environment.NewLine +
+ "[tx] {bytes} transfer bytes over the CEC line." + System.Environment.NewLine +
+ "[txn] {bytes} transfer bytes but don't wait for transmission ACK." + System.Environment.NewLine +
+ "[on] {address} power on the device with the given logical address." + System.Environment.NewLine +
+ "[standby] {address} put the device with the given address in standby mode." + System.Environment.NewLine +
+ "[la] {logical_address} change the logical address of the CEC adapter." + System.Environment.NewLine +
+ "[pa] {physical_address} change the physical address of the CEC adapter." + System.Environment.NewLine +
+ "[osd] {addr} {string} set OSD message on the specified device." + System.Environment.NewLine +
+ "[ver] {addr} get the CEC version of the specified device." + System.Environment.NewLine +
+ "[ven] {addr} get the vendor ID of the specified device." + System.Environment.NewLine +
+ "[lang] {addr} get the menu language of the specified device." + System.Environment.NewLine +
+ "[pow] {addr} get the power status of the specified device." + System.Environment.NewLine +
+ "[poll] {addr} poll the specified device." + System.Environment.NewLine +
+ "[scan] scan the CEC bus and display device info" + System.Environment.NewLine +
+ "[mon] {1|0} enable or disable CEC bus monitoring." + System.Environment.NewLine +
+ "[log] {1 - 31} change the log level. see cectypes.h for values." + System.Environment.NewLine +
+ "[ping] send a ping command to the CEC adapter." + System.Environment.NewLine +
+ "[bl] to let the adapter enter the bootloader, to upgrade" + System.Environment.NewLine +
+ " the flash rom." + System.Environment.NewLine +
+ "[r] reconnect to the CEC adapter." + System.Environment.NewLine +
+ "[h] or [help] show this help." + System.Environment.NewLine +
+ "[q] or [quit] to quit the CEC test client and switch off all" + System.Environment.NewLine +
+ " connected CEC devices." + System.Environment.NewLine +
+ "================================================================================");
+ }
+
+ public void MainLoop()
+ {
+ Lib.PowerOnDevices(CecLogicalAddress.Tv);
+ FlushLog();
+
+ Lib.SetActiveSource(CecDeviceType.PlaybackDevice);
+ FlushLog();
+
+ bool bContinue = true;
+ string command;
+ while (bContinue)
+ {
+ FlushLog();
+ Console.WriteLine("waiting for input");
+
+ command = Console.ReadLine();
+ if (command.Length == 0)
+ continue;
+ string[] splitCommand = command.Split(' ');
+ if (splitCommand[0] == "tx" || splitCommand[0] == "txn")
+ {
+ CecCommand bytes = new CecCommand();
+ for (int iPtr = 1; iPtr < splitCommand.Length; iPtr++)
+ {
+ bytes.PushBack(byte.Parse(splitCommand[iPtr], System.Globalization.NumberStyles.HexNumber));
+ }
+
+ if (command == "txn")
+ bytes.TransmitTimeout = 0;
+
+ Lib.Transmit(bytes);
+ }
+ else if (splitCommand[0] == "on")
+ {
+ if (splitCommand.Length > 1)
+ Lib.PowerOnDevices((CecLogicalAddress)byte.Parse(splitCommand[1], System.Globalization.NumberStyles.HexNumber));
+ else
+ Lib.PowerOnDevices(CecLogicalAddress.Broadcast);
+ }
+ else if (splitCommand[0] == "standby")
+ {
+ if (splitCommand.Length > 1)
+ Lib.StandbyDevices((CecLogicalAddress)byte.Parse(splitCommand[1], System.Globalization.NumberStyles.HexNumber));
+ else
+ Lib.StandbyDevices(CecLogicalAddress.Broadcast);
+ }
+ else if (splitCommand[0] == "poll")
+ {
+ bool bSent = false;
+ if (splitCommand.Length > 1)
+ bSent = Lib.PollDevice((CecLogicalAddress)byte.Parse(splitCommand[1], System.Globalization.NumberStyles.HexNumber));
+ else
+ bSent = Lib.PollDevice(CecLogicalAddress.Broadcast);
+ if (bSent)
+ Console.WriteLine("POLL message sent");
+ else
+ Console.WriteLine("POLL message not sent");
+ }
+ else if (splitCommand[0] == "la")
+ {
+ if (splitCommand.Length > 1)
+ Lib.SetLogicalAddress((CecLogicalAddress)byte.Parse(splitCommand[1], System.Globalization.NumberStyles.HexNumber));
+ }
+ else if (splitCommand[0] == "pa")
+ {
+ if (splitCommand.Length > 1)
+ Lib.SetPhysicalAddress(short.Parse(splitCommand[1], System.Globalization.NumberStyles.HexNumber));
+ }
+ else if (splitCommand[0] == "osd")
+ {
+ if (splitCommand.Length > 2)
+ {
+ StringBuilder osdString = new StringBuilder();
+ for (int iPtr = 1; iPtr < splitCommand.Length; iPtr++)
+ {
+ osdString.Append(splitCommand[iPtr]);
+ if (iPtr != splitCommand.Length - 1)
+ osdString.Append(" ");
+ }
+ Lib.SetOSDString((CecLogicalAddress)byte.Parse(splitCommand[1], System.Globalization.NumberStyles.HexNumber), CecDisplayControl.DisplayForDefaultTime, osdString.ToString());
+ }
+ }
+ else if (splitCommand[0] == "ping")
+ {
+ Lib.PingAdapter();
+ }
+ else if (splitCommand[0] == "mon")
+ {
+ bool enable = splitCommand.Length > 1 ? splitCommand[1] == "1" : false;
+ Lib.SwitchMonitoring(enable);
+ }
+ else if (splitCommand[0] == "bl")
+ {
+ Lib.StartBootloader();
+ }
+ else if (splitCommand[0] == "lang")
+ {
+ if (splitCommand.Length > 1)
+ {
+ string language = Lib.GetDeviceMenuLanguage((CecLogicalAddress)byte.Parse(splitCommand[1], System.Globalization.NumberStyles.HexNumber));
+ Console.WriteLine("Menu language: " + language);
+ }
+ }
+ else if (splitCommand[0] == "ven")
+ {
+ if (splitCommand.Length > 1)
+ {
+ CecVendorId vendor = Lib.GetDeviceVendorId((CecLogicalAddress)byte.Parse(splitCommand[1], System.Globalization.NumberStyles.HexNumber));
+ Console.WriteLine("Vendor ID: " + Lib.ToString(vendor));
+ }
+ }
+ else if (splitCommand[0] == "ver")
+ {
+ if (splitCommand.Length > 1)
+ {
+ CecVersion version = Lib.GetDeviceCecVersion((CecLogicalAddress)byte.Parse(splitCommand[1], System.Globalization.NumberStyles.HexNumber));
+ Console.WriteLine("CEC version: " + Lib.ToString(version));
+ }
+ }
+ else if (splitCommand[0] == "pow")
+ {
+ if (splitCommand.Length > 1)
+ {
+ CecPowerStatus power = Lib.GetDevicePowerStatus((CecLogicalAddress)byte.Parse(splitCommand[1], System.Globalization.NumberStyles.HexNumber));
+ Console.WriteLine("power status: " + Lib.ToString(power));
+ }
+ }
+ else if (splitCommand[0] == "r")
+ {
+ Console.WriteLine("closing the connection");
+ Lib.Close();
+ FlushLog();
+
+ Console.WriteLine("opening a new connection");
+ Connect(10000);
+ FlushLog();
+
+ Console.WriteLine("setting active source");
+ Lib.SetActiveSource(CecDeviceType.PlaybackDevice);
+ }
+ else if (splitCommand[0] == "scan")
+ {
+ Console.WriteLine("CEC bus information");
+ Console.WriteLine("===================");
+ CecLogicalAddresses addresses = Lib.GetActiveDevices();
+ for (int iPtr = 0; iPtr < addresses.Addresses.Count(); iPtr++)
+ {
+ CecLogicalAddress address = (CecLogicalAddress)iPtr;
+ if (!addresses.IsSet(address))
+ continue;
+
+ CecVendorId iVendorId = Lib.GetDeviceVendorId(address);
+ bool bActive = Lib.IsActiveDevice(address);
+ ushort iPhysicalAddress = Lib.GetDevicePhysicalAddress(address);
+ string strAddr = string.Format("{0,4:X}", iPhysicalAddress);
+ CecVersion iCecVersion = Lib.GetDeviceCecVersion(address);
+ CecPowerStatus power = Lib.GetDevicePowerStatus(address);
+ string osdName = Lib.GetDeviceOSDName(address);
+ string lang = Lib.GetDeviceMenuLanguage(address);
+
+ StringBuilder output = new StringBuilder();
+ output.AppendLine("device #" + iPtr + ": " + Lib.ToString(address));
+ output.AppendLine("address: " + strAddr);
+ output.AppendLine("active source: " + (bActive ? "yes" : "no"));
+ output.AppendLine("vendor: " + Lib.ToString(iVendorId));
+ output.AppendLine("osd string: " + osdName);
+ output.AppendLine("CEC version: " + Lib.ToString(iCecVersion));
+ output.AppendLine("power status: " + Lib.ToString(power));
+ if (!string.IsNullOrEmpty(lang))
+ output.AppendLine("language: " + lang);
+
+ Console.WriteLine(output.ToString());
+ }
+ }
+ else if (splitCommand[0] == "h" || splitCommand[0] == "help")
+ ShowConsoleHelp();
+ else if (splitCommand[0] == "q" || splitCommand[0] == "quit")
+ bContinue = false;
+ else if (splitCommand[0] == "log" && splitCommand.Length > 1)
+ LogLevel = int.Parse(splitCommand[1]);
+ }
+ }
+
+ static void Main(string[] args)
+ {
+ CecSharpClient p = new CecSharpClient();
+ if (p.Connect(10000))
+ {
+ p.MainLoop();
+ }
+ else
+ {
+ Console.WriteLine("Could not open a connection to the CEC adapter");
+ }
+ p.FlushLog();
+ }
+
+ private int LogLevel;
+ private LibCecSharp Lib;
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{47EF8EFE-5758-4E82-B9BA-F9B002F9C0D4}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>CecSharpClient</RootNamespace>
+ <AssemblyName>CecSharpClient</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <TargetFrameworkProfile>Client</TargetFrameworkProfile>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+ <PlatformTarget>x86</PlatformTarget>
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>..\..\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+ <PlatformTarget>x86</PlatformTarget>
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="LibCecSharp, Version=1.0.4334.36379, Culture=neutral, processorArchitecture=x86">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\LibCecSharp.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="AssemblyInfo.cs" />
+ <Compile Include="CecSharpClient.cs" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
\ No newline at end of file
--- /dev/null
+#include "stdafx.h"
+
+using namespace System;
+using namespace System::Reflection;
+using namespace System::Runtime::CompilerServices;
+using namespace System::Runtime::InteropServices;
+using namespace System::Security::Permissions;
+
+//
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+//
+[assembly:AssemblyTitleAttribute("LibCecSharp")];
+[assembly:AssemblyDescriptionAttribute("")];
+[assembly:AssemblyConfigurationAttribute("")];
+[assembly:AssemblyCompanyAttribute("Pulse-Eight Ltd.")];
+[assembly:AssemblyProductAttribute("LibCecSharp")];
+[assembly:AssemblyCopyrightAttribute("Copyright (c) Pulse-Eight Ltd. 2011")];
+[assembly:AssemblyTrademarkAttribute("")];
+[assembly:AssemblyCultureAttribute("")];
+
+//
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the value or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+
+[assembly:AssemblyVersionAttribute("1.0.*")];
+
+[assembly:ComVisible(false)];
+
+[assembly:CLSCompliantAttribute(true)];
+
+[assembly:SecurityPermission(SecurityAction::RequestMinimum, UnmanagedCode = true)];
--- /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 "stdafx.h"
+#include <windows.h>
+#include <vcclr.h>
+#include <msclr/marshal.h>
+#include <cec.h>
+#using <System.dll>
+
+using namespace System;
+using namespace CEC;
+using namespace msclr::interop;
+
+public enum class CecDeviceType
+{
+ Tv = 0,
+ RecordingDevice = 1,
+ Reserved = 2,
+ Tuner = 3,
+ PlaybackDevice = 4,
+ AudioSystem = 5
+};
+
+public enum class CecLogLevel
+{
+ None = 0,
+ Error = 1,
+ Warning = 2,
+ Notice = 4,
+ Traffic = 8,
+ Debug = 16,
+ All = 31
+};
+
+public enum class CecLogicalAddress
+{
+ Unknown = -1, //not a valid logical address
+ Tv = 0,
+ RecordingDevice1 = 1,
+ RecordingDevice2 = 2,
+ Tuner1 = 3,
+ PlaybackDevice1 = 4,
+ AudioSystem = 5,
+ Tuner2 = 6,
+ Tuner3 = 7,
+ PlaybackDevice2 = 8,
+ RecordingDevice3 = 9,
+ Tuner4 = 10,
+ PlaybackDevice3 = 11,
+ Reserved1 = 12,
+ Reserved2 = 13,
+ FreeUse = 14,
+ Unregistered = 15,
+ Broadcast = 15
+};
+
+public enum class CecPowerStatus
+{
+ On = 0x00,
+ Standby = 0x01,
+ InTransitionStandbyToOn = 0x02,
+ InTransitionOnToStandby = 0x03,
+ Unknown = 0x99
+};
+
+public enum class CecVersion
+{
+ Unknown = 0x00,
+ V1_2 = 0x01,
+ V1_2A = 0x02,
+ V1_3 = 0x03,
+ V1_3A = 0x04,
+ V1_4 = 0x05
+};
+
+public enum class CecDisplayControl
+{
+ DisplayForDefaultTime = 0x00,
+ DisplayUntilCleared = 0x40,
+ ClearPreviousMessage = 0x80,
+ ReservedForFutureUse = 0xC0
+};
+
+public enum class CecMenuState
+{
+ Activated = 0,
+ Deactivated = 1
+};
+
+public enum class CecDeckControlMode
+{
+ SkipForwardWind = 1,
+ SkipReverseRewind = 2,
+ Stop = 3,
+ Eject = 4
+};
+
+public enum class CecDeckInfo
+{
+ Play = 0x11,
+ Record = 0x12,
+ Reverse = 0x13,
+ Still = 0x14,
+ Slow = 0x15,
+ SlowReverse = 0x16,
+ FastForward = 0x17,
+ FastReverse = 0x18,
+ NoMedia = 0x19,
+ Stop = 0x1A,
+ SkipForwardWind = 0x1B,
+ SkipReverseRewind = 0x1C,
+ IndexSearchForward = 0x1D,
+ IndexSearchReverse = 0x1E,
+ OtherStatus = 0x1F
+};
+
+public enum class CecUserControlCode
+{
+ Select = 0x00,
+ Up = 0x01,
+ Down = 0x02,
+ Left = 0x03,
+ Right = 0x04,
+ RightUp = 0x05,
+ RightDown = 0x06,
+ LeftUp = 0x07,
+ LeftDown = 0x08,
+ RootMenu = 0x09,
+ SetupMenu = 0x0A,
+ ContentsMenu = 0x0B,
+ FavoriteMenu = 0x0C,
+ Exit = 0x0D,
+ Number0 = 0x20,
+ Number1 = 0x21,
+ Number2 = 0x22,
+ Number3 = 0x23,
+ Number4 = 0x24,
+ Number5 = 0x25,
+ Number6 = 0x26,
+ Number7 = 0x27,
+ Number8 = 0x28,
+ Number9 = 0x29,
+ Dot = 0x2A,
+ Enter = 0x2B,
+ Clear = 0x2C,
+ NextFavorite = 0x2F,
+ ChannelUp = 0x30,
+ ChannelDown = 0x31,
+ PreviousChannel = 0x32,
+ SoundSelect = 0x33,
+ InputSelect = 0x34,
+ DisplayInformation = 0x35,
+ Help = 0x36,
+ PageUp = 0x37,
+ PageDown = 0x38,
+ Power = 0x40,
+ VolumeUp = 0x41,
+ VolumeDown = 0x42,
+ Mute = 0x43,
+ Play = 0x44,
+ Stop = 0x45,
+ Pause = 0x46,
+ Record = 0x47,
+ Rewind = 0x48,
+ FastForward = 0x49,
+ Eject = 0x4A,
+ Forward = 0x4B,
+ Backward = 0x4C,
+ StopRecord = 0x4D,
+ PauseRecord = 0x4E,
+ Angle = 0x50,
+ SubPicture = 0x51,
+ VideoOnDemand = 0x52,
+ ElectronicProgramGuide = 0x53,
+ TimerProgramming = 0x54,
+ InitialConfiguration = 0x55,
+ PlayFunction = 0x60,
+ PausePlayFunction = 0x61,
+ RecordFunction = 0x62,
+ PauseRecordFunction = 0x63,
+ StopFunction = 0x64,
+ MuteFunction = 0x65,
+ RestoreVolumeFunction = 0x66,
+ TuneFunction = 0x67,
+ SelectMediaFunction = 0x68,
+ SelectAVInputFunction = 0x69,
+ SelectAudioInputFunction = 0x6A,
+ PowerToggleFunction = 0x6B,
+ PowerOffFunction = 0x6C,
+ PowerOnFunction = 0x6D,
+ F1Blue = 0x71,
+ F2Red = 0X72,
+ F3Green = 0x73,
+ F4Yellow = 0x74,
+ F5 = 0x75,
+ Data = 0x76,
+ Max = 0x76,
+ Unknown
+};
+
+public enum class CecVendorId
+{
+ Samsung = 0x00F0,
+ LG = 0xE091,
+ Panasonic = 0x8045,
+ Pioneer = 0xE036,
+ Onkyo = 0x09B0,
+ Yamaha = 0xA0DE,
+ Philips = 0x903E,
+ Unknown = 0
+};
+
+public enum class CecAudioStatus
+{
+ MuteStatusMask = 0x80,
+ VolumeStatusMask = 0x7F,
+ VolumeMin = 0x00,
+ VolumeMax = 0x64,
+ VolumeStatusUnknown = 0x7F
+};
+
+public enum class CecOpcode
+{
+ ActiveSource = 0x82,
+ ImageViewOn = 0x04,
+ TextViewOn = 0x0D,
+ InactiveSource = 0x9D,
+ RequestActiveSource = 0x85,
+ RoutingChange = 0x80,
+ RoutingInformation = 0x81,
+ SetStreamPath = 0x86,
+ Standby = 0x36,
+ RecordOff = 0x0B,
+ RecordOn = 0x09,
+ RecordStatus = 0x0A,
+ RecordTvScreen = 0x0F,
+ ClearAnalogueTimer = 0x33,
+ ClearDigitalTimer = 0x99,
+ ClearExternalTimer = 0xA1,
+ SetAnalogueTimer = 0x34,
+ SetDigitalTimer = 0x97,
+ SetExternalTimer = 0xA2,
+ SetTimerProgramTitle = 0x67,
+ TimerClearedStatus = 0x43,
+ TimerStatus = 0x35,
+ CecVersion = 0x9E,
+ GetCecVersion = 0x9F,
+ GivePhysicalAddress = 0x83,
+ GetMenuLanguage = 0x91,
+ ReportPhysicalAddress = 0x84,
+ SetMenuLanguage = 0x32,
+ DeckControl = 0x42,
+ DeckStatus = 0x1B,
+ GiveDeckStatus = 0x1A,
+ Play = 0x41,
+ GiveTunerDeviceStatus = 0x08,
+ SelectAnalogueService = 0x92,
+ SelectDigtalService = 0x93,
+ TunerDeviceStatus = 0x07,
+ TunerStepDecrement = 0x06,
+ TunerStepIncrement = 0x05,
+ DeviceVendorId = 0x87,
+ GiveDeviceVendorId = 0x8C,
+ VendorCommand = 0x89,
+ VendorCommandWithId = 0xA0,
+ VendorRemoteButtonDown = 0x8A,
+ VendorRemoteButtonUp = 0x8B,
+ SetOsdString = 0x64,
+ GiveOsdName = 0x46,
+ SetOsdName = 0x47,
+ MenuRequest = 0x8D,
+ MenuStatus = 0x8E,
+ UserControlPressed = 0x44,
+ UserControlRelease = 0x45,
+ GiveDevicePowerStatus = 0x8F,
+ ReportPowerStatus = 0x90,
+ FeatureAbort = 0x00,
+ Abort = 0xFF,
+ GiveAudioStatus = 0x71,
+ GiveSystemAudioMode = 0x7D,
+ ReportAudioStatus = 0x7A,
+ SetSystemAudioMode = 0x72,
+ SystemAudioModeRequest = 0x70,
+ SystemAudioModeStatus = 0x7E,
+ SetAudioRate = 0x9A,
+ /* when this opcode is set, no opcode will be sent to the device. this is one of the reserved numbers */
+ None = 0xFD
+};
+
+public enum class CecSystemAudioStatus
+{
+ Off = 0,
+ On = 1
+};
+
+public ref class CecAdapter
+{
+public:
+ CecAdapter(String ^ strPath, String ^ strComPort)
+ {
+ Path = strPath;
+ ComPort = strComPort;
+ }
+
+ property String ^ Path;
+ property String ^ ComPort;
+};
+
+public ref class CecDeviceTypeList
+{
+public:
+ CecDeviceTypeList(void)
+ {
+ Types = gcnew array<CecDeviceType>(5);
+ for (unsigned int iPtr = 0; iPtr < 5; iPtr++)
+ Types[iPtr] = CecDeviceType::Reserved;
+ }
+
+ property array<CecDeviceType> ^ Types;
+};
+
+public ref class CecLogicalAddresses
+{
+public:
+ CecLogicalAddresses(void)
+ {
+ Addresses = gcnew array<CecLogicalAddress>(16);
+ for (unsigned int iPtr = 0; iPtr < 16; iPtr++)
+ Addresses[iPtr] = CecLogicalAddress::Unregistered;
+ }
+
+ bool IsSet(CecLogicalAddress iAddress)
+ {
+ return Addresses[(unsigned int)iAddress] != CecLogicalAddress::Unregistered;
+ }
+
+ property array<CecLogicalAddress> ^ Addresses;
+};
+
+public ref class CecDatapacket
+{
+public:
+ CecDatapacket(void)
+ {
+ Data = gcnew array<uint8_t>(100);
+ Size = 0;
+ }
+
+ void PushBack(uint8_t data)
+ {
+ if (Size < 100)
+ {
+ Data[Size] = data;
+ Size++;
+ }
+ }
+
+ property array<uint8_t> ^ Data;
+ property uint8_t Size;
+};
+
+public ref class CecCommand
+{
+public:
+ CecCommand(CecLogicalAddress iInitiator, CecLogicalAddress iDestination, bool bAck, bool bEom, CecOpcode iOpcode, int32_t iTransmitTimeout)
+ {
+ Initiator = iInitiator;
+ Destination = iDestination;
+ Ack = bAck;
+ Eom = bEom;
+ Opcode = iOpcode;
+ OpcodeSet = true;
+ TransmitTimeout = iTransmitTimeout;
+ Parameters = gcnew CecDatapacket;
+ Empty = false;
+ }
+
+ CecCommand(void)
+ {
+ Initiator = CecLogicalAddress::Unknown;
+ Destination = CecLogicalAddress::Unknown;
+ Ack = false;
+ Eom = false;
+ Opcode = CecOpcode::None;
+ OpcodeSet = false;
+ TransmitTimeout = 0;
+ Parameters = gcnew CecDatapacket;
+ Empty = true;
+ }
+
+ void PushBack(uint8_t data)
+ {
+ if (Initiator == CecLogicalAddress::Unknown && Destination == CecLogicalAddress::Unknown)
+ {
+ Initiator = (CecLogicalAddress) (data >> 4);
+ Destination = (CecLogicalAddress) (data & 0xF);
+ }
+ else if (!OpcodeSet)
+ {
+ OpcodeSet = true;
+ Opcode = (CecOpcode)data;
+ }
+ else
+ {
+ Parameters->PushBack(data);
+ }
+ }
+
+ property bool Empty;
+ property CecLogicalAddress Initiator;
+ property CecLogicalAddress Destination;
+ property bool Ack;
+ property bool Eom;
+ property CecOpcode Opcode;
+ property CecDatapacket ^ Parameters;
+ property bool OpcodeSet;
+ property int32_t TransmitTimeout;
+};
+
+public ref class CecKeypress
+{
+public:
+ CecKeypress(int iKeycode, unsigned int iDuration)
+ {
+ Keycode = iKeycode;
+ Duration = iDuration;
+ Empty = false;
+ }
+
+ CecKeypress(void)
+ {
+ Keycode = 0;
+ Duration = 0;
+ Empty = true;
+ }
+
+ property bool Empty;
+ property int Keycode;
+ property unsigned int Duration;
+};
+
+public ref class CecLogMessage
+{
+public:
+ CecLogMessage(String ^ strMessage, CecLogLevel iLevel, int64_t iTime)
+ {
+ Message = strMessage;
+ Level = iLevel;
+ Time = iTime;
+ Empty = false;
+ }
+
+ CecLogMessage(void)
+ {
+ Message = "";
+ Level = CecLogLevel::None;
+ Time = 0;
+ Empty = true;
+ }
+
+ property bool Empty;
+ property String ^ Message;
+ property CecLogLevel Level;
+ property int64_t Time;
+};
+
+public ref class LibCecSharp
+{
+public:
+ LibCecSharp(String ^ strDeviceName, CecDeviceTypeList ^ deviceTypes)
+ {
+ marshal_context ^ context = gcnew marshal_context();
+
+ const char* strDeviceNameC = context->marshal_as<const char*>(strDeviceName);
+
+ cec_device_type_list types;
+ for (unsigned int iPtr = 0; iPtr < 5; iPtr++)
+ types.types[iPtr] = (cec_device_type)deviceTypes->Types[iPtr];
+ m_libCec = (ICECAdapter *) CECInit(strDeviceNameC, types);
+ delete context;
+ }
+
+ ~LibCecSharp(void)
+ {
+ CECDestroy(m_libCec);
+ m_libCec = NULL;
+ }
+
+protected:
+ !LibCecSharp(void)
+ {
+ CECDestroy(m_libCec);
+ m_libCec = NULL;
+ }
+
+public:
+ array<CecAdapter ^> ^ FindAdapters(String ^ path)
+ {
+ cec_adapter *devices = new cec_adapter[10];
+
+ marshal_context ^ context = gcnew marshal_context();
+ const char* strPathC = path->Length > 0 ? context->marshal_as<const char*>(path) : NULL;
+
+ uint8_t iDevicesFound = m_libCec->FindAdapters(devices, 10, NULL);
+
+ array<CecAdapter ^> ^ adapters = gcnew array<CecAdapter ^>(iDevicesFound);
+ for (unsigned int iPtr = 0; iPtr < iDevicesFound; iPtr++)
+ adapters[iPtr] = gcnew CecAdapter(gcnew String(devices[iPtr].path), gcnew String(devices[iPtr].comm));
+
+ delete devices;
+ delete context;
+ return adapters;
+ }
+
+ bool Open(String ^ strPort, int iTimeoutMs)
+ {
+ marshal_context ^ context = gcnew marshal_context();
+ const char* strPortC = context->marshal_as<const char*>(strPort);
+ bool bReturn = m_libCec->Open(strPortC, iTimeoutMs);
+ delete context;
+ return bReturn;
+ }
+
+ void Close(void)
+ {
+ m_libCec->Close();
+ }
+
+ bool PingAdapter(void)
+ {
+ return m_libCec->PingAdapter();
+ }
+
+ bool StartBootloader(void)
+ {
+ return m_libCec->StartBootloader();
+ }
+
+ int GetMinLibVersion(void)
+ {
+ return m_libCec->GetMinLibVersion();
+ }
+
+ int GetLibVersionMajor(void)
+ {
+ return m_libCec->GetLibVersionMajor();
+ }
+
+ int GetLibVersionMinor(void)
+ {
+ return m_libCec->GetLibVersionMinor();
+ }
+
+ CecLogMessage ^ GetNextLogMessage(void)
+ {
+ cec_log_message msg;
+ if (m_libCec->GetNextLogMessage(&msg))
+ {
+ return gcnew CecLogMessage(gcnew String(msg.message), (CecLogLevel)msg.level, msg.time);
+ }
+
+ return gcnew CecLogMessage();
+ }
+
+ CecKeypress ^ GetNextKeypress(void)
+ {
+ cec_keypress key;
+ if (m_libCec->GetNextKeypress(&key))
+ {
+ return gcnew CecKeypress(key.keycode, key.duration);
+ }
+
+ return gcnew CecKeypress();
+ }
+
+ CecCommand ^ GetNextCommand(void)
+ {
+ cec_command command;
+ if (m_libCec->GetNextCommand(&command))
+ {
+ CecCommand ^ retVal = gcnew CecCommand((CecLogicalAddress)command.initiator, (CecLogicalAddress)command.destination, command.ack == 1 ? true : false, command.eom == 1 ? true : false, (CecOpcode)command.opcode, command.transmit_timeout);
+ for (uint8_t iPtr = 0; iPtr < command.parameters.size; iPtr++)
+ retVal->Parameters->PushBack(command.parameters[iPtr]);
+ return retVal;
+ }
+
+ return gcnew CecCommand();
+ }
+
+ bool Transmit(CecCommand ^ command)
+ {
+ cec_command ccommand;
+ cec_command::Format(ccommand, (cec_logical_address)command->Initiator, (cec_logical_address)command->Destination, (cec_opcode)command->Opcode);
+ ccommand.transmit_timeout = command->TransmitTimeout;
+ ccommand.eom = command->Eom;
+ ccommand.ack = command->Ack;
+ for (unsigned int iPtr = 0; iPtr < command->Parameters->Size; iPtr++)
+ ccommand.parameters.PushBack(command->Parameters->Data[iPtr]);
+
+ return m_libCec->Transmit(ccommand);
+ }
+
+ bool SetLogicalAddress(CecLogicalAddress logicalAddress)
+ {
+ return m_libCec->SetLogicalAddress((cec_logical_address) logicalAddress);
+ }
+
+ bool SetPhysicalAddress(int16_t physicalAddress)
+ {
+ return m_libCec->SetPhysicalAddress(physicalAddress);
+ }
+
+ bool PowerOnDevices(CecLogicalAddress logicalAddress)
+ {
+ return m_libCec->PowerOnDevices((cec_logical_address) logicalAddress);
+ }
+
+ bool StandbyDevices(CecLogicalAddress logicalAddress)
+ {
+ return m_libCec->StandbyDevices((cec_logical_address) logicalAddress);
+ }
+
+ bool PollDevice(CecLogicalAddress logicalAddress)
+ {
+ return m_libCec->PollDevice((cec_logical_address) logicalAddress);
+ }
+
+ bool SetActiveSource(CecDeviceType type)
+ {
+ return m_libCec->SetActiveSource((cec_device_type) type);
+ }
+
+ bool SetDeckControlMode(CecDeckControlMode mode, bool sendUpdate)
+ {
+ return m_libCec->SetDeckControlMode((cec_deck_control_mode) mode, sendUpdate);
+ }
+
+ bool SetDeckInfo(CecDeckInfo info, bool sendUpdate)
+ {
+ return m_libCec->SetDeckInfo((cec_deck_info) info, sendUpdate);
+ }
+
+ bool SetInactiveView(void)
+ {
+ return m_libCec->SetInactiveView();
+ }
+
+ bool SetMenuState(CecMenuState state, bool sendUpdate)
+ {
+ return m_libCec->SetMenuState((cec_menu_state) state, sendUpdate);
+ }
+
+ bool SetOSDString(CecLogicalAddress logicalAddress, CecDisplayControl duration, String ^ message)
+ {
+ marshal_context ^ context = gcnew marshal_context();
+ const char* strMessageC = context->marshal_as<const char*>(message);
+
+ bool bReturn = m_libCec->SetOSDString((cec_logical_address) logicalAddress, (cec_display_control) duration, strMessageC);
+
+ delete context;
+ return bReturn;
+ }
+
+ bool SwitchMonitoring(bool enable)
+ {
+ return m_libCec->SwitchMonitoring(enable);
+ }
+
+ CecVersion GetDeviceCecVersion(CecLogicalAddress logicalAddress)
+ {
+ return (CecVersion) m_libCec->GetDeviceCecVersion((cec_logical_address) logicalAddress);
+ }
+
+ String ^ GetDeviceMenuLanguage(CecLogicalAddress logicalAddress)
+ {
+ cec_menu_language lang;
+ if (m_libCec->GetDeviceMenuLanguage((cec_logical_address) logicalAddress, &lang))
+ {
+ return gcnew String(lang.language);
+ }
+
+ return gcnew String("");
+ }
+
+ CecVendorId GetDeviceVendorId(CecLogicalAddress logicalAddress)
+ {
+ return (CecVendorId)m_libCec->GetDeviceVendorId((cec_logical_address) logicalAddress);
+ }
+
+ CecPowerStatus GetDevicePowerStatus(CecLogicalAddress logicalAddress)
+ {
+ return (CecPowerStatus) m_libCec->GetDevicePowerStatus((cec_logical_address) logicalAddress);
+ }
+
+ CecLogicalAddresses ^ GetActiveDevices(void)
+ {
+ CecLogicalAddresses ^ retVal = gcnew CecLogicalAddresses();
+ unsigned int iDevices = 0;
+
+ cec_logical_addresses activeDevices = m_libCec->GetActiveDevices();
+
+ for (uint8_t iPtr = 0; iPtr < 16; iPtr++)
+ if (activeDevices[iPtr])
+ retVal->Addresses[iDevices++] = (CecLogicalAddress)iPtr;
+
+ return retVal;
+ }
+
+ bool IsActiveDevice(CecLogicalAddress logicalAddress)
+ {
+ return m_libCec->IsActiveDevice((cec_logical_address)logicalAddress);
+ }
+
+ bool IsActiveDeviceType(CecDeviceType type)
+ {
+ return m_libCec->IsActiveDeviceType((cec_device_type)type);
+ }
+
+ bool SetHDMIPort(CecLogicalAddress address, uint8_t port)
+ {
+ return m_libCec->SetHDMIPort((cec_logical_address)address, port);
+ }
+
+ uint8_t VolumeUp(bool wait)
+ {
+ return m_libCec->VolumeUp(wait);
+ }
+
+ uint8_t VolumeDown(bool wait)
+ {
+ return m_libCec->VolumeDown(wait);
+ }
+
+ uint8_t MuteAudio(bool wait)
+ {
+ return m_libCec->MuteAudio(wait);
+ }
+
+ bool SendKeypress(CecLogicalAddress destination, CecUserControlCode key, bool wait)
+ {
+ return m_libCec->SendKeypress((cec_logical_address)destination, (cec_user_control_code)key, wait);
+ }
+
+ bool SendKeyRelease(CecLogicalAddress destination, bool wait)
+ {
+ return m_libCec->SendKeyRelease((cec_logical_address)destination, wait);
+ }
+
+ String ^ GetDeviceOSDName(CecLogicalAddress logicalAddress)
+ {
+ cec_osd_name osd = m_libCec->GetDeviceOSDName((cec_logical_address) logicalAddress);
+ return gcnew String(osd.name);
+ }
+
+ CecLogicalAddress GetActiveSource()
+ {
+ return (CecLogicalAddress)m_libCec->GetActiveSource();
+ }
+
+ bool IsActiveSource(CecLogicalAddress logicalAddress)
+ {
+ return m_libCec->IsActiveSource((cec_logical_address)logicalAddress);
+ }
+
+ uint16_t GetDevicePhysicalAddress(CecLogicalAddress iAddress)
+ {
+ return m_libCec->GetDevicePhysicalAddress((cec_logical_address)iAddress);
+ }
+
+ String ^ ToString(CecLogicalAddress iAddress)
+ {
+ const char *retVal = m_libCec->ToString((cec_logical_address)iAddress);
+ return gcnew String(retVal);
+ }
+
+ String ^ ToString(CecVendorId iVendorId)
+ {
+ const char *retVal = m_libCec->ToString((cec_vendor_id)iVendorId);
+ return gcnew String(retVal);
+ }
+
+ String ^ ToString(CecVersion iVersion)
+ {
+ const char *retVal = m_libCec->ToString((cec_version)iVersion);
+ return gcnew String(retVal);
+ }
+
+ String ^ ToString(CecPowerStatus iState)
+ {
+ const char *retVal = m_libCec->ToString((cec_power_status)iState);
+ return gcnew String(retVal);
+ }
+
+ String ^ ToString(CecMenuState iState)
+ {
+ const char *retVal = m_libCec->ToString((cec_menu_state)iState);
+ return gcnew String(retVal);
+ }
+
+ String ^ ToString(CecDeckControlMode iMode)
+ {
+ const char *retVal = m_libCec->ToString((cec_deck_control_mode)iMode);
+ return gcnew String(retVal);
+ }
+
+ String ^ ToString(CecDeckInfo status)
+ {
+ const char *retVal = m_libCec->ToString((cec_deck_info)status);
+ return gcnew String(retVal);
+ }
+
+ String ^ ToString(CecOpcode opcode)
+ {
+ const char *retVal = m_libCec->ToString((cec_opcode)opcode);
+ return gcnew String(retVal);
+ }
+
+ String ^ ToString(CecSystemAudioStatus mode)
+ {
+ const char *retVal = m_libCec->ToString((cec_system_audio_status)mode);
+ return gcnew String(retVal);
+ }
+
+ String ^ ToString(CecAudioStatus status)
+ {
+ const char *retVal = m_libCec->ToString((cec_audio_status)status);
+ return gcnew String(retVal);
+ }
+
+private:
+ ICECAdapter *m_libCec;
+};
--- /dev/null
+// stdafx.cpp : source file that includes just the standard includes
+// LibCecSharp.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
--- /dev/null
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently,
+// but are changed infrequently
+
+#pragma once
+
+
--- /dev/null
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by app.rc
#include "AdapterCommunication.h"
-#include "LibCEC.h"
+#include "CECProcessor.h"
#include "platform/serialport.h"
#include "util/StdString.h"
#include "platform/timeutils.h"
if (command.opcode_set == 1)
{
push_back(MSGSTART);
- push_escaped(command.parameters.empty() ? (uint8_t)MSGCODE_TRANSMIT_EOM : (uint8_t)MSGCODE_TRANSMIT);
+ push_escaped(command.parameters.IsEmpty() ? (uint8_t)MSGCODE_TRANSMIT_EOM : (uint8_t)MSGCODE_TRANSMIT);
push_back((uint8_t) command.opcode);
push_back(MSGEND);
CStdString CCECAdapterMessage::ToString(void) const
{
CStdString strMsg;
- strMsg = MessageCodeAsString();
-
- switch (message())
+ if (size() == 0)
{
- case MSGCODE_TIMEOUT_ERROR:
- case MSGCODE_HIGH_ERROR:
- case MSGCODE_LOW_ERROR:
+ strMsg = "empty message";
+ }
+ else
+ {
+ strMsg = MessageCodeAsString();
+
+ switch (message())
{
- int iLine = (size() >= 3) ? (at(1) << 8) | at(2) : 0;
- uint32_t iTime = (size() >= 7) ? (at(3) << 24) | (at(4) << 16) | (at(5) << 8) | at(6) : 0;
- strMsg.AppendFormat(" line:%i", iLine);
- strMsg.AppendFormat(" time:%u", iTime);
+ case MSGCODE_TIMEOUT_ERROR:
+ case MSGCODE_HIGH_ERROR:
+ case MSGCODE_LOW_ERROR:
+ {
+ int iLine = (size() >= 3) ? (at(1) << 8) | at(2) : 0;
+ uint32_t iTime = (size() >= 7) ? (at(3) << 24) | (at(4) << 16) | (at(5) << 8) | at(6) : 0;
+ strMsg.AppendFormat(" line:%i", iLine);
+ strMsg.AppendFormat(" time:%u", iTime);
+ }
+ break;
+ case MSGCODE_FRAME_START:
+ if (size() >= 2)
+ strMsg.AppendFormat(" initiator:%1x destination:%1x ack:%s %s", initiator(), destination(), ack() ? "high" : "low", eom() ? "eom" : "");
+ break;
+ case MSGCODE_FRAME_DATA:
+ if (size() >= 2)
+ strMsg.AppendFormat(" %02x %s", at(1), eom() ? "eom" : "");
+ break;
+ default:
+ break;
}
- break;
- case MSGCODE_FRAME_START:
- if (size() >= 2)
- strMsg.AppendFormat(" initiator:%1x destination:%1x ack:%s %s", initiator(), destination(), ack() ? "high" : "low", eom() ? "eom" : "");
- break;
- case MSGCODE_FRAME_DATA:
- if (size() >= 2)
- strMsg.AppendFormat(" %02x %s", at(1), eom() ? "eom" : "");
- break;
- default:
- break;
}
return strMsg;
bool CCECAdapterMessage::is_error(void) const
{
cec_adapter_messagecode code = message();
- return (code == MSGCODE_TIMEOUT_ERROR ||
- code == MSGCODE_HIGH_ERROR ||
+ return (code == MSGCODE_HIGH_ERROR ||
code == MSGCODE_LOW_ERROR ||
code == MSGCODE_RECEIVE_FAILED ||
code == MSGCODE_COMMAND_REJECTED ||
- code == MSGCODE_TRANSMIT_LINE_TIMEOUT ||
+ code == MSGCODE_TRANSMIT_LINE_TIMEOUT ||
code == MSGCODE_TRANSMIT_FAILED_LINE ||
- code == MSGCODE_TRANSMIT_FAILED_ACK ||
+ code == MSGCODE_TRANSMIT_FAILED_ACK ||
code == MSGCODE_TRANSMIT_FAILED_TIMEOUT_DATA ||
code == MSGCODE_TRANSMIT_FAILED_TIMEOUT_LINE);
}
void CCECAdapterMessage::push_escaped(uint8_t byte)
{
- if (byte >= MSGESC && byte != MSGSTART)
+ if (byte >= MSGESC)
{
push_back(MSGESC);
push_back(byte - ESCOFFSET);
push_back(byte);
}
-CAdapterCommunication::CAdapterCommunication(CLibCEC *controller) :
+CAdapterCommunication::CAdapterCommunication(CCECProcessor *processor) :
m_port(NULL),
- m_controller(controller)
+ m_processor(processor),
+ m_iLineTimeout(0)
{
m_port = new CSerialPort;
}
CLockObject lock(&m_mutex);
if (!m_port)
{
- m_controller->AddLog(CEC_LOG_ERROR, "port is NULL");
+ m_processor->AddLog(CEC_LOG_ERROR, "port is NULL");
return false;
}
if (IsOpen())
{
- m_controller->AddLog(CEC_LOG_ERROR, "port is already open");
+ m_processor->AddLog(CEC_LOG_ERROR, "port is already open");
}
if (!m_port->Open(strPort, iBaudRate))
{
CStdString strError;
strError.Format("error opening serial port '%s': %s", strPort, m_port->GetError().c_str());
- m_controller->AddLog(CEC_LOG_ERROR, strError);
+ m_processor->AddLog(CEC_LOG_ERROR, strError);
return false;
}
- m_controller->AddLog(CEC_LOG_DEBUG, "connection opened");
+ m_processor->AddLog(CEC_LOG_DEBUG, "connection opened");
//clear any input bytes
- uint8_t buff[1024];
- m_port->Read(buff, sizeof(buff), 500);
+ uint8_t buff[1];
+ while (m_port->Read(buff, 1, 5) == 1) {}
if (CreateThread())
{
m_startCondition.Wait(&m_mutex);
- m_controller->AddLog(CEC_LOG_DEBUG, "communication thread started");
+ m_processor->AddLog(CEC_LOG_DEBUG, "communication thread started");
return true;
}
else
{
- m_controller->AddLog(CEC_LOG_DEBUG, "could not create a communication thread");
+ m_processor->AddLog(CEC_LOG_DEBUG, "could not create a communication thread");
}
return false;
while (!IsStopped())
{
- ReadFromDevice(500);
+ ReadFromDevice(50);
Sleep(5);
WriteNextCommand();
}
+ CCECAdapterMessage *msg;
+ if (m_outBuffer.Pop(msg))
+ msg->condition.Broadcast();
+
return NULL;
}
{
CStdString strError;
strError.Format("error reading from serial port: %s", m_port->GetError().c_str());
- m_controller->AddLog(CEC_LOG_ERROR, strError);
+ m_processor->AddLog(CEC_LOG_ERROR, strError);
return false;
}
else if (iBytesRead > 0)
{
CCECAdapterMessage *msg;
if (m_outBuffer.Pop(msg))
+ SendMessageToAdapter(msg);
+}
+
+void CAdapterCommunication::SendMessageToAdapter(CCECAdapterMessage *msg)
+{
+ CLockObject lock(&msg->mutex);
+ if (m_port->Write(msg) != (int32_t) msg->size())
{
- CLockObject lock(&msg->mutex);
- if (m_port->Write(msg) != (int32_t) msg->size())
- {
- CStdString strError;
- strError.Format("error writing to serial port: %s", m_port->GetError().c_str());
- m_controller->AddLog(CEC_LOG_ERROR, strError);
- msg->state = ADAPTER_MESSAGE_STATE_ERROR;
- }
- else
- {
- m_controller->AddLog(CEC_LOG_DEBUG, "command sent");
- CCondition::Sleep((uint32_t) msg->size() * 24 /*data*/ + 5 /*start bit (4.5 ms)*/ + 10);
- msg->state = ADAPTER_MESSAGE_STATE_SENT;
- }
- msg->condition.Signal();
+ CStdString strError;
+ strError.Format("error writing to serial port: %s", m_port->GetError().c_str());
+ m_processor->AddLog(CEC_LOG_ERROR, strError);
+ msg->state = ADAPTER_MESSAGE_STATE_ERROR;
}
+ else
+ {
+ m_processor->AddLog(CEC_LOG_DEBUG, "command sent");
+ msg->state = ADAPTER_MESSAGE_STATE_SENT;
+ }
+ msg->condition.Signal();
}
bool CAdapterCommunication::Write(CCECAdapterMessage *data)
}
else if (buf == MSGSTART) //we found a msgstart before msgend, this is not right, remove
{
- m_controller->AddLog(CEC_LOG_ERROR, "received MSGSTART before MSGEND");
+ if (msg.size() > 0)
+ m_processor->AddLog(CEC_LOG_WARNING, "received MSGSTART before MSGEND, removing previous buffer contents");
msg.clear();
bGotStart = true;
}
if (!IsRunning())
return bReturn;
- m_controller->AddLog(CEC_LOG_DEBUG, "starting the bootloader");
+ m_processor->AddLog(CEC_LOG_DEBUG, "starting the bootloader");
CCECAdapterMessage *output = new CCECAdapterMessage;
output->push_back(MSGSTART);
output->push_escaped(MSGCODE_START_BOOTLOADER);
output->push_back(MSGEND);
- if ((bReturn = Write(output)) == false)
- m_controller->AddLog(CEC_LOG_ERROR, "could not start the bootloader");
-
+ CLockObject lock(&output->mutex);
+ if (Write(output))
+ output->condition.Wait(&output->mutex);
+ bReturn = output->state == ADAPTER_MESSAGE_STATE_SENT;
delete output;
return bReturn;
if (!IsRunning())
return bReturn;
- m_controller->AddLog(CEC_LOG_DEBUG, "sending ping");
+ m_processor->AddLog(CEC_LOG_DEBUG, "sending ping");
CCECAdapterMessage *output = new CCECAdapterMessage;
output->push_back(MSGSTART);
output->push_escaped(MSGCODE_PING);
output->push_back(MSGEND);
- if ((bReturn = Write(output)) == false)
- m_controller->AddLog(CEC_LOG_ERROR, "could not send ping command");
-
- // TODO check for pong
+ CLockObject lock(&output->mutex);
+ if (Write(output))
+ output->condition.Wait(&output->mutex);
+ bReturn = output->state == ADAPTER_MESSAGE_STATE_SENT;
delete output;
return bReturn;
}
+bool CAdapterCommunication::SetLineTimeout(uint8_t iTimeout)
+{
+ bool bReturn(m_iLineTimeout != iTimeout);
+
+ if (!bReturn)
+ {
+ CCECAdapterMessage *output = new CCECAdapterMessage;
+
+ output->push_back(MSGSTART);
+ output->push_escaped(MSGCODE_TRANSMIT_IDLETIME);
+ output->push_escaped(iTimeout);
+ output->push_back(MSGEND);
+
+ if ((bReturn = Write(output)) == false)
+ m_processor->AddLog(CEC_LOG_ERROR, "could not set the idletime");
+ delete output;
+ }
+
+ return bReturn;
+}
+
bool CAdapterCommunication::IsOpen(void) const
{
return !IsStopped() && m_port->IsOpen() && IsRunning();
CStdString ToString(void) const;
CStdString MessageCodeAsString(void) const;
- bool empty(void) const { return packet.empty(); }
+ bool empty(void) const { return packet.IsEmpty(); }
uint8_t operator[](uint8_t pos) const { return packet[pos]; }
uint8_t at(uint8_t pos) const { return packet[pos]; }
uint8_t size(void) const { return packet.size; }
- void clear(void) { state = ADAPTER_MESSAGE_STATE_UNKNOWN; transmit_timeout = 0; packet.clear(); }
- void shift(uint8_t iShiftBy) { packet.shift(iShiftBy); }
- void push_back(uint8_t add) { packet.push_back(add); }
- cec_adapter_messagecode message(void) const { return packet.size >= 1 ? (cec_adapter_messagecode) (packet.at(0) & ~(MSGCODE_FRAME_EOM | MSGCODE_FRAME_ACK)) : MSGCODE_NOTHING; }
- bool eom(void) const { return packet.size >= 1 ? (packet.at(0) & MSGCODE_FRAME_EOM) != 0 : false; }
- bool ack(void) const { return packet.size >= 1 ? (packet.at(0) & MSGCODE_FRAME_ACK) != 0 : false; }
- cec_logical_address initiator(void) const { return packet.size >= 2 ? (cec_logical_address) (packet.at(1) >> 4) : CECDEVICE_UNKNOWN; };
- cec_logical_address destination(void) const { return packet.size >= 2 ? (cec_logical_address) (packet.at(1) & 0xF) : CECDEVICE_UNKNOWN; };
+ void clear(void) { state = ADAPTER_MESSAGE_STATE_UNKNOWN; transmit_timeout = 0; packet.Clear(); maxTries = CEC_DEFAULT_TRANSMIT_RETRIES + 1; tries = 0; reply = MSGCODE_NOTHING; }
+ void shift(uint8_t iShiftBy) { packet.Shift(iShiftBy); }
+ void push_back(uint8_t add) { packet.PushBack(add); }
+ cec_adapter_messagecode message(void) const { return packet.size >= 1 ? (cec_adapter_messagecode) (packet.At(0) & ~(MSGCODE_FRAME_EOM | MSGCODE_FRAME_ACK)) : MSGCODE_NOTHING; }
+ bool eom(void) const { return packet.size >= 1 ? (packet.At(0) & MSGCODE_FRAME_EOM) != 0 : false; }
+ bool ack(void) const { return packet.size >= 1 ? (packet.At(0) & MSGCODE_FRAME_ACK) != 0 : false; }
+ cec_logical_address initiator(void) const { return packet.size >= 2 ? (cec_logical_address) (packet.At(1) >> 4) : CECDEVICE_UNKNOWN; };
+ cec_logical_address destination(void) const { return packet.size >= 2 ? (cec_logical_address) (packet.At(1) & 0xF) : CECDEVICE_UNKNOWN; };
bool is_error(void) const;
void push_escaped(uint8_t byte);
+ bool needs_retry(void) const { return reply == MSGCODE_NOTHING ||
+ reply == MSGCODE_RECEIVE_FAILED ||
+ reply == MSGCODE_TIMEOUT_ERROR ||
+ reply == MSGCODE_TRANSMIT_FAILED_LINE ||
+ reply == MSGCODE_TRANSMIT_FAILED_TIMEOUT_DATA ||
+ reply == MSGCODE_TRANSMIT_FAILED_TIMEOUT_LINE ||
+ reply == MSGCODE_TRANSMIT_LINE_TIMEOUT; }
+ uint8_t maxTries;
+ uint8_t tries;
+ cec_adapter_messagecode reply;
cec_datapacket packet;
cec_adapter_message_state state;
int32_t transmit_timeout;
};
class CSerialPort;
- class CLibCEC;
+ class CCECProcessor;
class CAdapterCommunication : private CThread
{
public:
- CAdapterCommunication(CLibCEC *controller);
+ CAdapterCommunication(CCECProcessor *processor);
virtual ~CAdapterCommunication();
bool Open(const char *strPort, uint16_t iBaudRate = 38400, uint32_t iTimeoutMs = 10000);
void *Process(void);
+ bool SetLineTimeout(uint8_t iTimeout);
bool StartBootloader(void);
private:
+ void SendMessageToAdapter(CCECAdapterMessage *msg);
void WriteNextCommand(void);
void AddData(uint8_t *data, uint8_t iLen);
bool ReadFromDevice(uint32_t iTimeout);
CSerialPort * m_port;
- CLibCEC * m_controller;
+ CCECProcessor * m_processor;
CecBuffer<uint8_t> m_inBuffer;
CecBuffer<CCECAdapterMessage *> m_outBuffer;
CMutex m_mutex;
CCondition m_rcvCondition;
CCondition m_startCondition;
+ uint8_t m_iLineTimeout;
};
};
#include <IOKit/usb/IOUSBLib.h>
#include <IOKit/serial/IOSerialKeys.h>
#include <CoreFoundation/CoreFoundation.h>
-
-#elif !defined(__WINDOWS__)
-#include <dirent.h>
-#include <libudev.h>
-#include <poll.h>
-#else
+#elif defined(__WINDOWS__)
#include <setupapi.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 } };
+#elif defined(HAVE_LIBUDEV)
+#include <dirent.h>
+#include <libudev.h>
+#include <poll.h>
#endif
#define CEC_VID 0x2548
using namespace CEC;
using namespace std;
-#if !defined(__WINDOWS__)
+#if defined(HAVE_LIBUDEV)
bool TranslateComPort(CStdString &strString)
{
CStdString strTmp(strString);
}
IOObjectRelease(serialPortIterator);
}
-
-#elif !defined(__WINDOWS__)
+#elif defined(HAVE_LIBUDEV)
struct udev *udev;
if (!(udev = udev_new()))
return -1;
udev_enumerate_unref(enumerate);
udev_unref(udev);
-#else
+#elif defined(__WINDOWS__)
HDEVINFO hDevHandle;
DWORD required = 0, iMemberIndex = 0;
int nBufferSize = 0;
using namespace CEC;
using namespace std;
-CCECProcessor::CCECProcessor(CLibCEC *controller, CAdapterCommunication *serComm, const char *strDeviceName, cec_logical_address iLogicalAddress /* = CECDEVICE_PLAYBACKDEVICE1 */, uint16_t iPhysicalAddress /* = CEC_DEFAULT_PHYSICAL_ADDRESS*/) :
+CCECProcessor::CCECProcessor(CLibCEC *controller, const char *strDeviceName, cec_logical_address iLogicalAddress /* = CECDEVICE_PLAYBACKDEVICE1 */, uint16_t iPhysicalAddress /* = CEC_DEFAULT_PHYSICAL_ADDRESS*/) :
m_bStarted(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(serComm),
m_controller(controller),
- m_bMonitor(false)
+ m_bMonitor(false),
+ m_busScan(NULL),
+ m_iStandardLineTimeout(3),
+ m_iRetryLineTimeout(3),
+ m_iLastTransmission(0)
{
- m_logicalAddresses.clear();
- m_logicalAddresses.set(iLogicalAddress);
+ m_communication = new CAdapterCommunication(this);
+ m_logicalAddresses.Clear();
+ m_logicalAddresses.Set(iLogicalAddress);
m_types.clear();
for (int iPtr = 0; iPtr <= 16; iPtr++)
m_busDevices[iPtr] = new CCECBusDevice(this, (cec_logical_address) iPtr, iPtr == iLogicalAddress ? iPhysicalAddress : 0);
}
-CCECProcessor::CCECProcessor(CLibCEC *controller, CAdapterCommunication *serComm, const char *strDeviceName, const cec_device_type_list &types) :
+CCECProcessor::CCECProcessor(CLibCEC *controller, const char *strDeviceName, const cec_device_type_list &types) :
m_bStarted(false),
+ m_iHDMIPort(CEC_DEFAULT_HDMI_PORT),
+ m_iBaseDevice((cec_logical_address)CEC_DEFAULT_BASE_DEVICE),
m_strDeviceName(strDeviceName),
m_types(types),
- m_communication(serComm),
m_controller(controller),
- m_bMonitor(false)
+ m_bMonitor(false),
+ m_iStandardLineTimeout(3),
+ m_iRetryLineTimeout(3),
+ m_iLastTransmission(0)
{
- m_logicalAddresses.clear();
+ m_communication = new CAdapterCommunication(this);
+ m_logicalAddresses.Clear();
for (int iPtr = 0; iPtr < 16; iPtr++)
{
switch(iPtr)
CCECProcessor::~CCECProcessor(void)
{
+ m_bStarted = false;
m_startCondition.Broadcast();
StopThread();
+
+ delete m_communication;
m_communication = NULL;
m_controller = NULL;
for (unsigned int iPtr = 0; iPtr < 16; iPtr++)
delete m_busDevices[iPtr];
}
-bool CCECProcessor::Start(void)
+bool CCECProcessor::Start(const char *strPort, uint16_t iBaudRate /* = 38400 */, uint32_t iTimeoutMs /* = 10000 */)
{
CLockObject lock(&m_mutex);
- if (!m_communication || !m_communication->IsOpen())
+ if (!m_communication || m_communication->IsOpen())
+ {
+ m_controller->AddLog(CEC_LOG_ERROR, "connection already opened");
+ return false;
+ }
+
+ if (!m_communication->Open(strPort, iBaudRate, iTimeoutMs))
{
- m_controller->AddLog(CEC_LOG_ERROR, "connection is closed");
+ m_controller->AddLog(CEC_LOG_ERROR, "could not open a connection");
return false;
}
m_controller->AddLog(CEC_LOG_ERROR, "could not create a processor thread");
return false;
}
- return true;
- }
- else
- m_controller->AddLog(CEC_LOG_ERROR, "could not create a processor thread");
-
- return false;
-}
-bool CCECProcessor::TryLogicalAddress(cec_logical_address address, unsigned int iIndex)
-{
- const char *strLabel = CCECCommandHandler::ToString(address);
- CStdString strLog;
- strLog.Format("trying logical address '%s'", strLabel);
- AddLog(CEC_LOG_DEBUG, strLog);
+ lock.Leave();
- SetAckMask(0x1 << address);
- if (!m_busDevices[address]->TransmitPoll(address))
- {
- strLog.Format("using logical address '%s'", strLabel);
- AddLog(CEC_LOG_NOTICE, strLog);
+ m_busDevices[CECDEVICE_TV]->GetVendorId();
- /* only set our OSD name and active source for the primary device */
- if (m_logicalAddresses.empty())
+ if (SetHDMIPort(m_iBaseDevice, m_iHDMIPort, true))
{
- m_busDevices[address]->m_strDeviceName = m_strDeviceName;
- m_busDevices[address]->m_bActiveSource = true;
+ m_controller->AddLog(CEC_LOG_DEBUG, "processor thread started");
+ m_busScan = new CCECBusScan(this);
+ m_busScan->CreateThread(true);
+ return true;
}
- m_busDevices[address]->m_powerStatus = CEC_POWER_STATUS_STANDBY;
- m_busDevices[address]->m_cecVersion = CEC_VERSION_1_3A;
-
- m_logicalAddresses.set(address);
+ else
+ {
+ m_controller->AddLog(CEC_LOG_ERROR, "failed to initialise the processor");
+ }
+ }
- // TODO
- m_busDevices[address]->SetPhysicalAddress((uint16_t)CEC_DEFAULT_PHYSICAL_ADDRESS + ((uint16_t)iIndex * 0x100));
+ m_controller->AddLog(CEC_LOG_ERROR, "could not create a processor thread");
+ return false;
+}
+bool CCECProcessor::TryLogicalAddress(cec_logical_address address)
+{
+ if (m_busDevices[address]->TryLogicalAddress())
+ {
+ m_logicalAddresses.Set(address);
return true;
}
- strLog.Format("logical address '%s' already taken", strLabel);
- AddLog(CEC_LOG_DEBUG, strLog);
return false;
}
-bool CCECProcessor::FindLogicalAddressRecordingDevice(unsigned int iIndex)
+bool CCECProcessor::FindLogicalAddressRecordingDevice(void)
{
AddLog(CEC_LOG_DEBUG, "detecting logical address for type 'recording device'");
- return TryLogicalAddress(CECDEVICE_RECORDINGDEVICE1, iIndex) ||
- TryLogicalAddress(CECDEVICE_RECORDINGDEVICE2, iIndex) ||
- TryLogicalAddress(CECDEVICE_RECORDINGDEVICE3, iIndex);
+ return TryLogicalAddress(CECDEVICE_RECORDINGDEVICE1) ||
+ TryLogicalAddress(CECDEVICE_RECORDINGDEVICE2) ||
+ TryLogicalAddress(CECDEVICE_RECORDINGDEVICE3);
}
-bool CCECProcessor::FindLogicalAddressTuner(unsigned int iIndex)
+bool CCECProcessor::FindLogicalAddressTuner(void)
{
AddLog(CEC_LOG_DEBUG, "detecting logical address for type 'tuner'");
- return TryLogicalAddress(CECDEVICE_TUNER1, iIndex) ||
- TryLogicalAddress(CECDEVICE_TUNER2, iIndex) ||
- TryLogicalAddress(CECDEVICE_TUNER3, iIndex) ||
- TryLogicalAddress(CECDEVICE_TUNER4, iIndex);
+ return TryLogicalAddress(CECDEVICE_TUNER1) ||
+ TryLogicalAddress(CECDEVICE_TUNER2) ||
+ TryLogicalAddress(CECDEVICE_TUNER3) ||
+ TryLogicalAddress(CECDEVICE_TUNER4);
}
-bool CCECProcessor::FindLogicalAddressPlaybackDevice(unsigned int iIndex)
+bool CCECProcessor::FindLogicalAddressPlaybackDevice(void)
{
AddLog(CEC_LOG_DEBUG, "detecting logical address for type 'playback device'");
- return TryLogicalAddress(CECDEVICE_PLAYBACKDEVICE1, iIndex) ||
- TryLogicalAddress(CECDEVICE_PLAYBACKDEVICE2, iIndex) ||
- TryLogicalAddress(CECDEVICE_PLAYBACKDEVICE3, iIndex);
+ return TryLogicalAddress(CECDEVICE_PLAYBACKDEVICE1) ||
+ TryLogicalAddress(CECDEVICE_PLAYBACKDEVICE2) ||
+ TryLogicalAddress(CECDEVICE_PLAYBACKDEVICE3);
}
-bool CCECProcessor::FindLogicalAddressAudioSystem(unsigned int iIndex)
+bool CCECProcessor::FindLogicalAddressAudioSystem(void)
{
AddLog(CEC_LOG_DEBUG, "detecting logical address for type 'audio'");
- return TryLogicalAddress(CECDEVICE_AUDIOSYSTEM, iIndex);
+ return TryLogicalAddress(CECDEVICE_AUDIOSYSTEM);
}
bool CCECProcessor::FindLogicalAddresses(void)
{
bool bReturn(true);
- m_logicalAddresses.clear();
+ m_logicalAddresses.Clear();
CStdString strLog;
for (unsigned int iPtr = 0; iPtr < 5; iPtr++)
AddLog(CEC_LOG_DEBUG, strLog);
if (m_types.types[iPtr] == CEC_DEVICE_TYPE_RECORDING_DEVICE)
- bReturn &= FindLogicalAddressRecordingDevice(iPtr);
+ bReturn &= FindLogicalAddressRecordingDevice();
if (m_types.types[iPtr] == CEC_DEVICE_TYPE_TUNER)
- bReturn &= FindLogicalAddressTuner(iPtr);
+ bReturn &= FindLogicalAddressTuner();
if (m_types.types[iPtr] == CEC_DEVICE_TYPE_PLAYBACK_DEVICE)
- bReturn &= FindLogicalAddressPlaybackDevice(iPtr);
+ bReturn &= FindLogicalAddressPlaybackDevice();
if (m_types.types[iPtr] == CEC_DEVICE_TYPE_AUDIO_SYSTEM)
- bReturn &= FindLogicalAddressAudioSystem(iPtr);
+ bReturn &= FindLogicalAddressAudioSystem();
}
return bReturn;
cec_command command;
CCECAdapterMessage msg;
+ if (m_logicalAddresses.IsEmpty() && !FindLogicalAddresses())
{
- if (m_logicalAddresses.empty() && !FindLogicalAddresses())
- {
- CLockObject lock(&m_mutex);
- m_controller->AddLog(CEC_LOG_ERROR, "could not detect our logical addressed");
- m_startCondition.Signal();
- return NULL;
- }
+ CLockObject lock(&m_mutex);
+ m_controller->AddLog(CEC_LOG_ERROR, "could not detect our logical addresses");
+ m_startCondition.Signal();
+ return NULL;
+ }
+ else
+ {
+ /* only set our OSD name and active source for the primary device */
+ m_busDevices[m_logicalAddresses.primary]->m_strDeviceName = m_strDeviceName;
+ m_busDevices[m_logicalAddresses.primary]->m_bActiveSource = true;
- SetAckMask(m_logicalAddresses.ackmask());
+ SetAckMask(m_logicalAddresses.AckMask());
- {
- CLockObject lock(&m_mutex);
- m_controller->AddLog(CEC_LOG_DEBUG, "processor thread started");
- m_bStarted = true;
- m_startCondition.Signal();
- }
+ CLockObject lock(&m_mutex);
+ m_bStarted = true;
+ m_controller->AddLog(CEC_LOG_DEBUG, "processor thread started");
+ m_startCondition.Signal();
}
while (!IsStopped())
{
- command.clear();
+ command.Clear();
msg.clear();
{
}
else if (m_communication->IsOpen() && m_communication->Read(msg, 50))
{
- m_controller->AddLog(msg.is_error() ? CEC_LOG_WARNING : CEC_LOG_DEBUG, msg.ToString());
if ((bParseFrame = (ParseMessage(msg) && !IsStopped())) == true)
command = m_currentframe;
}
Sleep(5);
m_controller->CheckKeypressTimeout();
+ }
- for (unsigned int iDevicePtr = 0; iDevicePtr < 16; iDevicePtr++)
- m_busDevices[iDevicePtr]->PollVendorId();
-
- Sleep(5);
+ if (m_busScan)
+ {
+ m_busScan->StopThread();
+ delete m_busScan;
+ m_busScan = NULL;
}
+ if (m_communication)
+ m_communication->Close();
+
return NULL;
}
if (type != CEC_DEVICE_TYPE_RESERVED)
{
- for (uint8_t iPtr = 0; iPtr < 16; iPtr++)
+ for (uint8_t iPtr = 0; iPtr <= 11; iPtr++)
{
if (m_logicalAddresses[iPtr] && m_busDevices[iPtr]->m_type == type)
{
}
}
- return SetStreamPath(m_busDevices[addr]->GetPhysicalAddress());
+ m_busDevices[addr]->SetActiveSource();
+ bReturn = m_busDevices[addr]->TransmitActiveSource();
+
+ if (bReturn && (m_busDevices[addr]->GetType() == CEC_DEVICE_TYPE_PLAYBACK_DEVICE ||
+ m_busDevices[addr]->GetType() == CEC_DEVICE_TYPE_RECORDING_DEVICE))
+ {
+ bReturn = ((CCECPlaybackDevice *)m_busDevices[addr])->TransmitDeckStatus(CECDEVICE_TV);
+ }
+
+ return bReturn;
+}
+
+bool CCECProcessor::SetActiveSource(uint16_t iStreamPath)
+{
+ bool bReturn(false);
+
+ CCECBusDevice *device = GetDeviceByPhysicalAddress(iStreamPath);
+ if (device)
+ {
+ device->SetActiveSource();
+ bReturn = true;
+ }
+
+ return bReturn;
+}
+
+void CCECProcessor::SetStandardLineTimeout(uint8_t iTimeout)
+{
+ CLockObject lock(&m_mutex);
+ m_iStandardLineTimeout = iTimeout;
+}
+
+void CCECProcessor::SetRetryLineTimeout(uint8_t iTimeout)
+{
+ CLockObject lock(&m_mutex);
+ m_iRetryLineTimeout = iTimeout;
}
bool CCECProcessor::SetActiveView(void)
{
- return SetActiveSource();
+ return SetActiveSource(m_types.IsEmpty() ? CEC_DEVICE_TYPE_RESERVED : m_types[0]);
}
bool CCECProcessor::SetDeckControlMode(cec_deck_control_mode mode, bool bSendUpdate /* = true */)
return bReturn;
}
-bool CCECProcessor::SetStreamPath(uint16_t iStreamPath)
+bool CCECProcessor::SetHDMIPort(cec_logical_address iBaseDevice, uint8_t iPort, bool bForce /* = false */)
{
bool bReturn(false);
- CCECBusDevice *device = GetDeviceByPhysicalAddress(iStreamPath);
- if (device)
- {
- for (unsigned int iPtr = 0; iPtr < 16; iPtr++)
- m_busDevices[iPtr]->m_bActiveSource = false;
+ m_iBaseDevice = iBaseDevice;
+ m_iHDMIPort = iPort;
+ if (!m_bStarted && !bForce)
+ return true;
- device->m_bActiveSource = true;
- device->m_powerStatus = CEC_POWER_STATUS_ON;
+ CStdString strLog;
+ strLog.Format("setting HDMI port to %d on device %s (%d)", iPort, ToString(iBaseDevice), (int)iBaseDevice);
+ AddLog(CEC_LOG_DEBUG, strLog);
- bReturn = true;
+ uint16_t iPhysicalAddress(0);
+ if (iBaseDevice > CECDEVICE_TV)
+ iPhysicalAddress = m_busDevices[iBaseDevice]->GetPhysicalAddress();
+
+ if (iPhysicalAddress == 0xffff)
+ {
+ SetPhysicalAddress((uint16_t)iPort * 0x1000);
+ bReturn = false;
+ }
+ else
+ {
+ uint16_t iPos = 0;
+ if (iPhysicalAddress == 0)
+ iPos = 0x1000;
+ else if (iPhysicalAddress % 0x1000 == 0)
+ iPos = 0x100;
+ else if (iPhysicalAddress % 0x100 == 0)
+ iPos = 0x10;
+ else if (iPhysicalAddress % 0x10 == 0)
+ iPos = 0x1;
+
+ while(!bReturn && iPos > 0)
+ {
+ iPhysicalAddress += (uint16_t)(iPort * iPos);
+ strLog.Format("checking physical address %4x", iPhysicalAddress);
+ AddLog(CEC_LOG_DEBUG, strLog);
+ if (PhysicalAddressInUse(iPhysicalAddress))
+ {
+ strLog.Format("physical address %4x is in use", iPhysicalAddress);
+ AddLog(CEC_LOG_DEBUG, strLog);
+ iPos = (iPos == 1) ? 0 : iPos / 0x10;
+ }
+ else
+ {
+ strLog.Format("physical address %4x is free", iPhysicalAddress);
+ AddLog(CEC_LOG_DEBUG, strLog);
+ SetPhysicalAddress(iPhysicalAddress);
+ bReturn = true;
+ }
+ }
}
return bReturn;
}
-bool CCECProcessor::SetInactiveView(void)
+bool CCECProcessor::PhysicalAddressInUse(uint16_t iPhysicalAddress)
+{
+ for (unsigned int iPtr = 0; iPtr < 15; iPtr++)
+ {
+ if (m_busDevices[iPtr]->GetPhysicalAddress(false) == iPhysicalAddress)
+ return true;
+ }
+ return false;
+}
+
+bool CCECProcessor::TransmitInactiveSource(void)
{
if (!IsRunning())
return false;
- if (!m_logicalAddresses.empty() && m_busDevices[m_logicalAddresses.primary])
- return m_busDevices[m_logicalAddresses.primary]->TransmitInactiveView();
+ if (!m_logicalAddresses.IsEmpty() && m_busDevices[m_logicalAddresses.primary])
+ return m_busDevices[m_logicalAddresses.primary]->TransmitInactiveSource();
return false;
}
strLog.Format("<< setting primary logical address to %1x", iLogicalAddress);
m_controller->AddLog(CEC_LOG_NOTICE, strLog.c_str());
m_logicalAddresses.primary = iLogicalAddress;
- m_logicalAddresses.set(iLogicalAddress);
- return SetAckMask(m_logicalAddresses.ackmask());
+ m_logicalAddresses.Set(iLogicalAddress);
+ return SetAckMask(m_logicalAddresses.AckMask());
}
return true;
bool CCECProcessor::SetPhysicalAddress(uint16_t iPhysicalAddress)
{
- if (!m_logicalAddresses.empty() && m_busDevices[m_logicalAddresses.primary])
+ if (!m_logicalAddresses.IsEmpty())
{
- m_busDevices[m_logicalAddresses.primary]->SetPhysicalAddress(iPhysicalAddress);
+ for (uint8_t iPtr = 0; iPtr < 15; iPtr++)
+ if (m_logicalAddresses[iPtr])
+ {
+ m_busDevices[iPtr]->SetInactiveSource();
+ m_busDevices[iPtr]->SetPhysicalAddress(iPhysicalAddress);
+ m_busDevices[iPtr]->TransmitPhysicalAddress();
+ }
return SetActiveView();
}
return false;
strLog.Format("== %s monitoring mode ==", bEnable ? "enabling" : "disabling");
m_controller->AddLog(CEC_LOG_NOTICE, strLog.c_str());
- m_bMonitor = bEnable;
+ {
+ CLockObject lock(&m_mutex);
+ m_bMonitor = bEnable;
+
+ if (!bEnable)
+ {
+ if (!m_busScan)
+ {
+ m_busScan = new CCECBusScan(this);
+ m_busScan->CreateThread(true);
+ }
+ }
+ else
+ {
+ if (m_busScan)
+ {
+ m_busScan->StopThread();
+ delete m_busScan;
+ m_busScan = NULL;
+ }
+ }
+ }
+
if (bEnable)
return SetAckMask(0);
else
- return SetAckMask(m_logicalAddresses.ackmask());
+ return SetAckMask(m_logicalAddresses.AckMask());
}
bool CCECProcessor::PollDevice(cec_logical_address iAddress)
{
if (iAddress != CECDEVICE_UNKNOWN && m_busDevices[iAddress])
- return m_busDevices[m_logicalAddresses.primary]->TransmitPoll(iAddress);
+ {
+ return m_logicalAddresses.primary == CECDEVICE_UNKNOWN ?
+ m_busDevices[iAddress]->TransmitPoll(iAddress) :
+ m_busDevices[m_logicalAddresses.primary]->TransmitPoll(iAddress);
+ }
return false;
}
-CCECBusDevice *CCECProcessor::GetDeviceByPhysicalAddress(uint16_t iPhysicalAddress) const
+uint8_t CCECProcessor::VolumeUp(void)
{
- CCECBusDevice *device = NULL;
+ uint8_t status = 0;
+ if (IsPresentDevice(CECDEVICE_AUDIOSYSTEM))
+ status = ((CCECAudioSystem *)m_busDevices[CECDEVICE_AUDIOSYSTEM])->VolumeUp();
+
+ return status;
+}
+
+uint8_t CCECProcessor::VolumeDown(void)
+{
+ uint8_t status = 0;
+ if (IsPresentDevice(CECDEVICE_AUDIOSYSTEM))
+ status = ((CCECAudioSystem *)m_busDevices[CECDEVICE_AUDIOSYSTEM])->VolumeDown();
+
+ return status;
+}
+uint8_t CCECProcessor::MuteAudio(void)
+{
+ uint8_t status = 0;
+ if (IsPresentDevice(CECDEVICE_AUDIOSYSTEM))
+ status = ((CCECAudioSystem *)m_busDevices[CECDEVICE_AUDIOSYSTEM])->MuteAudio();
+
+ return status;
+}
+
+CCECBusDevice *CCECProcessor::GetDeviceByPhysicalAddress(uint16_t iPhysicalAddress, bool bRefresh /* = false */) const
+{
+ if (m_busDevices[m_logicalAddresses.primary]->GetPhysicalAddress(false) == iPhysicalAddress)
+ return m_busDevices[m_logicalAddresses.primary];
+
+ CCECBusDevice *device = NULL;
for (unsigned int iPtr = 0; iPtr < 16; iPtr++)
{
- if (m_busDevices[iPtr]->GetPhysicalAddress() == iPhysicalAddress)
+ if (m_busDevices[iPtr]->GetPhysicalAddress(bRefresh) == iPhysicalAddress)
{
device = m_busDevices[iPtr];
break;
return m_busDevices[iAddress]->GetCecVersion();
}
+cec_osd_name CCECProcessor::GetDeviceOSDName(cec_logical_address iAddress)
+{
+ CStdString strOSDName = m_busDevices[iAddress]->GetOSDName();
+ cec_osd_name retVal;
+
+ snprintf(retVal.name, sizeof(retVal.name), "%s", strOSDName.c_str());
+ retVal.device = iAddress;
+
+ return retVal;
+}
+
bool CCECProcessor::GetDeviceMenuLanguage(cec_logical_address iAddress, cec_menu_language *language)
{
if (m_busDevices[iAddress])
return false;
}
+uint16_t CCECProcessor::GetDevicePhysicalAddress(cec_logical_address iAddress)
+{
+ if (m_busDevices[iAddress])
+ return m_busDevices[iAddress]->GetPhysicalAddress(false);
+ return false;
+}
+
cec_power_status CCECProcessor::GetDevicePowerStatus(cec_logical_address iAddress)
{
if (m_busDevices[iAddress])
return CEC_POWER_STATUS_UNKNOWN;
}
+cec_logical_address CCECProcessor::GetActiveSource(void)
+{
+ for (uint8_t iPtr = 0; iPtr <= 11; iPtr++)
+ {
+ if (m_busDevices[iPtr]->IsActiveSource())
+ return (cec_logical_address)iPtr;
+ }
+
+ return CECDEVICE_UNKNOWN;
+}
+
+bool CCECProcessor::IsActiveSource(cec_logical_address iAddress)
+{
+ return m_busDevices[iAddress]->IsActiveSource();
+}
+
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);
- delete output;
+ /* set to "not present" on failed ack */
+ if (output->is_error() && output->reply == MSGCODE_TRANSMIT_FAILED_ACK &&
+ output->destination() != CECDEVICE_BROADCAST)
+ m_busDevices[output->destination()]->SetDeviceStatus(CEC_DEVICE_STATUS_NOT_PRESENT);
+
+ delete output;
return bReturn;
}
bool bReturn(false);
CLockObject lock(&m_mutex);
{
- CLockObject msgLock(&output->mutex);
- if (!m_communication || !m_communication->Write(output))
- return bReturn;
- else
+ m_iLastTransmission = GetTimeMs();
+ m_communication->SetLineTimeout(m_iStandardLineTimeout);
+ output->tries = 1;
+
+ do
{
- output->condition.Wait(&output->mutex);
- if (output->state != ADAPTER_MESSAGE_STATE_SENT)
- {
- m_controller->AddLog(CEC_LOG_ERROR, "command was not sent");
+ if (output->tries > 0)
+ m_communication->SetLineTimeout(m_iRetryLineTimeout);
+
+ CLockObject msgLock(&output->mutex);
+ if (!m_communication || !m_communication->Write(output))
return bReturn;
+ else
+ {
+ output->condition.Wait(&output->mutex);
+ if (output->state != ADAPTER_MESSAGE_STATE_SENT)
+ {
+ m_controller->AddLog(CEC_LOG_ERROR, "command was not sent");
+ return bReturn;
+ }
}
- }
- if (output->transmit_timeout > 0)
- {
- if ((bReturn = WaitForTransmitSucceeded(output->size(), output->transmit_timeout)) == false)
- m_controller->AddLog(CEC_LOG_DEBUG, "did not receive ack");
- }
- else
- bReturn = true;
+ if (output->transmit_timeout > 0)
+ {
+ if ((bReturn = WaitForTransmitSucceeded(output)) == false)
+ m_controller->AddLog(CEC_LOG_DEBUG, "did not receive ack");
+ }
+ else
+ bReturn = true;
+ }while (output->transmit_timeout > 0 && output->needs_retry() && ++output->tries < output->maxTries);
}
+ m_communication->SetLineTimeout(m_iStandardLineTimeout);
+
return bReturn;
}
cec_command command;
// TODO
- cec_command::format(command, m_logicalAddresses.primary, address, CEC_OPCODE_FEATURE_ABORT);
- command.parameters.push_back((uint8_t)opcode);
- command.parameters.push_back((uint8_t)reason);
+ cec_command::Format(command, m_logicalAddresses.primary, address, CEC_OPCODE_FEATURE_ABORT);
+ command.parameters.PushBack((uint8_t)opcode);
+ command.parameters.PushBack((uint8_t)reason);
Transmit(command);
}
-bool CCECProcessor::WaitForTransmitSucceeded(uint8_t iLength, uint32_t iTimeout /* = 1000 */)
+bool CCECProcessor::WaitForTransmitSucceeded(CCECAdapterMessage *message)
{
bool bError(false);
bool bTransmitSucceeded(false);
- uint8_t iPacketsLeft(iLength / 4);
+ uint8_t iPacketsLeft(message->size() / 4);
int64_t iNow = GetTimeMs();
- int64_t iTargetTime = iNow + (uint64_t) iTimeout;
+ int64_t iTargetTime = iNow + message->transmit_timeout;
- while (!bTransmitSucceeded && !bError && (iTimeout == 0 || iNow < iTargetTime))
+ while (!bTransmitSucceeded && !bError && (message->transmit_timeout == 0 || iNow < iTargetTime))
{
CCECAdapterMessage msg;
- if (!m_communication->Read(msg, iTimeout > 0 ? (int32_t)(iTargetTime - iNow) : 1000))
+ if (!m_communication->Read(msg, message->transmit_timeout > 0 ? (int32_t)(iTargetTime - iNow) : 1000))
+ {
+ iNow = GetTimeMs();
+ continue;
+ }
+
+ if (msg.message() == MSGCODE_FRAME_START && msg.ack())
{
+ m_busDevices[msg.initiator()]->GetHandler()->HandlePoll(msg.initiator(), msg.destination());
+ m_lastInitiator = msg.initiator();
iNow = GetTimeMs();
continue;
}
- if ((bError = msg.is_error()) == false)
+ bError = msg.is_error();
+ if (msg.message() == MSGCODE_RECEIVE_FAILED &&
+ m_lastInitiator != CECDEVICE_UNKNOWN &&
+ !m_busDevices[m_lastInitiator]->GetHandler()->HandleReceiveFailed())
{
- m_controller->AddLog(bError ? CEC_LOG_WARNING : CEC_LOG_DEBUG, msg.ToString());
+ iNow = GetTimeMs();
+ continue;
+ }
+ if (bError)
+ {
+ message->reply = msg.message();
+ m_controller->AddLog(CEC_LOG_DEBUG, msg.ToString());
+ }
+ else
+ {
switch(msg.message())
{
case MSGCODE_COMMAND_ACCEPTED:
+ m_controller->AddLog(CEC_LOG_DEBUG, msg.ToString());
if (iPacketsLeft > 0)
iPacketsLeft--;
break;
case MSGCODE_TRANSMIT_SUCCEEDED:
+ m_controller->AddLog(CEC_LOG_DEBUG, msg.ToString());
bTransmitSucceeded = (iPacketsLeft == 0);
bError = !bTransmitSucceeded;
+ message->reply = MSGCODE_TRANSMIT_SUCCEEDED;
break;
default:
- if (ParseMessage(msg))
- m_commandBuffer.Push(m_currentframe);
+ // ignore other data while waiting
+ break;
}
iNow = GetTimeMs();
bool CCECProcessor::ParseMessage(const CCECAdapterMessage &msg)
{
- bool bEom = false;
+ bool bEom(false);
+ bool bIsError(msg.is_error());
if (msg.empty())
return bEom;
{
case MSGCODE_FRAME_START:
{
- m_currentframe.clear();
+ m_currentframe.Clear();
if (msg.size() >= 2)
{
m_currentframe.initiator = msg.initiator();
m_currentframe.ack = msg.ack();
m_currentframe.eom = msg.eom();
}
+ 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.push_back(msg[1]);
+ m_currentframe.PushBack(msg[1]);
m_currentframe.eom = msg.eom();
}
bEom = msg.eom();
break;
}
+ m_controller->AddLog(bIsError ? CEC_LOG_WARNING : CEC_LOG_DEBUG, msg.ToString());
return bEom;
}
m_busDevices[(uint8_t)command.initiator]->HandleCommand(command);
}
+cec_logical_addresses CCECProcessor::GetActiveDevices(void)
+{
+ cec_logical_addresses addresses;
+ addresses.Clear();
+ for (unsigned int iPtr = 0; iPtr < 15; iPtr++)
+ {
+ if (m_busDevices[iPtr]->GetStatus() == CEC_DEVICE_STATUS_PRESENT)
+ addresses.Set((cec_logical_address) iPtr);
+ }
+ return addresses;
+}
+
+bool CCECProcessor::IsPresentDevice(cec_logical_address address)
+{
+ return m_busDevices[address]->GetStatus() == CEC_DEVICE_STATUS_PRESENT;
+}
+
+bool CCECProcessor::IsPresentDeviceType(cec_device_type type)
+{
+ for (unsigned int iPtr = 0; iPtr < 15; iPtr++)
+ {
+ if (m_busDevices[iPtr]->GetType() == type && m_busDevices[iPtr]->GetStatus() == CEC_DEVICE_STATUS_PRESENT)
+ return true;
+ }
+
+ return false;
+}
+
uint16_t CCECProcessor::GetPhysicalAddress(void) const
{
- if (!m_logicalAddresses.empty() && m_busDevices[m_logicalAddresses.primary])
- return m_busDevices[m_logicalAddresses.primary]->GetPhysicalAddress();
+ if (!m_logicalAddresses.IsEmpty() && m_busDevices[m_logicalAddresses.primary])
+ return m_busDevices[m_logicalAddresses.primary]->GetPhysicalAddress(false);
return false;
}
return bReturn;
}
+
+bool CCECProcessor::TransmitKeypress(cec_logical_address iDestination, cec_user_control_code key)
+{
+ return m_busDevices[iDestination]->TransmitKeypress(key);
+}
+
+bool CCECProcessor::TransmitKeyRelease(cec_logical_address iDestination)
+{
+ return m_busDevices[iDestination]->TransmitKeyRelease();
+}
+
+const char *CCECProcessor::ToString(const cec_menu_state state)
+{
+ switch (state)
+ {
+ case CEC_MENU_STATE_ACTIVATED:
+ return "activated";
+ case CEC_MENU_STATE_DEACTIVATED:
+ return "deactivated";
+ default:
+ return "unknown";
+ }
+}
+
+const char *CCECProcessor::ToString(const cec_version version)
+{
+ switch (version)
+ {
+ case CEC_VERSION_1_2:
+ return "1.2";
+ case CEC_VERSION_1_2A:
+ return "1.2a";
+ case CEC_VERSION_1_3:
+ return "1.3";
+ case CEC_VERSION_1_3A:
+ return "1.3a";
+ case CEC_VERSION_1_4:
+ return "1.4";
+ default:
+ return "unknown";
+ }
+}
+
+const char *CCECProcessor::ToString(const cec_power_status status)
+{
+ switch (status)
+ {
+ case CEC_POWER_STATUS_ON:
+ return "on";
+ case CEC_POWER_STATUS_STANDBY:
+ return "standby";
+ case CEC_POWER_STATUS_IN_TRANSITION_ON_TO_STANDBY:
+ return "in transition from on to standby";
+ case CEC_POWER_STATUS_IN_TRANSITION_STANDBY_TO_ON:
+ return "in transition from standby to on";
+ default:
+ return "unknown";
+ }
+}
+
+const char *CCECProcessor::ToString(const cec_logical_address address)
+{
+ switch(address)
+ {
+ case CECDEVICE_AUDIOSYSTEM:
+ return "Audio";
+ case CECDEVICE_BROADCAST:
+ return "Broadcast";
+ case CECDEVICE_FREEUSE:
+ return "Free use";
+ case CECDEVICE_PLAYBACKDEVICE1:
+ return "Playback 1";
+ case CECDEVICE_PLAYBACKDEVICE2:
+ return "Playback 2";
+ case CECDEVICE_PLAYBACKDEVICE3:
+ return "Playback 3";
+ case CECDEVICE_RECORDINGDEVICE1:
+ return "Recorder 1";
+ case CECDEVICE_RECORDINGDEVICE2:
+ return "Recorder 2";
+ case CECDEVICE_RECORDINGDEVICE3:
+ return "Recorder 3";
+ case CECDEVICE_RESERVED1:
+ return "Reserved 1";
+ case CECDEVICE_RESERVED2:
+ return "Reserved 2";
+ case CECDEVICE_TUNER1:
+ return "Tuner 1";
+ case CECDEVICE_TUNER2:
+ return "Tuner 2";
+ case CECDEVICE_TUNER3:
+ return "Tuner 3";
+ case CECDEVICE_TUNER4:
+ return "Tuner 4";
+ case CECDEVICE_TV:
+ return "TV";
+ default:
+ return "unknown";
+ }
+}
+
+const char *CCECProcessor::ToString(const cec_deck_control_mode mode)
+{
+ switch (mode)
+ {
+ case CEC_DECK_CONTROL_MODE_SKIP_FORWARD_WIND:
+ return "skip forward wind";
+ case CEC_DECK_CONTROL_MODE_EJECT:
+ return "eject";
+ case CEC_DECK_CONTROL_MODE_SKIP_REVERSE_REWIND:
+ return "reverse rewind";
+ case CEC_DECK_CONTROL_MODE_STOP:
+ return "stop";
+ default:
+ return "unknown";
+ }
+}
+
+const char *CCECProcessor::ToString(const cec_deck_info status)
+{
+ switch (status)
+ {
+ case CEC_DECK_INFO_PLAY:
+ return "play";
+ case CEC_DECK_INFO_RECORD:
+ return "record";
+ case CEC_DECK_INFO_PLAY_REVERSE:
+ return "play reverse";
+ case CEC_DECK_INFO_STILL:
+ return "still";
+ case CEC_DECK_INFO_SLOW:
+ return "slow";
+ case CEC_DECK_INFO_SLOW_REVERSE:
+ return "slow reverse";
+ case CEC_DECK_INFO_FAST_FORWARD:
+ return "fast forward";
+ case CEC_DECK_INFO_FAST_REVERSE:
+ return "fast reverse";
+ case CEC_DECK_INFO_NO_MEDIA:
+ return "no media";
+ case CEC_DECK_INFO_STOP:
+ return "stop";
+ case CEC_DECK_INFO_SKIP_FORWARD_WIND:
+ return "info skip forward wind";
+ case CEC_DECK_INFO_SKIP_REVERSE_REWIND:
+ return "info skip reverse rewind";
+ case CEC_DECK_INFO_INDEX_SEARCH_FORWARD:
+ return "info index search forward";
+ case CEC_DECK_INFO_INDEX_SEARCH_REVERSE:
+ return "info index search reverse";
+ case CEC_DECK_INFO_OTHER_STATUS:
+ return "other";
+ default:
+ return "unknown";
+ }
+}
+
+const char *CCECProcessor::ToString(const cec_opcode opcode)
+{
+ switch (opcode)
+ {
+ case CEC_OPCODE_ACTIVE_SOURCE:
+ return "active source";
+ case CEC_OPCODE_IMAGE_VIEW_ON:
+ return "image view on";
+ case CEC_OPCODE_TEXT_VIEW_ON:
+ return "text view on";
+ case CEC_OPCODE_INACTIVE_SOURCE:
+ return "inactive source";
+ case CEC_OPCODE_REQUEST_ACTIVE_SOURCE:
+ return "request active source";
+ case CEC_OPCODE_ROUTING_CHANGE:
+ return "routing change";
+ case CEC_OPCODE_ROUTING_INFORMATION:
+ return "routing information";
+ case CEC_OPCODE_SET_STREAM_PATH:
+ return "set stream path";
+ case CEC_OPCODE_STANDBY:
+ return "standby";
+ case CEC_OPCODE_RECORD_OFF:
+ return "record off";
+ case CEC_OPCODE_RECORD_ON:
+ return "record on";
+ case CEC_OPCODE_RECORD_STATUS:
+ return "record status";
+ case CEC_OPCODE_RECORD_TV_SCREEN:
+ return "record tv screen";
+ case CEC_OPCODE_CLEAR_ANALOGUE_TIMER:
+ return "clear analogue timer";
+ case CEC_OPCODE_CLEAR_DIGITAL_TIMER:
+ return "clear digital timer";
+ case CEC_OPCODE_CLEAR_EXTERNAL_TIMER:
+ return "clear external timer";
+ case CEC_OPCODE_SET_ANALOGUE_TIMER:
+ return "set analogue timer";
+ case CEC_OPCODE_SET_DIGITAL_TIMER:
+ return "set digital timer";
+ case CEC_OPCODE_SET_EXTERNAL_TIMER:
+ return "set external timer";
+ case CEC_OPCODE_SET_TIMER_PROGRAM_TITLE:
+ return "set timer program title";
+ case CEC_OPCODE_TIMER_CLEARED_STATUS:
+ return "timer cleared status";
+ case CEC_OPCODE_TIMER_STATUS:
+ return "timer status";
+ case CEC_OPCODE_CEC_VERSION:
+ return "cec version";
+ case CEC_OPCODE_GET_CEC_VERSION:
+ return "get cec version";
+ case CEC_OPCODE_GIVE_PHYSICAL_ADDRESS:
+ return "give physical address";
+ case CEC_OPCODE_GET_MENU_LANGUAGE:
+ return "get menu language";
+ case CEC_OPCODE_REPORT_PHYSICAL_ADDRESS:
+ return "report physical address";
+ case CEC_OPCODE_SET_MENU_LANGUAGE:
+ return "set menu language";
+ case CEC_OPCODE_DECK_CONTROL:
+ return "deck control";
+ case CEC_OPCODE_DECK_STATUS:
+ return "deck status";
+ case CEC_OPCODE_GIVE_DECK_STATUS:
+ return "give deck status";
+ case CEC_OPCODE_PLAY:
+ return "play";
+ case CEC_OPCODE_GIVE_TUNER_DEVICE_STATUS:
+ return "give tuner status";
+ case CEC_OPCODE_SELECT_ANALOGUE_SERVICE:
+ return "select analogue service";
+ case CEC_OPCODE_SELECT_DIGITAL_SERVICE:
+ return "set digital service";
+ case CEC_OPCODE_TUNER_DEVICE_STATUS:
+ return "tuner device status";
+ case CEC_OPCODE_TUNER_STEP_DECREMENT:
+ return "tuner step decrement";
+ case CEC_OPCODE_TUNER_STEP_INCREMENT:
+ return "tuner step increment";
+ case CEC_OPCODE_DEVICE_VENDOR_ID:
+ return "device vendor id";
+ case CEC_OPCODE_GIVE_DEVICE_VENDOR_ID:
+ return "give device vendor id";
+ case CEC_OPCODE_VENDOR_COMMAND:
+ return "vendor command";
+ case CEC_OPCODE_VENDOR_COMMAND_WITH_ID:
+ return "vendor command with id";
+ case CEC_OPCODE_VENDOR_REMOTE_BUTTON_DOWN:
+ return "vendor remote button down";
+ case CEC_OPCODE_VENDOR_REMOTE_BUTTON_UP:
+ return "vendor remote button up";
+ case CEC_OPCODE_SET_OSD_STRING:
+ return "set osd string";
+ case CEC_OPCODE_GIVE_OSD_NAME:
+ return "give osd name";
+ case CEC_OPCODE_SET_OSD_NAME:
+ return "set osd name";
+ case CEC_OPCODE_MENU_REQUEST:
+ return "menu request";
+ case CEC_OPCODE_MENU_STATUS:
+ return "menu status";
+ case CEC_OPCODE_USER_CONTROL_PRESSED:
+ return "user control pressed";
+ case CEC_OPCODE_USER_CONTROL_RELEASE:
+ return "user control release";
+ case CEC_OPCODE_GIVE_DEVICE_POWER_STATUS:
+ return "give device power status";
+ case CEC_OPCODE_REPORT_POWER_STATUS:
+ return "report power status";
+ case CEC_OPCODE_FEATURE_ABORT:
+ return "feature abort";
+ case CEC_OPCODE_ABORT:
+ return "abort";
+ case CEC_OPCODE_GIVE_AUDIO_STATUS:
+ return "give audio status";
+ case CEC_OPCODE_GIVE_SYSTEM_AUDIO_MODE_STATUS:
+ return "give audio mode status";
+ case CEC_OPCODE_REPORT_AUDIO_STATUS:
+ return "report audio status";
+ case CEC_OPCODE_SET_SYSTEM_AUDIO_MODE:
+ return "set system audio mode";
+ case CEC_OPCODE_SYSTEM_AUDIO_MODE_REQUEST:
+ return "system audio mode request";
+ case CEC_OPCODE_SYSTEM_AUDIO_MODE_STATUS:
+ return "system audio mode status";
+ case CEC_OPCODE_SET_AUDIO_RATE:
+ return "set audio rate";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+const char *CCECProcessor::ToString(const cec_system_audio_status mode)
+{
+ switch(mode)
+ {
+ case CEC_SYSTEM_AUDIO_STATUS_ON:
+ return "on";
+ case CEC_SYSTEM_AUDIO_STATUS_OFF:
+ return "off";
+ default:
+ return "unknown";
+ }
+}
+
+const char *CCECProcessor::ToString(const cec_audio_status status)
+{
+ // TODO this is a mask
+ return "TODO";
+}
+
+const char *CCECProcessor::ToString(const cec_vendor_id vendor)
+{
+ switch (vendor)
+ {
+ case CEC_VENDOR_SAMSUNG:
+ return "Samsung";
+ case CEC_VENDOR_LG:
+ return "LG";
+ case CEC_VENDOR_PANASONIC:
+ return "Panasonic";
+ case CEC_VENDOR_PIONEER:
+ return "Pioneer";
+ case CEC_VENDOR_ONKYO:
+ return "Onkyo";
+ case CEC_VENDOR_YAMAHA:
+ return "Yamaha";
+ case CEC_VENDOR_PHILIPS:
+ return "Philips";
+ default:
+ return "Unknown";
+ }
+}
+
+void *CCECBusScan::Process(void)
+{
+ CCECBusDevice *device(NULL);
+ uint8_t iCounter(0);
+
+ while (!IsStopped())
+ {
+ if (++iCounter < 10)
+ {
+ Sleep(1000);
+ continue;
+ }
+ for (unsigned int iPtr = 0; iPtr <= 11 && !IsStopped(); iPtr++)
+ {
+ device = m_processor->m_busDevices[iPtr];
+ WaitUntilIdle();
+ if (device && device->GetStatus(true) == CEC_DEVICE_STATUS_PRESENT)
+ {
+ WaitUntilIdle();
+ if (!IsStopped())
+ device->GetVendorId();
+
+ WaitUntilIdle();
+ if (!IsStopped())
+ device->GetPowerStatus(true);
+ }
+ }
+ }
+
+ return NULL;
+}
+
+void CCECBusScan::WaitUntilIdle(void)
+{
+ if (IsStopped())
+ return;
+
+ int32_t iWaitTime = 3000 - (int32_t)(GetTimeMs() - m_processor->GetLastTransmission());
+ while (iWaitTime > 0)
+ {
+ Sleep(iWaitTime);
+ iWaitTime = 3000 - (int32_t)(GetTimeMs() - m_processor->GetLastTransmission());
+ }
+}
+
+bool CCECProcessor::StartBootloader(void)
+{
+ return m_communication->StartBootloader();
+}
+
+bool CCECProcessor::PingAdapter(void)
+{
+ return m_communication->PingAdapter();
+}
class CCECProcessor : public CThread
{
public:
- CCECProcessor(CLibCEC *controller, CAdapterCommunication *serComm, const char *strDeviceName, cec_logical_address iLogicalAddress = CECDEVICE_PLAYBACKDEVICE1, uint16_t iPhysicalAddress = CEC_DEFAULT_PHYSICAL_ADDRESS);
- CCECProcessor(CLibCEC *controller, CAdapterCommunication *serComm, const char *strDeviceName, const cec_device_type_list &types);
+ CCECProcessor(CLibCEC *controller, const char *strDeviceName, cec_logical_address iLogicalAddress = CECDEVICE_PLAYBACKDEVICE1, uint16_t iPhysicalAddress = CEC_DEFAULT_PHYSICAL_ADDRESS);
+ CCECProcessor(CLibCEC *controller, const char *strDeviceName, const cec_device_type_list &types);
virtual ~CCECProcessor(void);
- virtual bool Start(void);
+ virtual bool Start(const char *strPort, uint16_t iBaudRate = 38400, uint32_t iTimeoutMs = 10000);
virtual void *Process(void);
virtual bool IsMonitoring(void) const { return m_bMonitor; }
- virtual CCECBusDevice * GetDeviceByPhysicalAddress(uint16_t iPhysicalAddress) const;
+ virtual CCECBusDevice * GetDeviceByPhysicalAddress(uint16_t iPhysicalAddress, bool bRefresh = false) const;
virtual CCECBusDevice * GetDeviceByType(cec_device_type type) const;
virtual cec_version GetDeviceCecVersion(cec_logical_address iAddress);
virtual bool GetDeviceMenuLanguage(cec_logical_address iAddress, cec_menu_language *language);
virtual const std::string & GetDeviceName(void) { return m_strDeviceName; }
+ virtual cec_osd_name GetDeviceOSDName(cec_logical_address iAddress);
virtual uint64_t GetDeviceVendorId(cec_logical_address iAddress);
virtual cec_power_status GetDevicePowerStatus(cec_logical_address iAddress);
virtual cec_logical_address GetLogicalAddress(void) const { return m_logicalAddresses.primary; }
virtual cec_logical_addresses GetLogicalAddresses(void) const { return m_logicalAddresses; }
- virtual bool HasLogicalAddress(cec_logical_address address) const { return m_logicalAddresses.isset(address); }
+ virtual cec_logical_addresses GetActiveDevices(void);
+ virtual uint16_t GetDevicePhysicalAddress(cec_logical_address iAddress);
+ virtual bool HasLogicalAddress(cec_logical_address address) const { return m_logicalAddresses.IsSet(address); }
+ virtual bool IsPresentDevice(cec_logical_address address);
+ 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 SetActiveView(void);
virtual bool SetActiveSource(cec_device_type type = CEC_DEVICE_TYPE_RESERVED);
virtual bool SetDeckControlMode(cec_deck_control_mode mode, bool bSendUpdate = true);
virtual bool SetDeckInfo(cec_deck_info info, bool bSendUpdate = true);
- virtual bool SetInactiveView(void);
+ virtual bool SetHDMIPort(cec_logical_address iBaseDevice, uint8_t iPort, bool bForce = false);
+ virtual bool TransmitInactiveSource(void);
virtual bool SetLogicalAddress(cec_logical_address iLogicalAddress);
virtual bool SetMenuState(cec_menu_state state, bool bSendUpdate = true);
virtual bool SetPhysicalAddress(uint16_t iPhysicalAddress);
- virtual bool SetStreamPath(uint16_t iStreamPath);
+ virtual bool SetActiveSource(uint16_t iStreamPath);
virtual bool SwitchMonitoring(bool bEnable);
virtual bool PollDevice(cec_logical_address iAddress);
+ virtual uint8_t VolumeUp(void);
+ virtual uint8_t VolumeDown(void);
+ virtual uint8_t MuteAudio(void);
+ virtual bool TransmitKeypress(cec_logical_address iDestination, cec_user_control_code key);
+ virtual bool TransmitKeyRelease(cec_logical_address iDestination);
+ virtual bool EnablePhysicalAddressDetection(void) { return false; };
+ void SetStandardLineTimeout(uint8_t iTimeout);
+ void SetRetryLineTimeout(uint8_t iTimeout);
+
+ bool SetLineTimeout(uint8_t iTimeout);
+
+ const char *ToString(const cec_menu_state state);
+ const char *ToString(const cec_version version);
+ const char *ToString(const cec_power_status status);
+ const char *ToString(const cec_logical_address address);
+ const char *ToString(const cec_deck_control_mode mode);
+ const char *ToString(const cec_deck_info status);
+ const char *ToString(const cec_opcode opcode);
+ const char *ToString(const cec_system_audio_status mode);
+ const char *ToString(const cec_audio_status status);
+ const char *ToString(const cec_vendor_id vendor);
virtual bool Transmit(const cec_command &data);
virtual bool Transmit(CCECAdapterMessage *output);
virtual void AddLog(cec_log_level level, const CStdString &strMessage);
virtual bool FindLogicalAddresses(void);
+ virtual bool SetAckMask(uint16_t iMask);
+
+ virtual bool StartBootloader(void);
+ virtual bool PingAdapter(void);
CCECBusDevice *m_busDevices[16];
+ CMutex m_transmitMutex;
private:
- bool TryLogicalAddress(cec_logical_address address, unsigned int iIndex);
- bool FindLogicalAddressRecordingDevice(unsigned int iIndex);
- bool FindLogicalAddressTuner(unsigned int iIndex);
- bool FindLogicalAddressPlaybackDevice(unsigned int iIndex);
- bool FindLogicalAddressAudioSystem(unsigned int iIndex);
+ void ScanCECBus(void);
+ bool PhysicalAddressInUse(uint16_t iPhysicalAddress);
+ bool TryLogicalAddress(cec_logical_address address);
+ bool FindLogicalAddressRecordingDevice(void);
+ bool FindLogicalAddressTuner(void);
+ bool FindLogicalAddressPlaybackDevice(void);
+ bool FindLogicalAddressAudioSystem(void);
- bool SetAckMask(uint16_t iMask);
void LogOutput(const cec_command &data);
- bool WaitForTransmitSucceeded(uint8_t iLength, uint32_t iTimeout = 1000);
+ bool WaitForTransmitSucceeded(CCECAdapterMessage *message);
bool ParseMessage(const CCECAdapterMessage &msg);
void ParseCommand(cec_command &command);
bool m_bStarted;
+ 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;
CMutex m_mutex;
CLibCEC* m_controller;
bool m_bMonitor;
CecBuffer<cec_command> m_commandBuffer;
+ cec_keypress m_previousKey;
+ CThread * m_busScan;
+ uint8_t m_iLineTimeout;
+ uint8_t m_iStandardLineTimeout;
+ uint8_t m_iRetryLineTimeout;
+ uint64_t m_iLastTransmission;
+ };
+
+ class CCECBusScan : public CThread
+ {
+ public:
+ CCECBusScan(CCECProcessor *processor) { m_processor = processor; }
+ virtual ~CCECBusScan(void) { StopThread(true); }
+ virtual void *Process(void);
+
+ private:
+ void WaitUntilIdle(void);
+
+ CCECProcessor *m_processor;
};
};
m_iCurrentButton(CEC_USER_CONTROL_CODE_UNKNOWN),
m_buttontime(0)
{
- m_comm = new CAdapterCommunication(this);
- m_cec = new CCECProcessor(this, m_comm, strDeviceName, types);
+ m_cec = new CCECProcessor(this, strDeviceName, types);
}
CLibCEC::CLibCEC(const char *strDeviceName, cec_logical_address iLogicalAddress /* = CECDEVICE_PLAYBACKDEVICE1 */, uint16_t iPhysicalAddress /* = CEC_DEFAULT_PHYSICAL_ADDRESS */) :
m_iCurrentButton(CEC_USER_CONTROL_CODE_UNKNOWN),
m_buttontime(0)
{
- m_comm = new CAdapterCommunication(this);
- m_cec = new CCECProcessor(this, m_comm, strDeviceName, iLogicalAddress, iPhysicalAddress);
+ m_cec = new CCECProcessor(this, strDeviceName, iLogicalAddress, iPhysicalAddress);
}
CLibCEC::~CLibCEC(void)
{
Close();
delete m_cec;
- delete m_comm;
}
bool CLibCEC::Open(const char *strPort, uint32_t iTimeoutMs /* = 10000 */)
{
- if (!m_comm)
- {
- AddLog(CEC_LOG_ERROR, "no comm port");
- return false;
- }
-
- if (m_comm->IsOpen())
+ if (m_cec->IsRunning())
{
AddLog(CEC_LOG_ERROR, "connection already open");
return false;
}
- int64_t iNow = GetTimeMs();
- int64_t iTarget = iNow + iTimeoutMs;
-
- bool bOpened(false);
- while (!bOpened && iNow < iTarget)
- {
- bOpened = m_comm->Open(strPort, 38400, iTimeoutMs);
- iNow = GetTimeMs();
- }
-
- if (!bOpened)
- {
- AddLog(CEC_LOG_ERROR, "could not open a connection");
- return false;
- }
-
- if (!m_cec->Start())
+ if (!m_cec->Start(strPort, 38400, iTimeoutMs))
{
AddLog(CEC_LOG_ERROR, "could not start CEC communications");
return false;
{
if (m_cec)
m_cec->StopThread();
- if (m_comm)
- m_comm->Close();
}
int8_t CLibCEC::FindAdapters(cec_adapter *deviceList, uint8_t iBufSize, const char *strDevicePath /* = NULL */)
bool CLibCEC::PingAdapter(void)
{
- return m_comm ? m_comm->PingAdapter() : false;
+ return m_cec ? m_cec->PingAdapter() : false;
}
bool CLibCEC::StartBootloader(void)
{
- return m_comm ? m_comm->StartBootloader() : false;
+ return m_cec ? m_cec->StartBootloader() : false;
}
bool CLibCEC::GetNextLogMessage(cec_log_message *message)
return m_cec ? m_cec->SetLogicalAddress(iLogicalAddress) : false;
}
-bool CLibCEC::SetPhysicalAddress(uint16_t iPhysicalAddress)
+bool CLibCEC::SetPhysicalAddress(uint16_t iPhysicalAddress /* = CEC_DEFAULT_PHYSICAL_ADDRESS */)
{
return m_cec ? m_cec->SetPhysicalAddress(iPhysicalAddress) : false;
}
+bool CLibCEC::SetHDMIPort(cec_logical_address iBaseDevice, uint8_t iPort /* = CEC_DEFAULT_HDMI_PORT */)
+{
+ return m_cec ? m_cec->SetHDMIPort(iBaseDevice, iPort) : false;
+}
+
+bool CLibCEC::EnablePhysicalAddressDetection(void)
+{
+ return m_cec ? m_cec->EnablePhysicalAddressDetection() : false;
+}
+
bool CLibCEC::PowerOnDevices(cec_logical_address address /* = CECDEVICE_TV */)
{
return m_cec && address >= CECDEVICE_TV && address <= CECDEVICE_BROADCAST ? m_cec->m_busDevices[(uint8_t)address]->PowerOn() : false;
bool CLibCEC::SetInactiveView(void)
{
- return m_cec ? m_cec->SetInactiveView() : false;
+ return m_cec ? m_cec->TransmitInactiveSource() : false;
}
bool CLibCEC::SetMenuState(cec_menu_state state, bool bSendUpdate /* = true */)
return 0;
}
+uint16_t CLibCEC::GetDevicePhysicalAddress(cec_logical_address iAddress)
+{
+ if (m_cec && iAddress >= CECDEVICE_TV && iAddress < CECDEVICE_BROADCAST)
+ return m_cec->GetDevicePhysicalAddress(iAddress);
+ return 0;
+}
+
+cec_logical_address CLibCEC::GetActiveSource(void)
+{
+ return m_cec ? m_cec->GetActiveSource() : CECDEVICE_UNKNOWN;
+}
+
+bool CLibCEC::IsActiveSource(cec_logical_address iAddress)
+{
+ if (m_cec && iAddress >= CECDEVICE_TV && iAddress < CECDEVICE_BROADCAST)
+ return m_cec->IsActiveSource(iAddress);
+ return false;
+}
+
cec_power_status CLibCEC::GetDevicePowerStatus(cec_logical_address iAddress)
{
if (m_cec && iAddress >= CECDEVICE_TV && iAddress < CECDEVICE_BROADCAST)
return false;
}
+cec_logical_addresses CLibCEC::GetActiveDevices(void)
+{
+ cec_logical_addresses addresses;
+ addresses.Clear();
+ if (m_cec)
+ addresses = m_cec->GetActiveDevices();
+ return addresses;
+}
+
+bool CLibCEC::IsActiveDevice(cec_logical_address iAddress)
+{
+ if (m_cec && iAddress >= CECDEVICE_TV && iAddress < CECDEVICE_BROADCAST)
+ return m_cec->IsPresentDevice(iAddress);
+ return false;
+}
+
+bool CLibCEC::IsActiveDeviceType(cec_device_type type)
+{
+ if (m_cec && type >= CEC_DEVICE_TYPE_TV && type <= CEC_DEVICE_TYPE_AUDIO_SYSTEM)
+ return m_cec->IsPresentDeviceType(type);
+ return false;
+}
+
+uint8_t CLibCEC::VolumeUp(bool bWait /* = true */)
+{
+ if (m_cec)
+ return m_cec->VolumeUp();
+ return 0;
+}
+
+uint8_t CLibCEC::VolumeDown(bool bWait /* = true */)
+{
+ if (m_cec)
+ return m_cec->VolumeDown();
+ return 0;
+}
+
+
+uint8_t CLibCEC::MuteAudio(bool bWait /* = true */)
+{
+ if (m_cec)
+ return m_cec->MuteAudio();
+ return 0;
+}
+
+bool CLibCEC::SendKeypress(cec_logical_address iDestination, cec_user_control_code key, bool bWait /* = false */)
+{
+ if (m_cec)
+ return m_cec->TransmitKeypress(iDestination, key);
+ return false;
+}
+
+bool CLibCEC::SendKeyRelease(cec_logical_address iDestination, bool bWait /* = false */)
+{
+ if (m_cec)
+ return m_cec->TransmitKeyRelease(iDestination);
+ return false;
+}
+
+cec_osd_name CLibCEC::GetDeviceOSDName(cec_logical_address iAddress)
+{
+ cec_osd_name retVal;
+ retVal.device = iAddress;
+ retVal.name[0] = 0;
+
+ if (m_cec)
+ retVal = m_cec->GetDeviceOSDName(iAddress);
+
+ return retVal;
+}
+
void CLibCEC::AddLog(cec_log_level level, const string &strMessage)
{
if (m_cec)
if (lib)
delete lib;
}
+
+const char *CLibCEC::ToString(const cec_menu_state state)
+{
+ return m_cec->ToString(state);
+}
+
+const char *CLibCEC::ToString(const cec_version version)
+{
+ return m_cec->ToString(version);
+}
+
+const char *CLibCEC::ToString(const cec_power_status status)
+{
+ return m_cec->ToString(status);
+}
+
+const char *CLibCEC::ToString(const cec_logical_address address)
+{
+ return m_cec->ToString(address);
+}
+
+const char *CLibCEC::ToString(const cec_deck_control_mode mode)
+{
+ return m_cec->ToString(mode);
+}
+
+const char *CLibCEC::ToString(const cec_deck_info status)
+{
+ return m_cec->ToString(status);
+}
+
+const char *CLibCEC::ToString(const cec_opcode opcode)
+{
+ return m_cec->ToString(opcode);
+}
+
+const char *CLibCEC::ToString(const cec_system_audio_status mode)
+{
+ return m_cec->ToString(mode);
+}
+
+const char *CLibCEC::ToString(const cec_audio_status status)
+{
+ return m_cec->ToString(status);
+}
+
+const char *CLibCEC::ToString(const cec_vendor_id vendor)
+{
+ return m_cec->ToString(vendor);
+}
virtual cec_version GetDeviceCecVersion(cec_logical_address iAddress);
virtual bool GetDeviceMenuLanguage(cec_logical_address iAddress, cec_menu_language *language);
virtual uint64_t GetDeviceVendorId(cec_logical_address iAddress);
+ virtual uint16_t GetDevicePhysicalAddress(cec_logical_address iAddress);
virtual cec_power_status GetDevicePowerStatus(cec_logical_address iAddress);
virtual bool PollDevice(cec_logical_address iAddress);
+ virtual cec_logical_addresses GetActiveDevices(void);
+ virtual bool IsActiveDevice(cec_logical_address iAddress);
+ virtual bool IsActiveDeviceType(cec_device_type type);
+ virtual bool SetHDMIPort(cec_logical_address iBaseDevice, uint8_t iPort = CEC_DEFAULT_HDMI_PORT);
+ virtual uint8_t VolumeUp(bool bWait = true);
+ virtual uint8_t VolumeDown(bool bWait = true);
+ virtual uint8_t MuteAudio(bool bWait = true);
+ virtual bool SendKeypress(cec_logical_address iDestination, cec_user_control_code key, bool bWait = false);
+ virtual bool SendKeyRelease(cec_logical_address iDestination, bool bWait = false);
+ virtual cec_osd_name GetDeviceOSDName(cec_logical_address iAddress);
+ virtual bool EnablePhysicalAddressDetection(void);
+ virtual cec_logical_address GetActiveSource(void);
+ virtual bool IsActiveSource(cec_logical_address iAddress);
+
+ const char *ToString(const cec_menu_state state);
+ const char *ToString(const cec_version version);
+ const char *ToString(const cec_power_status status);
+ const char *ToString(const cec_logical_address address);
+ const char *ToString(const cec_deck_control_mode mode);
+ const char *ToString(const cec_deck_info status);
+ const char *ToString(const cec_opcode opcode);
+ const char *ToString(const cec_system_audio_status mode);
+ const char *ToString(const cec_audio_status status);
+ const char *ToString(const cec_vendor_id vendor);
//@}
virtual void AddLog(cec_log_level level, const std::string &strMessage);
cec_user_control_code m_iCurrentButton;
int64_t m_buttontime;
CCECProcessor *m_cec;
- CAdapterCommunication *m_comm;
CecBuffer<cec_log_message> m_logBuffer;
CecBuffer<cec_keypress> m_keyBuffer;
CecBuffer<cec_command> m_commandBuffer;
return -1;
}
+int cec_set_deck_control_mode(cec_deck_control_mode mode, int bSendUpdate) {
+ if (cec_parser)
+ return cec_parser->SetDeckControlMode(mode, bSendUpdate == 1) ? 1 : 0;
+ return -1;
+}
+
+int cec_set_deck_info(cec_deck_info info, int bSendUpdate) {
+ if (cec_parser)
+ return cec_parser->SetDeckInfo(info, bSendUpdate == 1) ? 1 : 0;
+ return -1;
+
+}
+
int cec_set_inactive_view(void)
{
if (cec_parser)
return -1;
}
+int cec_set_menu_state(cec_menu_state state, int bSendUpdate) {
+ if (cec_parser)
+ return cec_parser->SetMenuState(state, bSendUpdate == 1) ? 1 : 0;
+ return -1;
+}
+
int cec_set_osd_string(cec_logical_address iLogicalAddress, cec_display_control duration, const char *strMessage)
{
if (cec_parser)
return 0;
}
+uint16_t cec_get_device_physical_address(cec_logical_address iLogicalAddress)
+{
+ if (cec_parser)
+ return cec_parser->GetDevicePhysicalAddress(iLogicalAddress);
+ return 0;
+}
+
+cec_logical_address cec_get_active_source(void)
+{
+ if (cec_parser)
+ return cec_parser->GetActiveSource();
+ return CECDEVICE_UNKNOWN;
+}
+
+int cec_is_active_source(cec_logical_address iAddress)
+{
+ if (cec_parser)
+ return cec_parser->IsActiveSource(iAddress);
+ return false;
+}
+
cec_power_status cec_get_device_power_status(cec_logical_address iLogicalAddress)
{
if (cec_parser)
int cec_poll_device(cec_logical_address iLogicalAddress)
{
if (cec_parser)
- return cec_parser->PollDevice(iLogicalAddress);
+ return cec_parser->PollDevice(iLogicalAddress) ? 1 : 0;
+ return -1;
+}
+
+cec_logical_addresses cec_get_active_devices(void)
+{
+ cec_logical_addresses addresses;
+ addresses.Clear();
+ if (cec_parser)
+ addresses = cec_parser->GetActiveDevices();
+ return addresses;
+}
+
+int cec_is_active_device(cec_logical_address iAddress)
+{
+ if (cec_parser)
+ return cec_parser->IsActiveDevice(iAddress) ? 1 : 0;
+ return -1;
+}
+
+int cec_is_active_device_type(cec_device_type type)
+{
+ if (cec_parser)
+ return cec_parser->IsActiveDeviceType(type) ? 1 : 0;
+ return -1;
+}
+
+int cec_set_hdmi_port(cec_logical_address iBaseDevice, uint8_t iPort)
+{
+ if (cec_parser)
+ return cec_parser->SetHDMIPort(iBaseDevice, iPort) ? 1 : 0;
+ return -1;
+}
+
+int cec_volume_up(int bWait)
+{
+ if (cec_parser)
+ return cec_parser->VolumeUp(bWait == 1);
+ return -1;
+}
+
+int cec_volume_down(int bWait)
+{
+ if (cec_parser)
+ return cec_parser->VolumeDown(bWait == 1);
+ return -1;
+}
+
+int cec_mute_audio(int bWait)
+{
+ if (cec_parser)
+ return cec_parser->MuteAudio(bWait == 1);
+ return -1;
+}
+
+int cec_send_keypress(cec_logical_address iDestination, cec_user_control_code key, int bWait)
+{
+ if (cec_parser)
+ return cec_parser->SendKeypress(iDestination, key, bWait == 1) ? 1 : 0;
+ return -1;
+}
+
+int cec_send_key_release(cec_logical_address iDestination, int bWait)
+{
+ if (cec_parser)
+ return cec_parser->SendKeyRelease(iDestination, bWait == 1) ? 1 : 0;
return -1;
}
+cec_osd_name cec_get_device_osd_name(cec_logical_address iAddress)
+{
+ cec_osd_name retVal;
+ retVal.device = iAddress;
+ retVal.name[0] = 0;
+
+ if (cec_parser)
+ retVal = cec_parser->GetDeviceOSDName(iAddress);
+
+ return retVal;
+}
+
+int cec_enable_physical_address_detection(void)
+{
+ return cec_parser ? (cec_parser->EnablePhysicalAddressDetection() ? 1 : 0) : -1;
+}
+
//@}
using namespace CEC;
+#define ToString(p) m_processor->ToString(p)
+
CCECAudioSystem::CCECAudioSystem(CCECProcessor *processor, cec_logical_address address, uint16_t iPhysicalAddress /* = 0 */) :
CCECBusDevice(processor, address, iPhysicalAddress),
m_systemAudioStatus(CEC_SYSTEM_AUDIO_STATUS_ON),
m_type = CEC_DEVICE_TYPE_AUDIO_SYSTEM;
}
-bool CCECAudioSystem::SetAudioStatus(const cec_audio_status status)
+bool CCECAudioSystem::SetAudioStatus(uint8_t status)
{
+ CLockObject lock(&m_writeMutex);
if (m_audioStatus != status)
{
CStdString strLog;
- strLog.Format(">> %s (%X): audio status changed from %s to %s", GetLogicalAddressName(), m_iLogicalAddress, CCECCommandHandler::ToString(m_audioStatus), CCECCommandHandler::ToString(status));
+ strLog.Format(">> %s (%X): audio status changed from %2x to %2x", GetLogicalAddressName(), m_iLogicalAddress, m_audioStatus, status);
AddLog(CEC_LOG_DEBUG, strLog.c_str());
m_audioStatus = status;
return false;
}
-bool CCECAudioSystem::SetSystemAudioMode(const cec_system_audio_status mode)
+bool CCECAudioSystem::SetSystemAudioModeStatus(const cec_system_audio_status mode)
{
+ CLockObject lock(&m_writeMutex);
if (m_systemAudioStatus != mode)
{
CStdString strLog;
- strLog.Format(">> %s (%X): system audio mode changed from %s to %s", GetLogicalAddressName(), m_iLogicalAddress, CCECCommandHandler::ToString(m_systemAudioStatus), CCECCommandHandler::ToString(mode));
+ strLog.Format(">> %s (%X): system audio mode status changed from %s to %s", GetLogicalAddressName(), m_iLogicalAddress, ToString(m_systemAudioStatus), ToString(mode));
AddLog(CEC_LOG_DEBUG, strLog.c_str());
m_systemAudioStatus = mode;
return false;
}
-bool CCECAudioSystem::SetSystemAudioMode(const cec_command &command)
+bool CCECAudioSystem::TransmitAudioStatus(cec_logical_address dest)
{
- SetSystemAudioMode((command.parameters.size == 0) ?
- CEC_SYSTEM_AUDIO_STATUS_OFF :
- CEC_SYSTEM_AUDIO_STATUS_ON);
+ uint8_t state;
+ {
+ CLockObject lock(&m_writeMutex);
+ CStdString strLog;
+ strLog.Format("<< %x -> %x: audio status '%2x'", m_iLogicalAddress, dest, m_audioStatus);
+ AddLog(CEC_LOG_NOTICE, strLog);
+ state = m_audioStatus;
+ }
- return TransmitAudioStatus(command.initiator);
+ return m_handler->TransmitAudioStatus(m_iLogicalAddress, dest, state);
}
-bool CCECAudioSystem::TransmitAudioStatus(cec_logical_address dest)
+bool CCECAudioSystem::TransmitSetSystemAudioMode(cec_logical_address dest)
{
- CStdString strLog;
- strLog.Format("<< %x -> %x: audio status '%2x'", m_iLogicalAddress, dest, CCECCommandHandler::ToString(m_audioStatus));
- AddLog(CEC_LOG_NOTICE, strLog);
-
- cec_command command;
- cec_command::format(command, m_iLogicalAddress, dest, CEC_OPCODE_REPORT_AUDIO_STATUS);
- command.parameters.push_back((uint8_t) m_audioStatus);
+ cec_system_audio_status state;
+ {
+ CLockObject lock(&m_writeMutex);
+ CStdString strLog;
+ strLog.Format("<< %x -> %x: set system audio mode '%2x'", m_iLogicalAddress, dest, m_audioStatus);
+ AddLog(CEC_LOG_NOTICE, strLog);
+ state = m_systemAudioStatus;
+ }
- return m_processor->Transmit(command);
+ return m_handler->TransmitSetSystemAudioMode(m_iLogicalAddress, dest, state);
}
bool CCECAudioSystem::TransmitSystemAudioModeStatus(cec_logical_address dest)
{
- CStdString strLog;
- strLog.Format("<< %x -> %x: system audio mode '%s'", m_iLogicalAddress, dest, CCECCommandHandler::ToString(m_systemAudioStatus));
- AddLog(CEC_LOG_NOTICE, strLog);
+ cec_system_audio_status state;
+ {
+ CLockObject lock(&m_writeMutex);
+ CStdString strLog;
+ strLog.Format("<< %x -> %x: system audio mode '%s'", m_iLogicalAddress, dest, ToString(m_systemAudioStatus));
+ AddLog(CEC_LOG_NOTICE, strLog);
+ state = m_systemAudioStatus;
+ }
+
+ return m_handler->TransmitSystemAudioModeStatus(m_iLogicalAddress, dest, state);
+}
+
+uint8_t CCECAudioSystem::VolumeUp(void)
+{
+ if (TransmitKeypress(CEC_USER_CONTROL_CODE_VOLUME_UP))
+ TransmitKeyRelease();
+
+ CLockObject lock(&m_mutex);
+ return m_audioStatus;
+}
+
+uint8_t CCECAudioSystem::VolumeDown(void)
+{
+ if (TransmitKeypress(CEC_USER_CONTROL_CODE_VOLUME_DOWN))
+ TransmitKeyRelease();
- cec_command command;
- cec_command::format(command, m_iLogicalAddress, dest, CEC_OPCODE_SYSTEM_AUDIO_MODE_STATUS);
- command.parameters.push_back((uint8_t) m_systemAudioStatus);
+ CLockObject lock(&m_mutex);
+ return m_audioStatus;
+}
+
+uint8_t CCECAudioSystem::MuteAudio(void)
+{
+ if (TransmitKeypress(CEC_USER_CONTROL_CODE_MUTE))
+ TransmitKeyRelease();
- return m_processor->Transmit(command);
+ CLockObject lock(&m_mutex);
+ return m_audioStatus;
}
CCECAudioSystem(CCECProcessor *processor, cec_logical_address address, uint16_t iPhysicalAddress = 0);
virtual ~CCECAudioSystem(void) {};
- virtual bool SetAudioStatus(const cec_audio_status status);
- virtual bool SetSystemAudioMode(const cec_system_audio_status mode);
- virtual bool SetSystemAudioMode(const cec_command &command);
+ virtual bool SetAudioStatus(uint8_t status);
+ virtual bool SetSystemAudioModeStatus(const cec_system_audio_status mode);
virtual bool TransmitAudioStatus(cec_logical_address dest);
+ virtual bool TransmitSetSystemAudioMode(cec_logical_address dest);
virtual bool TransmitSystemAudioModeStatus(cec_logical_address dest);
+ virtual uint8_t VolumeUp(void);
+ virtual uint8_t VolumeDown(void);
+ virtual uint8_t MuteAudio(void);
+
virtual bool TransmitActiveSource(void) { return false; }
protected:
cec_system_audio_status m_systemAudioStatus;
- cec_audio_status m_audioStatus;
+ uint8_t m_audioStatus;
};
}
using namespace CEC;
-#define ToString(p) CCECCommandHandler::ToString(p)
+#define ToString(p) m_processor->ToString(p)
CCECBusDevice::CCECBusDevice(CCECProcessor *processor, cec_logical_address iLogicalAddress, uint16_t iPhysicalAddress) :
m_type(CEC_DEVICE_TYPE_RESERVED),
m_vendor(CEC_VENDOR_UNKNOWN),
m_menuState(CEC_MENU_STATE_ACTIVATED),
m_bActiveSource(false),
- m_iLastCommandSent(0),
m_iLastActive(0),
- m_cecVersion(CEC_VERSION_UNKNOWN)
+ m_cecVersion(CEC_VERSION_UNKNOWN),
+ m_deviceStatus(CEC_DEVICE_STATUS_UNKNOWN)
{
m_handler = new CCECCommandHandler(this);
CCECBusDevice::~CCECBusDevice(void)
{
- m_condition.Broadcast();
delete m_handler;
}
bool CCECBusDevice::HandleCommand(const cec_command &command)
{
- CLockObject lock(&m_mutex);
- m_iLastActive = GetTimeMs();
- m_handler->HandleCommand(command);
- m_condition.Signal();
- return true;
-}
+ bool bHandled(false);
-void CCECBusDevice::PollVendorId(void)
-{
- CLockObject lock(&m_mutex);
- if (m_iLastActive > 0 && m_iLogicalAddress != CECDEVICE_BROADCAST &&
- m_vendor == CEC_VENDOR_UNKNOWN &&
- GetTimeMs() - m_iLastCommandSent > 5000 &&
- !m_processor->IsMonitoring())
+ /* update "last active" */
{
- CStdString strLog;
- strLog.Format("<< requesting vendor ID of '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
- AddLog(CEC_LOG_NOTICE, strLog);
- m_iLastCommandSent = GetTimeMs();
+ CLockObject lock(&m_writeMutex);
+ m_iLastActive = GetTimeMs();
- cec_command command;
- cec_command::format(command, GetMyLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_GIVE_DEVICE_VENDOR_ID);
- if (m_processor->Transmit(command))
- m_condition.Wait(&m_mutex, 1000);
+ if (m_deviceStatus != CEC_DEVICE_STATUS_HANDLED_BY_LIBCEC)
+ m_deviceStatus = CEC_DEVICE_STATUS_PRESENT;
}
-}
-bool CCECBusDevice::PowerOn(void)
-{
- cec_power_status current = GetPowerStatus();
- if (current != CEC_POWER_STATUS_ON &&
- current != CEC_POWER_STATUS_IN_TRANSITION_STANDBY_TO_ON)
+ /* handle the command */
+ bHandled = m_handler->HandleCommand(command);
+
+ /* change status to present */
+ if (bHandled)
{
- CStdString strLog;
- strLog.Format("<< powering on '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
- AddLog(CEC_LOG_DEBUG, strLog.c_str());
+ CLockObject lock(&m_writeMutex);
+ if (m_deviceStatus != CEC_DEVICE_STATUS_HANDLED_BY_LIBCEC)
+ {
+ if (m_deviceStatus != CEC_DEVICE_STATUS_PRESENT)
+ {
+ CStdString strLog;
+ strLog.Format("device %s (%x) status changed to present after command %s", GetLogicalAddressName(), (uint8_t)GetLogicalAddress(), ToString(command.opcode));
+ AddLog(CEC_LOG_DEBUG, strLog);
+ }
+ m_deviceStatus = CEC_DEVICE_STATUS_PRESENT;
+ }
+ }
- SetPowerStatus(CEC_POWER_STATUS_IN_TRANSITION_STANDBY_TO_ON);
+ return bHandled;
+}
- cec_command command;
- cec_command::format(command, GetMyLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_IMAGE_VIEW_ON);
+bool CCECBusDevice::PowerOn(void)
+{
+ CStdString strLog;
+ strLog.Format("<< powering on '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
+ AddLog(CEC_LOG_DEBUG, strLog.c_str());
- return m_processor->Transmit(command);
+ if (m_handler->TransmitPowerOn(GetMyLogicalAddress(), m_iLogicalAddress))
+ {
+ {
+ CLockObject lock(&m_mutex);
+// m_powerStatus = CEC_POWER_STATUS_UNKNOWN;
+ m_powerStatus = CEC_POWER_STATUS_IN_TRANSITION_STANDBY_TO_ON;
+ }
+// cec_power_status status = GetPowerStatus();
+// if (status == CEC_POWER_STATUS_STANDBY || status == CEC_POWER_STATUS_UNKNOWN)
+// {
+// /* sending the normal power on command appears to have failed */
+// CStdString strLog;
+// strLog.Format("<< sending power on keypress to '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
+// AddLog(CEC_LOG_DEBUG, strLog.c_str());
+//
+// TransmitKeypress(CEC_USER_CONTROL_CODE_POWER);
+// return TransmitKeyRelease();
+// }
+ return true;
}
- return true;
+ return false;
}
bool CCECBusDevice::Standby(void)
strLog.Format("<< putting '%s' (%X) in standby mode", GetLogicalAddressName(), m_iLogicalAddress);
AddLog(CEC_LOG_DEBUG, strLog.c_str());
- cec_command command;
- cec_command::format(command, GetMyLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_STANDBY);
-
- return m_processor->Transmit(command);
+ return m_handler->TransmitStandby(GetMyLogicalAddress(), m_iLogicalAddress);
}
/** @name Getters */
//@{
-cec_version CCECBusDevice::GetCecVersion(void)
+cec_version CCECBusDevice::GetCecVersion(bool bUpdate /* = false */)
{
- if (m_cecVersion == CEC_VERSION_UNKNOWN)
- {
- if (!MyLogicalAddressContains(m_iLogicalAddress))
- {
- CStdString strLog;
- strLog.Format("<< requesting CEC version of '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
- AddLog(CEC_LOG_NOTICE, strLog);
- cec_command command;
- cec_command::format(command, GetMyLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_GET_CEC_VERSION);
- CLockObject lock(&m_mutex);
- if (m_processor->Transmit(command))
- m_condition.Wait(&m_mutex, 1000);
- }
- }
+ CLockObject lock(&m_mutex);
+ if (GetStatus() == CEC_DEVICE_STATUS_PRESENT &&
+ (bUpdate || m_cecVersion == CEC_VERSION_UNKNOWN))
+ RequestCecVersion();
return m_cecVersion;
}
+bool CCECBusDevice::RequestCecVersion(void)
+{
+ bool bReturn(false);
+ if (!MyLogicalAddressContains(m_iLogicalAddress))
+ {
+ CStdString strLog;
+ strLog.Format("<< requesting CEC version of '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
+ AddLog(CEC_LOG_NOTICE, strLog);
+
+ bReturn = m_handler->TransmitRequestCecVersion(GetMyLogicalAddress(), m_iLogicalAddress);
+ }
+ return bReturn;
+}
+
const char* CCECBusDevice::GetLogicalAddressName(void) const
{
return ToString(m_iLogicalAddress);
}
-cec_menu_language &CCECBusDevice::GetMenuLanguage(void)
+cec_menu_language &CCECBusDevice::GetMenuLanguage(bool bUpdate /* = false */)
{
- if (!strcmp(m_menuLanguage.language, "???"))
- {
- if (!MyLogicalAddressContains(m_iLogicalAddress))
- {
- CStdString strLog;
- strLog.Format("<< requesting menu language of '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
- AddLog(CEC_LOG_NOTICE, strLog);
- cec_command command;
- cec_command::format(command, GetMyLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_GET_MENU_LANGUAGE);
- CLockObject lock(&m_mutex);
- if (m_processor->Transmit(command))
- m_condition.Wait(&m_mutex, 1000);
- }
- }
+ CLockObject lock(&m_mutex);
+ if (GetStatus() == CEC_DEVICE_STATUS_PRESENT &&
+ (bUpdate || !strcmp(m_menuLanguage.language, "???")))
+ RequestMenuLanguage();
return m_menuLanguage;
}
+bool CCECBusDevice::RequestMenuLanguage(void)
+{
+ bool bReturn(false);
+ if (!MyLogicalAddressContains(m_iLogicalAddress))
+ {
+ CStdString strLog;
+ strLog.Format("<< requesting menu language of '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
+ AddLog(CEC_LOG_NOTICE, strLog);
+ bReturn = m_handler->TransmitRequestMenuLanguage(GetMyLogicalAddress(), m_iLogicalAddress);
+ }
+ return bReturn;
+}
+
cec_logical_address CCECBusDevice::GetMyLogicalAddress(void) const
{
return m_processor->GetLogicalAddress();
return m_processor->GetPhysicalAddress();
}
-cec_power_status CCECBusDevice::GetPowerStatus(void)
+CStdString CCECBusDevice::GetOSDName(bool bUpdate /* = false */)
+{
+ CLockObject lock(&m_mutex);
+ if (GetStatus() == CEC_DEVICE_STATUS_PRESENT &&
+ (bUpdate || m_strDeviceName.Equals(ToString(m_iLogicalAddress))) &&
+ m_type != CEC_DEVICE_TYPE_TV)
+ RequestOSDName();
+
+ return m_strDeviceName;
+}
+
+bool CCECBusDevice::RequestOSDName(void)
{
- if (m_powerStatus == CEC_POWER_STATUS_UNKNOWN)
+ bool bReturn(false);
+ if (!MyLogicalAddressContains(m_iLogicalAddress))
{
- if (!MyLogicalAddressContains(m_iLogicalAddress))
- {
- CStdString strLog;
- strLog.Format("<< requesting power status of '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
- AddLog(CEC_LOG_NOTICE, strLog);
- cec_command command;
- cec_command::format(command, GetMyLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_GIVE_DEVICE_POWER_STATUS);
- CLockObject lock(&m_mutex);
- if (m_processor->Transmit(command))
- m_condition.Wait(&m_mutex, 1000);
- }
+ CStdString strLog;
+ strLog.Format("<< requesting OSD name of '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
+ AddLog(CEC_LOG_NOTICE, strLog);
+ bReturn = m_handler->TransmitRequestOSDName(GetMyLogicalAddress(), m_iLogicalAddress);
}
+ return bReturn;
+}
- return m_powerStatus;
+uint16_t CCECBusDevice::GetPhysicalAddress(bool bUpdate /* = false */)
+{
+ CLockObject lock(&m_mutex);
+ if (GetStatus() == CEC_DEVICE_STATUS_PRESENT &&
+ (m_iPhysicalAddress == 0xFFFF || bUpdate))
+ {
+ if (!RequestPhysicalAddress())
+ AddLog(CEC_LOG_ERROR, "failed to request the physical address");
+ }
+
+ return m_iPhysicalAddress;
}
-const cec_vendor_id CCECBusDevice::GetVendorId(void)
+bool CCECBusDevice::RequestPhysicalAddress(void)
{
- if (m_vendor == CEC_VENDOR_UNKNOWN)
+ bool bReturn(false);
+ if (!MyLogicalAddressContains(m_iLogicalAddress))
{
- if (!MyLogicalAddressContains(m_iLogicalAddress))
- {
- CStdString strLog;
- strLog.Format("<< requesting vendor ID of '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
- AddLog(CEC_LOG_NOTICE, strLog);
- cec_command command;
- cec_command::format(command, GetMyLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_GIVE_DEVICE_VENDOR_ID);
- CLockObject lock(&m_mutex);
+ CStdString strLog;
+ strLog.Format("<< requesting physical address of '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
+ AddLog(CEC_LOG_NOTICE, strLog);
+ bReturn = m_handler->TransmitRequestPhysicalAddress(GetMyLogicalAddress(), m_iLogicalAddress);
+ }
+ return bReturn;
+}
- if (m_processor->Transmit(command))
- m_condition.Wait(&m_mutex, 1000);
- }
+cec_power_status CCECBusDevice::GetPowerStatus(bool bUpdate /* = false */)
+{
+ CLockObject lock(&m_mutex);
+ if (GetStatus() == CEC_DEVICE_STATUS_PRESENT &&
+ (bUpdate || m_powerStatus == CEC_POWER_STATUS_UNKNOWN))
+ RequestPowerStatus();
+
+ return m_powerStatus;
+}
+
+bool CCECBusDevice::RequestPowerStatus(void)
+{
+ bool bReturn(false);
+ if (!MyLogicalAddressContains(m_iLogicalAddress))
+ {
+ CStdString strLog;
+ strLog.Format("<< requesting power status of '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
+ AddLog(CEC_LOG_NOTICE, strLog);
+ bReturn = m_handler->TransmitRequestPowerStatus(GetMyLogicalAddress(), m_iLogicalAddress);
}
+ return bReturn;
+}
+
+cec_vendor_id CCECBusDevice::GetVendorId(bool bUpdate /* = false */)
+{
+ CLockObject lock(&m_mutex);
+ if (GetStatus() == CEC_DEVICE_STATUS_PRESENT &&
+ (bUpdate || m_vendor == CEC_VENDOR_UNKNOWN))
+ RequestVendorId();
return m_vendor;
}
-const char *CCECBusDevice::GetVendorName(void)
+bool CCECBusDevice::RequestVendorId(void)
+{
+ bool bReturn(false);
+ if (!MyLogicalAddressContains(m_iLogicalAddress))
+ {
+ CStdString strLog;
+ strLog.Format("<< requesting vendor ID of '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
+ AddLog(CEC_LOG_NOTICE, strLog);
+ bReturn = m_handler->TransmitRequestVendorId(GetMyLogicalAddress(), m_iLogicalAddress);
+ }
+ return bReturn;
+}
+
+const char *CCECBusDevice::GetVendorName(bool bUpdate /* = false */)
{
- GetVendorId();
- return ToString(m_vendor);
+ return ToString(GetVendorId(bUpdate));
}
bool CCECBusDevice::MyLogicalAddressContains(cec_logical_address address) const
return m_processor->HasLogicalAddress(address);
}
+bool CCECBusDevice::NeedsPoll(void)
+{
+ bool bSendPoll(false);
+ switch (m_iLogicalAddress)
+ {
+ case CECDEVICE_PLAYBACKDEVICE3:
+ if (m_processor->m_busDevices[CECDEVICE_PLAYBACKDEVICE2]->GetStatus() == CEC_DEVICE_STATUS_PRESENT)
+ bSendPoll = true;
+ break;
+ case CECDEVICE_PLAYBACKDEVICE2:
+ if (m_processor->m_busDevices[CECDEVICE_PLAYBACKDEVICE1]->GetStatus() == CEC_DEVICE_STATUS_PRESENT)
+ bSendPoll = true;
+ break;
+ case CECDEVICE_RECORDINGDEVICE3:
+ if (m_processor->m_busDevices[CECDEVICE_RECORDINGDEVICE2]->GetStatus() == CEC_DEVICE_STATUS_PRESENT)
+ bSendPoll = true;
+ break;
+ case CECDEVICE_RECORDINGDEVICE2:
+ if (m_processor->m_busDevices[CECDEVICE_RECORDINGDEVICE1]->GetStatus() == CEC_DEVICE_STATUS_PRESENT)
+ bSendPoll = true;
+ break;
+ case CECDEVICE_TUNER4:
+ if (m_processor->m_busDevices[CECDEVICE_TUNER3]->GetStatus() == CEC_DEVICE_STATUS_PRESENT)
+ bSendPoll = true;
+ break;
+ case CECDEVICE_TUNER3:
+ if (m_processor->m_busDevices[CECDEVICE_TUNER2]->GetStatus() == CEC_DEVICE_STATUS_PRESENT)
+ bSendPoll = true;
+ break;
+ case CECDEVICE_TUNER2:
+ if (m_processor->m_busDevices[CECDEVICE_TUNER1]->GetStatus() == CEC_DEVICE_STATUS_PRESENT)
+ bSendPoll = true;
+ break;
+ case CECDEVICE_AUDIOSYSTEM:
+ case CECDEVICE_PLAYBACKDEVICE1:
+ case CECDEVICE_RECORDINGDEVICE1:
+ case CECDEVICE_TUNER1:
+ case CECDEVICE_TV:
+ bSendPoll = true;
+ break;
+ default:
+ break;
+ }
+
+ return bSendPoll;
+}
+
+cec_bus_device_status CCECBusDevice::GetStatus(bool bForcePoll /* = false */)
+{
+ CLockObject lock(&m_writeMutex);
+ if (m_deviceStatus != CEC_DEVICE_STATUS_HANDLED_BY_LIBCEC &&
+ (m_deviceStatus == CEC_DEVICE_STATUS_UNKNOWN || bForcePoll))
+ {
+ lock.Leave();
+ bool bPollAcked(false);
+ if (bForcePoll || NeedsPoll())
+ bPollAcked = m_processor->PollDevice(m_iLogicalAddress);
+
+ lock.Lock();
+ m_deviceStatus = bPollAcked ? CEC_DEVICE_STATUS_PRESENT : CEC_DEVICE_STATUS_NOT_PRESENT;
+ }
+
+ return m_deviceStatus;
+}
+
//@}
/** @name Setters */
void CCECBusDevice::SetMenuLanguage(const cec_menu_language &language)
{
+ CLockObject lock(&m_writeMutex);
if (language.device == m_iLogicalAddress)
{
CStdString strLog;
}
}
+void CCECBusDevice::SetOSDName(CStdString strName)
+{
+ CLockObject lock(&m_writeMutex);
+ if (m_strDeviceName != strName)
+ {
+ CStdString strLog;
+ strLog.Format(">> %s (%X): osd name set to '%s'", GetLogicalAddressName(), m_iLogicalAddress, strName);
+ m_processor->AddLog(CEC_LOG_DEBUG, strLog);
+ m_strDeviceName = strName;
+ }
+}
+
void CCECBusDevice::SetMenuState(const cec_menu_state state)
{
+ CLockObject lock(&m_writeMutex);
if (m_menuState != state)
{
CStdString strLog;
}
}
+void CCECBusDevice::SetInactiveSource(void)
+{
+ {
+ CLockObject lock(&m_writeMutex);
+ m_bActiveSource = false;
+ }
+
+ if (MyLogicalAddressContains(m_iLogicalAddress))
+ SetPowerStatus(CEC_POWER_STATUS_STANDBY);
+}
+
+void CCECBusDevice::SetActiveSource(void)
+{
+ CLockObject lock(&m_writeMutex);
+
+ for (int iPtr = 0; iPtr < 16; iPtr++)
+ if (iPtr != m_iLogicalAddress)
+ m_processor->m_busDevices[iPtr]->SetInactiveSource();
+
+ m_bActiveSource = true;
+ m_powerStatus = CEC_POWER_STATUS_ON;
+}
+
+bool CCECBusDevice::TryLogicalAddress(void)
+{
+ CStdString strLog;
+ strLog.Format("trying logical address '%s'", GetLogicalAddressName());
+ AddLog(CEC_LOG_DEBUG, strLog);
+
+ m_processor->SetAckMask(0x1 << m_iLogicalAddress);
+ if (!TransmitPoll(m_iLogicalAddress))
+ {
+ strLog.Format("using logical address '%s'", GetLogicalAddressName());
+ AddLog(CEC_LOG_NOTICE, strLog);
+ SetDeviceStatus(CEC_DEVICE_STATUS_HANDLED_BY_LIBCEC);
+
+ return true;
+ }
+
+ strLog.Format("logical address '%s' already taken", GetLogicalAddressName());
+ AddLog(CEC_LOG_DEBUG, strLog);
+ SetDeviceStatus(CEC_DEVICE_STATUS_PRESENT);
+ return false;
+}
+
+void CCECBusDevice::SetDeviceStatus(const cec_bus_device_status newStatus)
+{
+ CLockObject lock(&m_writeMutex);
+ switch (newStatus)
+ {
+ case CEC_DEVICE_STATUS_UNKNOWN:
+ m_iStreamPath = 0;
+ m_powerStatus = CEC_POWER_STATUS_UNKNOWN;
+ m_vendor = CEC_VENDOR_UNKNOWN;
+ m_menuState = CEC_MENU_STATE_ACTIVATED;
+ m_bActiveSource = false;
+ m_iLastActive = 0;
+ m_cecVersion = CEC_VERSION_UNKNOWN;
+ m_deviceStatus = newStatus;
+ break;
+ case CEC_DEVICE_STATUS_HANDLED_BY_LIBCEC:
+ m_iStreamPath = 0;
+ m_powerStatus = CEC_POWER_STATUS_ON;
+ m_vendor = CEC_VENDOR_UNKNOWN;
+ m_menuState = CEC_MENU_STATE_ACTIVATED;
+ m_bActiveSource = false;
+ m_iLastActive = 0;
+ m_cecVersion = CEC_VERSION_1_3A;
+ m_deviceStatus = newStatus;
+ break;
+ case CEC_DEVICE_STATUS_PRESENT:
+ case CEC_DEVICE_STATUS_NOT_PRESENT:
+ m_deviceStatus = newStatus;
+ break;
+ }
+}
+
void CCECBusDevice::SetPhysicalAddress(uint16_t iNewAddress)
{
- if (iNewAddress > 0)
+ CLockObject lock(&m_writeMutex);
+ if (iNewAddress > 0 && m_iPhysicalAddress != iNewAddress)
{
CStdString strLog;
strLog.Format(">> %s (%X): physical address changed from %04x to %04x", GetLogicalAddressName(), m_iLogicalAddress, m_iPhysicalAddress, iNewAddress);
void CCECBusDevice::SetStreamPath(uint16_t iNewAddress, uint16_t iOldAddress /* = 0 */)
{
+ CLockObject lock(&m_writeMutex);
if (iNewAddress > 0)
{
CStdString strLog;
- strLog.Format(">> %s (%X): stream path changed from %04x to %04x", GetLogicalAddressName(), m_iLogicalAddress, iOldAddress, iNewAddress);
+ strLog.Format(">> %s (%X): stream path changed from %04x to %04x", GetLogicalAddressName(), m_iLogicalAddress, iOldAddress == 0 ? m_iStreamPath : iOldAddress, iNewAddress);
AddLog(CEC_LOG_DEBUG, strLog.c_str());
m_iStreamPath = iNewAddress;
if (iNewAddress > 0)
+ {
+ lock.Leave();
SetPowerStatus(CEC_POWER_STATUS_ON);
+ }
}
}
void CCECBusDevice::SetPowerStatus(const cec_power_status powerStatus)
{
+ CLockObject lock(&m_writeMutex);
if (m_powerStatus != powerStatus)
{
CStdString strLog;
}
}
-void CCECBusDevice::SetVendorId(uint64_t iVendorId)
+bool CCECBusDevice::SetVendorId(uint64_t iVendorId, bool bInitHandler /* = true */)
{
- m_vendor = (cec_vendor_id)iVendorId;
+ bool bVendorChanged(false);
- switch (iVendorId)
{
- case CEC_VENDOR_SAMSUNG:
- if (m_handler->GetVendorId() != CEC_VENDOR_SAMSUNG)
- {
- delete m_handler;
- m_handler = new CANCommandHandler(this);
- }
- break;
- case CEC_VENDOR_LG:
- if (m_handler->GetVendorId() != CEC_VENDOR_LG)
- {
- delete m_handler;
- m_handler = new CSLCommandHandler(this);
- }
- break;
- case CEC_VENDOR_PANASONIC:
- if (m_handler->GetVendorId() != CEC_VENDOR_PANASONIC)
- {
+ CLockObject lock(&m_writeMutex);
+ bVendorChanged = (m_vendor != (cec_vendor_id)iVendorId);
+ m_vendor = (cec_vendor_id)iVendorId;
+
+ if (bVendorChanged)
delete m_handler;
- m_handler = new CVLCommandHandler(this);
- }
- break;
- default:
- if (m_handler->GetVendorId() != CEC_VENDOR_UNKNOWN)
+
+ switch (iVendorId)
{
- delete m_handler;
- m_handler = new CCECCommandHandler(this);
+ case CEC_VENDOR_SAMSUNG:
+ if (bVendorChanged)
+ m_handler = new CANCommandHandler(this);
+ break;
+ case CEC_VENDOR_LG:
+ if (bVendorChanged)
+ m_handler = new CSLCommandHandler(this);
+ break;
+ case CEC_VENDOR_PANASONIC:
+ if (bVendorChanged)
+ m_handler = new CVLCommandHandler(this);
+ break;
+ default:
+ if (bVendorChanged)
+ m_handler = new CCECCommandHandler(this);
+ break;
}
- break;
}
+ if (bVendorChanged && bInitHandler)
+ m_handler->InitHandler();
+
CStdString strLog;
- strLog.Format("%s (%X): vendor = %s (%06x)", GetLogicalAddressName(), m_iLogicalAddress, GetVendorName(), GetVendorId());
+ strLog.Format("%s (%X): vendor = %s (%06x)", GetLogicalAddressName(), m_iLogicalAddress, ToString(m_vendor), m_vendor);
m_processor->AddLog(CEC_LOG_DEBUG, strLog.c_str());
+
+ return bVendorChanged;
}
//@}
//@{
bool CCECBusDevice::TransmitActiveSource(void)
{
- if (m_powerStatus != CEC_POWER_STATUS_ON)
- {
- CStdString strLog;
- strLog.Format("<< %s (%X) is not powered on", GetLogicalAddressName(), m_iLogicalAddress);
- AddLog(CEC_LOG_DEBUG, strLog);
- }
- else if (m_bActiveSource)
- {
- CStdString strLog;
- strLog.Format("<< %s (%X) -> broadcast (F): active source (%4x)", GetLogicalAddressName(), m_iLogicalAddress, m_iPhysicalAddress);
- AddLog(CEC_LOG_NOTICE, strLog);
+ bool bSendActiveSource(false);
- cec_command command;
- cec_command::format(command, m_iLogicalAddress, CECDEVICE_BROADCAST, CEC_OPCODE_ACTIVE_SOURCE);
- command.parameters.push_back((uint8_t) ((m_iPhysicalAddress >> 8) & 0xFF));
- command.parameters.push_back((uint8_t) (m_iPhysicalAddress & 0xFF));
-
- return m_processor->Transmit(command);
- }
- else
{
- CStdString strLog;
- strLog.Format("<< %s (%X) is not the active source", GetLogicalAddressName(), m_iLogicalAddress);
- AddLog(CEC_LOG_DEBUG, strLog);
+ CLockObject lock(&m_writeMutex);
+ if (m_powerStatus != CEC_POWER_STATUS_ON)
+ {
+ CStdString strLog;
+ strLog.Format("<< %s (%X) is not powered on", GetLogicalAddressName(), m_iLogicalAddress);
+ AddLog(CEC_LOG_DEBUG, strLog);
+ }
+ else if (m_bActiveSource)
+ {
+ CStdString strLog;
+ strLog.Format("<< %s (%X) -> broadcast (F): active source (%4x)", GetLogicalAddressName(), m_iLogicalAddress, m_iPhysicalAddress);
+ AddLog(CEC_LOG_NOTICE, strLog);
+ bSendActiveSource = true;
+ }
+ else
+ {
+ CStdString strLog;
+ strLog.Format("<< %s (%X) is not the active source", GetLogicalAddressName(), m_iLogicalAddress);
+ AddLog(CEC_LOG_DEBUG, strLog);
+ }
}
- return false;
+ return bSendActiveSource ? m_handler->TransmitActiveSource(m_iLogicalAddress, m_iPhysicalAddress) : false;
}
bool CCECBusDevice::TransmitCECVersion(cec_logical_address dest)
{
- CStdString strLog;
- strLog.Format("<< %s (%X) -> %s (%X): cec version %s", GetLogicalAddressName(), m_iLogicalAddress, ToString(dest), dest, ToString(m_cecVersion));
- AddLog(CEC_LOG_NOTICE, strLog);
-
- cec_command command;
- cec_command::format(command, m_iLogicalAddress, dest, CEC_OPCODE_CEC_VERSION);
- command.parameters.push_back((uint8_t)m_cecVersion);
+ cec_version version;
+ {
+ CLockObject lock(&m_writeMutex);
+ CStdString strLog;
+ strLog.Format("<< %s (%X) -> %s (%X): cec version %s", GetLogicalAddressName(), m_iLogicalAddress, ToString(dest), dest, ToString(m_cecVersion));
+ AddLog(CEC_LOG_NOTICE, strLog);
+ version = m_cecVersion;
+ }
- return m_processor->Transmit(command);
+ return m_handler->TransmitCECVersion(m_iLogicalAddress, dest, version);
}
-bool CCECBusDevice::TransmitInactiveView(void)
+bool CCECBusDevice::TransmitInactiveSource(void)
{
- CStdString strLog;
- strLog.Format("<< %s (%X) -> broadcast (F): inactive view", GetLogicalAddressName(), m_iLogicalAddress);
- AddLog(CEC_LOG_NOTICE, strLog);
-
- cec_command command;
- cec_command::format(command, m_iLogicalAddress, CECDEVICE_BROADCAST, CEC_OPCODE_INACTIVE_SOURCE);
- command.parameters.push_back((m_iPhysicalAddress >> 8) & 0xFF);
- command.parameters.push_back(m_iPhysicalAddress & 0xFF);
+ uint16_t iPhysicalAddress;
+ {
+ CLockObject lock(&m_writeMutex);
+ CStdString strLog;
+ strLog.Format("<< %s (%X) -> broadcast (F): inactive source", GetLogicalAddressName(), m_iLogicalAddress);
+ AddLog(CEC_LOG_NOTICE, strLog);
+ iPhysicalAddress = m_iPhysicalAddress;
+ }
- return m_processor->Transmit(command);
+ return m_handler->TransmitInactiveSource(m_iLogicalAddress, iPhysicalAddress);
}
bool CCECBusDevice::TransmitMenuState(cec_logical_address dest)
{
- CStdString strLog;
- strLog.Format("<< %s (%X) -> %s (%X): menu state '%s'", GetLogicalAddressName(), m_iLogicalAddress, ToString(dest), dest, ToString(m_menuState));
- AddLog(CEC_LOG_NOTICE, strLog);
-
- cec_command command;
- cec_command::format(command, m_iLogicalAddress, dest, CEC_OPCODE_MENU_STATUS);
- command.parameters.push_back((uint8_t)m_menuState);
+ cec_menu_state menuState;
+ {
+ CLockObject lock(&m_writeMutex);
+ CStdString strLog;
+ strLog.Format("<< %s (%X) -> %s (%X): menu state '%s'", GetLogicalAddressName(), m_iLogicalAddress, ToString(dest), dest, ToString(m_menuState));
+ AddLog(CEC_LOG_NOTICE, strLog);
+ menuState = m_menuState;
+ }
- return m_processor->Transmit(command);
+ return m_handler->TransmitMenuState(m_iLogicalAddress, dest, menuState);
}
bool CCECBusDevice::TransmitOSDName(cec_logical_address dest)
{
- CStdString strLog;
- strLog.Format("<< %s (%X) -> %s (%X): OSD name '%s'", GetLogicalAddressName(), m_iLogicalAddress, ToString(dest), dest, m_strDeviceName.c_str());
- AddLog(CEC_LOG_NOTICE, strLog.c_str());
-
- cec_command command;
- cec_command::format(command, m_iLogicalAddress, dest, CEC_OPCODE_SET_OSD_NAME);
- for (unsigned int iPtr = 0; iPtr < m_strDeviceName.length(); iPtr++)
- command.parameters.push_back(m_strDeviceName.at(iPtr));
+ CStdString strDeviceName;
+ {
+ CLockObject lock(&m_writeMutex);
+ CStdString strLog;
+ strLog.Format("<< %s (%X) -> %s (%X): OSD name '%s'", GetLogicalAddressName(), m_iLogicalAddress, ToString(dest), dest, m_strDeviceName.c_str());
+ AddLog(CEC_LOG_NOTICE, strLog.c_str());
+ strDeviceName = m_strDeviceName;
+ }
- return m_processor->Transmit(command);
+ return m_handler->TransmitOSDName(m_iLogicalAddress, dest, strDeviceName);
}
bool CCECBusDevice::TransmitOSDString(cec_logical_address dest, cec_display_control duration, const char *strMessage)
strLog.Format("<< %s (%X) -> %s (%X): display OSD message '%s'", GetLogicalAddressName(), m_iLogicalAddress, ToString(dest), dest, strMessage);
AddLog(CEC_LOG_NOTICE, strLog.c_str());
- cec_command command;
- cec_command::format(command, m_iLogicalAddress, dest, CEC_OPCODE_SET_OSD_STRING);
- command.parameters.push_back((uint8_t)duration);
-
- unsigned int iLen = strlen(strMessage);
- if (iLen > 13) iLen = 13;
-
- for (unsigned int iPtr = 0; iPtr < iLen; iPtr++)
- command.parameters.push_back(strMessage[iPtr]);
-
- return m_processor->Transmit(command);
+ return m_handler->TransmitOSDString(m_iLogicalAddress, dest, duration, strMessage);
}
bool CCECBusDevice::TransmitPhysicalAddress(void)
{
- CStdString strLog;
- strLog.Format("<< %s (%X) -> broadcast (F): physical adddress %4x", GetLogicalAddressName(), m_iLogicalAddress, m_iPhysicalAddress);
- AddLog(CEC_LOG_NOTICE, strLog.c_str());
+ uint16_t iPhysicalAddress;
+ cec_device_type type;
+ {
+ CLockObject lock(&m_writeMutex);
+ if (m_iPhysicalAddress == 0xffff)
+ return false;
- cec_command command;
- cec_command::format(command, m_iLogicalAddress, CECDEVICE_BROADCAST, CEC_OPCODE_REPORT_PHYSICAL_ADDRESS);
- command.parameters.push_back((uint8_t) ((m_iPhysicalAddress >> 8) & 0xFF));
- command.parameters.push_back((uint8_t) (m_iPhysicalAddress & 0xFF));
- command.parameters.push_back((uint8_t) (m_type));
+ CStdString strLog;
+ strLog.Format("<< %s (%X) -> broadcast (F): physical adddress %4x", GetLogicalAddressName(), m_iLogicalAddress, m_iPhysicalAddress);
+ AddLog(CEC_LOG_NOTICE, strLog.c_str());
- return m_processor->Transmit(command);
+ iPhysicalAddress = m_iPhysicalAddress;
+ type = m_type;
+ }
+
+ return m_handler->TransmitPhysicalAddress(m_iLogicalAddress, iPhysicalAddress, type);
}
bool CCECBusDevice::TransmitPoll(cec_logical_address dest)
{
bool bReturn(false);
-
if (dest == CECDEVICE_UNKNOWN)
dest = m_iLogicalAddress;
+ CCECBusDevice *destDevice = m_processor->m_busDevices[dest];
+ if (destDevice->m_deviceStatus == CEC_DEVICE_STATUS_HANDLED_BY_LIBCEC)
+ return bReturn;
+
CStdString strLog;
strLog.Format("<< %s (%X) -> %s (%X): POLL", GetLogicalAddressName(), m_iLogicalAddress, ToString(dest), dest);
AddLog(CEC_LOG_NOTICE, strLog.c_str());
+ bReturn = m_handler->TransmitPoll(m_iLogicalAddress, dest);
+ AddLog(CEC_LOG_DEBUG, bReturn ? ">> POLL sent" : ">> POLL not sent");
- cec_command command;
- cec_command::format(command, m_iLogicalAddress, dest, CEC_OPCODE_NONE);
- CLockObject lock(&m_mutex);
+ CLockObject lock(&m_writeMutex);
+ if (bReturn)
+ {
+ m_iLastActive = GetTimeMs();
+ destDevice->m_deviceStatus = CEC_DEVICE_STATUS_PRESENT;
+ }
+ else
+ destDevice->m_deviceStatus = CEC_DEVICE_STATUS_NOT_PRESENT;
- bReturn = m_processor->Transmit(command);
- AddLog(CEC_LOG_DEBUG, bReturn ? ">> POLL sent" : ">> POLL not sent");
return bReturn;
}
bool CCECBusDevice::TransmitPowerState(cec_logical_address dest)
{
- CStdString strLog;
- strLog.Format("<< %s (%X) -> %s (%X): %s", GetLogicalAddressName(), m_iLogicalAddress, ToString(dest), dest, ToString(m_powerStatus));
- AddLog(CEC_LOG_NOTICE, strLog.c_str());
-
- cec_command command;
- cec_command::format(command, m_iLogicalAddress, dest, CEC_OPCODE_REPORT_POWER_STATUS);
- command.parameters.push_back((uint8_t) m_powerStatus);
+ cec_power_status state;
+ {
+ CLockObject lock(&m_writeMutex);
+ CStdString strLog;
+ strLog.Format("<< %s (%X) -> %s (%X): %s", GetLogicalAddressName(), m_iLogicalAddress, ToString(dest), dest, ToString(m_powerStatus));
+ AddLog(CEC_LOG_NOTICE, strLog.c_str());
+ state = m_powerStatus;
+ }
- return m_processor->Transmit(command);
+ return m_handler->TransmitPowerState(m_iLogicalAddress, dest, state);
}
-bool CCECBusDevice::TransmitVendorID(cec_logical_address dest)
+bool CCECBusDevice::TransmitVendorID(cec_logical_address dest, bool bSendAbort /* = true */)
{
- if (m_vendor == CEC_VENDOR_UNKNOWN)
+ uint64_t iVendorId;
{
- CStdString strLog;
- strLog.Format("<< %s (%X) -> %s (%X): vendor id feature abort", GetLogicalAddressName(), m_iLogicalAddress, ToString(dest), dest);
- AddLog(CEC_LOG_NOTICE, strLog);
+ CLockObject lock(&m_writeMutex);
+ iVendorId = (uint64_t)m_vendor;
+ }
- m_processor->TransmitAbort(dest, CEC_OPCODE_GIVE_DEVICE_VENDOR_ID);
+ if (iVendorId == CEC_VENDOR_UNKNOWN)
+ {
+ if (bSendAbort)
+ {
+ CStdString strLog;
+ strLog.Format("<< %s (%X) -> %s (%X): vendor id feature abort", GetLogicalAddressName(), m_iLogicalAddress, ToString(dest), dest);
+ AddLog(CEC_LOG_NOTICE, strLog);
+
+ m_processor->TransmitAbort(dest, CEC_OPCODE_GIVE_DEVICE_VENDOR_ID);
+ }
return false;
}
else
{
CStdString strLog;
- strLog.Format("<< %s (%X) -> %s (%X): vendor id %s (%x)", GetLogicalAddressName(), m_iLogicalAddress, ToString(dest), dest, ToString(m_vendor), (uint64_t)m_vendor);
+ strLog.Format("<< %s (%X) -> %s (%X): vendor id %s (%x)", GetLogicalAddressName(), m_iLogicalAddress, ToString(dest), dest, ToString((cec_vendor_id)iVendorId), iVendorId);
AddLog(CEC_LOG_NOTICE, strLog);
- cec_command command;
- cec_command::format(command, m_iLogicalAddress, dest, CEC_OPCODE_GIVE_DEVICE_VENDOR_ID);
+ return m_handler->TransmitVendorID(m_iLogicalAddress, iVendorId);
+ }
+}
- command.parameters.push_back((uint8_t) (((uint64_t)m_vendor >> 16) & 0xFF));
- command.parameters.push_back((uint8_t) (((uint64_t)m_vendor >> 8) & 0xFF));
- command.parameters.push_back((uint8_t) ((uint64_t)m_vendor & 0xFF));
+bool CCECBusDevice::TransmitKeypress(cec_user_control_code key)
+{
+ return m_handler->TransmitKeypress(m_processor->GetLogicalAddress(), m_iLogicalAddress, key);
+}
- return m_processor->Transmit(command);
- }
+bool CCECBusDevice::TransmitKeyRelease(void)
+{
+ return m_handler->TransmitKeyRelease(m_processor->GetLogicalAddress(), m_iLogicalAddress);
}
//@}
{
class CCECProcessor;
class CCECCommandHandler;
+ class CSLCommandHandler;
class CCECBusDevice
{
friend class CCECProcessor;
+ friend class CSLCommandHandler;
public:
CCECBusDevice(CCECProcessor *processor, cec_logical_address address, uint16_t iPhysicalAddress = 0);
virtual void AddLog(cec_log_level level, const CStdString &strMessage);
virtual bool HandleCommand(const cec_command &command);
- virtual void PollVendorId(void);
virtual bool PowerOn(void);
virtual bool Standby(void);
- virtual cec_version GetCecVersion(void);
- virtual CCECCommandHandler *GetHandler(void) const { return m_handler; };
- virtual uint64_t GetCommandSent(void) const { return m_iLastCommandSent; }
- virtual uint64_t GetLastActive(void) const { return m_iLastActive; }
- virtual cec_logical_address GetLogicalAddress(void) const { return m_iLogicalAddress; }
- virtual const char* GetLogicalAddressName(void) const;
- virtual cec_menu_language & GetMenuLanguage(void);
- virtual cec_logical_address GetMyLogicalAddress(void) const;
- virtual uint16_t GetMyPhysicalAddress(void) const;
- virtual uint16_t GetPhysicalAddress(void) const { return m_iPhysicalAddress; }
- virtual cec_power_status GetPowerStatus(void);
- virtual CCECProcessor * GetProcessor(void) const { return m_processor; }
- virtual cec_device_type GetType(void) const { return m_type; }
- virtual const cec_vendor_id GetVendorId(void);
- virtual const char * GetVendorName(void);
- virtual bool MyLogicalAddressContains(cec_logical_address address) const;
+ virtual cec_version GetCecVersion(bool bUpdate = false);
+ virtual CCECCommandHandler * GetHandler(void) const { return m_handler; };
+ virtual uint64_t GetLastActive(void) const { return m_iLastActive; }
+ virtual cec_logical_address GetLogicalAddress(void) const { return m_iLogicalAddress; }
+ virtual const char* GetLogicalAddressName(void) const;
+ virtual cec_menu_language & GetMenuLanguage(bool bUpdate = false);
+ virtual cec_logical_address GetMyLogicalAddress(void) const;
+ virtual uint16_t GetMyPhysicalAddress(void) const;
+ virtual CStdString GetOSDName(bool bUpdate = false);
+ virtual uint16_t GetPhysicalAddress(bool bUpdate = false);
+ virtual cec_power_status GetPowerStatus(bool bUpdate = false);
+ virtual CCECProcessor * GetProcessor(void) const { return m_processor; }
+ virtual cec_device_type GetType(void) const { return m_type; }
+ virtual cec_vendor_id GetVendorId(bool bUpdate = false);
+ virtual const char * GetVendorName(bool bUpdate = false);
+ virtual bool MyLogicalAddressContains(cec_logical_address address) const;
+ virtual cec_bus_device_status GetStatus(bool bForcePoll = false);
+ virtual bool IsActiveSource(void) const { return m_bActiveSource; }
+
+ virtual void SetInactiveSource(void);
+ virtual void SetActiveSource(void);
+ virtual bool TryLogicalAddress(void);
+
+ virtual void SetDeviceStatus(const cec_bus_device_status newStatus);
virtual void SetPhysicalAddress(uint16_t iNewAddress);
virtual void SetStreamPath(uint16_t iNewAddress, uint16_t iOldAddress = 0);
virtual void SetCecVersion(const cec_version newVersion);
virtual void SetMenuLanguage(const cec_menu_language &menuLanguage);
+ virtual void SetOSDName(CStdString strName);
virtual void SetMenuState(const cec_menu_state state);
- virtual void SetVendorId(uint64_t iVendorId);
+ virtual bool SetVendorId(uint64_t iVendorId, bool bInitHandler = true);
virtual void SetPowerStatus(const cec_power_status powerStatus);
virtual bool TransmitActiveSource(void);
virtual bool TransmitCECVersion(cec_logical_address dest);
- virtual bool TransmitInactiveView(void);
+ virtual bool TransmitInactiveSource(void);
virtual bool TransmitMenuState(cec_logical_address dest);
virtual bool TransmitOSDName(cec_logical_address dest);
virtual bool TransmitOSDString(cec_logical_address dest, cec_display_control duration, const char *strMessage);
virtual bool TransmitPhysicalAddress(void);
virtual bool TransmitPowerState(cec_logical_address dest);
virtual bool TransmitPoll(cec_logical_address dest);
- virtual bool TransmitVendorID(cec_logical_address dest);
+ virtual bool TransmitVendorID(cec_logical_address dest, bool bSendAbort = true);
+ virtual bool TransmitKeypress(cec_user_control_code key);
+ virtual bool TransmitKeyRelease(void);
protected:
- cec_device_type m_type;
- CStdString m_strDeviceName;
- uint16_t m_iPhysicalAddress;
- uint16_t m_iStreamPath;
- cec_logical_address m_iLogicalAddress;
- cec_power_status m_powerStatus;
- cec_menu_language m_menuLanguage;
- CCECProcessor *m_processor;
- CCECCommandHandler *m_handler;
- cec_vendor_id m_vendor;
- cec_menu_state m_menuState;
- bool m_bActiveSource;
- uint64_t m_iLastCommandSent;
- uint64_t m_iLastActive;
- cec_version m_cecVersion;
- CMutex m_mutex;
- CCondition m_condition;
+ bool RequestCecVersion(void);
+ bool RequestMenuLanguage(void);
+ bool RequestPowerStatus(void);
+ bool RequestVendorId(void);
+ bool RequestPhysicalAddress(void);
+ bool RequestOSDName(void);
+
+ bool NeedsPoll(void);
+
+ cec_device_type m_type;
+ CStdString m_strDeviceName;
+ uint16_t m_iPhysicalAddress;
+ uint16_t m_iStreamPath;
+ cec_logical_address m_iLogicalAddress;
+ cec_power_status m_powerStatus;
+ cec_menu_language m_menuLanguage;
+ CCECProcessor * m_processor;
+ CCECCommandHandler * m_handler;
+ cec_vendor_id m_vendor;
+ cec_menu_state m_menuState;
+ bool m_bActiveSource;
+ uint64_t m_iLastActive;
+ cec_version m_cecVersion;
+ cec_bus_device_status m_deviceStatus;
+ CMutex m_writeMutex;
+ CMutex m_mutex;
};
};
using namespace CEC;
+#define ToString(p) m_processor->ToString(p)
+
CCECPlaybackDevice::CCECPlaybackDevice(CCECProcessor *processor, cec_logical_address address, uint16_t iPhysicalAddress /* = 0 */) :
CCECBusDevice(processor, address, iPhysicalAddress),
m_deckStatus(CEC_DECK_INFO_STOP),
m_type = CEC_DEVICE_TYPE_PLAYBACK_DEVICE;
}
+cec_deck_info CCECPlaybackDevice::GetDeckStatus(void)
+{
+ CLockObject lock(&m_mutex);
+ return m_deckStatus;
+}
+
void CCECPlaybackDevice::SetDeckStatus(cec_deck_info deckStatus)
{
- if (m_deckStatus != deckStatus)
+ CLockObject lock(&m_writeMutex);
+ if (m_deckStatus != deckStatus && m_deckStatus != CEC_DECK_INFO_OTHER_STATUS_LG)
{
CStdString strLog;
- strLog.Format(">> %s (%X): deck status changed from '%s' to '%s'", GetLogicalAddressName(), m_iLogicalAddress, CCECCommandHandler::ToString(m_deckStatus), CCECCommandHandler::ToString(deckStatus));
+ strLog.Format(">> %s (%X): deck status changed from '%s' to '%s'", GetLogicalAddressName(), m_iLogicalAddress, ToString(m_deckStatus), ToString(deckStatus));
AddLog(CEC_LOG_DEBUG, strLog.c_str());
m_deckStatus = deckStatus;
}
}
+cec_deck_control_mode CCECPlaybackDevice::GetDeckControlMode(void)
+{
+ CLockObject lock(&m_mutex);
+ return m_deckControlMode;
+}
+
void CCECPlaybackDevice::SetDeckControlMode(cec_deck_control_mode mode)
{
+ CLockObject lock(&m_writeMutex);
if (m_deckControlMode != mode)
{
CStdString strLog;
- strLog.Format(">> %s (%X): deck control mode changed from '%s' to '%s'", GetLogicalAddressName(), m_iLogicalAddress, CCECCommandHandler::ToString(m_deckControlMode), CCECCommandHandler::ToString(mode));
+ strLog.Format(">> %s (%X): deck control mode changed from '%s' to '%s'", GetLogicalAddressName(), m_iLogicalAddress, ToString(m_deckControlMode), ToString(mode));
AddLog(CEC_LOG_DEBUG, strLog.c_str());
m_deckControlMode = mode;
bool CCECPlaybackDevice::TransmitDeckStatus(cec_logical_address dest)
{
- CStdString strLog;
- strLog.Format("<< %s (%X) -> %s (%X): deck status '%s'", GetLogicalAddressName(), m_iLogicalAddress, CCECCommandHandler::ToString(dest), dest, CCECCommandHandler::ToString(m_deckStatus));
- AddLog(CEC_LOG_NOTICE, strLog);
-
- cec_command command;
- cec_command::format(command, m_iLogicalAddress, dest, CEC_OPCODE_DECK_STATUS);
- command.push_back((uint8_t)m_deckStatus);
+ cec_deck_info state;
+ {
+ CLockObject lock(&m_writeMutex);
+ CStdString strLog;
+ strLog.Format("<< %s (%X) -> %s (%X): deck status '%s'", GetLogicalAddressName(), m_iLogicalAddress, ToString(dest), dest, ToString(m_deckStatus));
+ AddLog(CEC_LOG_NOTICE, strLog);
+ state = m_deckStatus;
+ }
- return m_processor->Transmit(command);
+ return m_handler->TransmitDeckStatus(m_iLogicalAddress, dest, state);
}
CCECPlaybackDevice(CCECProcessor *processor, cec_logical_address address, uint16_t iPhysicalAddress = 0);
virtual ~CCECPlaybackDevice(void) {};
- virtual cec_deck_info GetDeckStatus(void) const { return m_deckStatus; };
- virtual cec_deck_control_mode GetDeckControlMode(void) const { return m_deckControlMode; };
+ virtual cec_deck_info GetDeckStatus(void);
+ virtual cec_deck_control_mode GetDeckControlMode(void);
virtual void SetDeckStatus(cec_deck_info deckStatus);
virtual void SetDeckControlMode(cec_deck_control_mode mode);
using namespace CEC;
CCECRecordingDevice::CCECRecordingDevice(CCECProcessor *processor, cec_logical_address address, uint16_t iPhysicalAddress /* = 0 */) :
- CCECBusDevice(processor, address, iPhysicalAddress)
+ CCECBusDevice(processor, address, iPhysicalAddress),
+ m_playbackDevice(processor, address, iPhysicalAddress),
+ m_tuner(processor, address, iPhysicalAddress)
{
- m_type = CEC_DEVICE_TYPE_RECORDING_DEVICE;
+ m_type = CEC_DEVICE_TYPE_RECORDING_DEVICE;
+}
+
+cec_deck_info CCECRecordingDevice::GetDeckStatus(void)
+{
+ return m_playbackDevice.GetDeckStatus();
+}
+
+cec_deck_control_mode CCECRecordingDevice::GetDeckControlMode(void)
+{
+ return m_playbackDevice.GetDeckControlMode();
+}
+
+void CCECRecordingDevice::SetDeckStatus(cec_deck_info deckStatus)
+{
+ m_playbackDevice.SetDeckStatus(deckStatus);
+}
+
+void CCECRecordingDevice::SetDeckControlMode(cec_deck_control_mode mode)
+{
+ m_playbackDevice.SetDeckControlMode(mode);
+}
+
+bool CCECRecordingDevice::TransmitDeckStatus(cec_logical_address dest)
+{
+ return m_playbackDevice.TransmitDeckStatus(dest);
}
*/
#include "CECBusDevice.h"
+#include "CECPlaybackDevice.h"
+#include "CECTuner.h"
namespace CEC
{
public:
CCECRecordingDevice(CCECProcessor *processor, cec_logical_address address, uint16_t iPhysicalAddress = 0);
virtual ~CCECRecordingDevice(void) {};
+
+ /* playback device methods */
+ virtual cec_deck_info GetDeckStatus(void);
+ virtual cec_deck_control_mode GetDeckControlMode(void);
+
+ virtual void SetDeckStatus(cec_deck_info deckStatus);
+ virtual void SetDeckControlMode(cec_deck_control_mode mode);
+
+ virtual bool TransmitDeckStatus(cec_logical_address dest);
+
+ /* tuner methods */
+ //TODO
+
+ protected:
+ CCECPlaybackDevice m_playbackDevice;
+ CCECTuner m_tuner;
};
}
bool CANCommandHandler::HandleVendorRemoteButtonDown(const cec_command &command)
{
- if (command.parameters.size > 0)
+ if (m_processor->IsStarted() && command.parameters.size > 0)
{
cec_keypress key;
key.duration = CEC_BUTTON_TIMEOUT;
using namespace CEC;
using namespace std;
-CCECCommandHandler::CCECCommandHandler(CCECBusDevice *busDevice)
+CCECCommandHandler::CCECCommandHandler(CCECBusDevice *busDevice) :
+ m_busDevice(busDevice),
+ m_processor(m_busDevice->GetProcessor()),
+ m_iTransmitTimeout(CEC_DEFAULT_TRANSMIT_TIMEOUT),
+ m_iTransmitWait(CEC_DEFAULT_TRANSMIT_WAIT),
+ m_iTransmitRetries(CEC_DEFAULT_TRANSMIT_RETRIES)
{
- m_busDevice = busDevice;
+}
+
+CCECCommandHandler::~CCECCommandHandler(void)
+{
+ m_condition.Broadcast();
}
bool CCECCommandHandler::HandleCommand(const cec_command &command)
{
- bool bHandled(true);
+ bool bHandled(true), bHandlerChanged(false);
CStdString strLog;
- strLog.Format(">> %s (%X) -> %s (%X): %s (%2X)", ToString(command.initiator), command.initiator, ToString(command.destination), command.destination, ToString(command.opcode), command.opcode);
+ strLog.Format(">> %s (%X) -> %s (%X): %s (%2X)", m_processor->ToString(command.initiator), command.initiator, m_processor->ToString(command.destination), command.destination, m_processor->ToString(command.opcode), command.opcode);
m_busDevice->AddLog(CEC_LOG_NOTICE, strLog);
- if (m_busDevice->MyLogicalAddressContains(command.destination))
- {
- switch(command.opcode)
- {
- case CEC_OPCODE_REPORT_POWER_STATUS:
- HandleReportPowerStatus(command);
- break;
- case CEC_OPCODE_CEC_VERSION:
- HandleDeviceCecVersion(command);
- break;
- case CEC_OPCODE_SET_MENU_LANGUAGE:
- HandleSetMenuLanguage(command);
- /* pass to listeners */
- m_busDevice->GetProcessor()->AddCommand(command);
- break;
- case CEC_OPCODE_GIVE_PHYSICAL_ADDRESS:
- HandleGivePhysicalAddress(command);
- break;
- case CEC_OPCODE_GIVE_OSD_NAME:
- HandleGiveOSDName(command);
- break;
- case CEC_OPCODE_GIVE_DEVICE_VENDOR_ID:
- HandleGiveDeviceVendorId(command);
- break;
- case CEC_OPCODE_DEVICE_VENDOR_ID:
- HandleDeviceVendorId(command);
- break;
- case CEC_OPCODE_VENDOR_COMMAND_WITH_ID:
- HandleDeviceVendorCommandWithId(command);
- break;
- case CEC_OPCODE_GIVE_DECK_STATUS:
- HandleGiveDeckStatus(command);
- break;
- case CEC_OPCODE_DECK_CONTROL:
- HandleDeckControl(command);
- /* pass to listeners */
- m_busDevice->GetProcessor()->AddCommand(command);
- break;
- case CEC_OPCODE_MENU_REQUEST:
- HandleMenuRequest(command);
- break;
- case CEC_OPCODE_GIVE_DEVICE_POWER_STATUS:
- HandleGiveDevicePowerStatus(command);
- break;
- case CEC_OPCODE_GET_CEC_VERSION:
- HandleGetCecVersion(command);
- break;
- case CEC_OPCODE_USER_CONTROL_PRESSED:
- HandleUserControlPressed(command);
- break;
- case CEC_OPCODE_USER_CONTROL_RELEASE:
- HandleUserControlRelease(command);
- break;
- case CEC_OPCODE_GIVE_AUDIO_STATUS:
- HandleGiveAudioStatus(command);
- break;
- case CEC_OPCODE_GIVE_SYSTEM_AUDIO_MODE_STATUS:
- HandleGiveSystemAudioModeStatus(command);
- break;
- case CEC_OPCODE_SYSTEM_AUDIO_MODE_REQUEST:
- HandleSetSystemAudioModeRequest(command);
- break;
- default:
- UnhandledCommand(command);
- /* pass to listeners */
- m_busDevice->GetProcessor()->AddCommand(command);
- bHandled = false;
- break;
- }
- }
- else if (command.destination == CECDEVICE_BROADCAST)
+ m_processor->AddCommand(command);
+
+ switch(command.opcode)
{
- CStdString strLog;
- switch (command.opcode)
- {
- case CEC_OPCODE_SET_MENU_LANGUAGE:
- HandleSetMenuLanguage(command);
- /* pass to listeners */
- m_busDevice->GetProcessor()->AddCommand(command);
- break;
- case CEC_OPCODE_REQUEST_ACTIVE_SOURCE:
- HandleRequestActiveSource(command);
- break;
- case CEC_OPCODE_SET_STREAM_PATH:
- HandleSetStreamPath(command);
- break;
- case CEC_OPCODE_ROUTING_CHANGE:
- HandleRoutingChange(command);
- break;
- case CEC_OPCODE_DEVICE_VENDOR_ID:
- HandleDeviceVendorId(command);
- break;
- case CEC_OPCODE_VENDOR_COMMAND_WITH_ID:
- HandleDeviceVendorCommandWithId(command);
- break;
- case CEC_OPCODE_STANDBY:
- HandleStandby(command);
- /* pass to listeners */
- m_busDevice->GetProcessor()->AddCommand(command);
- break;
- case CEC_OPCODE_ACTIVE_SOURCE:
- HandleActiveSource(command);
- /* pass to listeners */
- m_busDevice->GetProcessor()->AddCommand(command);
- break;
- default:
- UnhandledCommand(command);
- /* pass to listeners */
- m_busDevice->GetProcessor()->AddCommand(command);
- bHandled = false;
- break;
- }
+ case CEC_OPCODE_REPORT_POWER_STATUS:
+ HandleReportPowerStatus(command);
+ break;
+ case CEC_OPCODE_CEC_VERSION:
+ HandleDeviceCecVersion(command);
+ break;
+ case CEC_OPCODE_SET_MENU_LANGUAGE:
+ HandleSetMenuLanguage(command);
+ break;
+ case CEC_OPCODE_GIVE_PHYSICAL_ADDRESS:
+ HandleGivePhysicalAddress(command);
+ break;
+ case CEC_OPCODE_GIVE_OSD_NAME:
+ HandleGiveOSDName(command);
+ break;
+ case CEC_OPCODE_GIVE_DEVICE_VENDOR_ID:
+ HandleGiveDeviceVendorId(command);
+ break;
+ case CEC_OPCODE_DEVICE_VENDOR_ID:
+ bHandlerChanged = HandleDeviceVendorId(command);
+ break;
+ case CEC_OPCODE_VENDOR_COMMAND_WITH_ID:
+ HandleDeviceVendorCommandWithId(command);
+ break;
+ case CEC_OPCODE_GIVE_DECK_STATUS:
+ HandleGiveDeckStatus(command);
+ break;
+ case CEC_OPCODE_DECK_CONTROL:
+ HandleDeckControl(command);
+ break;
+ case CEC_OPCODE_MENU_REQUEST:
+ HandleMenuRequest(command);
+ break;
+ case CEC_OPCODE_GIVE_DEVICE_POWER_STATUS:
+ HandleGiveDevicePowerStatus(command);
+ break;
+ case CEC_OPCODE_GET_CEC_VERSION:
+ HandleGetCecVersion(command);
+ break;
+ case CEC_OPCODE_USER_CONTROL_PRESSED:
+ HandleUserControlPressed(command);
+ break;
+ case CEC_OPCODE_USER_CONTROL_RELEASE:
+ HandleUserControlRelease(command);
+ break;
+ case CEC_OPCODE_GIVE_AUDIO_STATUS:
+ HandleGiveAudioStatus(command);
+ break;
+ case CEC_OPCODE_GIVE_SYSTEM_AUDIO_MODE_STATUS:
+ HandleGiveSystemAudioModeStatus(command);
+ break;
+ case CEC_OPCODE_SYSTEM_AUDIO_MODE_REQUEST:
+ HandleSystemAudioModeRequest(command);
+ break;
+ case CEC_OPCODE_REPORT_AUDIO_STATUS:
+ HandleReportAudioStatus(command);
+ break;
+ case CEC_OPCODE_SYSTEM_AUDIO_MODE_STATUS:
+ HandleSystemAudioModeStatus(command);
+ break;
+ case CEC_OPCODE_SET_SYSTEM_AUDIO_MODE:
+ HandleSetSystemAudioMode(command);
+ break;
+ case CEC_OPCODE_REQUEST_ACTIVE_SOURCE:
+ HandleRequestActiveSource(command);
+ break;
+ case CEC_OPCODE_SET_STREAM_PATH:
+ HandleSetStreamPath(command);
+ break;
+ case CEC_OPCODE_ROUTING_CHANGE:
+ HandleRoutingChange(command);
+ break;
+ case CEC_OPCODE_ROUTING_INFORMATION:
+ HandleRoutingInformation(command);
+ break;
+ case CEC_OPCODE_STANDBY:
+ HandleStandby(command);
+ break;
+ case CEC_OPCODE_ACTIVE_SOURCE:
+ HandleActiveSource(command);
+ break;
+ case CEC_OPCODE_REPORT_PHYSICAL_ADDRESS:
+ HandleReportPhysicalAddress(command);
+ break;
+ case CEC_OPCODE_SET_OSD_NAME:
+ HandleSetOSDName(command);
+ break;
+ case CEC_OPCODE_IMAGE_VIEW_ON:
+ HandleImageViewOn(command);
+ break;
+ case CEC_OPCODE_TEXT_VIEW_ON:
+ HandleTextViewOn(command);
+ break;
+ default:
+ UnhandledCommand(command);
+ bHandled = false;
+ break;
}
- else
+
+ if (bHandled && !bHandlerChanged)
{
- CStdString strLog;
- strLog.Format("ignoring frame: we're not at destination %x", command.destination);
- m_busDevice->AddLog(CEC_LOG_DEBUG, strLog.c_str());
- bHandled = false;
+ CLockObject lock(&m_receiveMutex);
+ m_condition.Signal();
}
return bHandled;
if (command.parameters.size == 2)
{
uint16_t iAddress = ((uint16_t)command.parameters[0] << 8) | ((uint16_t)command.parameters[1]);
- return m_busDevice->GetProcessor()->SetStreamPath(iAddress);
+ return m_processor->SetActiveSource(iAddress);
}
return true;
bool CCECCommandHandler::HandleDeckControl(const cec_command &command)
{
CCECBusDevice *device = GetDevice(command.destination);
- if (device && device->GetType() == CEC_DEVICE_TYPE_PLAYBACK_DEVICE && command.parameters.size > 0)
+ if (device && (device->GetType() == CEC_DEVICE_TYPE_PLAYBACK_DEVICE || device->GetType() == CEC_DEVICE_TYPE_RECORDING_DEVICE) && command.parameters.size > 0)
{
((CCECPlaybackDevice *) device)->SetDeckControlMode((cec_deck_control_mode) command.parameters[0]);
return true;
bool CCECCommandHandler::HandleDeviceVendorCommandWithId(const cec_command &command)
{
- SetVendorId(command);
- m_busDevice->GetProcessor()->TransmitAbort(command.initiator, command.opcode, CEC_ABORT_REASON_REFUSED);
+ if (m_processor->IsStarted() && m_busDevice->MyLogicalAddressContains(command.destination))
+ m_processor->TransmitAbort(command.initiator, command.opcode, CEC_ABORT_REASON_REFUSED);
+
return true;
}
bool CCECCommandHandler::HandleDeviceVendorId(const cec_command &command)
{
- SetVendorId(command);
- return true;
+ return SetVendorId(command);
}
bool CCECCommandHandler::HandleGetCecVersion(const cec_command &command)
{
- CCECBusDevice *device = GetDevice(command.destination);
- if (device)
- return device->TransmitCECVersion(command.initiator);
+ if (m_processor->IsStarted() && m_busDevice->MyLogicalAddressContains(command.destination))
+ {
+ CCECBusDevice *device = GetDevice(command.destination);
+ if (device)
+ return device->TransmitCECVersion(command.initiator);
+ }
return false;
}
bool CCECCommandHandler::HandleGiveAudioStatus(const cec_command &command)
{
- CCECBusDevice *device = GetDevice(command.destination);
- if (device && device->GetType() == CEC_DEVICE_TYPE_AUDIO_SYSTEM)
- return ((CCECAudioSystem *) device)->TransmitAudioStatus(command.initiator);
+ if (m_processor->IsStarted() && m_busDevice->MyLogicalAddressContains(command.destination))
+ {
+ CCECBusDevice *device = GetDevice(command.destination);
+ if (device && device->GetType() == CEC_DEVICE_TYPE_AUDIO_SYSTEM)
+ return ((CCECAudioSystem *) device)->TransmitAudioStatus(command.initiator);
+ }
return false;
}
bool CCECCommandHandler::HandleGiveDeckStatus(const cec_command &command)
{
- CCECBusDevice *device = GetDevice(command.destination);
- if (device && device->GetType() == CEC_DEVICE_TYPE_PLAYBACK_DEVICE)
- return ((CCECPlaybackDevice *) device)->TransmitDeckStatus(command.initiator);
+ if (m_processor->IsStarted() && 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))
+ return ((CCECPlaybackDevice *) device)->TransmitDeckStatus(command.initiator);
+ }
return false;
}
bool CCECCommandHandler::HandleGiveDevicePowerStatus(const cec_command &command)
{
- CCECBusDevice *device = GetDevice(command.destination);
- if (device)
- return device->TransmitPowerState(command.initiator);
+ if (m_processor->IsStarted() && m_busDevice->MyLogicalAddressContains(command.destination))
+ {
+ CCECBusDevice *device = GetDevice(command.destination);
+ if (device)
+ return device->TransmitPowerState(command.initiator);
+ }
return false;
}
bool CCECCommandHandler::HandleGiveDeviceVendorId(const cec_command &command)
{
- CCECBusDevice *device = GetDevice(command.destination);
- if (device)
- return device->TransmitVendorID(command.initiator);
+ if (m_processor->IsStarted() && m_busDevice->MyLogicalAddressContains(command.destination))
+ {
+ CCECBusDevice *device = GetDevice(command.destination);
+ if (device)
+ return device->TransmitVendorID(command.initiator);
+ }
return false;
}
bool CCECCommandHandler::HandleGiveOSDName(const cec_command &command)
{
- CCECBusDevice *device = GetDevice(command.destination);
- if (device)
- return device->TransmitOSDName(command.initiator);
+ if (m_processor->IsStarted() && m_busDevice->MyLogicalAddressContains(command.destination))
+ {
+ CCECBusDevice *device = GetDevice(command.destination);
+ if (device)
+ return device->TransmitOSDName(command.initiator);
+ }
return false;
}
bool CCECCommandHandler::HandleGivePhysicalAddress(const cec_command &command)
{
- CCECBusDevice *device = GetDevice(command.destination);
- if (device)
- return device->TransmitPhysicalAddress();
+ if (m_processor->IsStarted() && m_busDevice->MyLogicalAddressContains(command.destination))
+ {
+ CCECBusDevice *device = GetDevice(command.destination);
+ if (device)
+ return device->TransmitPhysicalAddress();
+ }
return false;
}
-bool CCECCommandHandler::HandleMenuRequest(const cec_command &command)
+bool CCECCommandHandler::HandleGiveSystemAudioModeStatus(const cec_command &command)
{
- if (command.parameters[0] == CEC_MENU_REQUEST_TYPE_QUERY)
+ if (m_processor->IsStarted() && m_busDevice->MyLogicalAddressContains(command.destination))
{
CCECBusDevice *device = GetDevice(command.destination);
- if (device)
- return device->TransmitMenuState(command.initiator);
+ if (device && device->GetType() == CEC_DEVICE_TYPE_AUDIO_SYSTEM)
+ return ((CCECAudioSystem *) device)->TransmitSystemAudioModeStatus(command.initiator);
+ }
+
+ return false;
+}
+
+bool CCECCommandHandler::HandleImageViewOn(const cec_command &command)
+{
+ m_processor->m_busDevices[command.initiator]->SetActiveSource();
+ return true;
+}
+
+bool CCECCommandHandler::HandleMenuRequest(const cec_command &command)
+{
+ if (m_processor->IsStarted() && m_busDevice->MyLogicalAddressContains(command.destination))
+ {
+ if (command.parameters[0] == CEC_MENU_REQUEST_TYPE_QUERY)
+ {
+ CCECBusDevice *device = GetDevice(command.destination);
+ if (device)
+ return device->TransmitMenuState(command.initiator);
+ }
}
+
return false;
}
+bool CCECCommandHandler::HandleReportAudioStatus(const cec_command &command)
+{
+ if (command.parameters.size == 1)
+ {
+ CCECBusDevice *device = GetDevice(command.initiator);
+ if (device && device->GetType() == CEC_DEVICE_TYPE_AUDIO_SYSTEM)
+ {
+ ((CCECAudioSystem *)device)->SetAudioStatus(command.parameters[0]);
+ return true;
+ }
+ }
+ return false;
+}
+
+bool CCECCommandHandler::HandleReportPhysicalAddress(const cec_command &command)
+{
+ if (command.parameters.size == 3)
+ {
+ uint16_t iNewAddress = ((uint16_t)command.parameters[0] << 8) | ((uint16_t)command.parameters[1]);
+ SetPhysicalAddress(command.initiator, iNewAddress);
+ }
+ return true;
+}
+
bool CCECCommandHandler::HandleReportPowerStatus(const cec_command &command)
{
if (command.parameters.size == 1)
bool CCECCommandHandler::HandleRequestActiveSource(const cec_command &command)
{
- CStdString strLog;
- strLog.Format(">> %i requests active source", (uint8_t) command.initiator);
- m_busDevice->AddLog(CEC_LOG_DEBUG, strLog.c_str());
+ if (m_processor->IsStarted())
+ {
+ CStdString strLog;
+ strLog.Format(">> %i requests active source", (uint8_t) command.initiator);
+ m_busDevice->AddLog(CEC_LOG_DEBUG, strLog.c_str());
- vector<CCECBusDevice *> devices;
- for (int iDevicePtr = (int)GetMyDevices(devices)-1; iDevicePtr >=0; iDevicePtr--)
- devices[iDevicePtr]->TransmitActiveSource();
+ vector<CCECBusDevice *> devices;
+ for (int iDevicePtr = (int)GetMyDevices(devices)-1; iDevicePtr >=0; iDevicePtr--)
+ devices[iDevicePtr]->TransmitActiveSource();
- return true;
+ return true;
+ }
+ return false;
}
bool CCECCommandHandler::HandleRoutingChange(const cec_command &command)
return true;
}
+bool CCECCommandHandler::HandleRoutingInformation(const cec_command &command)
+{
+ if (command.parameters.size == 2)
+ {
+ uint16_t iNewAddress = ((uint16_t)command.parameters[0] << 8) | ((uint16_t)command.parameters[1]);
+ m_processor->SetActiveSource(iNewAddress);
+ }
+
+ return false;
+}
+
bool CCECCommandHandler::HandleSetMenuLanguage(const cec_command &command)
{
if (command.parameters.size == 3)
language.language[iPtr] = command.parameters[iPtr];
language.language[3] = 0;
device->SetMenuLanguage(language);
+ return true;
}
}
- return true;
+ return false;
+}
+
+bool CCECCommandHandler::HandleSetOSDName(const cec_command &command)
+{
+ if (command.parameters.size > 0)
+ {
+ CCECBusDevice *device = GetDevice(command.initiator);
+ if (device)
+ {
+ char buf[1024];
+ for (uint8_t iPtr = 0; iPtr < command.parameters.size; iPtr++)
+ buf[iPtr] = (char)command.parameters[iPtr];
+ buf[command.parameters.size] = 0;
+
+ CStdString strName(buf);
+ device->SetOSDName(strName);
+
+ return true;
+ }
+ }
+ return false;
}
bool CCECCommandHandler::HandleSetStreamPath(const cec_command &command)
{
- if (command.parameters.size >= 2)
+ if (m_processor->IsStarted() && command.parameters.size >= 2)
{
uint16_t iStreamAddress = ((uint16_t)command.parameters[0] << 8) | ((uint16_t)command.parameters[1]);
CStdString strLog;
strLog.Format(">> %i sets stream path to physical address %04x", command.initiator, iStreamAddress);
m_busDevice->AddLog(CEC_LOG_DEBUG, strLog.c_str());
- if (m_busDevice->GetProcessor()->SetStreamPath(iStreamAddress))
+ /* one of the device handled by libCEC has been made active */
+ CCECBusDevice *device = GetDeviceByPhysicalAddress(iStreamAddress);
+ if (device && m_busDevice->MyLogicalAddressContains(device->GetLogicalAddress()))
{
- CCECBusDevice *device = GetDeviceByPhysicalAddress(iStreamAddress);
- if (device)
- {
- return device->TransmitActiveSource() &&
- device->TransmitMenuState(command.initiator);
- }
+ device->SetActiveSource();
+ device->TransmitActiveSource();
}
- return false;
}
- return true;
+ return false;
}
-bool CCECCommandHandler::HandleSetSystemAudioModeRequest(const cec_command &command)
+bool CCECCommandHandler::HandleSystemAudioModeRequest(const cec_command &command)
{
- if (command.parameters.size >= 1)
+ if (m_processor->IsStarted() && m_busDevice->MyLogicalAddressContains(command.destination))
{
CCECBusDevice *device = GetDevice(command.destination);
- if (device&& device->GetType() == CEC_DEVICE_TYPE_AUDIO_SYSTEM)
- return ((CCECAudioSystem *) device)->SetSystemAudioMode(command);
+ if (device && device->GetType() == CEC_DEVICE_TYPE_AUDIO_SYSTEM)
+ {
+ if (command.parameters.size >= 2)
+ {
+ device->SetPowerStatus(CEC_POWER_STATUS_ON);
+ ((CCECAudioSystem *) device)->SetSystemAudioModeStatus(CEC_SYSTEM_AUDIO_STATUS_ON);
+ uint16_t iNewAddress = ((uint16_t)command.parameters[0] << 8) | ((uint16_t)command.parameters[1]);
+ CCECBusDevice *newActiveDevice = GetDeviceByPhysicalAddress(iNewAddress);
+ if (newActiveDevice)
+ newActiveDevice->SetActiveSource();
+ return ((CCECAudioSystem *) device)->TransmitSetSystemAudioMode(command.initiator);
+ }
+ else
+ {
+ ((CCECAudioSystem *) device)->SetSystemAudioModeStatus(CEC_SYSTEM_AUDIO_STATUS_OFF);
+ return ((CCECAudioSystem *) device)->TransmitSetSystemAudioMode(command.initiator);
+ }
+ }
}
- return true;
+ return false;
}
bool CCECCommandHandler::HandleStandby(const cec_command &command)
CCECBusDevice *device = GetDevice(command.initiator);
if (device)
device->SetPowerStatus(CEC_POWER_STATUS_STANDBY);
+
return true;
}
-bool CCECCommandHandler::HandleGiveSystemAudioModeStatus(const cec_command &command)
+bool CCECCommandHandler::HandleSystemAudioModeStatus(const cec_command &command)
{
- CCECBusDevice *device = GetDevice(command.destination);
- if (device && device->GetType() == CEC_DEVICE_TYPE_AUDIO_SYSTEM)
- return ((CCECAudioSystem *) device)->TransmitSystemAudioModeStatus(command.initiator);
+ if (command.parameters.size == 1)
+ {
+ CCECBusDevice *device = GetDevice(command.initiator);
+ if (device && device->GetType() == CEC_DEVICE_TYPE_AUDIO_SYSTEM)
+ {
+ ((CCECAudioSystem *)device)->SetSystemAudioModeStatus((cec_system_audio_status)command.parameters[0]);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool CCECCommandHandler::HandleSetSystemAudioMode(const cec_command &command)
+{
+ if (command.parameters.size == 1)
+ {
+ CCECBusDevice *device = GetDevice(command.initiator);
+ if (device && device->GetType() == CEC_DEVICE_TYPE_AUDIO_SYSTEM)
+ {
+ ((CCECAudioSystem *)device)->SetSystemAudioModeStatus((cec_system_audio_status)command.parameters[0]);
+ return true;
+ }
+ }
return false;
}
+bool CCECCommandHandler::HandleTextViewOn(const cec_command &command)
+{
+ m_processor->m_busDevices[command.initiator]->SetActiveSource();
+ return true;
+}
+
bool CCECCommandHandler::HandleUserControlPressed(const cec_command &command)
{
- if (command.parameters.size > 0)
+ if (m_processor->IsStarted() && m_busDevice->MyLogicalAddressContains(command.destination) && command.parameters.size > 0)
{
- m_busDevice->GetProcessor()->AddKey();
+ m_processor->AddKey();
if (command.parameters[0] <= CEC_USER_CONTROL_CODE_MAX)
{
{
CCECBusDevice *device = GetDevice(command.destination);
if (device)
+ {
device->SetPowerStatus(CEC_POWER_STATUS_ON);
+ if (device->MyLogicalAddressContains(device->GetLogicalAddress()))
+ {
+ device->SetActiveSource();
+ device->TransmitActiveSource();
+
+ if (device->GetType() == CEC_DEVICE_TYPE_PLAYBACK_DEVICE ||
+ device->GetType() == CEC_DEVICE_TYPE_RECORDING_DEVICE)
+ ((CCECPlaybackDevice *)device)->TransmitDeckStatus(command.initiator);
+ }
+ }
}
- m_busDevice->GetProcessor()->SetCurrentButton((cec_user_control_code) command.parameters[0]);
+ m_processor->SetCurrentButton((cec_user_control_code) command.parameters[0]);
+ return true;
}
}
- return true;
+ return false;
}
bool CCECCommandHandler::HandleUserControlRelease(const cec_command &command)
{
- m_busDevice->GetProcessor()->AddKey();
+ if (m_processor->IsStarted() && m_busDevice->MyLogicalAddressContains(command.destination))
+ m_processor->AddKey();
+
return true;
}
{
unsigned int iReturn(0);
- cec_logical_addresses addresses = m_busDevice->GetProcessor()->GetLogicalAddresses();
+ cec_logical_addresses addresses = m_processor->GetLogicalAddresses();
for (uint8_t iPtr = 0; iPtr < 16; iPtr++)
{
if (addresses[iPtr])
CCECBusDevice *device = NULL;
if (iLogicalAddress >= CECDEVICE_TV && iLogicalAddress <= CECDEVICE_BROADCAST)
- device = m_busDevice->GetProcessor()->m_busDevices[iLogicalAddress];
+ device = m_processor->m_busDevices[iLogicalAddress];
return device;
}
CCECBusDevice *CCECCommandHandler::GetDeviceByPhysicalAddress(uint16_t iPhysicalAddress) const
{
- return m_busDevice->GetProcessor()->GetDeviceByPhysicalAddress(iPhysicalAddress);
+ return m_processor->GetDeviceByPhysicalAddress(iPhysicalAddress);
}
CCECBusDevice *CCECCommandHandler::GetDeviceByType(cec_device_type type) const
{
- return m_busDevice->GetProcessor()->GetDeviceByType(type);
+ return m_processor->GetDeviceByType(type);
}
-void CCECCommandHandler::SetVendorId(const cec_command &command)
+bool CCECCommandHandler::SetVendorId(const cec_command &command)
{
+ bool bChanged(false);
if (command.parameters.size < 3)
{
m_busDevice->AddLog(CEC_LOG_WARNING, "invalid vendor ID received");
- return;
+ return bChanged;
}
uint64_t iVendorId = ((uint64_t)command.parameters[0] << 16) +
CCECBusDevice *device = GetDevice((cec_logical_address) command.initiator);
if (device)
- device->SetVendorId(iVendorId);
+ bChanged = device->SetVendorId(iVendorId);
+ return bChanged;
}
-const char *CCECCommandHandler::ToString(const cec_menu_state state)
+void CCECCommandHandler::SetPhysicalAddress(cec_logical_address iAddress, uint16_t iNewAddress)
{
- switch (state)
+ if (!m_busDevice->MyLogicalAddressContains(iAddress))
{
- case CEC_MENU_STATE_ACTIVATED:
- return "activated";
- case CEC_MENU_STATE_DEACTIVATED:
- return "deactivated";
- default:
- return "unknown";
+ bool bOurAddress(m_processor->GetPhysicalAddress() == iNewAddress);
+ GetDevice(iAddress)->SetPhysicalAddress(iNewAddress);
+ if (bOurAddress)
+ {
+ /* another device reported the same physical address as ours
+ * since we don't have physical address detection yet, we'll just use the
+ * given address, increased by 0x100 for now */
+ m_processor->SetPhysicalAddress(iNewAddress + 0x100);
+ }
}
}
-const char *CCECCommandHandler::ToString(const cec_version version)
+void CCECCommandHandler::HandlePoll(const cec_logical_address iInitiator, const cec_logical_address iDestination)
{
- switch (version)
- {
- case CEC_VERSION_1_2:
- return "1.2";
- case CEC_VERSION_1_2A:
- return "1.2a";
- case CEC_VERSION_1_3:
- return "1.3";
- case CEC_VERSION_1_3A:
- return "1.3a";
- case CEC_VERSION_1_4:
- return "1.4";
- default:
- return "unknown";
- }
+ CStdString strLog;
+ strLog.Format("<< POLL: %s (%x) -> %s (%x)", m_processor->ToString(iInitiator), iInitiator, m_processor->ToString(iDestination), iDestination);
+ m_processor->AddLog(CEC_LOG_DEBUG, strLog);
}
-const char *CCECCommandHandler::ToString(const cec_power_status status)
+bool CCECCommandHandler::HandleReceiveFailed(void)
{
- switch (status)
- {
- case CEC_POWER_STATUS_ON:
- return "on";
- case CEC_POWER_STATUS_STANDBY:
- return "standby";
- case CEC_POWER_STATUS_IN_TRANSITION_ON_TO_STANDBY:
- return "in transition from on to standby";
- case CEC_POWER_STATUS_IN_TRANSITION_STANDBY_TO_ON:
- return "in transition from standby to on";
- default:
- return "unknown";
- }
+ /* default = error */
+ return true;
}
-const char *CCECCommandHandler::ToString(const cec_logical_address address)
+bool CCECCommandHandler::TransmitPowerOn(const cec_logical_address iInitiator, const cec_logical_address iDestination)
{
- switch(address)
- {
- case CECDEVICE_AUDIOSYSTEM:
- return "Audio";
- case CECDEVICE_BROADCAST:
- return "Broadcast";
- case CECDEVICE_FREEUSE:
- return "Free use";
- case CECDEVICE_PLAYBACKDEVICE1:
- return "Playback 1";
- case CECDEVICE_PLAYBACKDEVICE2:
- return "Playback 2";
- case CECDEVICE_PLAYBACKDEVICE3:
- return "Playback 3";
- case CECDEVICE_RECORDINGDEVICE1:
- return "Recorder 1";
- case CECDEVICE_RECORDINGDEVICE2:
- return "Recorder 2";
- case CECDEVICE_RECORDINGDEVICE3:
- return "Recorder 3";
- case CECDEVICE_RESERVED1:
- return "Reserved 1";
- case CECDEVICE_RESERVED2:
- return "Reserved 2";
- case CECDEVICE_TUNER1:
- return "Tuner 1";
- case CECDEVICE_TUNER2:
- return "Tuner 2";
- case CECDEVICE_TUNER3:
- return "Tuner 3";
- case CECDEVICE_TUNER4:
- return "Tuner 4";
- case CECDEVICE_TV:
- return "TV";
- default:
- return "unknown";
- }
+ cec_command command;
+ cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_IMAGE_VIEW_ON);
+
+ return Transmit(command);
}
-const char *CCECCommandHandler::ToString(const cec_deck_control_mode mode)
+bool CCECCommandHandler::TransmitStandby(const cec_logical_address iInitiator, const cec_logical_address iDestination)
{
- switch (mode)
- {
- case CEC_DECK_CONTROL_MODE_SKIP_FORWARD_WIND:
- return "skip forward wind";
- case CEC_DECK_CONTROL_MODE_EJECT:
- return "eject";
- case CEC_DECK_CONTROL_MODE_SKIP_REVERSE_REWIND:
- return "reverse rewind";
- case CEC_DECK_CONTROL_MODE_STOP:
- return "stop";
- default:
- return "unknown";
- }
+ cec_command command;
+ cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_STANDBY);
+
+ return Transmit(command);
}
-const char *CCECCommandHandler::ToString(const cec_deck_info status)
+bool CCECCommandHandler::TransmitRequestCecVersion(const cec_logical_address iInitiator, const cec_logical_address iDestination)
{
- switch (status)
- {
- case CEC_DECK_INFO_PLAY:
- return "play";
- case CEC_DECK_INFO_RECORD:
- return "record";
- case CEC_DECK_INFO_PLAY_REVERSE:
- return "play reverse";
- case CEC_DECK_INFO_STILL:
- return "still";
- case CEC_DECK_INFO_SLOW:
- return "slow";
- case CEC_DECK_INFO_SLOW_REVERSE:
- return "slow reverse";
- case CEC_DECK_INFO_FAST_FORWARD:
- return "fast forward";
- case CEC_DECK_INFO_FAST_REVERSE:
- return "fast reverse";
- case CEC_DECK_INFO_NO_MEDIA:
- return "no media";
- case CEC_DECK_INFO_STOP:
- return "stop";
- case CEC_DECK_INFO_SKIP_FORWARD_WIND:
- return "info skip forward wind";
- case CEC_DECK_INFO_SKIP_REVERSE_REWIND:
- return "info skip reverse rewind";
- case CEC_DECK_INFO_INDEX_SEARCH_FORWARD:
- return "info index search forward";
- case CEC_DECK_INFO_INDEX_SEARCH_REVERSE:
- return "info index search reverse";
- case CEC_DECK_INFO_OTHER_STATUS:
- return "other";
- default:
- return "unknown";
- }
+ cec_command command;
+ cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_GET_CEC_VERSION);
+
+ return Transmit(command);
}
-const char *CCECCommandHandler::ToString(const cec_opcode opcode)
+bool CCECCommandHandler::TransmitRequestMenuLanguage(const cec_logical_address iInitiator, const cec_logical_address iDestination)
{
- switch (opcode)
- {
- case CEC_OPCODE_ACTIVE_SOURCE:
- return "active source";
- case CEC_OPCODE_IMAGE_VIEW_ON:
- return "image view on";
- case CEC_OPCODE_TEXT_VIEW_ON:
- return "text view on";
- case CEC_OPCODE_INACTIVE_SOURCE:
- return "inactive source";
- case CEC_OPCODE_REQUEST_ACTIVE_SOURCE:
- return "request active source";
- case CEC_OPCODE_ROUTING_CHANGE:
- return "routing change";
- case CEC_OPCODE_ROUTING_INFORMATION:
- return "routing information";
- case CEC_OPCODE_SET_STREAM_PATH:
- return "set stream path";
- case CEC_OPCODE_STANDBY:
- return "standby";
- case CEC_OPCODE_RECORD_OFF:
- return "record off";
- case CEC_OPCODE_RECORD_ON:
- return "record on";
- case CEC_OPCODE_RECORD_STATUS:
- return "record status";
- case CEC_OPCODE_RECORD_TV_SCREEN:
- return "record tv screen";
- case CEC_OPCODE_CLEAR_ANALOGUE_TIMER:
- return "clear analogue timer";
- case CEC_OPCODE_CLEAR_DIGITAL_TIMER:
- return "clear digital timer";
- case CEC_OPCODE_CLEAR_EXTERNAL_TIMER:
- return "clear external timer";
- case CEC_OPCODE_SET_ANALOGUE_TIMER:
- return "set analogue timer";
- case CEC_OPCODE_SET_DIGITAL_TIMER:
- return "set digital timer";
- case CEC_OPCODE_SET_EXTERNAL_TIMER:
- return "set external timer";
- case CEC_OPCODE_SET_TIMER_PROGRAM_TITLE:
- return "set timer program title";
- case CEC_OPCODE_TIMER_CLEARED_STATUS:
- return "timer cleared status";
- case CEC_OPCODE_TIMER_STATUS:
- return "timer status";
- case CEC_OPCODE_CEC_VERSION:
- return "cec version";
- case CEC_OPCODE_GET_CEC_VERSION:
- return "get cec version";
- case CEC_OPCODE_GIVE_PHYSICAL_ADDRESS:
- return "give physical address";
- case CEC_OPCODE_GET_MENU_LANGUAGE:
- return "get menu language";
- case CEC_OPCODE_REPORT_PHYSICAL_ADDRESS:
- return "report physical address";
- case CEC_OPCODE_SET_MENU_LANGUAGE:
- return "set menu language";
- case CEC_OPCODE_DECK_CONTROL:
- return "deck control";
- case CEC_OPCODE_DECK_STATUS:
- return "deck status";
- case CEC_OPCODE_GIVE_DECK_STATUS:
- return "give deck status";
- case CEC_OPCODE_PLAY:
- return "play";
- case CEC_OPCODE_GIVE_TUNER_DEVICE_STATUS:
- return "give tuner status";
- case CEC_OPCODE_SELECT_ANALOGUE_SERVICE:
- return "select analogue service";
- case CEC_OPCODE_SELECT_DIGITAL_SERVICE:
- return "set digital service";
- case CEC_OPCODE_TUNER_DEVICE_STATUS:
- return "tuner device status";
- case CEC_OPCODE_TUNER_STEP_DECREMENT:
- return "tuner step decrement";
- case CEC_OPCODE_TUNER_STEP_INCREMENT:
- return "tuner step increment";
- case CEC_OPCODE_DEVICE_VENDOR_ID:
- return "device vendor id";
- case CEC_OPCODE_GIVE_DEVICE_VENDOR_ID:
- return "give device vendor id";
- case CEC_OPCODE_VENDOR_COMMAND:
- return "vendor command";
- case CEC_OPCODE_VENDOR_COMMAND_WITH_ID:
- return "vendor command with id";
- case CEC_OPCODE_VENDOR_REMOTE_BUTTON_DOWN:
- return "vendor remote button down";
- case CEC_OPCODE_VENDOR_REMOTE_BUTTON_UP:
- return "vendor remote button up";
- case CEC_OPCODE_SET_OSD_STRING:
- return "set osd string";
- case CEC_OPCODE_GIVE_OSD_NAME:
- return "give osd name";
- case CEC_OPCODE_SET_OSD_NAME:
- return "set osd name";
- case CEC_OPCODE_MENU_REQUEST:
- return "menu request";
- case CEC_OPCODE_MENU_STATUS:
- return "menu status";
- case CEC_OPCODE_USER_CONTROL_PRESSED:
- return "user control pressed";
- case CEC_OPCODE_USER_CONTROL_RELEASE:
- return "user control release";
- case CEC_OPCODE_GIVE_DEVICE_POWER_STATUS:
- return "give device power status";
- case CEC_OPCODE_REPORT_POWER_STATUS:
- return "report power status";
- case CEC_OPCODE_FEATURE_ABORT:
- return "feature abort";
- case CEC_OPCODE_ABORT:
- return "abort";
- case CEC_OPCODE_GIVE_AUDIO_STATUS:
- return "give audio status";
- case CEC_OPCODE_GIVE_SYSTEM_AUDIO_MODE_STATUS:
- return "give audio mode status";
- case CEC_OPCODE_REPORT_AUDIO_STATUS:
- return "report audio status";
- case CEC_OPCODE_SET_SYSTEM_AUDIO_MODE:
- return "set system audio mode";
- case CEC_OPCODE_SYSTEM_AUDIO_MODE_REQUEST:
- return "system audio mode request";
- case CEC_OPCODE_SYSTEM_AUDIO_MODE_STATUS:
- return "system audio mode status";
- case CEC_OPCODE_SET_AUDIO_RATE:
- return "set audio rate";
- default:
- return "UNKNOWN";
- }
+ cec_command command;
+ cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_GET_MENU_LANGUAGE);
+
+ return Transmit(command);
}
-const char *CCECCommandHandler::ToString(const cec_system_audio_status mode)
+bool CCECCommandHandler::TransmitRequestOSDName(const cec_logical_address iInitiator, const cec_logical_address iDestination)
{
- switch(mode)
- {
- case CEC_SYSTEM_AUDIO_STATUS_ON:
- return "on";
- case CEC_SYSTEM_AUDIO_STATUS_OFF:
- return "off";
- default:
- return "unknown";
- }
+ cec_command command;
+ cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_GIVE_OSD_NAME);
+
+ return Transmit(command);
+}
+
+bool CCECCommandHandler::TransmitRequestPhysicalAddress(const cec_logical_address iInitiator, const cec_logical_address iDestination)
+{
+ cec_command command;
+ cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_GIVE_PHYSICAL_ADDRESS);
+
+ return Transmit(command);
+}
+
+bool CCECCommandHandler::TransmitRequestPowerStatus(const cec_logical_address iInitiator, const cec_logical_address iDestination)
+{
+ cec_command command;
+ cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_GIVE_DEVICE_POWER_STATUS);
+
+ return Transmit(command);
+}
+
+bool CCECCommandHandler::TransmitRequestVendorId(const cec_logical_address iInitiator, const cec_logical_address iDestination)
+{
+ cec_command command;
+ cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_GIVE_DEVICE_VENDOR_ID);
+
+ return Transmit(command);
+}
+
+bool CCECCommandHandler::TransmitActiveSource(const cec_logical_address iInitiator, uint16_t iPhysicalAddress)
+{
+ cec_command command;
+ cec_command::Format(command, iInitiator, CECDEVICE_BROADCAST, CEC_OPCODE_ACTIVE_SOURCE);
+ command.parameters.PushBack((uint8_t) ((iPhysicalAddress >> 8) & 0xFF));
+ command.parameters.PushBack((uint8_t) (iPhysicalAddress & 0xFF));
+
+ return Transmit(command);
+}
+
+bool CCECCommandHandler::TransmitCECVersion(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_version cecVersion)
+{
+ cec_command command;
+ cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_CEC_VERSION);
+ command.parameters.PushBack((uint8_t)cecVersion);
+
+ return Transmit(command);
+}
+
+bool CCECCommandHandler::TransmitInactiveSource(const cec_logical_address iInitiator, uint16_t iPhysicalAddress)
+{
+ cec_command command;
+ cec_command::Format(command, iInitiator, CECDEVICE_TV, CEC_OPCODE_INACTIVE_SOURCE);
+ command.parameters.PushBack((iPhysicalAddress >> 8) & 0xFF);
+ command.parameters.PushBack(iPhysicalAddress & 0xFF);
+
+ return Transmit(command);
+}
+
+bool CCECCommandHandler::TransmitMenuState(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_menu_state menuState)
+{
+ cec_command command;
+ cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_MENU_STATUS);
+ command.parameters.PushBack((uint8_t)menuState);
+
+ return Transmit(command);
+}
+
+bool CCECCommandHandler::TransmitOSDName(const cec_logical_address iInitiator, const cec_logical_address iDestination, CStdString strDeviceName)
+{
+ cec_command command;
+ cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_SET_OSD_NAME);
+ for (unsigned int iPtr = 0; iPtr < strDeviceName.length(); iPtr++)
+ command.parameters.PushBack(strDeviceName.at(iPtr));
+
+ return Transmit(command);
+}
+
+bool CCECCommandHandler::TransmitOSDString(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_display_control duration, const char *strMessage)
+{
+ cec_command command;
+ cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_SET_OSD_STRING);
+ command.parameters.PushBack((uint8_t)duration);
+
+ unsigned int iLen = strlen(strMessage);
+ if (iLen > 13) iLen = 13;
+
+ for (unsigned int iPtr = 0; iPtr < iLen; iPtr++)
+ command.parameters.PushBack(strMessage[iPtr]);
+
+ return Transmit(command);
+}
+
+bool CCECCommandHandler::TransmitPhysicalAddress(const cec_logical_address iInitiator, uint16_t iPhysicalAddress, cec_device_type type)
+{
+ cec_command command;
+ cec_command::Format(command, iInitiator, CECDEVICE_BROADCAST, CEC_OPCODE_REPORT_PHYSICAL_ADDRESS);
+ command.parameters.PushBack((uint8_t) ((iPhysicalAddress >> 8) & 0xFF));
+ command.parameters.PushBack((uint8_t) (iPhysicalAddress & 0xFF));
+ command.parameters.PushBack((uint8_t) (type));
+
+ return Transmit(command);
+}
+
+bool CCECCommandHandler::TransmitPoll(const cec_logical_address iInitiator, const cec_logical_address iDestination)
+{
+ cec_command command;
+ cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_NONE);
+
+ return Transmit(command, false);
+}
+
+bool CCECCommandHandler::TransmitPowerState(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_power_status state)
+{
+ cec_command command;
+ cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_REPORT_POWER_STATUS);
+ command.parameters.PushBack((uint8_t) state);
+
+ return Transmit(command);
+}
+
+bool CCECCommandHandler::TransmitVendorID(const cec_logical_address iInitiator, uint64_t iVendorId)
+{
+ cec_command command;
+ cec_command::Format(command, iInitiator, CECDEVICE_BROADCAST, CEC_OPCODE_DEVICE_VENDOR_ID);
+
+ command.parameters.PushBack((uint8_t) (((uint64_t)iVendorId >> 16) & 0xFF));
+ command.parameters.PushBack((uint8_t) (((uint64_t)iVendorId >> 8) & 0xFF));
+ command.parameters.PushBack((uint8_t) ((uint64_t)iVendorId & 0xFF));
+
+ return Transmit(command);
+}
+
+bool CCECCommandHandler::TransmitAudioStatus(const cec_logical_address iInitiator, const cec_logical_address iDestination, uint8_t state)
+{
+ cec_command command;
+ cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_REPORT_AUDIO_STATUS);
+ command.parameters.PushBack(state);
+
+ return Transmit(command);
+}
+
+bool CCECCommandHandler::TransmitSetSystemAudioMode(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_system_audio_status state)
+{
+ cec_command command;
+ cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_SET_SYSTEM_AUDIO_MODE);
+ command.parameters.PushBack((uint8_t)state);
+
+ return Transmit(command);
}
-const char *CCECCommandHandler::ToString(const cec_audio_status status)
+bool CCECCommandHandler::TransmitSystemAudioModeStatus(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_system_audio_status state)
{
- // TODO this is a mask
- return "TODO";
+ cec_command command;
+ cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_SYSTEM_AUDIO_MODE_STATUS);
+ command.parameters.PushBack((uint8_t)state);
+
+ return Transmit(command);
}
-const char *CCECCommandHandler::ToString(const cec_vendor_id vendor)
+bool CCECCommandHandler::TransmitDeckStatus(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_deck_info state)
{
- switch (vendor)
+ cec_command command;
+ cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_DECK_STATUS);
+ command.PushBack((uint8_t)state);
+
+ return Transmit(command);
+}
+
+bool CCECCommandHandler::TransmitKeypress(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_user_control_code key)
+{
+ cec_command command;
+ cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_USER_CONTROL_PRESSED);
+ command.parameters.PushBack((uint8_t)key);
+
+ return Transmit(command);
+}
+
+bool CCECCommandHandler::TransmitKeyRelease(const cec_logical_address iInitiator, const cec_logical_address iDestination)
+{
+ cec_command command;
+ cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_USER_CONTROL_RELEASE);
+
+ return Transmit(command);
+}
+
+bool CCECCommandHandler::Transmit(cec_command &command, bool bExpectResponse /* = true */)
+{
+ command.transmit_timeout = m_iTransmitTimeout;
+
+ CLockObject writeLock(&m_processor->m_transmitMutex);
+ CLockObject receiveLock(&m_receiveMutex);
+ if (m_processor->Transmit(command))
{
- case CEC_VENDOR_SAMSUNG:
- return "Samsung";
- case CEC_VENDOR_LG:
- return "LG";
- case CEC_VENDOR_PANASONIC:
- return "Panasonic";
- case CEC_VENDOR_PIONEER:
- return "Pioneer";
- default:
- return "Unknown";
+ if (bExpectResponse)
+ return m_condition.Wait(&m_receiveMutex, m_iTransmitWait);
+ return true;
}
+
+ return false;
}
#include <cectypes.h>
#include <vector>
+#include "../util/StdString.h"
+#include "../platform/threads.h"
namespace CEC
{
+ class CCECProcessor;
class CCECBusDevice;
class CCECCommandHandler
{
public:
CCECCommandHandler(CCECBusDevice *busDevice);
- virtual ~CCECCommandHandler(void) {};
+ virtual ~CCECCommandHandler(void);
virtual bool HandleCommand(const cec_command &command);
virtual cec_vendor_id GetVendorId(void) { return CEC_VENDOR_UNKNOWN; };
+ virtual void HandlePoll(const cec_logical_address iInitiator, const cec_logical_address iDestination);
+ virtual bool HandleReceiveFailed(void);
- static const char *ToString(const cec_menu_state state);
- static const char *ToString(const cec_deck_control_mode mode);
- static const char *ToString(const cec_version version);
- static const char *ToString(const cec_power_status status);
- static const char *ToString(const cec_deck_info status);
- static const char* ToString(const cec_logical_address address);
- static const char* ToString(const cec_opcode opcode);
- static const char *ToString(const cec_system_audio_status mode);
- static const char *ToString(const cec_audio_status status);
- static const char *ToString(const cec_vendor_id vendor);
+ virtual bool InitHandler(void) { return true; }
+ virtual uint8_t GetTransmitRetries(void) const { return m_iTransmitRetries; }
+
+ virtual bool TransmitPowerOn(const cec_logical_address iInitiator, const cec_logical_address iDestination);
+ virtual bool TransmitStandby(const cec_logical_address iInitiator, const cec_logical_address iDestination);
+ virtual bool TransmitRequestCecVersion(const cec_logical_address iInitiator, const cec_logical_address iDestination);
+ virtual bool TransmitRequestMenuLanguage(const cec_logical_address iInitiator, const cec_logical_address iDestination);
+ virtual bool TransmitRequestOSDName(const cec_logical_address iInitiator, const cec_logical_address iDestination);
+ virtual bool TransmitRequestPhysicalAddress(const cec_logical_address iInitiator, const cec_logical_address iDestination);
+ virtual bool TransmitRequestPowerStatus(const cec_logical_address iInitiator, const cec_logical_address iDestination);
+ virtual bool TransmitRequestVendorId(const cec_logical_address iInitiator, const cec_logical_address iDestination);
+ virtual bool TransmitActiveSource(const cec_logical_address iInitiator, uint16_t iPhysicalAddress);
+ virtual bool TransmitCECVersion(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_version cecVersion);
+ virtual bool TransmitInactiveSource(const cec_logical_address iInitiator, uint16_t iPhysicalAddress);
+ virtual bool TransmitMenuState(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_menu_state menuState);
+ virtual bool TransmitOSDName(const cec_logical_address iInitiator, const cec_logical_address iDestination, CStdString strDeviceName);
+ virtual bool TransmitOSDString(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_display_control duration, const char *strMessage);
+ virtual bool TransmitPhysicalAddress(const cec_logical_address iInitiator, uint16_t iPhysicalAddress, cec_device_type type);
+ virtual bool TransmitPoll(const cec_logical_address iInitiator, const cec_logical_address iDestination);
+ virtual bool TransmitPowerState(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_power_status state);
+ virtual bool TransmitVendorID(const cec_logical_address iInitiator, uint64_t iVendorId);
+ virtual bool TransmitAudioStatus(const cec_logical_address iInitiator, const cec_logical_address iDestination, uint8_t state);
+ virtual bool TransmitSetSystemAudioMode(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_system_audio_status state);
+ virtual bool TransmitSystemAudioModeStatus(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_system_audio_status state);
+ 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);
+ virtual bool TransmitKeyRelease(const cec_logical_address iInitiator, const cec_logical_address iDestination);
protected:
virtual bool HandleActiveSource(const cec_command &command);
virtual bool HandleGiveDeviceVendorId(const cec_command &command);
virtual bool HandleGiveOSDName(const cec_command &command);
virtual bool HandleGivePhysicalAddress(const cec_command &command);
+ virtual bool HandleGiveSystemAudioModeStatus(const cec_command &command);
+ virtual bool HandleImageViewOn(const cec_command &command);
virtual bool HandleMenuRequest(const cec_command &command);
+ virtual bool HandleReportAudioStatus(const cec_command &command);
+ virtual bool HandleReportPhysicalAddress(const cec_command &command);
virtual bool HandleReportPowerStatus(const cec_command &command);
virtual bool HandleRequestActiveSource(const cec_command &command);
virtual bool HandleRoutingChange(const cec_command &command);
+ virtual bool HandleRoutingInformation(const cec_command &command);
virtual bool HandleSetMenuLanguage(const cec_command &command);
+ virtual bool HandleSetOSDName(const cec_command &command);
virtual bool HandleSetStreamPath(const cec_command &command);
- virtual bool HandleSetSystemAudioModeRequest(const cec_command &command);
+ virtual bool HandleSystemAudioModeRequest(const cec_command &command);
virtual bool HandleStandby(const cec_command &command);
- virtual bool HandleGiveSystemAudioModeStatus(const cec_command &command);
+ virtual bool HandleSystemAudioModeStatus(const cec_command &command);
+ virtual bool HandleSetSystemAudioMode(const cec_command &command);
+ virtual bool HandleTextViewOn(const cec_command &command);
virtual bool HandleUserControlPressed(const cec_command &command);
virtual bool HandleUserControlRelease(const cec_command &command);
virtual void UnhandledCommand(const cec_command &command);
virtual CCECBusDevice *GetDeviceByPhysicalAddress(uint16_t iPhysicalAddress) const;
virtual CCECBusDevice *GetDeviceByType(cec_device_type type) const;
- virtual void SetVendorId(const cec_command &command);
+ virtual bool SetVendorId(const cec_command &command);
+ virtual void SetPhysicalAddress(cec_logical_address iAddress, uint16_t iNewAddress);
+
+ virtual bool Transmit(cec_command &command, bool bExpectResponse = true);
+
CCECBusDevice *m_busDevice;
+ CCECProcessor *m_processor;
+ int32_t m_iTransmitTimeout;
+ int32_t m_iTransmitWait;
+ int8_t m_iTransmitRetries;
+ CMutex m_receiveMutex;
+ CCondition m_condition;
};
};
*/
#include "SLCommandHandler.h"
+#include "../devices/CECBusDevice.h"
+#include "../devices/CECPlaybackDevice.h"
+#include "../CECProcessor.h"
+#include "../platform/timeutils.h"
using namespace CEC;
+#define SL_COMMAND_UNKNOWN_01 0x01
+#define SL_COMMAND_UNKNOWN_02 0x02
+#define SL_COMMAND_UNKNOWN_03 0x05
+
+#define SL_COMMAND_REQUEST_POWER_STATUS 0xa0
+#define SL_COMMAND_POWER_ON 0x03
+#define SL_COMMAND_CONNECT_REQUEST 0x04
+#define SL_COMMAND_CONNECT_ACCEPT 0x05
+
CSLCommandHandler::CSLCommandHandler(CCECBusDevice *busDevice) :
- CCECCommandHandler(busDevice)
+ CCECCommandHandler(busDevice),
+ m_bAwaitingReceiveFailed(false),
+ m_bSLEnabled(false),
+ m_bVendorIdSent(false)
+{
+ /* TODO set to powered off until we fixed the connect on start loop issue */
+ m_processor->m_busDevices[m_processor->GetLogicalAddresses().primary]->m_powerStatus = CEC_POWER_STATUS_STANDBY;
+}
+
+bool CSLCommandHandler::HandleVendorCommand(const cec_command &command)
+{
+ if (command.parameters.size == 1 &&
+ command.parameters[0] == SL_COMMAND_UNKNOWN_01)
+ {
+ HandleVendorCommand01(command);
+ return true;
+ }
+ else if (command.parameters.size == 2 &&
+ command.parameters[0] == SL_COMMAND_POWER_ON)
+ {
+ HandleVendorCommandPowerOn(command);
+ return true;
+ }
+ else if (command.parameters.size == 2 &&
+ command.parameters[0] == SL_COMMAND_CONNECT_REQUEST)
+ {
+ HandleVendorCommandSLConnect(command);
+ return true;
+ }
+ else if (command.parameters.size == 1 &&
+ command.parameters[0] == SL_COMMAND_REQUEST_POWER_STATUS)
+ {
+ HandleVendorCommandPowerOnStatus(command);
+ return true;
+ }
+
+ return false;
+}
+
+bool CSLCommandHandler::HandleGiveDeckStatus(const cec_command &command)
+{
+ if (command.parameters.size == 1)
+ {
+ if (command.parameters[0] == CEC_STATUS_REQUEST_ONCE ||
+ command.parameters[0] == CEC_STATUS_REQUEST_ON)
+ {
+ TransmitDeckStatus(command.initiator);
+ }
+ else
+ {
+ CCECCommandHandler::HandleGiveDeckStatus(command);
+ }
+ }
+ return true;
+}
+
+void CSLCommandHandler::HandleVendorCommand01(const cec_command &command)
+{
+ TransmitVendorCommand0205(command.destination, command.initiator);
+}
+
+void CSLCommandHandler::TransmitVendorCommand0205(const cec_logical_address iSource, const cec_logical_address iDestination)
+{
+ cec_command response;
+ cec_command::Format(response, iSource, iDestination, CEC_OPCODE_VENDOR_COMMAND);
+ response.PushBack(SL_COMMAND_UNKNOWN_02);
+ response.PushBack(SL_COMMAND_UNKNOWN_03);
+
+ Transmit(response);
+}
+
+void CSLCommandHandler::TransmitVendorCommand05(const cec_logical_address iSource, const cec_logical_address iDestination)
+{
+ m_bSLEnabled = true;
+ cec_command response;
+ cec_command::Format(response, iSource, iDestination, CEC_OPCODE_VENDOR_COMMAND);
+ response.PushBack(SL_COMMAND_CONNECT_ACCEPT);
+ response.PushBack((uint8_t)iSource);
+ Transmit(response);
+}
+
+void CSLCommandHandler::HandleVendorCommandPowerOn(const cec_command &command)
+{
+ CCECBusDevice *device = m_processor->m_busDevices[m_processor->GetLogicalAddresses().primary];
+ if (device)
+ {
+ m_bSLEnabled = true;
+ device->SetPowerStatus(CEC_POWER_STATUS_IN_TRANSITION_STANDBY_TO_ON);
+ device->TransmitPowerState(command.initiator);
+ device->TransmitVendorID(command.initiator);
+ TransmitPowerOn(device->GetLogicalAddress(), command.initiator);
+ }
+}
+
+void CSLCommandHandler::HandleVendorCommandSLConnect(const cec_command &command)
+{
+ m_bSLEnabled = true;
+ m_processor->m_busDevices[command.initiator]->SetActiveSource();
+ m_processor->m_busDevices[command.destination]->TransmitActiveSource();
+ TransmitVendorCommand05(command.destination, command.initiator);
+ TransmitDeckStatus(command.initiator);
+}
+
+void CSLCommandHandler::HandleVendorCommandPowerOnStatus(const cec_command &command)
+{
+ if (command.destination != CECDEVICE_BROADCAST)
+ {
+ CCECBusDevice *device = m_processor->m_busDevices[m_processor->GetLogicalAddresses().primary];
+ device->SetPowerStatus(CEC_POWER_STATUS_IN_TRANSITION_STANDBY_TO_ON);
+ device->TransmitPowerState(command.initiator);
+ device->SetPowerStatus(CEC_POWER_STATUS_ON);
+ }
+}
+
+void CSLCommandHandler::TransmitDeckStatus(const cec_logical_address iDestination)
+{
+ /* set deck status for the playback device */
+ CCECBusDevice *primary = m_processor->m_busDevices[m_processor->GetLogicalAddresses().primary];
+ if (primary->GetType() == CEC_DEVICE_TYPE_PLAYBACK_DEVICE || primary->GetType() == CEC_DEVICE_TYPE_RECORDING_DEVICE)
+ {
+ ((CCECPlaybackDevice *)primary)->SetDeckStatus(CEC_DECK_INFO_OTHER_STATUS_LG);
+ ((CCECPlaybackDevice *)primary)->TransmitDeckStatus(iDestination);
+ }
+}
+
+bool CSLCommandHandler::TransmitLGVendorId(const cec_logical_address iInitiator, const cec_logical_address iDestination)
{
+ cec_command response;
+ cec_command::Format(response, iInitiator, iDestination, CEC_OPCODE_DEVICE_VENDOR_ID);
+ response.parameters.PushBack((uint8_t) (((uint64_t)CEC_VENDOR_LG >> 16) & 0xFF));
+ response.parameters.PushBack((uint8_t) (((uint64_t)CEC_VENDOR_LG >> 8) & 0xFF));
+ response.parameters.PushBack((uint8_t) ((uint64_t)CEC_VENDOR_LG & 0xFF));
+
+ Transmit(response);
+ return true;
+}
+
+bool CSLCommandHandler::HandleGiveDeviceVendorId(const cec_command &command)
+{
+ /* imitate LG devices */
+ CCECBusDevice *device = GetDevice(command.destination);
+ if (device)
+ device->SetVendorId(CEC_VENDOR_LG);
+
+ return CCECCommandHandler::HandleGiveDeviceVendorId(command);
+}
+
+bool CSLCommandHandler::HandleCommand(const cec_command &command)
+{
+ bool bHandled(false);
+
+ if (m_processor->IsStarted() && (m_busDevice->MyLogicalAddressContains(command.destination) ||
+ command.destination == CECDEVICE_BROADCAST))
+ {
+ switch(command.opcode)
+ {
+ case CEC_OPCODE_VENDOR_COMMAND:
+ bHandled = HandleVendorCommand(command);
+ break;
+ case CEC_OPCODE_FEATURE_ABORT:
+ {
+ if (!m_bVendorIdSent)
+ {
+ m_bVendorIdSent = true;
+ TransmitLGVendorId(m_processor->GetLogicalAddresses().primary, CECDEVICE_BROADCAST);
+ }
+ }
+ bHandled = true;
+ default:
+ break;
+ }
+ }
+
+ if (!bHandled)
+ bHandled = CCECCommandHandler::HandleCommand(command);
+
+ return bHandled;
+}
+
+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)
+{
+ m_processor->SetStandardLineTimeout(3);
+ m_processor->SetRetryLineTimeout(3);
+
+ /* increase the number of retries because the tv is keeping the bus busy at times */
+ m_iTransmitWait = 2000;
+ m_iTransmitRetries = 4;
+ m_iTransmitTimeout = 500;
+
+ CCECBusDevice *primary = m_processor->m_busDevices[m_processor->GetLogicalAddresses().primary];
+ if (m_busDevice->GetLogicalAddress() != primary->GetLogicalAddress())
+ {
+ primary->SetVendorId(CEC_VENDOR_LG, false);
+ primary->TransmitVendorID(CECDEVICE_TV, false);
+ }
+
+ if (m_busDevice->GetLogicalAddress() == CECDEVICE_TV)
+ {
+ /* LG TVs don't always reply to CEC version requests, so just set it to 1.3a */
+ m_busDevice->SetCecVersion(CEC_VERSION_1_3A);
+ }
+
+ /* LG devices always return "korean" as language */
+ cec_menu_language lang;
+ lang.device = m_busDevice->GetLogicalAddress();
+ snprintf(lang.language, 4, "eng");
+ m_busDevice->SetMenuLanguage(lang);
+
+ if (m_busDevice->GetLogicalAddress() == CECDEVICE_TV)
+ {
+ m_processor->SetActiveSource();
+
+ /* LG TVs only route keypresses when the deck status is set to 0x20 */
+ cec_logical_addresses addr = m_processor->GetLogicalAddresses();
+ for (uint8_t iPtr = 0; iPtr < 15; iPtr++)
+ {
+ CCECBusDevice *device = m_processor->m_busDevices[iPtr];
+
+ if (addr[iPtr])
+ {
+ if (device && (device->GetType() == CEC_DEVICE_TYPE_PLAYBACK_DEVICE ||
+ device->GetType() == CEC_DEVICE_TYPE_RECORDING_DEVICE))
+ {
+ ((CCECPlaybackDevice *)device)->SetDeckStatus(CEC_DECK_INFO_OTHER_STATUS_LG);
+ ((CCECPlaybackDevice *)device)->TransmitDeckStatus(CECDEVICE_TV);
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+bool CSLCommandHandler::TransmitPowerOn(const cec_logical_address iInitiator, const cec_logical_address iDestination)
+{
+ if (iDestination != CECDEVICE_BROADCAST &&
+ iDestination != CECDEVICE_TV &&
+ m_processor->m_busDevices[iDestination]->GetVendorId(false) == CEC_VENDOR_LG)
+ {
+ cec_command command;
+ cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_VENDOR_COMMAND);
+ command.parameters.PushBack((uint8_t)SL_COMMAND_POWER_ON);
+ command.parameters.PushBack(0x00);
+ return Transmit(command);
+ }
+
+ return CCECCommandHandler::TransmitPowerOn(iInitiator, iDestination);
+}
+
CSLCommandHandler(CCECBusDevice *busDevice);
virtual ~CSLCommandHandler(void) {};
virtual cec_vendor_id GetVendorId(void) { return CEC_VENDOR_LG; };
+
+ virtual bool HandleCommand(const cec_command &command);
+ virtual void HandlePoll(const cec_logical_address iInitiator, const cec_logical_address iDestination);
+ virtual bool HandleReceiveFailed(void);
+ virtual bool InitHandler(void);
+ virtual bool TransmitLGVendorId(const cec_logical_address iInitiator, const cec_logical_address iDestination);
+ virtual bool TransmitPowerOn(const cec_logical_address iInitiator, const cec_logical_address iDestination);
+
+ protected:
+ virtual void HandleVendorCommand01(const cec_command &command);
+ virtual void HandleVendorCommandPowerOn(const cec_command &command);
+ virtual void HandleVendorCommandSLConnect(const cec_command &command);
+ virtual void HandleVendorCommandPowerOnStatus(const cec_command &command);
+
+ virtual void TransmitVendorCommand0205(const cec_logical_address iSource, const cec_logical_address iDestination);
+ virtual void TransmitVendorCommand05(const cec_logical_address iSource, const cec_logical_address iDestination);
+ virtual void TransmitDeckStatus(const cec_logical_address iDestination);
+ virtual bool HandleGiveDeviceVendorId(const cec_command &command);
+ virtual bool HandleVendorCommand(const cec_command &command);
+ virtual bool HandleGiveDeckStatus(const cec_command &command);
+
+ bool m_bAwaitingReceiveFailed;
+ bool m_bSLEnabled;
+ bool m_bVendorIdSent;
};
};
CSerialPort::CSerialPort()
{
m_fd = -1;
+ m_tostdout = false;
}
CSerialPort::~CSerialPort()
int32_t byteswritten = 0;
+ 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 < (int32_t) data->size())
{
FD_ZERO(&port);
FD_SET(m_fd, &port);
- int returnv = select(m_fd + 1, NULL, &port, NULL, NULL);
- if (returnv == -1)
+ 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->packet.data + byteswritten, data->size() - byteswritten);
if (returnv == -1)
}
//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", (unsigned int)data[i]);
-//
-// printf("\n");
-// }
+ if (m_tostdout)
+ {
+ printf("%s write:", m_name.c_str());
+ for (int i = 0; i < byteswritten; i++)
+ printf(" %02x", data->at(i));
+
+ printf("\n");
+ }
return byteswritten;
}
}
//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", (unsigned int)data[i]);
-//
-// printf("\n");
-// }
+ 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;
}
std::string m_error;
std::string m_name;
CMutex m_mutex;
+ bool m_tostdout;
#ifdef __WINDOWS__
bool SetTimeouts(bool bBlocking);
#include <sstream>
#include "../lib/platform/threads.h"
#include "../lib/util/StdString.h"
+#include "../lib/implementations/CECCommandHandler.h"
using namespace CEC;
using namespace std;
#include <cecloader.h>
-int g_cecLogLevel = CEC_LOG_ALL;
-ofstream g_logOutput;
-bool g_bShortLog = false;
-CStdString g_strPort;
+int g_cecLogLevel(CEC_LOG_ALL);
+ofstream g_logOutput;
+bool g_bShortLog(false);
+CStdString g_strPort;
+uint8_t g_iHDMIPort(CEC_DEFAULT_HDMI_PORT);
+cec_logical_address g_iBaseDevice((cec_logical_address)CEC_DEFAULT_BASE_DEVICE);
+cec_device_type_list g_typeList;
+bool g_bSingleCommand(false);
+
inline bool HexStrToInt(const std::string& data, uint8_t& value)
{
return true;
}
-void flush_log(ICECAdapter *cecParser)
+void FlushLog(ICECAdapter *cecParser)
{
cec_log_message message;
while (cecParser && cecParser->GetNextLogMessage(&message))
}
}
-void list_devices(ICECAdapter *parser)
+void ListDevices(ICECAdapter *parser)
{
cec_adapter *devices = new cec_adapter[10];
uint8_t iDevicesFound = parser->FindAdapters(devices, 10, NULL);
}
}
-void show_help(const char* strExec)
+void ShowHelpCommandLine(const char* strExec)
{
cout << endl <<
strExec << " {-h|--help|-l|--list-devices|[COM PORT]}" << endl <<
" -h --help Shows this help text" << endl <<
" -l --list-devices List all devices on this system" << endl <<
" -t --type {p|r|t|a} The device type to use. More than one is possible." << endl <<
+ " -p --port {int} The HDMI port to use as active source." << endl <<
+ " -b --base {int} The logical address of the device to with this " << endl <<
+ " adapter is connected." << endl <<
" -f --log-file {file} Writes all libCEC log message to a file" << endl <<
" -sf --short-log-file {file} Writes all libCEC log message without timestamps" << endl <<
" and log levels to a file." << endl <<
" -d --log-level {level} Sets the log level. See cectypes.h for values." << endl <<
+ " -s --single-command Execute a single command and exit. Does not power" << endl <<
+ " on devices on startup and power them off on exit." << endl <<
" [COM PORT] The com port to connect to. If no COM" << endl <<
" port is given, the client tries to connect to the" << endl <<
" first device that is detected." << endl <<
"available commands" << endl;
}
-ICECAdapter *create_parser(cec_device_type_list typeList)
+ICECAdapter *CreateParser(cec_device_type_list typeList)
{
ICECAdapter *parser = LibCecInit("CECTester", typeList);
if (!parser || parser->GetMinLibVersion() > CEC_TEST_CLIENT_VERSION)
return parser;
}
-void show_console_help(void)
+void ShowHelpConsole(void)
{
cout << endl <<
"================================================================================" << endl <<
"Available commands:" << endl <<
endl <<
- "tx {bytes} transfer bytes over the CEC line." << endl <<
- "txn {bytes} transfer bytes but don't wait for transmission ACK." << endl <<
- "[tx 40 00 FF 11 22 33] sends bytes 0x40 0x00 0xFF 0x11 0x22 0x33" << endl <<
- endl <<
- "on {address} power on the device with the given logical address." << endl <<
- "[on 5] power on a connected audio system" << endl <<
- endl <<
- "standby {address} put the device with the given address in standby mode." << endl <<
- "[standby 0] powers off the TV" << endl <<
- endl <<
- "la {logical_address} change the logical address of the CEC adapter." << endl <<
- "[la 4] logical address 4" << endl <<
- endl <<
- "pa {physical_address} change the physical address of the CEC adapter." << endl <<
- "[pa 10 00] physical address 1.0.0.0" << endl <<
- endl <<
- "osd {addr} {string} set OSD message on the specified device." << endl <<
- "[osd 0 Test Message] displays 'Test Message' on the TV" << endl <<
- endl <<
- "ver {addr} get the CEC version of the specified device." << endl <<
- "[ver 0] get the CEC version of the TV" << endl <<
- endl <<
- "ven {addr} get the vendor ID of the specified device." << endl <<
- "[ven 0] get the vendor ID of the TV" << endl <<
- endl <<
- "lang {addr} get the menu language of the specified device." << endl <<
- "[lang 0] get the menu language of the TV" << endl <<
- endl <<
- "pow {addr} get the power status of the specified device." << endl <<
- "[pow 0] get the power status of the TV" << endl <<
- endl <<
- "poll {addr} poll the specified device." << endl <<
- "[poll 0] sends a poll message to the TV" << endl <<
- endl <<
+ "[tx] {bytes} transfer bytes over the CEC line." << endl <<
+ "[txn] {bytes} transfer bytes but don't wait for transmission ACK." << endl <<
+ "[on] {address} power on the device with the given logical address." << endl <<
+ "[standby] {address} put the device with the given address in standby mode." << endl <<
+ "[la] {logical address} change the logical address of the CEC adapter." << endl <<
+ "[p] {device} {port} change the HDMI port number of the CEC adapter." << endl <<
+ "[pa] {physical address} change the physical address of the CEC adapter." << endl <<
+ "[as] make the CEC adapter the active source." << endl <<
+ "[osd] {addr} {string} set OSD message on the specified device." << endl <<
+ "[ver] {addr} get the CEC version of the specified device." << endl <<
+ "[ven] {addr} get the vendor ID of the specified device." << endl <<
+ "[lang] {addr} get the menu language of the specified device." << endl <<
+ "[pow] {addr} get the power status of the specified device." << endl <<
+ "[name] {addr} get the OSD name of the specified device." << endl <<
+ "[poll] {addr} poll the specified device." << endl <<
+ "[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 <<
+ "[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 <<
+ "[scan] scan the CEC bus and display device info" << endl <<
"[mon] {1|0} enable or disable CEC bus monitoring." << endl <<
"[log] {1 - 31} change the log level. see cectypes.h for values." << endl <<
"[ping] send a ping command to the CEC adapter." << endl <<
"================================================================================" << endl;
}
-int main (int argc, char *argv[])
+bool ProcessCommandTX(ICECAdapter *parser, const string &command, string &arguments)
+{
+ if (command == "tx" || command == "txn")
+ {
+ string strvalue;
+ uint8_t ivalue;
+ cec_command bytes;
+ bytes.Clear();
+
+ while (GetWord(arguments, strvalue) && HexStrToInt(strvalue, ivalue))
+ bytes.PushBack(ivalue);
+
+ if (command == "txn")
+ bytes.transmit_timeout = 0;
+
+ parser->Transmit(bytes);
+
+ return true;
+ }
+
+ return false;
+}
+
+bool ProcessCommandON(ICECAdapter *parser, const string &command, string &arguments)
+{
+ if (command == "on")
+ {
+ string strValue;
+ uint8_t iValue = 0;
+ if (GetWord(arguments, strValue) && HexStrToInt(strValue, iValue) && iValue <= 0xF)
+ {
+ parser->PowerOnDevices((cec_logical_address) iValue);
+ return true;
+ }
+ else
+ {
+ cout << "invalid destination" << endl;
+ }
+ }
+
+ return false;
+}
+
+bool ProcessCommandSTANDBY(ICECAdapter *parser, const string &command, string &arguments)
+{
+ if (command == "standby")
+ {
+ string strValue;
+ uint8_t iValue = 0;
+ if (GetWord(arguments, strValue) && HexStrToInt(strValue, iValue) && iValue <= 0xF)
+ {
+ parser->StandbyDevices((cec_logical_address) iValue);
+ return true;
+ }
+ else
+ {
+ cout << "invalid destination" << endl;
+ }
+ }
+
+ return false;
+}
+
+bool ProcessCommandPOLL(ICECAdapter *parser, const string &command, string &arguments)
+{
+ if (command == "poll")
+ {
+ string strValue;
+ uint8_t iValue = 0;
+ if (GetWord(arguments, strValue) && HexStrToInt(strValue, iValue) && iValue <= 0xF)
+ {
+ if (parser->PollDevice((cec_logical_address) iValue))
+ cout << "POLL message sent" << endl;
+ else
+ cout << "POLL message not sent" << endl;
+ return true;
+ }
+ else
+ {
+ cout << "invalid destination" << endl;
+ }
+ }
+
+ return false;
+}
+
+bool ProcessCommandLA(ICECAdapter *parser, const string &command, string &arguments)
+{
+ if (command == "la")
+ {
+ string strvalue;
+ if (GetWord(arguments, strvalue))
+ {
+ parser->SetLogicalAddress((cec_logical_address) atoi(strvalue.c_str()));
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool ProcessCommandP(ICECAdapter *parser, const string &command, string &arguments)
+{
+ if (command == "p")
+ {
+ string strPort, strDevice;
+ if (GetWord(arguments, strDevice) && GetWord(arguments, strPort))
+ {
+ parser->SetHDMIPort((cec_logical_address)atoi(strDevice.c_str()), (uint8_t)atoi(strPort.c_str()));
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool ProcessCommandPA(ICECAdapter *parser, const string &command, string &arguments)
+{
+ if (command == "pa")
+ {
+ string strB1, strB2;
+ uint8_t iB1, iB2;
+ if (GetWord(arguments, strB1) && HexStrToInt(strB1, iB1) &&
+ GetWord(arguments, strB2) && HexStrToInt(strB2, iB2))
+ {
+ uint16_t iPhysicalAddress = ((uint16_t)iB1 << 8) + iB2;
+ parser->SetPhysicalAddress(iPhysicalAddress);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool ProcessCommandOSD(ICECAdapter *parser, const string &command, string &arguments)
+{
+ if (command == "osd")
+ {
+ bool bFirstWord(false);
+ string strAddr, strMessage, strWord;
+ uint8_t iAddr;
+ if (GetWord(arguments, strAddr) && HexStrToInt(strAddr, iAddr) && iAddr < 0xF)
+ {
+ while (GetWord(arguments, strWord))
+ {
+ if (bFirstWord)
+ {
+ bFirstWord = false;
+ strMessage.append(" ");
+ }
+ strMessage.append(strWord);
+ }
+ parser->SetOSDString((cec_logical_address) iAddr, CEC_DISPLAY_CONTROL_DISPLAY_FOR_DEFAULT_TIME, strMessage.c_str());
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool ProcessCommandAS(ICECAdapter *parser, const string &command, string &arguments)
+{
+ if (command == "as")
+ {
+ parser->SetActiveView();
+ return true;
+ }
+
+ return false;
+}
+
+
+bool ProcessCommandPING(ICECAdapter *parser, const string &command, string &arguments)
+{
+ if (command == "ping")
+ {
+ parser->PingAdapter();
+ return true;
+ }
+
+ return false;
+}
+
+bool ProcessCommandVOLUP(ICECAdapter *parser, const string &command, string &arguments)
+{
+ if (command == "volup")
+ {
+ CStdString strLog;
+ strLog.Format("volume up: %2X", parser->VolumeUp());
+ cout << strLog.c_str() << endl;
+ return true;
+ }
+
+ return false;
+}
+
+bool ProcessCommandVOLDOWN(ICECAdapter *parser, const string &command, string &arguments)
+{
+ if (command == "voldown")
+ {
+ CStdString strLog;
+ strLog.Format("volume up: %2X", parser->VolumeDown());
+ cout << strLog.c_str() << endl;
+ return true;
+ }
+
+ return false;
+}
+
+bool ProcessCommandMUTE(ICECAdapter *parser, const string &command, string &arguments)
+{
+ if (command == "mute")
+ {
+ CStdString strLog;
+ strLog.Format("mute: %2X", parser->MuteAudio());
+ cout << strLog.c_str() << endl;
+ return true;
+ }
+
+ return false;
+}
+
+bool ProcessCommandMON(ICECAdapter *parser, const string &command, string &arguments)
+{
+ if (command == "mon")
+ {
+ CStdString strEnable;
+ if (GetWord(arguments, strEnable) && (strEnable.Equals("0") || strEnable.Equals("1")))
+ {
+ parser->SwitchMonitoring(strEnable.Equals("1"));
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool ProcessCommandBL(ICECAdapter *parser, const string &command, string &arguments)
{
- cec_device_type_list typeList;
- typeList.clear();
+ if (command == "bl")
+ {
+ parser->StartBootloader();
+ return true;
+ }
+
+ return false;
+}
+
+bool ProcessCommandLANG(ICECAdapter *parser, const string &command, string &arguments)
+{
+ if (command == "lang")
+ {
+ CStdString strDev;
+ if (GetWord(arguments, strDev))
+ {
+ int iDev = atoi(strDev);
+ if (iDev >= 0 && iDev < 15)
+ {
+ CStdString strLog;
+ cec_menu_language language;
+ if (parser->GetDeviceMenuLanguage((cec_logical_address) iDev, &language))
+ strLog.Format("menu language '%s'", language.language);
+ else
+ strLog = "failed!";
+ cout << strLog.c_str() << endl;
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool ProcessCommandVEN(ICECAdapter *parser, const string &command, string &arguments)
+{
+ if (command == "ven")
+ {
+ CStdString strDev;
+ if (GetWord(arguments, strDev))
+ {
+ int iDev = atoi(strDev);
+ if (iDev >= 0 && iDev < 15)
+ {
+ uint64_t iVendor = parser->GetDeviceVendorId((cec_logical_address) iDev);
+ CStdString strLog;
+ strLog.Format("vendor id: %06x", iVendor);
+ cout << strLog.c_str() << endl;
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool ProcessCommandVER(ICECAdapter *parser, const string &command, string &arguments)
+{
+ if (command == "ver")
+ {
+ CStdString strDev;
+ if (GetWord(arguments, strDev))
+ {
+ int iDev = atoi(strDev);
+ if (iDev >= 0 && iDev < 15)
+ {
+ cec_version iVersion = parser->GetDeviceCecVersion((cec_logical_address) iDev);
+ cout << "CEC version " << parser->ToString(iVersion) << endl;
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool ProcessCommandPOW(ICECAdapter *parser, const string &command, string &arguments)
+{
+ if (command == "pow")
+ {
+ CStdString strDev;
+ if (GetWord(arguments, strDev))
+ {
+ int iDev = atoi(strDev);
+ if (iDev >= 0 && iDev < 15)
+ {
+ cec_power_status iPower = parser->GetDevicePowerStatus((cec_logical_address) iDev);
+ cout << "power status: " << parser->ToString(iPower) << endl;
+
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+bool ProcessCommandNAME(ICECAdapter *parser, const string &command, string &arguments)
+{
+ if (command == "name")
+ {
+ CStdString strDev;
+ if (GetWord(arguments, strDev))
+ {
+ int iDev = atoi(strDev);
+ if (iDev >= 0 && iDev < 15)
+ {
+ cec_osd_name name = parser->GetDeviceOSDName((cec_logical_address)iDev);
+ cout << "OSD name of device " << iDev << " is '" << name.name << "'" << endl;
+ }
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool ProcessCommandLAD(ICECAdapter *parser, const string &command, string &arguments)
+{
+ if (command == "lad")
+ {
+ cout << "listing active devices:" << endl;
+ cec_logical_addresses addresses = parser->GetActiveDevices();
+ for (uint8_t iPtr = 0; iPtr <= 11; iPtr++)
+ if (addresses[iPtr])
+ cout << "logical address " << (int)iPtr << endl;
+ return true;
+ }
+
+ return false;
+}
+
+bool ProcessCommandAD(ICECAdapter *parser, const string &command, string &arguments)
+{
+ if (command == "ad")
+ {
+ CStdString strDev;
+ if (GetWord(arguments, strDev))
+ {
+ int iDev = atoi(strDev);
+ if (iDev >= 0 && iDev < 15)
+ cout << "logical address " << iDev << " is " << (parser->IsActiveDevice((cec_logical_address)iDev) ? "active" : "not active") << endl;
+ }
+ }
+
+ return false;
+}
+
+bool ProcessCommandAT(ICECAdapter *parser, const string &command, string &arguments)
+{
+ if (command == "at")
+ {
+ CStdString strType;
+ if (GetWord(arguments, strType))
+ {
+ cec_device_type type = CEC_DEVICE_TYPE_TV;
+ if (strType.Equals("a"))
+ type = CEC_DEVICE_TYPE_AUDIO_SYSTEM;
+ else if (strType.Equals("p"))
+ type = CEC_DEVICE_TYPE_PLAYBACK_DEVICE;
+ else if (strType.Equals("r"))
+ type = CEC_DEVICE_TYPE_RECORDING_DEVICE;
+ else if (strType.Equals("t"))
+ type = CEC_DEVICE_TYPE_TUNER;
+ cout << "device " << type << " is " << (parser->IsActiveDeviceType(type) ? "active" : "not active") << endl;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool ProcessCommandR(ICECAdapter *parser, const string &command, string &arguments)
+{
+ if (command == "r")
+ {
+ cout << "closing the connection" << endl;
+ parser->Close();
+ FlushLog(parser);
+
+ cout << "opening a new connection" << endl;
+ parser->Open(g_strPort.c_str());
+ FlushLog(parser);
+
+ cout << "setting active source" << endl;
+ parser->SetActiveSource();
+ return true;
+ }
+
+ return false;
+}
+
+bool ProcessCommandH(ICECAdapter *parser, const string &command, string &arguments)
+{
+ if (command == "h" || command == "help")
+ {
+ ShowHelpConsole();
+ return true;
+ }
+
+ return false;
+}
+
+bool ProcessCommandLOG(ICECAdapter *parser, const string &command, string &arguments)
+{
+ if (command == "log")
+ {
+ CStdString strLevel;
+ if (GetWord(arguments, strLevel))
+ {
+ int iNewLevel = atoi(strLevel);
+ if (iNewLevel >= CEC_LOG_ERROR && iNewLevel <= CEC_LOG_ALL)
+ {
+ g_cecLogLevel = iNewLevel;
+ cout << "log level changed to " << strLevel.c_str() << endl;
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool ProcessCommandSCAN(ICECAdapter *parser, const string &command, string &arguments)
+{
+ if (command == "scan")
+ {
+ cout << "CEC bus information" << endl;
+ cout << "===================" << endl;
+ cec_logical_addresses addresses = parser->GetActiveDevices();
+ for (uint8_t iPtr = 0; iPtr < 16; iPtr++)
+ {
+ if (addresses[iPtr])
+ {
+ uint64_t iVendorId = parser->GetDeviceVendorId((cec_logical_address)iPtr);
+ bool bActive = parser->IsActiveSource((cec_logical_address)iPtr);
+ uint16_t iPhysicalAddress = parser->GetDevicePhysicalAddress((cec_logical_address)iPtr);
+ cec_version iCecVersion = parser->GetDeviceCecVersion((cec_logical_address)iPtr);
+ cec_power_status power = parser->GetDevicePowerStatus((cec_logical_address)iPtr);
+ cec_osd_name osdName = parser->GetDeviceOSDName((cec_logical_address)iPtr);
+ CStdString strAddr;
+ strAddr.Format("%04x", iPhysicalAddress);
+ cec_menu_language lang;
+ lang.device = CECDEVICE_UNKNOWN;
+ parser->GetDeviceMenuLanguage((cec_logical_address)iPtr, &lang);
+
+ cout << "device #" << (int)iPtr << ": " << parser->ToString((cec_logical_address)iPtr) << endl;
+ cout << "address: " << strAddr.c_str() << endl;
+ cout << "active source: " << (bActive ? "yes" : "no") << endl;
+ cout << "vendor: " << parser->ToString((cec_vendor_id)iVendorId) << endl;
+ cout << "osd string: " << osdName.name << endl;
+ cout << "CEC version: " << parser->ToString(iCecVersion) << endl;
+ cout << "power status: " << parser->ToString(power) << endl;
+ if ((uint8_t)lang.device == iPtr)
+ cout << "language: " << lang.language << endl;
+ cout << endl;
+ }
+ }
+ return true;
+ }
+
+ return false;
+}
+
+bool ProcessConsoleCommand(ICECAdapter *parser, string &input)
+{
+ if (!input.empty())
+ {
+ string command;
+ if (GetWord(input, command))
+ {
+ if (command == "q" || command == "quit")
+ return false;
+
+ ProcessCommandTX(parser, command, input) ||
+ ProcessCommandON(parser, command, input) ||
+ ProcessCommandSTANDBY(parser, command, input) ||
+ ProcessCommandPOLL(parser, command, input) ||
+ ProcessCommandLA(parser, command, input) ||
+ ProcessCommandP(parser, command, input) ||
+ ProcessCommandPA(parser, command, input) ||
+ ProcessCommandAS(parser, command, input) ||
+ ProcessCommandOSD(parser, command, input) ||
+ ProcessCommandPING(parser, command, input) ||
+ ProcessCommandVOLUP(parser, command, input) ||
+ ProcessCommandVOLDOWN(parser, command, input) ||
+ ProcessCommandMUTE(parser, command, input) ||
+ ProcessCommandMON(parser, command, input) ||
+ ProcessCommandBL(parser, command, input) ||
+ ProcessCommandLANG(parser, command, input) ||
+ ProcessCommandVEN(parser, command, input) ||
+ ProcessCommandVER(parser, command, input) ||
+ ProcessCommandPOW(parser, command, input) ||
+ ProcessCommandNAME(parser, command, input) ||
+ ProcessCommandLAD(parser, command, input) ||
+ ProcessCommandAD(parser, command, input) ||
+ ProcessCommandAT(parser, command, input) ||
+ ProcessCommandR(parser, command, input) ||
+ ProcessCommandH(parser, command, input) ||
+ ProcessCommandLOG(parser, command, input) ||
+ ProcessCommandSCAN(parser, command, input);
+ }
+ }
+ return true;
+}
+
+bool ProcessCommandLineArguments(int argc, char *argv[])
+{
+ bool bReturn(true);
int iArgPtr = 1;
- while (iArgPtr < argc)
+ while (iArgPtr < argc && bReturn)
{
if (argc >= iArgPtr + 1)
{
if (iNewLevel >= CEC_LOG_ERROR && iNewLevel <= CEC_LOG_ALL)
{
g_cecLogLevel = iNewLevel;
- cout << "log level set to " << argv[iArgPtr + 1] << endl;
+ if (!g_bSingleCommand)
+ cout << "log level set to " << argv[iArgPtr + 1] << endl;
}
else
{
{
if (!strcmp(argv[iArgPtr + 1], "p"))
{
- cout << "== using device type 'playback device'" << endl;
- typeList.add(CEC_DEVICE_TYPE_PLAYBACK_DEVICE);
+ if (!g_bSingleCommand)
+ cout << "== using device type 'playback device'" << endl;
+ g_typeList.add(CEC_DEVICE_TYPE_PLAYBACK_DEVICE);
}
else if (!strcmp(argv[iArgPtr + 1], "r"))
{
- cout << "== using device type 'recording device'" << endl;
- typeList.add(CEC_DEVICE_TYPE_RECORDING_DEVICE);
+ if (!g_bSingleCommand)
+ cout << "== using device type 'recording device'" << endl;
+ g_typeList.add(CEC_DEVICE_TYPE_RECORDING_DEVICE);
}
else if (!strcmp(argv[iArgPtr + 1], "t"))
{
- cout << "== using device type 'tuner'" << endl;
- typeList.add(CEC_DEVICE_TYPE_TUNER);
+ if (!g_bSingleCommand)
+ cout << "== using device type 'tuner'" << endl;
+ g_typeList.add(CEC_DEVICE_TYPE_TUNER);
}
else if (!strcmp(argv[iArgPtr + 1], "a"))
{
- cout << "== using device type 'audio system'" << endl;
- typeList.add(CEC_DEVICE_TYPE_AUDIO_SYSTEM);
+ if (!g_bSingleCommand)
+ cout << "== using device type 'audio system'" << endl;
+ g_typeList.add(CEC_DEVICE_TYPE_AUDIO_SYSTEM);
}
else
{
else if (!strcmp(argv[iArgPtr], "--list-devices") ||
!strcmp(argv[iArgPtr], "-l"))
{
- ICECAdapter *parser = create_parser(typeList);
+ ICECAdapter *parser = CreateParser(g_typeList);
if (parser)
{
- list_devices(parser);
+ ListDevices(parser);
UnloadLibCec(parser);
+ parser = NULL;
}
- return 0;
+ bReturn = false;
+ }
+ else if (!strcmp(argv[iArgPtr], "--single-command") ||
+ !strcmp(argv[iArgPtr], "-s"))
+ {
+ g_bSingleCommand = true;
+ ++iArgPtr;
}
else if (!strcmp(argv[iArgPtr], "--help") ||
!strcmp(argv[iArgPtr], "-h"))
{
- show_help(argv[0]);
+ ShowHelpCommandLine(argv[0]);
return 0;
}
+ else if (!strcmp(argv[iArgPtr], "-b") ||
+ !strcmp(argv[iArgPtr], "--base"))
+ {
+ if (argc >= iArgPtr + 2)
+ {
+ g_iBaseDevice = (cec_logical_address)atoi(argv[iArgPtr + 1]);
+ cout << "using base device '" << (int)g_iBaseDevice << "'" << endl;
+ ++iArgPtr;
+ }
+ ++iArgPtr;
+ }
+ else if (!strcmp(argv[iArgPtr], "-p") ||
+ !strcmp(argv[iArgPtr], "--port"))
+ {
+ if (argc >= iArgPtr + 2)
+ {
+ g_iHDMIPort = (int8_t)atoi(argv[iArgPtr + 1]);
+ cout << "using HDMI port '" << (int)g_iHDMIPort << "'" << endl;
+ ++iArgPtr;
+ }
+ ++iArgPtr;
+ }
else
{
g_strPort = argv[iArgPtr++];
}
}
- if (typeList.empty())
+ return bReturn;
+}
+
+int main (int argc, char *argv[])
+{
+ g_typeList.clear();
+
+ if (!ProcessCommandLineArguments(argc, argv))
+ return 0;
+
+ if (g_typeList.IsEmpty())
{
- cout << "No device type given. Using 'playback device'" << endl;
- typeList.add(CEC_DEVICE_TYPE_PLAYBACK_DEVICE);
+ if (!g_bSingleCommand)
+ cout << "No device type given. Using 'recording device'" << endl;
+ g_typeList.add(CEC_DEVICE_TYPE_RECORDING_DEVICE);
}
- ICECAdapter *parser = LibCecInit("CECTester", typeList);
+ ICECAdapter *parser = LibCecInit("CECTester", g_typeList);
if (!parser || parser->GetMinLibVersion() > CEC_TEST_CLIENT_VERSION)
{
#ifdef __WINDOWS__
#endif
return 1;
}
- CStdString strLog;
- strLog.Format("CEC Parser created - libcec version %d.%d", parser->GetLibVersionMajor(), parser->GetLibVersionMinor());
- cout << strLog.c_str() << endl;
- //make stdin non-blocking
-#ifndef __WINDOWS__
- int flags = fcntl(0, F_GETFL, 0);
- flags |= O_NONBLOCK;
- fcntl(0, F_SETFL, flags);
-#endif
+ if (!g_bSingleCommand)
+ {
+ CStdString strLog;
+ strLog.Format("CEC Parser created - libcec version %d.%d", parser->GetLibVersionMajor(), parser->GetLibVersionMinor());
+ cout << strLog.c_str() << endl;
+
+ //make stdin non-blocking
+ #ifndef __WINDOWS__
+ int flags = fcntl(0, F_GETFL, 0);
+ flags |= O_NONBLOCK;
+ fcntl(0, F_SETFL, flags);
+ #endif
+ }
if (g_strPort.IsEmpty())
{
- cout << "no serial port given. trying autodetect: ";
+ if (!g_bSingleCommand)
+ cout << "no serial port given. trying autodetect: ";
cec_adapter devices[10];
uint8_t iDevicesFound = parser->FindAdapters(devices, 10, NULL);
if (iDevicesFound <= 0)
{
+ if (g_bSingleCommand)
+ cout << "autodetect ";
cout << "FAILED" << endl;
UnloadLibCec(parser);
return 1;
}
else
{
- cout << endl << " path: " << devices[0].path << endl <<
- " com port: " << devices[0].comm << endl << endl;
+ if (!g_bSingleCommand)
+ {
+ cout << endl << " path: " << devices[0].path << endl <<
+ " com port: " << devices[0].comm << endl << endl;
+ }
g_strPort = devices[0].comm;
}
}
+ parser->SetHDMIPort(g_iBaseDevice, g_iHDMIPort);
+ cout << "opening a connection to the CEC adapter..." << endl;
+
if (!parser->Open(g_strPort.c_str()))
{
cout << "unable to open the device on port " << g_strPort << endl;
- flush_log(parser);
+ FlushLog(parser);
UnloadLibCec(parser);
return 1;
}
- cout << "cec device opened" << endl;
+ if (!g_bSingleCommand)
+ {
+ FlushLog(parser);
+ cout << "cec device opened" << endl;
+
+ parser->PowerOnDevices(CECDEVICE_TV);
+ FlushLog(parser);
- parser->PowerOnDevices(CECDEVICE_TV);
- flush_log(parser);
+ parser->SetActiveSource();
+ FlushLog(parser);
- parser->SetActiveSource();
- flush_log(parser);
+ cout << "waiting for input" << endl;
+ }
bool bContinue(true);
- cout << "waiting for input" << endl;
while (bContinue)
{
- flush_log(parser);
+ FlushLog(parser);
/* just ignore the command buffer and clear it */
cec_command dummy;
getline(cin, input);
cin.clear();
- if (!input.empty())
+ if (ProcessConsoleCommand(parser, input) && !g_bSingleCommand)
{
- string command;
- if (GetWord(input, command))
- {
- if (command == "tx" || command == "txn")
- {
- string strvalue;
- uint8_t ivalue;
- cec_command bytes;
- bytes.clear();
-
- while (GetWord(input, strvalue) && HexStrToInt(strvalue, ivalue))
- bytes.push_back(ivalue);
-
- if (command == "txn")
- bytes.transmit_timeout = 0;
-
- parser->Transmit(bytes);
- }
- else if (command == "on")
- {
- string strValue;
- uint8_t iValue = 0;
- if (GetWord(input, strValue) && HexStrToInt(strValue, iValue) && iValue <= 0xF)
- {
- parser->PowerOnDevices((cec_logical_address) iValue);
- }
- else
- {
- cout << "invalid destination" << endl;
- }
- }
- else if (command == "standby")
- {
- string strValue;
- uint8_t iValue = 0;
- if (GetWord(input, strValue) && HexStrToInt(strValue, iValue) && iValue <= 0xF)
- {
- parser->StandbyDevices((cec_logical_address) iValue);
- }
- else
- {
- cout << "invalid destination" << endl;
- }
- }
- else if (command == "poll")
- {
- string strValue;
- uint8_t iValue = 0;
- if (GetWord(input, strValue) && HexStrToInt(strValue, iValue) && iValue <= 0xF)
- {
- if (parser->PollDevice((cec_logical_address) iValue))
- cout << "POLL message sent" << endl;
- else
- cout << "POLL message not sent" << endl;
- }
- else
- {
- cout << "invalid destination" << endl;
- }
- }
- else if (command == "la")
- {
- string strvalue;
- if (GetWord(input, strvalue))
- {
- parser->SetLogicalAddress((cec_logical_address) atoi(strvalue.c_str()));
- }
- }
- else if (command == "pa")
- {
- string strB1, strB2;
- uint8_t iB1, iB2;
- if (GetWord(input, strB1) && HexStrToInt(strB1, iB1) &&
- GetWord(input, strB2) && HexStrToInt(strB2, iB2))
- {
- uint16_t iPhysicalAddress = ((uint16_t)iB1 << 8) + iB2;
- parser->SetPhysicalAddress(iPhysicalAddress);
- }
- }
- else if (command == "osd")
- {
- bool bFirstWord(false);
- string strAddr, strMessage, strWord;
- uint8_t iAddr;
- if (GetWord(input, strAddr) && HexStrToInt(strAddr, iAddr) && iAddr < 0xF)
- {
- while (GetWord(input, strWord))
- {
- if (bFirstWord)
- {
- bFirstWord = false;
- strMessage.append(" ");
- }
- strMessage.append(strWord);
- }
- parser->SetOSDString((cec_logical_address) iAddr, CEC_DISPLAY_CONTROL_DISPLAY_FOR_DEFAULT_TIME, strMessage.c_str());
- }
- }
- else if (command == "ping")
- {
- parser->PingAdapter();
- }
- else if (command == "mon")
- {
- CStdString strEnable;
- if (GetWord(input, strEnable) && (strEnable.Equals("0") || strEnable.Equals("1")))
- {
- parser->SwitchMonitoring(strEnable.Equals("1"));
- }
- }
- else if (command == "bl")
- {
- parser->StartBootloader();
- }
- else if (command == "lang")
- {
- CStdString strDev;
- if (GetWord(input, strDev))
- {
- int iDev = atoi(strDev);
- if (iDev >= 0 && iDev < 15)
- {
- CStdString strLog;
- cec_menu_language language;
- if (parser->GetDeviceMenuLanguage((cec_logical_address) iDev, &language))
- strLog.Format("menu language '%s'", language.language);
- else
- strLog = "failed!";
- cout << strLog.c_str() << endl;
- }
- }
- }
- else if (command == "ven")
- {
- CStdString strDev;
- if (GetWord(input, strDev))
- {
- int iDev = atoi(strDev);
- if (iDev >= 0 && iDev < 15)
- {
- uint64_t iVendor = parser->GetDeviceVendorId((cec_logical_address) iDev);
- CStdString strLog;
- strLog.Format("vendor id: %06x", iVendor);
- cout << strLog.c_str() << endl;
- }
- }
- }
- else if (command == "ver")
- {
- CStdString strDev;
- if (GetWord(input, strDev))
- {
- int iDev = atoi(strDev);
- if (iDev >= 0 && iDev < 15)
- {
- cec_version iVersion = parser->GetDeviceCecVersion((cec_logical_address) iDev);
- switch (iVersion)
- {
- case CEC_VERSION_1_2:
- cout << "CEC version 1.2" << endl;
- break;
- case CEC_VERSION_1_2A:
- cout << "CEC version 1.2a" << endl;
- break;
- case CEC_VERSION_1_3:
- cout << "CEC version 1.3" << endl;
- break;
- case CEC_VERSION_1_3A:
- cout << "CEC version 1.3a" << endl;
- break;
- default:
- cout << "unknown CEC version" << endl;
- break;
- }
- }
- }
- }
- else if (command == "pow")
- {
- CStdString strDev;
- if (GetWord(input, strDev))
- {
- int iDev = atoi(strDev);
- if (iDev >= 0 && iDev < 15)
- {
- cec_power_status iPower = parser->GetDevicePowerStatus((cec_logical_address) iDev);
- switch (iPower)
- {
- case CEC_POWER_STATUS_ON:
- cout << "powered on" << endl;
- break;
- case CEC_POWER_STATUS_IN_TRANSITION_ON_TO_STANDBY:
- cout << "on -> standby" << endl;
- break;
- case CEC_POWER_STATUS_IN_TRANSITION_STANDBY_TO_ON:
- cout << "standby -> on" << endl;
- break;
- case CEC_POWER_STATUS_STANDBY:
- cout << "standby" << endl;
- break;
- default:
- cout << "unknown power status" << endl;
- break;
- }
- }
- }
- }
- else if (command == "r")
- {
- cout << "closing the connection" << endl;
- parser->Close();
- flush_log(parser);
-
- cout << "opening a new connection" << endl;
- parser->Open(g_strPort.c_str());
- flush_log(parser);
-
- cout << "setting active source" << endl;
- parser->SetActiveSource();
- }
- else if (command == "h" || command == "help")
- {
- show_console_help();
- }
- else if (command == "q" || command == "quit")
- {
- bContinue = false;
- }
- else if (command == "log")
- {
- CStdString strLevel;
- if (GetWord(input, strLevel))
- {
- int iNewLevel = atoi(strLevel);
- if (iNewLevel >= CEC_LOG_ERROR && iNewLevel <= CEC_LOG_ALL)
- {
- g_cecLogLevel = iNewLevel;
- cout << "log level changed to " << strLevel.c_str() << endl;
- }
- }
- }
- }
- if (bContinue)
+ if (!input.empty())
cout << "waiting for input" << endl;
}
- CCondition::Sleep(50);
+ else
+ bContinue = false;
+
+ if (bContinue)
+ CCondition::Sleep(50);
}
- parser->StandbyDevices(CECDEVICE_BROADCAST);
+ if (!g_bSingleCommand)
+ parser->StandbyDevices(CECDEVICE_BROADCAST);
+
parser->Close();
- flush_log(parser);
+ FlushLog(parser);
UnloadLibCec(parser);
if (g_logOutput.is_open())