Imported Upstream version 1.0.0
[platform/upstream/iotivity.git] / plugins / zigbee_wrapper / telegesis_wrapper / src / twsocketlist.c
1 //******************************************************************
2 //
3 // Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
21 /**
22  * @file
23  *
24  * This API only works with:
25  *      Telegesis ETRX357
26  *      CICIE R310 B110615
27  *
28  */
29
30 #include "twsocketlist.h"
31 #include "logger.h"
32 #include "oic_malloc.h"
33
34 #include <sys/stat.h>
35 #include <fcntl.h>
36 #include <errno.h>
37 #include <termios.h>
38 #include <string.h>
39 #include <unistd.h>
40
41 #define TAG "TWSocketList"
42
43
44 /**
45  *
46  * Apply terminal settings.
47  *
48  */
49 static int SetTerminalInfo(int fd, int speed, int parity, int shouldBlock);
50
51 /**
52  *
53  * Internal function to close socket. For outside callers to close a socket, they must properly
54  * call TWDeleteTWSock() for the same affect to ensure all things are cleaned up on shutdown.
55  *
56  */
57 TWResultCode TWCloseTWSock(TWSock * sock);
58
59 static TWSock * g_twSockList = NULL;
60
61 TWResultCode TWAddTWSock(TWSock * sock, PIPlugin * plugin, const char * fileLoc)
62 {
63     if(!sock || !plugin || !fileLoc)
64     {
65         return TW_RESULT_ERROR_INVALID_PARAMS;
66     }
67
68     TWSock * out = NULL;
69     TWSock * temp = NULL;
70     LL_FOREACH_SAFE(g_twSockList, out, temp)
71     {
72         if(out == sock)
73         {
74             // Ignore requests to add a socket that's already in the queue.
75             return TW_RESULT_OK;
76         }
77     }
78
79     sock->plugin = plugin;
80     sock->fd = open(fileLoc, O_RDWR | O_NOCTTY | O_SYNC);
81     if(sock->fd <= 0)
82     {
83         OC_LOG_V(INFO, TAG, "Could not open port. Errno is: %d\n", errno);
84         return TW_RESULT_ERROR;
85     }
86
87     // set speed to 19,200 bps, 8n1 (no parity), no blocking.
88     int ret = SetTerminalInfo(sock->fd, DEVICE_BAUDRATE, 0, 0);
89     if(ret != 0)
90     {
91         TWResultCode result = TWCloseTWSock(sock);
92         if(result != TW_RESULT_OK)
93         {
94             return result;
95         }
96         return TW_RESULT_ERROR;
97     }
98
99     sock->buffer = NULL;
100     sock->queue = NULL;
101     pthread_mutexattr_t mutexAttr;
102     pthread_mutexattr_init(&mutexAttr);
103     pthread_mutexattr_settype(&mutexAttr, PTHREAD_MUTEX_ERRORCHECK);
104     pthread_mutex_init(&(sock->mutex), &mutexAttr); // TODO: Use OIC_MUTEX instead.
105     pthread_cond_init(&(sock->queueCV), NULL);
106     sock->next = NULL;
107     sock->isActive = true;
108
109     LL_APPEND(g_twSockList, sock);
110     return TW_RESULT_OK;
111 }
112
113 TWSock * TWGetSock(PIPlugin * plugin)
114 {
115     if(!plugin)
116     {
117         return NULL;
118     }
119     TWSock * out = NULL;
120     TWSock * tmp = NULL;
121     LL_FOREACH_SAFE(g_twSockList, out, tmp)
122     {
123         if(out->plugin == plugin)
124         {
125             return out;
126         }
127     }
128     return NULL;
129 }
130
131 TWResultCode TWCloseTWSock(TWSock * sock)
132 {
133     if(!sock)
134     {
135         return TW_RESULT_ERROR_INVALID_PARAMS;
136     }
137     int ret = close(sock->fd);
138     if(ret != 0)
139     {
140         OC_LOG_V(ERROR, TAG, "Could not close port. Errno is: %d", errno);
141         return TW_RESULT_ERROR;
142     }
143     return TW_RESULT_OK;
144 }
145
146 TWResultCode TWDeleteTWSock(TWSock * sock)
147 {
148     if(!sock)
149     {
150         return TW_RESULT_ERROR_INVALID_PARAMS;
151     }
152     TWSock * out = NULL;
153     TWSock * tmp = NULL;
154     LL_FOREACH_SAFE(g_twSockList, out, tmp)
155     {
156         if(out == sock)
157         {
158             LL_DELETE(g_twSockList, out);
159         }
160     }
161
162     OICFree(sock->buffer);
163     OICFree(sock->eui);
164     TWFreeQueue(sock->plugin);
165
166     int mutexRet = pthread_mutex_destroy(&(sock->mutex));
167     if(mutexRet != 0)
168     {
169         OC_LOG_V(ERROR, TAG, "Failed to destroy mutex. Error: %d", mutexRet);
170         return TW_RESULT_ERROR;
171     }
172     TWResultCode result = TWCloseTWSock(sock);
173
174     return result;
175 }
176
177 TWResultCode TWDeleteAllTWSock()
178 {
179     TWSock * out = NULL;
180     TWSock * tmp = NULL;
181     LL_FOREACH_SAFE(g_twSockList, out, tmp)
182     {
183         TWDeleteTWSock(out);
184     }
185     return TW_RESULT_OK;
186 }
187
188 /**
189  *
190  * Apply interface attribute values to terminal settings.
191  *
192  */
193 int SetTerminalInfo(int fd, int speed, int parity, int shouldBlock)
194 {
195     OC_LOG(INFO, TAG, "Enter SetTerminalInfo()");
196
197     int ret = 0;
198     struct termios terminalInfo = {
199                                    .c_iflag = 0
200                                   };
201
202     errno = 0;
203     ret = tcgetattr(fd, &terminalInfo);
204     if (ret != 0)
205     {
206         OC_LOG_V(ERROR, TAG, "tcgetattr() - ret=%d errno=%d", ret, errno);
207         ret = -1;
208         goto exit;
209     }
210
211     errno = 0;
212     ret = cfsetispeed (&terminalInfo, speed);
213     if (ret != 0)
214     {
215         OC_LOG_V(ERROR, TAG, "cfsetispeed() - ret=%d errno=%d", ret, errno);
216         ret = -1;
217         goto exit;
218     }
219
220     errno = 0;
221     ret = cfsetospeed (&terminalInfo, speed);
222     if (ret != 0)
223     {
224         OC_LOG_V(ERROR, TAG, "cfsetospeed() - ret=%d errno=%d", ret, errno);
225         ret = -1;
226         goto exit;
227     }
228
229     terminalInfo.c_cflag = (terminalInfo.c_cflag & ~CSIZE);     //byte size
230     terminalInfo.c_cflag |= CS8;        //byte size is 8
231
232     terminalInfo.c_cflag &= ~PARENB;    //no parity
233     terminalInfo.c_cflag |= parity;     //no parity
234
235     terminalInfo.c_cflag &= ~CSTOPB;    //1 stop bit
236
237     terminalInfo.c_cflag |= CREAD;      //enable the receiver
238
239     //Input Control Settings
240     terminalInfo.c_iflag &= ~IGNBRK;    //break condition
241
242     //Local Mode Settings
243     terminalInfo.c_lflag = 0;
244
245     // whether to block on read and read time-out
246     terminalInfo.c_cc[VMIN]  = (shouldBlock >= 1) ? 1 : 0;
247     terminalInfo.c_cc[VTIME] = 5;
248
249     //Input Control Settings
250     terminalInfo.c_oflag = 0;
251
252     errno = 0;
253     ret = tcsetattr (fd, TCSANOW, &terminalInfo);
254     if (ret != 0)
255     {
256         OC_LOG_V(ERROR, TAG, "tcsetattr - ret=%d errno=%d", ret, errno);
257         ret = -1;
258     }
259
260 exit:
261     OC_LOG_V(INFO, TAG, "Leave SetTerminalInfo() with ret=%d", ret);
262     return ret;
263 }