*/
extern "C" DECLSPEC void * CECInitialise(CEC::libcec_configuration *configuration);
+/*!
+ * @brief Try to connect to the adapter and send the "start bootloader" command, without initialising libCEC and going through all checks
+ * @return True when the command was send, false otherwise.
+ */
+extern "C" DECLSPEC bool CECStartBootloader(void);
+
/*!
* @brief Unload the CEC adapter library.
*/
g_libCEC = NULL;
}
+/*!
+ * @brief Start the bootloader on the first device that was detected.
+ * @param strLib The name of and/or path to libCEC
+ * @return True when the command was sent, false otherwise.
+ */
+bool LibCecBootloader(const char *strLib = NULL)
+{
+ if (!g_libCEC)
+#if defined(_WIN64)
+ g_libCEC = LoadLibrary(strLib ? strLib : "libcec.x64.dll");
+#else
+ g_libCEC = LoadLibrary(strLib ? strLib : "libcec.dll");
+#endif
+ if (!g_libCEC)
+ return NULL;
+
+ typedef bool (__cdecl*_LibCecBootloader)(void);
+ _LibCecBootloader LibCecBootloader;
+ LibCecBootloader = (_LibCecBootloader) (GetProcAddress(g_libCEC, "CECStartBootloader"));
+ if (!LibCecBootloader)
+ return false;
+
+ bool bReturn = LibCecBootloader();
+ UnloadLibCec(static_cast< CEC::ICECAdapter* > g_libCEC);
+ return bReturn;
+}
+
#else
#include <dlfcn.h>
dlclose(g_libCEC);
}
+/*!
+ * @brief Start the bootloader on the first device that was detected.
+ * @param strLib The name of and/or path to libCEC
+ * @return True when the command was sent, false otherwise.
+ */
+bool LibCecBootloader(const char *strLib = NULL)
+{
+ if (!g_libCEC)
+ {
+#if defined(__APPLE__)
+ g_libCEC = dlopen(strLib ? strLib : "libcec.dylib", RTLD_LAZY);
+#else
+ g_libCEC = dlopen(strLib ? strLib : "libcec.so", RTLD_LAZY);
+#endif
+ if (!g_libCEC)
+ {
+#if defined(__APPLE__)
+ cout << "cannot find " << (strLib ? strLib : "libcec.dylib") << dlerror() << endl;
+#else
+ cout << "cannot find " << (strLib ? strLib : "libcec.so") << dlerror() << endl;
+#endif
+ return NULL;
+ }
+ }
+
+ typedef bool _LibCecBootloader(void);
+ _LibCecBootloader* LibCecBootloader = (_LibCecBootloader*) dlsym(g_libCEC, "CECStartBootloader");
+ if (!LibCecBootloader)
+ {
+ cout << "cannot find CECStartBootloader" << endl;
+ return NULL;
+ }
+
+ bool bReturn = LibCecBootloader();
+ UnloadLibCec((CEC::ICECAdapter*)g_libCEC);
+ return bReturn;
+}
+
#endif
#endif /* CECLOADER_H_ */
}
}
-bool CCECProcessor::StartBootloader(void)
+bool CCECProcessor::StartBootloader(const char *strPort /* = NULL */)
{
- return m_communication->StartBootloader();
+ if (!m_communication && strPort)
+ {
+ bool bReturn(false);
+ IAdapterCommunication *comm = new CUSBCECAdapterCommunication(this, strPort);
+ CTimeout timeout(10000);
+ int iConnectTry(0);
+ while (timeout.TimeLeft() > 0 && (bReturn = comm->Open(NULL, (timeout.TimeLeft() / CEC_CONNECT_TRIES)), true) == false)
+ {
+ CLibCEC::AddLog(CEC_LOG_ERROR, "could not open a connection (try %d)", ++iConnectTry);
+ comm->Close();
+ Sleep(500);
+ }
+ if (comm->IsOpen())
+ {
+ bReturn = comm->StartBootloader();
+ delete comm;
+ }
+ return bReturn;
+ }
+ else
+ {
+ return m_communication->StartBootloader();
+ }
}
bool CCECProcessor::PingAdapter(void)
virtual bool FindLogicalAddresses(void);
virtual bool SetAckMask(uint16_t iMask);
- virtual bool StartBootloader(void);
+ virtual bool StartBootloader(const char *strPort = NULL);
virtual bool PingAdapter(void);
virtual void HandlePoll(cec_logical_address initiator, cec_logical_address destination);
virtual bool HandleReceiveFailed(cec_logical_address initiator);
va_end(argList);
CLibCEC *instance = CLibCEC::GetInstance();
+ if (!instance)
+ return;
CLockObject lock(instance->m_mutex);
cec_log_message message;
void CLibCEC::AddKey(const cec_keypress &key)
{
CLibCEC *instance = CLibCEC::GetInstance();
+ if (!instance)
+ return;
CLockObject lock(instance->m_mutex);
AddLog(CEC_LOG_DEBUG, "key pressed: %1x", key.keycode);
void CLibCEC::AddKey(void)
{
CLibCEC *instance = CLibCEC::GetInstance();
+ if (!instance)
+ return;
CLockObject lock(instance->m_mutex);
if (instance->m_iCurrentButton != CEC_USER_CONTROL_CODE_UNKNOWN)
void CLibCEC::AddCommand(const cec_command &command)
{
CLibCEC *instance = CLibCEC::GetInstance();
+ if (!instance)
+ return;
CLockObject lock(instance->m_mutex);
AddLog(CEC_LOG_NOTICE, ">> %s (%X) -> %s (%X): %s (%2X)", instance->m_cec->ToString(command.initiator), command.initiator, instance->m_cec->ToString(command.destination), command.destination, instance->m_cec->ToString(command.opcode), command.opcode);
return static_cast< void* > (lib);
}
+bool CECStartBootloader(void)
+{
+ libcec_configuration dummy;
+ dummy.Clear();
+ CLibCEC *lib = new CLibCEC(&dummy);
+
+ bool bReturn(false);
+ cec_adapter deviceList[1];
+ if (CUSBCECAdapterDetection::FindAdapters(deviceList, 1) > 0)
+ {
+ bReturn = lib->m_cec->StartBootloader(deviceList[0].comm);
+ delete lib;
+ }
+ return bReturn;
+}
+
void CECDestroy(CEC::ICECAdapter *UNUSED(instance))
{
CLibCEC::SetInstance(NULL);
static CLibCEC *GetInstance(void);
static void SetInstance(CLibCEC *instance);
+ CCECProcessor * m_cec;
protected:
int64_t m_iStartTime;
cec_user_control_code m_iCurrentButton;
int64_t m_buttontime;
- CCECProcessor * m_cec;
PLATFORM::SyncedBuffer<cec_log_message> m_logBuffer;
PLATFORM::SyncedBuffer<cec_keypress> m_keyBuffer;
PLATFORM::SyncedBuffer<cec_command> m_commandBuffer;
* @brief Open a connection to the CEC adapter
* @param cb The callback struct. if set to NULL, the Read() method has to be used to read commands. if set, OnCommandReceived() will be called for each command that was received
* @param iTimeoutMs Connection timeout in ms
+ * @param bSkipChecks Skips all initial checks of the adapter, and starts the reader/writer threads directly after connecting.
* @return True when connected, false otherwise
*/
- virtual bool Open(IAdapterCommunicationCallback *cb, uint32_t iTimeoutMs = 10000) = 0;
+ virtual bool Open(IAdapterCommunicationCallback *cb, uint32_t iTimeoutMs = 10000, bool bSkipChecks = false) = 0;
/*!
* @brief Close an open connection
return bReturn;
}
-bool CUSBCECAdapterCommunication::Open(IAdapterCommunicationCallback *cb, uint32_t iTimeoutMs /* = 10000 */)
+bool CUSBCECAdapterCommunication::Open(IAdapterCommunicationCallback *cb, uint32_t iTimeoutMs /* = 10000 */, bool bSkipChecks /* = false */)
{
uint64_t iNow = GetTimeMs();
uint64_t iTimeout = iNow + iTimeoutMs;
CLibCEC::AddLog(CEC_LOG_DEBUG, "connection opened, clearing any previous input and waiting for active transmissions to end before starting");
- //clear any input bytes
- uint8_t buff[1024];
- while (m_port->Read(buff, 1024, 100) > 0)
+ if (!bSkipChecks)
{
- CLibCEC::AddLog(CEC_LOG_DEBUG, "data received, clearing it");
- Sleep(250);
+ //clear any input bytes
+ uint8_t buff[1024];
+ while (m_port->Read(buff, 1024, 100) > 0)
+ {
+ CLibCEC::AddLog(CEC_LOG_DEBUG, "data received, clearing it");
+ Sleep(250);
+ }
}
}
if (CreateThread())
{
- if (!CheckAdapter())
+ if (!bSkipChecks && !CheckAdapter())
{
StopThread();
CLibCEC::AddLog(CEC_LOG_ERROR, "the adapter failed to pass basic checks");
+ return false;
}
else
{
CUSBCECAdapterCommunication(CCECProcessor *processor, const char *strPort, uint16_t iBaudRate = 38400);
virtual ~CUSBCECAdapterCommunication();
- virtual bool Open(IAdapterCommunicationCallback *cb, uint32_t iTimeoutMs = 10000);
+ virtual bool Open(IAdapterCommunicationCallback *cb, uint32_t iTimeoutMs = 10000, bool bSkipChecks = false);
virtual void Close(void);
virtual bool IsOpen(void);
virtual CStdString GetError(void) const;
}
bReturn = false;
}
+ else if (!strcmp(argv[iArgPtr], "--bootloader"))
+ {
+ LibCecBootloader();
+ bReturn = false;
+ }
else if (!strcmp(argv[iArgPtr], "--single-command") ||
!strcmp(argv[iArgPtr], "-s"))
{
echo "Instructing the CEC adapter to enter bootloader mode"
cec_adapter=`lsusb | grep "2548:1001" | wc -l`
if [ $cec_adapter -gt 0 ]; then
- echo "bl" | cec-client -s -d 2
+ echo "bl" | cec-client --bootloader
echo "Waiting for the device to reinitialise"
sleep 5
fi