1 #pragma once
2 /*
3  * This file is part of the libCEC(R) library.
4  *
5  * libCEC(R) is Copyright (C) 2011-2015 Pulse-Eight Limited.  All rights reserved.
6  * libCEC(R) is an original work, containing original code.
7  *
8  * libCEC(R) is a trademark of Pulse-Eight Limited.
9  *
10  * This program is dual-licensed; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23  * 02110-1301  USA
24  *
25  *
26  * Alternatively, you can license this library under a commercial license,
27  * please contact Pulse-Eight Licensing for more information.
28  *
29  * For more information contact:
30  * Pulse-Eight Licensing       <license@pulse-eight.com>
31  *     http://www.pulse-eight.com/
32  *     http://www.pulse-eight.net/
33  */
34 
35 #include "env.h"
36 #include <string>
37 #include "p8-platform/threads/threads.h"
38 #include "p8-platform/util/buffer.h"
39 #include "adapter/AdapterCommunication.h"
40 #include "devices/CECDeviceMap.h"
41 #include "CECInputBuffer.h"
42 #include <memory>
43 
44 namespace CEC
45 {
46   class CLibCEC;
47   class IAdapterCommunication;
48   class CCECBusDevice;
49   class CCECAudioSystem;
50   class CCECPlaybackDevice;
51   class CCECRecordingDevice;
52   class CCECTuner;
53   class CCECTV;
54   class CCECClient;
55   class CCECProcessor;
56   class CCECStandbyProtection;
57   typedef std::shared_ptr<CCECClient> CECClientPtr;
58 
59   typedef struct
60   {
61     CECClientPtr    client;
62     cec_device_type from;
63     cec_device_type to;
64   } device_type_change_t;
65 
66   class CCECAllocateLogicalAddress : public P8PLATFORM::CThread
67   {
68   public:
69     CCECAllocateLogicalAddress(CCECProcessor* processor, CECClientPtr client);
70     void* Process(void);
71 
72   private:
73     CCECProcessor* m_processor;
74     CECClientPtr   m_client;
75   };
76 
77   class CCECProcessor : public P8PLATFORM::CThread, public IAdapterCommunicationCallback
78   {
79     public:
80       CCECProcessor(CLibCEC *libcec);
81       virtual ~CCECProcessor(void);
82 
83       bool Start(const char *strPort, uint16_t iBaudRate = CEC_SERIAL_DEFAULT_BAUDRATE, uint32_t iTimeoutMs = CEC_DEFAULT_CONNECT_TIMEOUT);
84       void *Process(void);
85       void Close(void);
86 
87       bool RegisterClient(CCECClient* client);
88       bool RegisterClient(CECClientPtr client);
89       bool UnregisterClient(CCECClient* client);
90       bool UnregisterClient(CECClientPtr client);
91       void UnregisterClients(void);
92       uint16_t GetPhysicalAddressFromEeprom(void);
93       CECClientPtr GetPrimaryClient(void);
94       CECClientPtr GetClient(const cec_logical_address address);
95 
96       bool                  OnCommandReceived(const cec_command &command);
97       void                  HandleLogicalAddressLost(cec_logical_address oldAddress);
98       void                  HandlePhysicalAddressChanged(uint16_t iNewAddress);
99 
100       CCECBusDevice *       GetDevice(cec_logical_address address) const;
101       CCECAudioSystem *     GetAudioSystem(void) const;
102       CCECPlaybackDevice *  GetPlaybackDevice(cec_logical_address address) const;
103       CCECRecordingDevice * GetRecordingDevice(cec_logical_address address) const;
104       CCECTuner *           GetTuner(cec_logical_address address) const;
105       CCECTV *              GetTV(void) const;
106 
107       CCECBusDevice *       GetDeviceByPhysicalAddress(uint16_t iPhysicalAddress, bool bSuppressUpdate = true);
108       CCECBusDevice *       GetPrimaryDevice(void);
109       cec_logical_address   GetLogicalAddress(void);
110       cec_logical_addresses GetLogicalAddresses(void);
111       bool                  IsPresentDevice(cec_logical_address address);
112       bool                  IsPresentDeviceType(cec_device_type type);
113       uint16_t              GetDetectedPhysicalAddress(void) const;
GetLastTransmission(void)114       uint64_t              GetLastTransmission(void) const { return m_iLastTransmission; }
115       cec_logical_address   GetActiveSource(bool bRequestActiveSource = true);
116       bool                  IsActiveSource(cec_logical_address iAddress);
117       bool                  CECInitialised(void);
118 
119       bool                  StandbyDevices(const cec_logical_address initiator, const CECDEVICEVEC &devices);
120       bool                  StandbyDevice(const cec_logical_address initiator, cec_logical_address address);
121       bool                  PowerOnDevices(const cec_logical_address initiator, const CECDEVICEVEC &devices);
122       bool                  PowerOnDevice(const cec_logical_address initiator, cec_logical_address address);
123 
124       void ChangeDeviceType(CECClientPtr client, cec_device_type from, cec_device_type to);
125       bool SetDeckInfo(cec_deck_info info, bool bSendUpdate = true);
126       bool ActivateSource(uint16_t iStreamPath);
127       void SetActiveSource(bool bSetTo, bool bClientUnregistered);
128       bool GetStats(struct cec_adapter_stats* stats);
129       bool PollDevice(cec_logical_address iAddress);
130       void SetStandardLineTimeout(uint8_t iTimeout);
131       uint8_t GetStandardLineTimeout(void);
132       void SetRetryLineTimeout(uint8_t iTimeout);
133       uint8_t GetRetryLineTimeout(void);
134       bool CanSaveConfiguration(void);
135       bool SaveConfiguration(const libcec_configuration &configuration);
136       bool SetAutoMode(bool automode);
137       void RescanActiveDevices(void);
138 
139       bool SetLineTimeout(uint8_t iTimeout);
140 
141       bool Transmit(const cec_command &data, bool bIsReply);
142       void TransmitAbort(cec_logical_address source, cec_logical_address destination, cec_opcode opcode, cec_abort_reason reason = CEC_ABORT_REASON_UNRECOGNIZED_OPCODE);
143 
144       bool StartBootloader(const char *strPort = NULL);
145       bool PingAdapter(void);
146       void HandlePoll(cec_logical_address initiator, cec_logical_address destination);
147       bool HandleReceiveFailed(cec_logical_address initiator);
148 
149       bool GetDeviceInformation(const char *strPort, libcec_configuration *config, uint32_t iTimeoutMs = CEC_DEFAULT_CONNECT_TIMEOUT);
150 
151       bool TransmitPendingActiveSourceCommands(void);
152 
GetDevices(void)153       CCECDeviceMap *GetDevices(void) const { return m_busDevices; }
GetLib(void)154       CLibCEC *GetLib(void) const { return m_libcec; }
155 
156       bool IsHandledByLibCEC(const cec_logical_address address) const;
157 
158       bool TryLogicalAddress(cec_logical_address address, cec_version libCECSpecVersion = CEC_VERSION_1_4);
159 
160       bool IsRunningLatestFirmware(void);
161       void SwitchMonitoring(bool bSwitchTo);
162 
163       bool AllocateLogicalAddresses(CECClientPtr client);
164 
165       uint16_t GetAdapterVendorId(void) const;
166       uint16_t GetAdapterProductId(void) const;
167     private:
168       bool OpenConnection(const char *strPort, uint16_t iBaudRate, uint32_t iTimeoutMs, bool bStartListening = true);
169       void SetCECInitialised(bool bSetTo = true);
170 
171       void ReplaceHandlers(void);
172       bool PhysicalAddressInUse(uint16_t iPhysicalAddress);
173 
174       bool ClearLogicalAddresses(void);
175       bool SetLogicalAddresses(const cec_logical_addresses &addresses);
176 
177       void LogOutput(const cec_command &data);
178       void ProcessCommand(const cec_command &command);
179 
180       void ResetMembers(void);
181 
182       bool                                        m_bInitialised;
183       P8PLATFORM::CMutex                          m_mutex;
184       IAdapterCommunication *                     m_communication;
185       CLibCEC*                                    m_libcec;
186       uint8_t                                     m_iStandardLineTimeout;
187       uint8_t                                     m_iRetryLineTimeout;
188       uint64_t                                    m_iLastTransmission;
189       CCECInputBuffer                             m_inBuffer;
190       CCECDeviceMap *                             m_busDevices;
191       std::map<cec_logical_address, CECClientPtr> m_clients;
192       bool                                        m_bMonitor;
193       CCECAllocateLogicalAddress*                 m_addrAllocator;
194       bool                                        m_bStallCommunication;
195       CCECStandbyProtection*                      m_connCheck;
196       std::vector<device_type_change_t>           m_deviceTypeChanges;
197   };
198 
199   class CCECStandbyProtection : public P8PLATFORM::CThread
200   {
201   public:
202     CCECStandbyProtection(CCECProcessor* processor);
203     virtual ~CCECStandbyProtection(void);
204     void* Process(void);
205 
206   private:
207     CCECProcessor* m_processor;
208   };
209 };
210