1 /*******************************************************************************
2 * Copyright (c) 2014, 2015 IBM Corp.
3 *
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * and Eclipse Distribution License v1.0 which accompany this distribution.
7 *
8 * The Eclipse Public License is available at
9 * http://www.eclipse.org/legal/epl-v10.html
10 * and the Eclipse Distribution License is available at
11 * http://www.eclipse.org/org/documents/edl-v10.php.
12 *
13 * Contributors:
14 * Allan Stockdill-Mander - initial API and implementation and/or initial documentation
15 * Ian Craggs - convert to FreeRTOS
16 *******************************************************************************/
17
18 #include "MQTTFreeRTOS.h"
19
20
ThreadStart(Thread * thread,void (* fn)(void *),void * arg)21 int ThreadStart(Thread* thread, void (*fn)(void*), void* arg)
22 {
23 int rc = 0;
24 uint16_t usTaskStackSize = (configMINIMAL_STACK_SIZE * 5);
25 UBaseType_t uxTaskPriority = uxTaskPriorityGet(NULL); /* set the priority as the same as the calling task*/
26
27 rc = xTaskCreate(fn, /* The function that implements the task. */
28 "MQTTTask", /* Just a text name for the task to aid debugging. */
29 usTaskStackSize, /* The stack size is defined in FreeRTOSIPConfig.h. */
30 arg, /* The task parameter, not used in this case. */
31 uxTaskPriority, /* The priority assigned to the task is defined in FreeRTOSConfig.h. */
32 &thread->task); /* The task handle is not used. */
33
34 return rc;
35 }
36
37
MutexInit(Mutex * mutex)38 void MutexInit(Mutex* mutex)
39 {
40 mutex->sem = xSemaphoreCreateMutex();
41 }
42
MutexLock(Mutex * mutex)43 int MutexLock(Mutex* mutex)
44 {
45 return xSemaphoreTake(mutex->sem, portMAX_DELAY);
46 }
47
MutexUnlock(Mutex * mutex)48 int MutexUnlock(Mutex* mutex)
49 {
50 return xSemaphoreGive(mutex->sem);
51 }
52
53
TimerCountdownMS(Timer * timer,unsigned int timeout_ms)54 void TimerCountdownMS(Timer* timer, unsigned int timeout_ms)
55 {
56 timer->xTicksToWait = timeout_ms / portTICK_PERIOD_MS; /* convert milliseconds to ticks */
57 vTaskSetTimeOutState(&timer->xTimeOut); /* Record the time at which this function was entered. */
58 }
59
60
TimerCountdown(Timer * timer,unsigned int timeout)61 void TimerCountdown(Timer* timer, unsigned int timeout)
62 {
63 TimerCountdownMS(timer, timeout * 1000);
64 }
65
66
TimerLeftMS(Timer * timer)67 int TimerLeftMS(Timer* timer)
68 {
69 xTaskCheckForTimeOut(&timer->xTimeOut, &timer->xTicksToWait); /* updates xTicksToWait to the number left */
70 return (timer->xTicksToWait < 0) ? 0 : (timer->xTicksToWait * portTICK_PERIOD_MS);
71 }
72
73
TimerIsExpired(Timer * timer)74 char TimerIsExpired(Timer* timer)
75 {
76 return xTaskCheckForTimeOut(&timer->xTimeOut, &timer->xTicksToWait) == pdTRUE;
77 }
78
79
TimerInit(Timer * timer)80 void TimerInit(Timer* timer)
81 {
82 timer->xTicksToWait = 0;
83 memset(&timer->xTimeOut, '\0', sizeof(timer->xTimeOut));
84 }
85
86
FreeRTOS_read(Network * n,unsigned char * buffer,int len,int timeout_ms)87 int FreeRTOS_read(Network* n, unsigned char* buffer, int len, int timeout_ms)
88 {
89 TickType_t xTicksToWait = timeout_ms / portTICK_PERIOD_MS; /* convert milliseconds to ticks */
90 TimeOut_t xTimeOut;
91 int recvLen = 0;
92
93 vTaskSetTimeOutState(&xTimeOut); /* Record the time at which this function was entered. */
94 do
95 {
96 int rc = 0;
97
98 FreeRTOS_setsockopt(n->my_socket, 0, FREERTOS_SO_RCVTIMEO, &xTicksToWait, sizeof(xTicksToWait));
99 rc = FreeRTOS_recv(n->my_socket, buffer + recvLen, len - recvLen, 0);
100 if (rc > 0)
101 recvLen += rc;
102 else if (rc < 0)
103 {
104 recvLen = rc;
105 break;
106 }
107 } while (recvLen < len && xTaskCheckForTimeOut(&xTimeOut, &xTicksToWait) == pdFALSE);
108
109 return recvLen;
110 }
111
112
FreeRTOS_write(Network * n,unsigned char * buffer,int len,int timeout_ms)113 int FreeRTOS_write(Network* n, unsigned char* buffer, int len, int timeout_ms)
114 {
115 TickType_t xTicksToWait = timeout_ms / portTICK_PERIOD_MS; /* convert milliseconds to ticks */
116 TimeOut_t xTimeOut;
117 int sentLen = 0;
118
119 vTaskSetTimeOutState(&xTimeOut); /* Record the time at which this function was entered. */
120 do
121 {
122 int rc = 0;
123
124 FreeRTOS_setsockopt(n->my_socket, 0, FREERTOS_SO_RCVTIMEO, &xTicksToWait, sizeof(xTicksToWait));
125 rc = FreeRTOS_send(n->my_socket, buffer + sentLen, len - sentLen, 0);
126 if (rc > 0)
127 sentLen += rc;
128 else if (rc < 0)
129 {
130 sentLen = rc;
131 break;
132 }
133 } while (sentLen < len && xTaskCheckForTimeOut(&xTimeOut, &xTicksToWait) == pdFALSE);
134
135 return sentLen;
136 }
137
138
FreeRTOS_disconnect(Network * n)139 void FreeRTOS_disconnect(Network* n)
140 {
141 FreeRTOS_closesocket(n->my_socket);
142 }
143
144
NetworkInit(Network * n)145 void NetworkInit(Network* n)
146 {
147 n->my_socket = 0;
148 n->mqttread = FreeRTOS_read;
149 n->mqttwrite = FreeRTOS_write;
150 n->disconnect = FreeRTOS_disconnect;
151 }
152
153
NetworkConnect(Network * n,char * addr,int port)154 int NetworkConnect(Network* n, char* addr, int port)
155 {
156 struct freertos_sockaddr sAddr;
157 int retVal = -1;
158 uint32_t ipAddress;
159
160 if ((ipAddress = FreeRTOS_gethostbyname(addr)) == 0)
161 goto exit;
162
163 sAddr.sin_port = FreeRTOS_htons(port);
164 sAddr.sin_addr = ipAddress;
165
166 if ((n->my_socket = FreeRTOS_socket(FREERTOS_AF_INET, FREERTOS_SOCK_STREAM, FREERTOS_IPPROTO_TCP)) < 0)
167 goto exit;
168
169 if ((retVal = FreeRTOS_connect(n->my_socket, &sAddr, sizeof(sAddr))) < 0)
170 {
171 FreeRTOS_closesocket(n->my_socket);
172 goto exit;
173 }
174
175 exit:
176 return retVal;
177 }
178
179
180 #if 0
181 int NetworkConnectTLS(Network *n, char* addr, int port, SlSockSecureFiles_t* certificates, unsigned char sec_method, unsigned int cipher, char server_verify)
182 {
183 SlSockAddrIn_t sAddr;
184 int addrSize;
185 int retVal;
186 unsigned long ipAddress;
187
188 retVal = sl_NetAppDnsGetHostByName(addr, strlen(addr), &ipAddress, AF_INET);
189 if (retVal < 0) {
190 return -1;
191 }
192
193 sAddr.sin_family = AF_INET;
194 sAddr.sin_port = sl_Htons((unsigned short)port);
195 sAddr.sin_addr.s_addr = sl_Htonl(ipAddress);
196
197 addrSize = sizeof(SlSockAddrIn_t);
198
199 n->my_socket = sl_Socket(SL_AF_INET, SL_SOCK_STREAM, SL_SEC_SOCKET);
200 if (n->my_socket < 0) {
201 return -1;
202 }
203
204 SlSockSecureMethod method;
205 method.secureMethod = sec_method;
206 retVal = sl_SetSockOpt(n->my_socket, SL_SOL_SOCKET, SL_SO_SECMETHOD, &method, sizeof(method));
207 if (retVal < 0) {
208 return retVal;
209 }
210
211 SlSockSecureMask mask;
212 mask.secureMask = cipher;
213 retVal = sl_SetSockOpt(n->my_socket, SL_SOL_SOCKET, SL_SO_SECURE_MASK, &mask, sizeof(mask));
214 if (retVal < 0) {
215 return retVal;
216 }
217
218 if (certificates != NULL) {
219 retVal = sl_SetSockOpt(n->my_socket, SL_SOL_SOCKET, SL_SO_SECURE_FILES, certificates->secureFiles, sizeof(SlSockSecureFiles_t));
220 if (retVal < 0)
221 {
222 return retVal;
223 }
224 }
225
226 retVal = sl_Connect(n->my_socket, (SlSockAddr_t *)&sAddr, addrSize);
227 if (retVal < 0) {
228 if (server_verify || retVal != -453) {
229 sl_Close(n->my_socket);
230 return retVal;
231 }
232 }
233
234 SysTickIntRegister(SysTickIntHandler);
235 SysTickPeriodSet(80000);
236 SysTickEnable();
237
238 return retVal;
239 }
240 #endif
241