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