Etherios Cloud Connector very first porting for mbed. Tested in an LPC1768

Etherios Cloud Connector for Embedded v2.1.0.3 library for mbed. Early porting.

This port is centered mainly in the platform code. So it should work properly with the provided examples of send_data, device_request, data_points, RCI and firmware_update (stub implementation, not a real one... yet ;-)). Filesystem is not implemented yet, and some examples might need changes.

To run, it needs the following libraries: - mbed - mbed-rtos - EthernetInterface

Find more information (and the source code!) about Etherios Cloud Connector for Embedded here: http://www.etherios.com/products/devicecloud/support/connector and in: http://www.etherios.com

Committer:
spastor
Date:
Tue Dec 03 13:34:02 2013 +0000
Revision:
0:1c358ea10753
First commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
spastor 0:1c358ea10753 1 /*
spastor 0:1c358ea10753 2 * Copyright (c) 2013 Digi International Inc.,
spastor 0:1c358ea10753 3 * All rights not expressly granted are reserved.
spastor 0:1c358ea10753 4 *
spastor 0:1c358ea10753 5 * This Source Code Form is subject to the terms of the Mozilla Public
spastor 0:1c358ea10753 6 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
spastor 0:1c358ea10753 7 * You can obtain one at http://mozilla.org/MPL/2.0/.
spastor 0:1c358ea10753 8 *
spastor 0:1c358ea10753 9 * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
spastor 0:1c358ea10753 10 * =======================================================================
spastor 0:1c358ea10753 11 */
spastor 0:1c358ea10753 12 static connector_status_t sm_get_user_data_length(connector_data_t * const connector_ptr, connector_sm_data_t * const sm_ptr, connector_sm_session_t * const session)
spastor 0:1c358ea10753 13 {
spastor 0:1c358ea10753 14 connector_status_t result;
spastor 0:1c358ea10753 15 connector_callback_status_t status = connector_callback_continue;
spastor 0:1c358ea10753 16
spastor 0:1c358ea10753 17 #if !(defined CONNECTOR_DATA_SERVICE) && !(defined CONNECTOR_SM_CLI)
spastor 0:1c358ea10753 18 (void)(connector_ptr); /* Unused argument */
spastor 0:1c358ea10753 19 #endif
spastor 0:1c358ea10753 20
spastor 0:1c358ea10753 21 switch (session->command)
spastor 0:1c358ea10753 22 {
spastor 0:1c358ea10753 23 case connector_sm_cmd_data:
spastor 0:1c358ea10753 24 case connector_sm_cmd_no_path_data:
spastor 0:1c358ea10753 25 {
spastor 0:1c358ea10753 26 #if (defined CONNECTOR_DATA_SERVICE)
spastor 0:1c358ea10753 27 connector_data_service_length_t cb_data;
spastor 0:1c358ea10753 28
spastor 0:1c358ea10753 29 cb_data.transport = session->transport;
spastor 0:1c358ea10753 30 cb_data.user_context = session->user.context;
spastor 0:1c358ea10753 31 cb_data.total_bytes = 0;
spastor 0:1c358ea10753 32
spastor 0:1c358ea10753 33 #if (defined CONNECTOR_DATA_POINTS)
spastor 0:1c358ea10753 34 if (SmIsDatapoint(session->flags))
spastor 0:1c358ea10753 35 {
spastor 0:1c358ea10753 36 status = dp_handle_callback(connector_ptr, connector_request_id_data_service_send_length, &cb_data);
spastor 0:1c358ea10753 37 }
spastor 0:1c358ea10753 38 else
spastor 0:1c358ea10753 39 #endif
spastor 0:1c358ea10753 40 {
spastor 0:1c358ea10753 41 connector_request_id_t request_id;
spastor 0:1c358ea10753 42
spastor 0:1c358ea10753 43 request_id.data_service_request = SmIsClientOwned(session->flags) ? connector_request_id_data_service_send_length : connector_request_id_data_service_receive_reply_length;
spastor 0:1c358ea10753 44 status = connector_callback(connector_ptr->callback, connector_class_id_data_service, request_id, &cb_data);
spastor 0:1c358ea10753 45 if (status == connector_callback_unrecognized)
spastor 0:1c358ea10753 46 status = connector_callback_continue;
spastor 0:1c358ea10753 47 }
spastor 0:1c358ea10753 48
spastor 0:1c358ea10753 49 session->in.bytes = cb_data.total_bytes;
spastor 0:1c358ea10753 50 #endif
spastor 0:1c358ea10753 51 break;
spastor 0:1c358ea10753 52 }
spastor 0:1c358ea10753 53
spastor 0:1c358ea10753 54 #if (defined CONNECTOR_SM_CLI)
spastor 0:1c358ea10753 55 case connector_sm_cmd_cli:
spastor 0:1c358ea10753 56 {
spastor 0:1c358ea10753 57 connector_sm_cli_response_length_t cb_data;
spastor 0:1c358ea10753 58 connector_request_id_t request_id;
spastor 0:1c358ea10753 59
spastor 0:1c358ea10753 60 cb_data.transport = session->transport;
spastor 0:1c358ea10753 61 cb_data.user_context = session->user.context;
spastor 0:1c358ea10753 62 cb_data.total_bytes = 0;
spastor 0:1c358ea10753 63
spastor 0:1c358ea10753 64 request_id.sm_request = connector_request_id_sm_cli_response_length;
spastor 0:1c358ea10753 65 status = connector_callback(connector_ptr->callback, connector_class_id_short_message, request_id, &cb_data);
spastor 0:1c358ea10753 66 if (status == connector_callback_unrecognized)
spastor 0:1c358ea10753 67 status = connector_callback_continue;
spastor 0:1c358ea10753 68 session->in.bytes = cb_data.total_bytes;
spastor 0:1c358ea10753 69 break;
spastor 0:1c358ea10753 70 }
spastor 0:1c358ea10753 71 #endif
spastor 0:1c358ea10753 72
spastor 0:1c358ea10753 73 default:
spastor 0:1c358ea10753 74 result = connector_abort;
spastor 0:1c358ea10753 75 ASSERT_GOTO(connector_false, error);
spastor 0:1c358ea10753 76 break;
spastor 0:1c358ea10753 77 }
spastor 0:1c358ea10753 78
spastor 0:1c358ea10753 79 result = sm_map_callback_status_to_connector_status(status);
spastor 0:1c358ea10753 80 if (status == connector_callback_continue)
spastor 0:1c358ea10753 81 {
spastor 0:1c358ea10753 82 ASSERT_GOTO(session->in.bytes < (sm_ptr->transport.sm_mtu_tx * UCHAR_MAX), error);
spastor 0:1c358ea10753 83 session->sm_state = connector_sm_state_prepare_payload;
spastor 0:1c358ea10753 84 }
spastor 0:1c358ea10753 85
spastor 0:1c358ea10753 86 error:
spastor 0:1c358ea10753 87 return result;
spastor 0:1c358ea10753 88 }
spastor 0:1c358ea10753 89
spastor 0:1c358ea10753 90 #if (defined CONNECTOR_DATA_SERVICE)
spastor 0:1c358ea10753 91 static connector_status_t sm_get_more_request_data(connector_data_t * const connector_ptr, connector_sm_session_t * const session)
spastor 0:1c358ea10753 92 {
spastor 0:1c358ea10753 93 connector_status_t result = connector_abort;
spastor 0:1c358ea10753 94 uint8_t * dptr = session->in.data;
spastor 0:1c358ea10753 95 connector_data_service_send_data_t cb_data;
spastor 0:1c358ea10753 96
spastor 0:1c358ea10753 97 ASSERT_GOTO(session->in.bytes > session->bytes_processed, error);
spastor 0:1c358ea10753 98
spastor 0:1c358ea10753 99 cb_data.transport = session->transport;
spastor 0:1c358ea10753 100 cb_data.user_context = session->user.context;
spastor 0:1c358ea10753 101 cb_data.buffer = &dptr[session->bytes_processed];
spastor 0:1c358ea10753 102 cb_data.bytes_available = session->in.bytes - session->bytes_processed;
spastor 0:1c358ea10753 103 cb_data.bytes_used = 0;
spastor 0:1c358ea10753 104 cb_data.more_data = connector_false;
spastor 0:1c358ea10753 105
spastor 0:1c358ea10753 106 {
spastor 0:1c358ea10753 107 connector_callback_status_t status;
spastor 0:1c358ea10753 108
spastor 0:1c358ea10753 109 #if (defined CONNECTOR_DATA_POINTS)
spastor 0:1c358ea10753 110 if (SmIsDatapoint(session->flags))
spastor 0:1c358ea10753 111 {
spastor 0:1c358ea10753 112 status = dp_handle_callback(connector_ptr, connector_request_id_data_service_send_data, &cb_data);
spastor 0:1c358ea10753 113 }
spastor 0:1c358ea10753 114 else
spastor 0:1c358ea10753 115 #endif
spastor 0:1c358ea10753 116 {
spastor 0:1c358ea10753 117 connector_request_id_t request_id;
spastor 0:1c358ea10753 118
spastor 0:1c358ea10753 119 request_id.data_service_request = connector_request_id_data_service_send_data;
spastor 0:1c358ea10753 120 status = connector_callback(connector_ptr->callback, connector_class_id_data_service, request_id, &cb_data);
spastor 0:1c358ea10753 121 }
spastor 0:1c358ea10753 122
spastor 0:1c358ea10753 123 result = sm_map_callback_status_to_connector_status(status);
spastor 0:1c358ea10753 124 }
spastor 0:1c358ea10753 125
spastor 0:1c358ea10753 126 session->user.context = cb_data.user_context;
spastor 0:1c358ea10753 127 if (result == connector_working)
spastor 0:1c358ea10753 128 {
spastor 0:1c358ea10753 129 session->bytes_processed += cb_data.bytes_used;
spastor 0:1c358ea10753 130 ASSERT(session->bytes_processed <= session->in.bytes);
spastor 0:1c358ea10753 131 if (!cb_data.more_data)
spastor 0:1c358ea10753 132 sm_set_payload_complete(session);
spastor 0:1c358ea10753 133 }
spastor 0:1c358ea10753 134
spastor 0:1c358ea10753 135 error:
spastor 0:1c358ea10753 136 return result;
spastor 0:1c358ea10753 137 }
spastor 0:1c358ea10753 138
spastor 0:1c358ea10753 139 static connector_status_t sm_get_more_response_data(connector_data_t * const connector_ptr, connector_sm_session_t * const session)
spastor 0:1c358ea10753 140 {
spastor 0:1c358ea10753 141 connector_status_t result = connector_abort;
spastor 0:1c358ea10753 142 uint8_t * dptr = session->in.data;
spastor 0:1c358ea10753 143 connector_data_service_receive_reply_data_t cb_data;
spastor 0:1c358ea10753 144
spastor 0:1c358ea10753 145 ASSERT_GOTO(session->in.bytes > session->bytes_processed, error);
spastor 0:1c358ea10753 146
spastor 0:1c358ea10753 147 cb_data.transport = session->transport;
spastor 0:1c358ea10753 148 cb_data.user_context = session->user.context;
spastor 0:1c358ea10753 149 cb_data.buffer = &dptr[session->bytes_processed];
spastor 0:1c358ea10753 150 cb_data.bytes_available = session->in.bytes - session->bytes_processed;
spastor 0:1c358ea10753 151 cb_data.bytes_used = 0;
spastor 0:1c358ea10753 152 cb_data.more_data = connector_false;
spastor 0:1c358ea10753 153
spastor 0:1c358ea10753 154 {
spastor 0:1c358ea10753 155 connector_callback_status_t status;
spastor 0:1c358ea10753 156 connector_request_id_t request_id;
spastor 0:1c358ea10753 157
spastor 0:1c358ea10753 158 request_id.data_service_request = connector_request_id_data_service_receive_reply_data;
spastor 0:1c358ea10753 159 status = connector_callback(connector_ptr->callback, connector_class_id_data_service, request_id, &cb_data);
spastor 0:1c358ea10753 160 result = sm_map_callback_status_to_connector_status(status);
spastor 0:1c358ea10753 161 }
spastor 0:1c358ea10753 162
spastor 0:1c358ea10753 163 session->user.context = cb_data.user_context;
spastor 0:1c358ea10753 164 if (result == connector_working)
spastor 0:1c358ea10753 165 {
spastor 0:1c358ea10753 166 session->bytes_processed += cb_data.bytes_used;
spastor 0:1c358ea10753 167 ASSERT(session->bytes_processed <= session->in.bytes);
spastor 0:1c358ea10753 168 if (!cb_data.more_data)
spastor 0:1c358ea10753 169 {
spastor 0:1c358ea10753 170 sm_set_payload_complete(session);
spastor 0:1c358ea10753 171 }
spastor 0:1c358ea10753 172 else
spastor 0:1c358ea10753 173 {
spastor 0:1c358ea10753 174 ASSERT(cb_data.bytes_used < cb_data.bytes_available);
spastor 0:1c358ea10753 175 }
spastor 0:1c358ea10753 176 }
spastor 0:1c358ea10753 177
spastor 0:1c358ea10753 178 error:
spastor 0:1c358ea10753 179 return result;
spastor 0:1c358ea10753 180 }
spastor 0:1c358ea10753 181 #endif
spastor 0:1c358ea10753 182
spastor 0:1c358ea10753 183 #if (defined CONNECTOR_COMPRESSION)
spastor 0:1c358ea10753 184 static connector_status_t sm_compress_data(connector_data_t * const connector_ptr, connector_sm_session_t * const session)
spastor 0:1c358ea10753 185 {
spastor 0:1c358ea10753 186 connector_status_t status;
spastor 0:1c358ea10753 187 size_t const excluded_header_adler32_footer_bytes = 6;
spastor 0:1c358ea10753 188
spastor 0:1c358ea10753 189 session->compress.out.data = NULL;
spastor 0:1c358ea10753 190 session->compress.out.bytes = session->bytes_processed + excluded_header_adler32_footer_bytes;
spastor 0:1c358ea10753 191 status = sm_allocate_user_buffer(connector_ptr, &session->compress.out);
spastor 0:1c358ea10753 192 ASSERT_GOTO(status == connector_working, error);
spastor 0:1c358ea10753 193
spastor 0:1c358ea10753 194 {
spastor 0:1c358ea10753 195 z_streamp const zlib_ptr = &session->compress.zlib;
spastor 0:1c358ea10753 196 int zret;
spastor 0:1c358ea10753 197
spastor 0:1c358ea10753 198 memset(zlib_ptr, 0, sizeof *zlib_ptr);
spastor 0:1c358ea10753 199 zret = deflateInit(zlib_ptr, Z_DEFAULT_COMPRESSION);
spastor 0:1c358ea10753 200 ASSERT_GOTO(zret == Z_OK, error);
spastor 0:1c358ea10753 201
spastor 0:1c358ea10753 202 zlib_ptr->next_in = session->in.data;
spastor 0:1c358ea10753 203 zlib_ptr->avail_in = session->bytes_processed;
spastor 0:1c358ea10753 204 zlib_ptr->next_out = session->compress.out.data;
spastor 0:1c358ea10753 205 zlib_ptr->avail_out = session->compress.out.bytes;
spastor 0:1c358ea10753 206 zret = deflate(zlib_ptr, Z_FINISH);
spastor 0:1c358ea10753 207 switch(zret)
spastor 0:1c358ea10753 208 {
spastor 0:1c358ea10753 209 case Z_STREAM_END:
spastor 0:1c358ea10753 210 {
spastor 0:1c358ea10753 211 size_t const compressed_bytes = session->compress.out.bytes - (zlib_ptr->avail_out + excluded_header_adler32_footer_bytes);
spastor 0:1c358ea10753 212
spastor 0:1c358ea10753 213 if (compressed_bytes < session->bytes_processed)
spastor 0:1c358ea10753 214 {
spastor 0:1c358ea10753 215 uint8_t * data_ptr = session->compress.out.data;
spastor 0:1c358ea10753 216
spastor 0:1c358ea10753 217 SmSetCompressed(session->flags);
spastor 0:1c358ea10753 218 status = free_data_buffer(connector_ptr, named_buffer_id(sm_data_block), session->in.data);
spastor 0:1c358ea10753 219 if (status != connector_working) goto error;
spastor 0:1c358ea10753 220 session->in.data = data_ptr;
spastor 0:1c358ea10753 221 session->bytes_processed = compressed_bytes;
spastor 0:1c358ea10753 222 sm_set_payload_process(session);
spastor 0:1c358ea10753 223 break;
spastor 0:1c358ea10753 224 }
spastor 0:1c358ea10753 225 }
spastor 0:1c358ea10753 226 /* no break */
spastor 0:1c358ea10753 227
spastor 0:1c358ea10753 228 case Z_OK:
spastor 0:1c358ea10753 229 status = free_data_buffer(connector_ptr, named_buffer_id(sm_data_block), session->compress.out.data);
spastor 0:1c358ea10753 230 if (status != connector_working) goto error;
spastor 0:1c358ea10753 231 sm_set_payload_process(session);
spastor 0:1c358ea10753 232 break;
spastor 0:1c358ea10753 233
spastor 0:1c358ea10753 234 default:
spastor 0:1c358ea10753 235 status = connector_abort;
spastor 0:1c358ea10753 236 ASSERT_GOTO(connector_false, error);
spastor 0:1c358ea10753 237 break;
spastor 0:1c358ea10753 238 }
spastor 0:1c358ea10753 239
spastor 0:1c358ea10753 240 zret = deflateEnd(zlib_ptr);
spastor 0:1c358ea10753 241 ASSERT_GOTO(zret == Z_OK, error);
spastor 0:1c358ea10753 242 }
spastor 0:1c358ea10753 243
spastor 0:1c358ea10753 244 error:
spastor 0:1c358ea10753 245 return status;
spastor 0:1c358ea10753 246 }
spastor 0:1c358ea10753 247 #endif
spastor 0:1c358ea10753 248
spastor 0:1c358ea10753 249 static connector_status_t sm_prepare_segment(connector_sm_data_t * const sm_ptr, connector_sm_session_t * const session)
spastor 0:1c358ea10753 250 {
spastor 0:1c358ea10753 251 connector_status_t result = connector_abort;
spastor 0:1c358ea10753 252 size_t const max_payload = sm_ptr->transport.sm_mtu_tx - record_end(segment);
spastor 0:1c358ea10753 253
spastor 0:1c358ea10753 254 session->segments.processed = 0;
spastor 0:1c358ea10753 255 session->segments.size_array = NULL;
spastor 0:1c358ea10753 256 if (session->in.bytes <= max_payload)
spastor 0:1c358ea10753 257 session->segments.count = 1;
spastor 0:1c358ea10753 258 #if (defined CONNECTOR_SM_MULTIPART)
spastor 0:1c358ea10753 259 else
spastor 0:1c358ea10753 260 {
spastor 0:1c358ea10753 261 size_t const segment0_overhead_bytes = record_end(segment0) - record_end(segmentn);
spastor 0:1c358ea10753 262 size_t const segment_count = (session->in.bytes + ((max_payload + segment0_overhead_bytes) - 1))/max_payload;
spastor 0:1c358ea10753 263
spastor 0:1c358ea10753 264 ASSERT_GOTO(segment_count < 256, error);
spastor 0:1c358ea10753 265 session->segments.count = segment_count;
spastor 0:1c358ea10753 266 SmSetMultiPart(session->flags);
spastor 0:1c358ea10753 267 }
spastor 0:1c358ea10753 268 #else
spastor 0:1c358ea10753 269 else
spastor 0:1c358ea10753 270 {
spastor 0:1c358ea10753 271 connector_debug_printf("sm_prepare_segment: Multipart is disabled. Please define CONNECTOR_SM_MULTIPART in connector_config.h.\n");
spastor 0:1c358ea10753 272 ASSERT(connector_false);
spastor 0:1c358ea10753 273 result = connector_invalid_data_size;
spastor 0:1c358ea10753 274 goto error;
spastor 0:1c358ea10753 275 }
spastor 0:1c358ea10753 276 #endif
spastor 0:1c358ea10753 277
spastor 0:1c358ea10753 278 session->sm_state = connector_sm_state_send_data;
spastor 0:1c358ea10753 279 result = connector_working;
spastor 0:1c358ea10753 280
spastor 0:1c358ea10753 281 error:
spastor 0:1c358ea10753 282 return result;
spastor 0:1c358ea10753 283 }
spastor 0:1c358ea10753 284
spastor 0:1c358ea10753 285 static connector_status_t sm_send_segment(connector_data_t * const connector_ptr, connector_sm_data_t * const sm_ptr)
spastor 0:1c358ea10753 286 {
spastor 0:1c358ea10753 287 connector_status_t result = connector_no_resource;
spastor 0:1c358ea10753 288 connector_sm_packet_t * const send_packet = &sm_ptr->network.send_packet;
spastor 0:1c358ea10753 289 connector_callback_status_t status;
spastor 0:1c358ea10753 290 connector_network_send_t send_data;
spastor 0:1c358ea10753 291 connector_request_id_t request_id;
spastor 0:1c358ea10753 292
spastor 0:1c358ea10753 293 send_data.buffer = &send_packet->data[send_packet->processed_bytes];
spastor 0:1c358ea10753 294 send_data.bytes_available = send_packet->total_bytes - send_packet->processed_bytes;
spastor 0:1c358ea10753 295 send_data.handle = sm_ptr->network.handle;
spastor 0:1c358ea10753 296 send_data.bytes_used = 0;
spastor 0:1c358ea10753 297
spastor 0:1c358ea10753 298 request_id.network_request = connector_request_id_network_send;
spastor 0:1c358ea10753 299 status = connector_callback(connector_ptr->callback, sm_ptr->network.class_id, request_id, &send_data);
spastor 0:1c358ea10753 300 ASSERT(status != connector_callback_unrecognized);
spastor 0:1c358ea10753 301 result = sm_map_callback_status_to_connector_status(status);
spastor 0:1c358ea10753 302 if (status != connector_callback_continue) goto error;
spastor 0:1c358ea10753 303
spastor 0:1c358ea10753 304 send_packet->processed_bytes += send_data.bytes_used;
spastor 0:1c358ea10753 305 if (send_packet->processed_bytes >= send_packet->total_bytes)
spastor 0:1c358ea10753 306 {
spastor 0:1c358ea10753 307 connector_sm_session_t * const session = send_packet->pending_session;
spastor 0:1c358ea10753 308
spastor 0:1c358ea10753 309 ASSERT_GOTO(session != NULL, error);
spastor 0:1c358ea10753 310 session->segments.processed++;
spastor 0:1c358ea10753 311 if (session->segments.count == session->segments.processed)
spastor 0:1c358ea10753 312 {
spastor 0:1c358ea10753 313 if (session->in.bytes != 0)
spastor 0:1c358ea10753 314 {
spastor 0:1c358ea10753 315 connector_debug_printf("ERROR: sm_send_segment: All segments processed but still remaining bytes\n");
spastor 0:1c358ea10753 316 }
spastor 0:1c358ea10753 317 result = sm_switch_path(connector_ptr, session, SmIsResponse(session->flags) ? connector_sm_state_complete : connector_sm_state_receive_data);
spastor 0:1c358ea10753 318 if (result != connector_working) goto error;
spastor 0:1c358ea10753 319 }
spastor 0:1c358ea10753 320
spastor 0:1c358ea10753 321 send_packet->total_bytes = 0;
spastor 0:1c358ea10753 322 send_packet->processed_bytes = 0;
spastor 0:1c358ea10753 323 send_packet->pending_session = NULL;
spastor 0:1c358ea10753 324 }
spastor 0:1c358ea10753 325
spastor 0:1c358ea10753 326 error:
spastor 0:1c358ea10753 327 return result;
spastor 0:1c358ea10753 328 }
spastor 0:1c358ea10753 329
spastor 0:1c358ea10753 330 #if (defined CONNECTOR_TRANSPORT_SMS)
spastor 0:1c358ea10753 331 static connector_status_t sm_encode_segment(connector_data_t * const connector_ptr, connector_sm_data_t * const sm_ptr, connector_sm_session_t * const session)
spastor 0:1c358ea10753 332 {
spastor 0:1c358ea10753 333 size_t const data_size = 1+(sm_ptr->network.send_packet.total_bytes * 5)/4;
spastor 0:1c358ea10753 334 void * data_ptr = NULL;
spastor 0:1c358ea10753 335 connector_status_t result = malloc_data_buffer(connector_ptr, data_size, named_buffer_id(sm_data_block), &data_ptr);
spastor 0:1c358ea10753 336
spastor 0:1c358ea10753 337 if (result == connector_working)
spastor 0:1c358ea10753 338 {
spastor 0:1c358ea10753 339 connector_sm_packet_t * const send_ptr = &sm_ptr->network.send_packet;
spastor 0:1c358ea10753 340
spastor 0:1c358ea10753 341 send_ptr->total_bytes = sm_encode85(data_ptr, data_size, send_ptr->data, send_ptr->total_bytes);
spastor 0:1c358ea10753 342 memcpy(send_ptr->data, data_ptr, send_ptr->total_bytes);
spastor 0:1c358ea10753 343 result = free_data_buffer(connector_ptr, named_buffer_id(sm_data_block), data_ptr);
spastor 0:1c358ea10753 344 if (result != connector_working) goto error;
spastor 0:1c358ea10753 345 session->sm_state = connector_sm_state_send_data;
spastor 0:1c358ea10753 346 }
spastor 0:1c358ea10753 347
spastor 0:1c358ea10753 348 error:
spastor 0:1c358ea10753 349 return result;
spastor 0:1c358ea10753 350 }
spastor 0:1c358ea10753 351 #endif
spastor 0:1c358ea10753 352
spastor 0:1c358ea10753 353 static connector_status_t sm_send_data(connector_data_t * const connector_ptr, connector_sm_data_t * const sm_ptr, connector_sm_session_t * const session)
spastor 0:1c358ea10753 354 {
spastor 0:1c358ea10753 355 connector_status_t result = connector_working;
spastor 0:1c358ea10753 356 connector_sm_packet_t * const send_ptr = &sm_ptr->network.send_packet;
spastor 0:1c358ea10753 357 uint8_t * data_ptr = send_ptr->data;
spastor 0:1c358ea10753 358 uint8_t * sm_header;
spastor 0:1c358ea10753 359
spastor 0:1c358ea10753 360 if (send_ptr->total_bytes > 0)
spastor 0:1c358ea10753 361 {
spastor 0:1c358ea10753 362 goto send;
spastor 0:1c358ea10753 363 }
spastor 0:1c358ea10753 364
spastor 0:1c358ea10753 365 switch (sm_ptr->network.transport)
spastor 0:1c358ea10753 366 {
spastor 0:1c358ea10753 367 #if (defined CONNECTOR_TRANSPORT_UDP)
spastor 0:1c358ea10753 368 case connector_transport_udp:
spastor 0:1c358ea10753 369 {
spastor 0:1c358ea10753 370 uint8_t const sm_udp_version_num = SM_UDP_VERSION << 4;
spastor 0:1c358ea10753 371 uint8_t const version_byte = sm_udp_version_num | sm_ptr->transport.id_type;
spastor 0:1c358ea10753 372
spastor 0:1c358ea10753 373 *data_ptr++ = version_byte;
spastor 0:1c358ea10753 374 ASSERT(connector_ptr->connector_got_device_id);
spastor 0:1c358ea10753 375 memcpy(data_ptr, sm_ptr->transport.id, sm_ptr->transport.id_length);
spastor 0:1c358ea10753 376 data_ptr += sm_ptr->transport.id_length;
spastor 0:1c358ea10753 377 break;
spastor 0:1c358ea10753 378 }
spastor 0:1c358ea10753 379 #endif
spastor 0:1c358ea10753 380
spastor 0:1c358ea10753 381 #if (defined CONNECTOR_TRANSPORT_SMS)
spastor 0:1c358ea10753 382 case connector_transport_sms:
spastor 0:1c358ea10753 383 {
spastor 0:1c358ea10753 384 /* service ID available? */
spastor 0:1c358ea10753 385 if (sm_ptr->transport.id_length > 0)
spastor 0:1c358ea10753 386 {
spastor 0:1c358ea10753 387 ASSERT(sm_ptr->transport.id != NULL);
spastor 0:1c358ea10753 388 memcpy(data_ptr, sm_ptr->transport.id, sm_ptr->transport.id_length);
spastor 0:1c358ea10753 389 data_ptr += sm_ptr->transport.id_length;
spastor 0:1c358ea10753 390 *data_ptr++ = ' ';
spastor 0:1c358ea10753 391 }
spastor 0:1c358ea10753 392
spastor 0:1c358ea10753 393 break;
spastor 0:1c358ea10753 394 }
spastor 0:1c358ea10753 395 #endif
spastor 0:1c358ea10753 396
spastor 0:1c358ea10753 397 default:
spastor 0:1c358ea10753 398 ASSERT(connector_false);
spastor 0:1c358ea10753 399 break;
spastor 0:1c358ea10753 400 }
spastor 0:1c358ea10753 401
spastor 0:1c358ea10753 402 sm_header = data_ptr;
spastor 0:1c358ea10753 403
spastor 0:1c358ea10753 404 {
spastor 0:1c358ea10753 405 uint8_t const sm_version_num = 0x01 << 5;
spastor 0:1c358ea10753 406 uint8_t const request_id_hi = (session->request_id & SM_REQUEST_ID_MASK) >> 8;
spastor 0:1c358ea10753 407 uint8_t const request_id_low = session->request_id & 0xFF;
spastor 0:1c358ea10753 408 uint8_t info_field = sm_version_num | request_id_hi;
spastor 0:1c358ea10753 409
spastor 0:1c358ea10753 410 if (SmIsResponse(session->flags))
spastor 0:1c358ea10753 411 SmSetResponse(info_field);
spastor 0:1c358ea10753 412 else if (SmIsResponseNeeded(session->flags))
spastor 0:1c358ea10753 413 SmSetResponseNeeded(info_field);
spastor 0:1c358ea10753 414
spastor 0:1c358ea10753 415 if (session->segments.processed == 0)
spastor 0:1c358ea10753 416 {
spastor 0:1c358ea10753 417 uint8_t cmd_field = SmIsRequest(session->flags) ? session->command : 0;
spastor 0:1c358ea10753 418
spastor 0:1c358ea10753 419 if (SmIsError(session->flags))
spastor 0:1c358ea10753 420 SmSetError(cmd_field);
spastor 0:1c358ea10753 421 if (SmIsCompressed(session->flags))
spastor 0:1c358ea10753 422 SmSetCompressed(cmd_field);
spastor 0:1c358ea10753 423
spastor 0:1c358ea10753 424 #if (defined CONNECTOR_SM_MULTIPART)
spastor 0:1c358ea10753 425 if (SmIsMultiPart(session->flags))
spastor 0:1c358ea10753 426 {
spastor 0:1c358ea10753 427 uint8_t * const segment0 = sm_header;
spastor 0:1c358ea10753 428
spastor 0:1c358ea10753 429 SmSetMultiPart(info_field);
spastor 0:1c358ea10753 430 message_store_u8(segment0, info, info_field);
spastor 0:1c358ea10753 431 message_store_u8(segment0, request, request_id_low);
spastor 0:1c358ea10753 432 message_store_u8(segment0, segment, session->segments.processed);
spastor 0:1c358ea10753 433 message_store_u8(segment0, count, session->segments.count);
spastor 0:1c358ea10753 434 message_store_u8(segment0, cmd_status, cmd_field);
spastor 0:1c358ea10753 435 message_store_be16(segment0, crc, 0);
spastor 0:1c358ea10753 436 data_ptr += record_end(segment0);
spastor 0:1c358ea10753 437 }
spastor 0:1c358ea10753 438 else
spastor 0:1c358ea10753 439 #endif
spastor 0:1c358ea10753 440 {
spastor 0:1c358ea10753 441 uint8_t * const segment = sm_header;
spastor 0:1c358ea10753 442
spastor 0:1c358ea10753 443 ASSERT_GOTO(SmIsNotMultiPart(session->flags), done);
spastor 0:1c358ea10753 444 message_store_u8(segment, info, info_field);
spastor 0:1c358ea10753 445 message_store_u8(segment, request, request_id_low);
spastor 0:1c358ea10753 446 message_store_u8(segment, cmd_status, cmd_field);
spastor 0:1c358ea10753 447 message_store_be16(segment, crc, 0);
spastor 0:1c358ea10753 448 data_ptr += record_end(segment);
spastor 0:1c358ea10753 449 }
spastor 0:1c358ea10753 450 }
spastor 0:1c358ea10753 451 else
spastor 0:1c358ea10753 452 {
spastor 0:1c358ea10753 453 uint8_t * const segmentn = sm_header;
spastor 0:1c358ea10753 454
spastor 0:1c358ea10753 455 ASSERT_GOTO(SmIsMultiPart(session->flags), done);
spastor 0:1c358ea10753 456 SmSetMultiPart(info_field);
spastor 0:1c358ea10753 457 message_store_u8(segmentn, info, info_field);
spastor 0:1c358ea10753 458 message_store_u8(segmentn, request, request_id_low);
spastor 0:1c358ea10753 459 message_store_u8(segmentn, segment, session->segments.processed);
spastor 0:1c358ea10753 460 message_store_be16(segmentn, crc, 0);
spastor 0:1c358ea10753 461 data_ptr += record_end(segmentn);
spastor 0:1c358ea10753 462 }
spastor 0:1c358ea10753 463 }
spastor 0:1c358ea10753 464
spastor 0:1c358ea10753 465 {
spastor 0:1c358ea10753 466 size_t const filled_bytes = data_ptr - send_ptr->data;
spastor 0:1c358ea10753 467 size_t const bytes_available = sm_ptr->transport.sm_mtu_tx - (data_ptr - sm_header);
spastor 0:1c358ea10753 468 size_t payload_bytes;
spastor 0:1c358ea10753 469
spastor 0:1c358ea10753 470 if (SmIsError(session->flags))
spastor 0:1c358ea10753 471 {
spastor 0:1c358ea10753 472 uint16_t const error_code = (uint16_t)session->error;
spastor 0:1c358ea10753 473 char * const error_text = (session->error == connector_sm_error_in_request) ? "Request error" : "Unexpected request";
spastor 0:1c358ea10753 474 size_t const error_text_length = strlen(error_text) + 1;
spastor 0:1c358ea10753 475 size_t const error_code_length = sizeof error_code;
spastor 0:1c358ea10753 476
spastor 0:1c358ea10753 477 StoreBE16(data_ptr, error_code);
spastor 0:1c358ea10753 478 memcpy(data_ptr + error_code_length, error_text, error_text_length);
spastor 0:1c358ea10753 479 payload_bytes = error_code_length + error_text_length;
spastor 0:1c358ea10753 480 }
spastor 0:1c358ea10753 481 else
spastor 0:1c358ea10753 482 {
spastor 0:1c358ea10753 483 payload_bytes = (session->in.bytes < bytes_available) ? session->in.bytes : bytes_available;
spastor 0:1c358ea10753 484
spastor 0:1c358ea10753 485 if (payload_bytes > 0)
spastor 0:1c358ea10753 486 {
spastor 0:1c358ea10753 487 memcpy(data_ptr, &session->in.data[session->bytes_processed], payload_bytes);
spastor 0:1c358ea10753 488 session->bytes_processed += payload_bytes;
spastor 0:1c358ea10753 489 session->in.bytes -= payload_bytes;
spastor 0:1c358ea10753 490 }
spastor 0:1c358ea10753 491 }
spastor 0:1c358ea10753 492
spastor 0:1c358ea10753 493 send_ptr->total_bytes = filled_bytes + payload_bytes;
spastor 0:1c358ea10753 494
spastor 0:1c358ea10753 495 {
spastor 0:1c358ea10753 496 uint8_t * const crc_field = data_ptr - 2;
spastor 0:1c358ea10753 497 size_t const header_bytes = data_ptr - sm_header;
spastor 0:1c358ea10753 498 size_t const crc_bytes = header_bytes + payload_bytes;
spastor 0:1c358ea10753 499 uint16_t crc_value = 0;
spastor 0:1c358ea10753 500
spastor 0:1c358ea10753 501 crc_value = sm_calculate_crc16(crc_value, sm_header, crc_bytes);
spastor 0:1c358ea10753 502 StoreBE16(crc_field, crc_value);
spastor 0:1c358ea10753 503 }
spastor 0:1c358ea10753 504 }
spastor 0:1c358ea10753 505
spastor 0:1c358ea10753 506 send_ptr->pending_session = session;
spastor 0:1c358ea10753 507 #if (defined CONNECTOR_TRANSPORT_SMS)
spastor 0:1c358ea10753 508 if (SmIsEncoded(session->flags))
spastor 0:1c358ea10753 509 {
spastor 0:1c358ea10753 510 session->sm_state = connector_sm_state_encoding;
spastor 0:1c358ea10753 511 /* Increase pointer to skip preamble encoding */
spastor 0:1c358ea10753 512 if (sm_ptr->transport.id_length)
spastor 0:1c358ea10753 513 {
spastor 0:1c358ea10753 514 send_ptr->data += (sm_ptr->transport.id_length + SMS_SERVICEID_WRAPPER_TX_SIZE);
spastor 0:1c358ea10753 515 send_ptr->total_bytes -= (sm_ptr->transport.id_length + SMS_SERVICEID_WRAPPER_TX_SIZE);
spastor 0:1c358ea10753 516 }
spastor 0:1c358ea10753 517
spastor 0:1c358ea10753 518 result = sm_encode_segment(connector_ptr, sm_ptr, session);
spastor 0:1c358ea10753 519
spastor 0:1c358ea10753 520 /* Restore pointer if it has preamble */
spastor 0:1c358ea10753 521 if (sm_ptr->transport.id_length)
spastor 0:1c358ea10753 522 {
spastor 0:1c358ea10753 523 send_ptr->data -= (sm_ptr->transport.id_length + SMS_SERVICEID_WRAPPER_TX_SIZE);
spastor 0:1c358ea10753 524 send_ptr->total_bytes += (sm_ptr->transport.id_length + SMS_SERVICEID_WRAPPER_TX_SIZE);
spastor 0:1c358ea10753 525 }
spastor 0:1c358ea10753 526 }
spastor 0:1c358ea10753 527 #endif
spastor 0:1c358ea10753 528 send:
spastor 0:1c358ea10753 529 if (result == connector_working)
spastor 0:1c358ea10753 530 {
spastor 0:1c358ea10753 531 result = sm_send_segment(connector_ptr, sm_ptr);
spastor 0:1c358ea10753 532 }
spastor 0:1c358ea10753 533
spastor 0:1c358ea10753 534 done:
spastor 0:1c358ea10753 535 return result;
spastor 0:1c358ea10753 536 }
spastor 0:1c358ea10753 537
spastor 0:1c358ea10753 538 static connector_status_t sm_process_send_path(connector_data_t * const connector_ptr, connector_sm_data_t * const sm_ptr, connector_sm_session_t * const session)
spastor 0:1c358ea10753 539 {
spastor 0:1c358ea10753 540 connector_status_t result = connector_abort;
spastor 0:1c358ea10753 541
spastor 0:1c358ea10753 542 ASSERT_GOTO(session != NULL, error);
spastor 0:1c358ea10753 543 switch (session->sm_state)
spastor 0:1c358ea10753 544 {
spastor 0:1c358ea10753 545 case connector_sm_state_get_total_length:
spastor 0:1c358ea10753 546 result = sm_get_user_data_length(connector_ptr, sm_ptr, session);
spastor 0:1c358ea10753 547 break;
spastor 0:1c358ea10753 548
spastor 0:1c358ea10753 549 case connector_sm_state_prepare_payload:
spastor 0:1c358ea10753 550 result = sm_prepare_payload(connector_ptr, session);
spastor 0:1c358ea10753 551 break;
spastor 0:1c358ea10753 552
spastor 0:1c358ea10753 553 case connector_sm_state_more_data:
spastor 0:1c358ea10753 554 #if (defined CONNECTOR_DATA_SERVICE)
spastor 0:1c358ea10753 555 result = SmIsClientOwned(session->flags) ? sm_get_more_request_data(connector_ptr, session) : sm_get_more_response_data(connector_ptr, session);
spastor 0:1c358ea10753 556 #endif
spastor 0:1c358ea10753 557 break;
spastor 0:1c358ea10753 558
spastor 0:1c358ea10753 559 #if (defined CONNECTOR_COMPRESSION)
spastor 0:1c358ea10753 560 case connector_sm_state_compress:
spastor 0:1c358ea10753 561 result = sm_compress_data(connector_ptr, session);
spastor 0:1c358ea10753 562 break;
spastor 0:1c358ea10753 563 #endif
spastor 0:1c358ea10753 564
spastor 0:1c358ea10753 565 case connector_sm_state_prepare_segment:
spastor 0:1c358ea10753 566 result = sm_prepare_segment(sm_ptr, session);
spastor 0:1c358ea10753 567 break;
spastor 0:1c358ea10753 568
spastor 0:1c358ea10753 569 #if (defined CONNECTOR_TRANSPORT_SMS)
spastor 0:1c358ea10753 570 case connector_sm_state_encoding:
spastor 0:1c358ea10753 571 result = sm_encode_segment(connector_ptr, sm_ptr, session);
spastor 0:1c358ea10753 572 if (result == connector_working)
spastor 0:1c358ea10753 573 {
spastor 0:1c358ea10753 574 result = sm_send_segment(connector_ptr, sm_ptr);
spastor 0:1c358ea10753 575 }
spastor 0:1c358ea10753 576 break;
spastor 0:1c358ea10753 577 #endif
spastor 0:1c358ea10753 578
spastor 0:1c358ea10753 579 case connector_sm_state_send_data:
spastor 0:1c358ea10753 580 result = sm_send_data(connector_ptr, sm_ptr, session);
spastor 0:1c358ea10753 581 break;
spastor 0:1c358ea10753 582
spastor 0:1c358ea10753 583 default:
spastor 0:1c358ea10753 584 ASSERT(connector_false);
spastor 0:1c358ea10753 585 break;
spastor 0:1c358ea10753 586 }
spastor 0:1c358ea10753 587
spastor 0:1c358ea10753 588 sm_verify_result(sm_ptr, &result);
spastor 0:1c358ea10753 589
spastor 0:1c358ea10753 590 error:
spastor 0:1c358ea10753 591 return result;
spastor 0:1c358ea10753 592 }
spastor 0:1c358ea10753 593
spastor 0:1c358ea10753 594