Merge "Fix the prevent issue - #38349" into tizen_2.2
[platform/framework/native/appfw.git] / src / io / FIo_SerialPortImpl.cpp
1 //
2 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
3 //
4 // Licensed under the Apache License, Version 2.0 (the License);
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://floralicense.org/license/
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 /**
18  * @file        FIo_SerialPortImpl.cpp
19  * @brief       This is the implementation file for _SerialPortImpl class.
20  */
21 #include <serial.h>
22 #include <unique_ptr.h>
23
24 #include <FBaseErrors.h>
25 #include <FBaseSysLog.h>
26 #include <FBaseRtIEventArg.h>
27
28 #include <FIo_AppServiceIpcMessages.h>
29 #include <FIo_IpcClient.h>
30 #include "FIo_SerialPortImpl.h"
31 #include "FSys_CommunicationDispatcherClient.h"
32
33 using namespace std;
34 using namespace Tizen::App;
35 using namespace Tizen::Base;
36 using namespace Tizen::Base::Runtime;
37 using namespace Tizen::Base::Collection;
38 using namespace Tizen::System;
39
40 namespace Tizen { namespace Io
41 {
42
43 const wchar_t COMMUNICATION_DISPATCHER_IPC_ID[] = L"osp.app.ipcserver.communicationdispatcher";
44 const wchar_t ACCESSORY_MANAGER_SERVICE_ID[] = L"osp.accessorymanager.service";
45 const wchar_t SERIAL_COMMAND_OPEN[] = L"Open";
46 const wchar_t SERIAL_COMMAND_CLOSE[] = L"Close";
47 const wchar_t SERIAL_COMMAND_WRITE[] = L"Write";
48 const wchar_t SERIAL_COMMAND_DATA[] = L"Data";
49 const wchar_t SERIAL_COMMAND_ERROR[] = L"Error";
50
51 const int SERIAL_BUFFER_SIZE = 512 * 1024; //512KB
52 const int SERIAL_DATA_HEAD = 1;
53 const int SERIAL_DATA_BODY = 2;
54
55 class _SerialPortEventArg
56         : public IEventArg
57 {
58 public:
59         _SerialPortEventArg(ByteBuffer* pBuffer)
60                 : __pBuffer(pBuffer)
61         {
62         }
63         ByteBuffer* __pBuffer;
64 };
65
66 class _SerialPortEvent
67         : public Event
68 {
69 protected:
70         virtual void FireImpl(IEventListener& listener, const IEventArg& arg)
71         {
72                 ISerialPortEventListener* pListener = dynamic_cast<ISerialPortEventListener*> (&listener);
73                 if (pListener != null)
74                 {
75                         const _SerialPortEventArg* pArg = dynamic_cast<const _SerialPortEventArg*>(&arg);
76                         if (pArg != null)
77                         {
78                                 if (pArg->__pBuffer == null)
79                                 {
80                                         pListener->OnSerialPortErrorOccured(E_SYSTEM);
81                                 }
82                                 else
83                                 {
84                                         SysLog(NID_IO, "Forward byte data to application.");
85                                         ByteBuffer* pBuffer = pArg->__pBuffer;
86                                         pListener->OnSerialPortDataReceivedN(*pBuffer);
87                                 }
88                         }
89                 }
90
91                 SysLog(NID_IO, "data is forwarded to application.");
92         }
93 };
94
95 _SerialPortImpl* _SerialPortImpl::__pSerialPortImpl = null;
96
97 _SerialPortImpl*
98 _SerialPortImpl::GetInstance(void)
99 {
100         SysLog(NID_IO, "Requires SerialPort instance");
101         if(__pSerialPortImpl == null)
102         {
103                 __pSerialPortImpl = new (std::nothrow) _SerialPortImpl();
104         }
105         return __pSerialPortImpl;
106 }
107
108 _SerialPortImpl::_SerialPortImpl()
109         : __pIpcClient(null)
110         , __pEvent(null)
111         , __isOpended(false)
112 {
113         SysLog(NID_IO, "Initialize SerialPort");
114         result r = E_SUCCESS;
115         _CommunicationDispatcherClient* pCommunicationDispatcherClient = _CommunicationDispatcherClient::GetInstance();
116         SysTryCatch(NID_IO, pCommunicationDispatcherClient != null, r = E_SYSTEM, r, "It is failed to get CommunicationDispatcherClient.");
117
118         r = pCommunicationDispatcherClient->RegisterCommunicationListener(ACCESSORY_MANAGER_SERVICE_ID, *this);
119         SysTryCatch(NID_IO, r == E_SUCCESS, r = E_SYSTEM, r, "It is failed to register on CommunicationDispatcherClient.");
120
121         __pIpcClient = pCommunicationDispatcherClient->GetIpcClient();
122         SysTryCatch(NID_IO, __pIpcClient != null, r = E_SYSTEM, r, "It is failed to get IpcClient from CommunicationDispatcherClient.");
123
124         __pEvent = new (std::nothrow) _SerialPortEvent();
125         SysTryCatch(NID_IO, __pEvent != null, r = E_OUT_OF_MEMORY, r, "[E_OUT_OF_MEMORY] The memory is insufficient.");
126
127 CATCH:
128         SetLastResult(r);
129 }
130
131 _SerialPortImpl::~_SerialPortImpl(void)
132 {
133         delete __pEvent;
134
135         __pEvent = null;
136         __pIpcClient = null;
137 }
138
139 result
140 _SerialPortImpl::SerialOpen(void)
141 {
142         result r = E_SUCCESS;
143         ArrayList request;
144         ArrayList response;
145         String serviceId(ACCESSORY_MANAGER_SERVICE_ID);
146         String commandId(SERIAL_COMMAND_OPEN);
147         SysLog(NID_IO, "Open SerialPort");
148         SysTryReturnResult(NID_IO, __pIpcClient != null, E_SYSTEM, "IPC is not ready.");
149
150         r = request.Construct();
151         r = response.Construct();
152
153         r = request.Add(serviceId);
154         r = request.Add(commandId);
155
156         unique_ptr<IoService_Request> pMsg(new (std::nothrow) IoService_Request(request, &response));
157         SysTryReturnResult(NID_IO, pMsg != NULL, r = E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
158
159         SysLog(NID_IO, "Try to send IPC message");
160         r = __pIpcClient->SendRequest(*pMsg);
161         SysTryReturnResult(NID_IO, r == E_SUCCESS, E_SYSTEM, "[%s] Propagated.", GetErrorMessage(r));
162
163         SysLog(NID_IO, "Sent IPC message");
164
165         __isOpended = true;
166         return r;
167 }
168
169 result
170 _SerialPortImpl::SerialClose(void)
171 {
172         result r = E_SUCCESS;
173         ArrayList request;
174         ArrayList response;
175         String serviceId(ACCESSORY_MANAGER_SERVICE_ID);
176         String commandId(SERIAL_COMMAND_CLOSE);
177
178         SysLog(NID_IO, "Close SerialPort");
179         SysTryReturnResult(NID_IO, __pIpcClient != null, E_SYSTEM, "IPC client is not ready.");
180
181         r = request.Construct();
182         r = request.Add(serviceId);
183         r = request.Add(commandId);
184         r = response.Construct();
185
186         unique_ptr<IoService_Request> pMsg(new (std::nothrow) IoService_Request(request, &response));
187         SysTryReturnResult(NID_IO, pMsg != NULL, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
188
189         r = __pIpcClient->SendRequest(*pMsg);
190         SysTryReturnResult(NID_IO, r == E_SUCCESS, r, "[%s] Propagated.", GetErrorMessage(r));
191
192         __isOpended = false;
193
194         return r;
195 }
196
197 bool
198 _SerialPortImpl::IsOpended(void)
199 {
200         return __isOpended;
201 }
202
203 result
204 _SerialPortImpl::SetSerialPortEventListener(ISerialPortEventListener& listener)
205 {
206         result r = E_SUCCESS;
207         SysTryReturnResult(NID_IO, __pEvent != null, E_SYSTEM, "Event is not ready.");
208         r = __pEvent->AddListener(listener);
209
210         return r;
211 }
212
213 result
214 _SerialPortImpl::Write(const Tizen::Base::ByteBuffer &byteBuffer)
215 {
216         result r = E_SUCCESS;
217         ByteBuffer* pByteBuffer = null;
218         ArrayList request;
219         ArrayList response;
220         String serviceId(ACCESSORY_MANAGER_SERVICE_ID);
221         String commandId(SERIAL_COMMAND_WRITE);
222
223         SysTryReturnResult(NID_IO, byteBuffer.GetCapacity() < SERIAL_BUFFER_SIZE, E_MAX_EXCEEDED, "[E_MAX_EXCEEDED] The buffer size exceeded a limit of the current device.");
224
225         pByteBuffer = const_cast <ByteBuffer *> (&byteBuffer);
226
227         SysTryReturnResult(NID_IO, __pIpcClient != null, E_SYSTEM, "[E_SYSTEM] IPC client is not ready");
228
229         r = request.Construct();
230         r = request.Add(serviceId);
231         r = request.Add(commandId);
232         r = request.Add(*pByteBuffer);
233         r = response.Construct();
234
235         unique_ptr<IoService_Request> pMsg(new (std::nothrow) IoService_Request(request, &response));
236         SysTryReturnResult(NID_IO, pMsg != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
237
238         r = __pIpcClient->SendRequest(pMsg.get());
239         SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] Propagated.", GetErrorMessage(r));
240
241         return E_SUCCESS;
242 }
243
244 int
245 _SerialPortImpl::GetWriteBufferSize(void) const
246 {
247         return SERIAL_BUFFER_SIZE;
248 }
249
250 void
251 _SerialPortImpl::OnDataReceived(const ArrayList& data)
252 {
253         ByteBuffer* pBuffer = null;
254
255         String* pCommand = (String*)(data.GetAt(SERIAL_DATA_HEAD));
256         SysTryReturnVoidResult(NID_APP, pCommand != null, E_SYSTEM, "[E_SYSTEM] There is no command");
257
258         if (pCommand->Equals(SERIAL_COMMAND_DATA, true))
259         {
260                 pBuffer = (ByteBuffer*)data.GetAt(SERIAL_DATA_BODY);
261                 if (pBuffer != null)
262                 {
263                         pBuffer->Flip();
264                         ArrayList* pData = const_cast<ArrayList*>(&data);
265                         pData->Remove(*pBuffer);
266                         _SerialPortEventArg* pEventArg= new (std::nothrow) _SerialPortEventArg(pBuffer);
267                         if(pEventArg != null)
268                         {
269                                 SysLog(NID_IO, "_SerialPortImpl::OnDataReceived Event Fire");
270                                 __pEvent->Fire(*pEventArg);
271                         }
272                 }
273         }
274         else if (pCommand->Equals(SERIAL_COMMAND_ERROR, true))
275         {
276                 _SerialPortEventArg* pEventArg= new (std::nothrow) _SerialPortEventArg(null);
277                  if(pEventArg != null)
278                  {
279                         SysLog(NID_IO, "_SerialPortImpl::OnDataReceived Event Fire");
280                         __pEvent->Fire(*pEventArg);
281                  }
282         }
283 }
284 }} // Tizen::Io
285