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 14:10:48 2013 +0000
Revision:
1:908afea5a49d
Parent:
0:1c358ea10753
Use internal Thread.h instead of Threads.h

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 void rci_set_output_error(rci_t * const rci, unsigned int const id, char const * const hint, rci_output_state_t state)
spastor 0:1c358ea10753 13 {
spastor 0:1c358ea10753 14 rci_global_error(rci, id, hint);
spastor 0:1c358ea10753 15 set_rci_output_state(rci, state);
spastor 0:1c358ea10753 16 state_call(rci, rci_parser_state_output);
spastor 0:1c358ea10753 17 }
spastor 0:1c358ea10753 18
spastor 0:1c358ea10753 19 static connector_bool_t rci_output_data(rci_t * const rci, rci_buffer_t * const output, uint8_t const * const data, size_t const bytes)
spastor 0:1c358ea10753 20 {
spastor 0:1c358ea10753 21 connector_bool_t const overflow = connector_bool(rci_buffer_remaining(output) < bytes);
spastor 0:1c358ea10753 22
spastor 0:1c358ea10753 23 if (overflow)
spastor 0:1c358ea10753 24 {
spastor 0:1c358ea10753 25 rci->status = rci_status_flush_output;
spastor 0:1c358ea10753 26 }
spastor 0:1c358ea10753 27 else
spastor 0:1c358ea10753 28 {
spastor 0:1c358ea10753 29 memcpy(rci_buffer_position(output), data, bytes);
spastor 0:1c358ea10753 30 rci_buffer_advance(output, bytes);
spastor 0:1c358ea10753 31 }
spastor 0:1c358ea10753 32
spastor 0:1c358ea10753 33 return overflow;
spastor 0:1c358ea10753 34 }
spastor 0:1c358ea10753 35
spastor 0:1c358ea10753 36 static size_t get_bytes_followed(uint32_t value)
spastor 0:1c358ea10753 37 {
spastor 0:1c358ea10753 38 /* Bytes needed for the value:
spastor 0:1c358ea10753 39 * 1 byte is 0 to 0x7F
spastor 0:1c358ea10753 40 * 2 bytes is 0 to 0x1FFF
spastor 0:1c358ea10753 41 * 3 bytes is 0 to 0xFFFF
spastor 0:1c358ea10753 42 * 5 bytes is 0 to 0xFFFFFFFF
spastor 0:1c358ea10753 43 *
spastor 0:1c358ea10753 44 * Get additional bytes needed according to the value.
spastor 0:1c358ea10753 45 */
spastor 0:1c358ea10753 46 size_t bytes = 0;
spastor 0:1c358ea10753 47 if (value <= UINT32_C(0x7F))
spastor 0:1c358ea10753 48 {
spastor 0:1c358ea10753 49 bytes = 0;
spastor 0:1c358ea10753 50 }
spastor 0:1c358ea10753 51 else if (value < UINT32_C(0x2000))
spastor 0:1c358ea10753 52 {
spastor 0:1c358ea10753 53 bytes = 1;
spastor 0:1c358ea10753 54 }
spastor 0:1c358ea10753 55 else if (value < UINT32_C(0x10000))
spastor 0:1c358ea10753 56 {
spastor 0:1c358ea10753 57 bytes = 2;
spastor 0:1c358ea10753 58 }
spastor 0:1c358ea10753 59 else
spastor 0:1c358ea10753 60 {
spastor 0:1c358ea10753 61 bytes = 4;
spastor 0:1c358ea10753 62 }
spastor 0:1c358ea10753 63
spastor 0:1c358ea10753 64 return bytes;
spastor 0:1c358ea10753 65 }
spastor 0:1c358ea10753 66
spastor 0:1c358ea10753 67 static connector_bool_t rci_output_uint32(rci_t * const rci, uint32_t const value)
spastor 0:1c358ea10753 68 {
spastor 0:1c358ea10753 69 connector_bool_t overflow;
spastor 0:1c358ea10753 70 size_t const bytes_follow = get_bytes_followed(value);
spastor 0:1c358ea10753 71
spastor 0:1c358ea10753 72 rci_buffer_t * const output = &rci->buffer.output;
spastor 0:1c358ea10753 73 size_t const total_bytes = bytes_follow + 1;
spastor 0:1c358ea10753 74
spastor 0:1c358ea10753 75 overflow = connector_bool(rci_buffer_remaining(output) < total_bytes);
spastor 0:1c358ea10753 76 if (overflow)
spastor 0:1c358ea10753 77 {
spastor 0:1c358ea10753 78 rci->status = rci_status_flush_output;
spastor 0:1c358ea10753 79 }
spastor 0:1c358ea10753 80 else
spastor 0:1c358ea10753 81 {
spastor 0:1c358ea10753 82 uint8_t * const rci_ber = rci_buffer_position(output);
spastor 0:1c358ea10753 83
spastor 0:1c358ea10753 84 /*
spastor 0:1c358ea10753 85 * opcode
spastor 0:1c358ea10753 86 * 7 6 5 4 3 2 1 0 bit
spastor 0:1c358ea10753 87 * ---------------
spastor 0:1c358ea10753 88 * 0 X X X X X X X (0 : 0x7F)
spastor 0:1c358ea10753 89 * 1 0 0 X X X X X + 1 byte followed (0: 0x1FFF)
spastor 0:1c358ea10753 90 * 1 0 1 - - - 0 0 + 2 bytes followed (0: 0xFFFF)
spastor 0:1c358ea10753 91 * 1 0 1 - - - 0 1 + 4 bytes followed (0: 0xFFFFFFFF)
spastor 0:1c358ea10753 92 * 1 0 1 - - - 1 0 + 8 bytes followed (0: 0xFFFFFFFFFFFFFFFF)
spastor 0:1c358ea10753 93 * 1 1 0 - - - - - Reserved
spastor 0:1c358ea10753 94 * 1 1 1 0 0 0 0 0 NONUM (No Value)
spastor 0:1c358ea10753 95 * 1 1 1 0 0 0 0 1 TRM (Terminator)
spastor 0:1c358ea10753 96 */
spastor 0:1c358ea10753 97 switch (total_bytes)
spastor 0:1c358ea10753 98 {
spastor 0:1c358ea10753 99 case record_bytes(rci_ber):
spastor 0:1c358ea10753 100 {
spastor 0:1c358ea10753 101 /* one byte with range [0, 0x7F] */
spastor 0:1c358ea10753 102 uint8_t const data = (uint8_t)value;
spastor 0:1c358ea10753 103 message_store_u8(rci_ber, value, data);
spastor 0:1c358ea10753 104 break;
spastor 0:1c358ea10753 105 }
spastor 0:1c358ea10753 106 case record_bytes(rci_ber_u8):
spastor 0:1c358ea10753 107 {
spastor 0:1c358ea10753 108 #define MAX_ONE_BYTE_FOLLOW_VALUE UINT32_C(0x1FFF)
spastor 0:1c358ea10753 109
spastor 0:1c358ea10753 110 /* two bytes with range [0, 0x1FFF] */
spastor 0:1c358ea10753 111 uint8_t * const rci_ber_u8 = rci_ber;
spastor 0:1c358ea10753 112 uint8_t data;
spastor 0:1c358ea10753 113 uint16_t data_value = (uint16_t)value;
spastor 0:1c358ea10753 114
spastor 0:1c358ea10753 115 ASSERT(value <= MAX_ONE_BYTE_FOLLOW_VALUE);
spastor 0:1c358ea10753 116
spastor 0:1c358ea10753 117 data = BINARY_RCI_SIZE_ALTERNATE_FLAG;
spastor 0:1c358ea10753 118 data |= HIGH8(data_value);
spastor 0:1c358ea10753 119 message_store_u8(rci_ber_u8, opcode, data);
spastor 0:1c358ea10753 120
spastor 0:1c358ea10753 121 data = LOW8(data_value);
spastor 0:1c358ea10753 122 message_store_u8(rci_ber_u8, value, data);
spastor 0:1c358ea10753 123
spastor 0:1c358ea10753 124 #undef MAX_ONE_BYTE_FOLLOW_VALUE
spastor 0:1c358ea10753 125 break;
spastor 0:1c358ea10753 126 }
spastor 0:1c358ea10753 127 case record_bytes(rci_ber_u16):
spastor 0:1c358ea10753 128 {
spastor 0:1c358ea10753 129 /* 3 bytes with range [0, 0xFFFF] */
spastor 0:1c358ea10753 130 uint8_t * const rci_ber_u16 = rci_ber;
spastor 0:1c358ea10753 131 uint8_t const opcode = BINARY_RCI_SET_MULTI_FOLLOW_BYTES(binary_rci_two_follow_byte);
spastor 0:1c358ea10753 132 uint16_t const data = (uint16_t)value;
spastor 0:1c358ea10753 133
spastor 0:1c358ea10753 134 message_store_u8(rci_ber_u16, opcode, opcode);
spastor 0:1c358ea10753 135 message_store_be16(rci_ber_u16, value, data);
spastor 0:1c358ea10753 136 break;
spastor 0:1c358ea10753 137 }
spastor 0:1c358ea10753 138 case record_bytes(rci_ber_u32):
spastor 0:1c358ea10753 139 {
spastor 0:1c358ea10753 140 /* 5 bytes with range [0, 0xFFFFFFFF */
spastor 0:1c358ea10753 141 uint8_t * const rci_ber_u32 = rci_ber;
spastor 0:1c358ea10753 142 uint8_t const opcode = BINARY_RCI_SET_MULTI_FOLLOW_BYTES(binary_rci_four_follow_byte);
spastor 0:1c358ea10753 143
spastor 0:1c358ea10753 144 message_store_u8(rci_ber_u32, opcode, opcode);
spastor 0:1c358ea10753 145 message_store_be32(rci_ber_u32, value, value);
spastor 0:1c358ea10753 146
spastor 0:1c358ea10753 147 break;
spastor 0:1c358ea10753 148
spastor 0:1c358ea10753 149 }
spastor 0:1c358ea10753 150 }
spastor 0:1c358ea10753 151 rci_buffer_advance(output, total_bytes);
spastor 0:1c358ea10753 152 }
spastor 0:1c358ea10753 153 return overflow;
spastor 0:1c358ea10753 154 }
spastor 0:1c358ea10753 155
spastor 0:1c358ea10753 156 static connector_bool_t rci_output_string(rci_t * const rci, char const * const string, size_t const length)
spastor 0:1c358ea10753 157 {
spastor 0:1c358ea10753 158
spastor 0:1c358ea10753 159 rci_buffer_t * const output = &rci->buffer.output;
spastor 0:1c358ea10753 160 connector_bool_t overflow = connector_true;
spastor 0:1c358ea10753 161
spastor 0:1c358ea10753 162 /* output: | length | string | */
spastor 0:1c358ea10753 163 if (!rcistr_valid(&rci->output.content))
spastor 0:1c358ea10753 164 {
spastor 0:1c358ea10753 165 /* set up the data and its length */
spastor 0:1c358ea10753 166 overflow = rci_output_uint32(rci, length);
spastor 0:1c358ea10753 167 if (overflow) goto done;
spastor 0:1c358ea10753 168 rci->output.content.data = (uint8_t *)string;
spastor 0:1c358ea10753 169 rci->output.content.length = length;
spastor 0:1c358ea10753 170 }
spastor 0:1c358ea10753 171
spastor 0:1c358ea10753 172 if (rci->output.content.length > 0)
spastor 0:1c358ea10753 173 {
spastor 0:1c358ea10753 174 size_t const avail_bytes = rci_buffer_remaining(output);
spastor 0:1c358ea10753 175 size_t const write_bytes = (rci->output.content.length < avail_bytes) ? rci->output.content.length : avail_bytes;
spastor 0:1c358ea10753 176
spastor 0:1c358ea10753 177 overflow = rci_output_data(rci, output, (uint8_t *)rci->output.content.data, write_bytes);
spastor 0:1c358ea10753 178 if (overflow) goto done;
spastor 0:1c358ea10753 179
spastor 0:1c358ea10753 180 rci->output.content.data += write_bytes;
spastor 0:1c358ea10753 181 rci->output.content.length -= write_bytes;
spastor 0:1c358ea10753 182
spastor 0:1c358ea10753 183 }
spastor 0:1c358ea10753 184
spastor 0:1c358ea10753 185 if (rci->output.content.length > 0)
spastor 0:1c358ea10753 186 {
spastor 0:1c358ea10753 187 overflow = connector_true;
spastor 0:1c358ea10753 188 rci->status = rci_status_flush_output;
spastor 0:1c358ea10753 189 }
spastor 0:1c358ea10753 190 else
spastor 0:1c358ea10753 191 {
spastor 0:1c358ea10753 192 clear_rcistr(&rci->output.content);
spastor 0:1c358ea10753 193 }
spastor 0:1c358ea10753 194
spastor 0:1c358ea10753 195 done:
spastor 0:1c358ea10753 196 return overflow;
spastor 0:1c358ea10753 197 }
spastor 0:1c358ea10753 198
spastor 0:1c358ea10753 199 #if defined RCI_PARSER_USES_IPV4
spastor 0:1c358ea10753 200 static connector_bool_t rci_output_ipv4(rci_t * const rci, char const * const string)
spastor 0:1c358ea10753 201 {
spastor 0:1c358ea10753 202 rci_buffer_t * const output = &rci->buffer.output;
spastor 0:1c358ea10753 203 connector_bool_t overflow = connector_true;
spastor 0:1c358ea10753 204 size_t const avail_bytes = rci_buffer_remaining(output);
spastor 0:1c358ea10753 205
spastor 0:1c358ea10753 206 if (avail_bytes < sizeof(uint32_t))
spastor 0:1c358ea10753 207 {
spastor 0:1c358ea10753 208 goto done;
spastor 0:1c358ea10753 209 }
spastor 0:1c358ea10753 210 else
spastor 0:1c358ea10753 211 {
spastor 0:1c358ea10753 212 uint32_t ipv4 = 0;
spastor 0:1c358ea10753 213 uint8_t * const rci_ber_u32 = rci_buffer_position(output);
spastor 0:1c358ea10753 214 int dot_count = 0;
spastor 0:1c358ea10753 215 size_t i;
spastor 0:1c358ea10753 216 size_t length = strlen(string);
spastor 0:1c358ea10753 217 char aux_string[4] = {'\0', '\0', '\0', '\0'}; /* Three chars plus terminator. */
spastor 0:1c358ea10753 218
spastor 0:1c358ea10753 219 size_t index = 0;
spastor 0:1c358ea10753 220
spastor 0:1c358ea10753 221 for (i = 0; i < length; i++)
spastor 0:1c358ea10753 222 {
spastor 0:1c358ea10753 223 if (index > sizeof(aux_string) - 1)
spastor 0:1c358ea10753 224 break;
spastor 0:1c358ea10753 225
spastor 0:1c358ea10753 226 if (string[i] != '.')
spastor 0:1c358ea10753 227 {
spastor 0:1c358ea10753 228 aux_string[index++] = string[i];
spastor 0:1c358ea10753 229 }
spastor 0:1c358ea10753 230
spastor 0:1c358ea10753 231 if (string[i] == '.' || i == (length -1))
spastor 0:1c358ea10753 232 {
spastor 0:1c358ea10753 233 long int val;
spastor 0:1c358ea10753 234 char * endptr;
spastor 0:1c358ea10753 235
spastor 0:1c358ea10753 236 val = strtol(aux_string, &endptr, 10);
spastor 0:1c358ea10753 237 if (endptr == NULL || *endptr != '\0' || val < 0 || val > 255)
spastor 0:1c358ea10753 238 {
spastor 0:1c358ea10753 239 break;
spastor 0:1c358ea10753 240 }
spastor 0:1c358ea10753 241
spastor 0:1c358ea10753 242 ipv4 = (ipv4 << 8) | val;
spastor 0:1c358ea10753 243 dot_count++;
spastor 0:1c358ea10753 244 index = 0;
spastor 0:1c358ea10753 245 memset(aux_string, '\0', sizeof aux_string);
spastor 0:1c358ea10753 246 }
spastor 0:1c358ea10753 247 }
spastor 0:1c358ea10753 248 if (dot_count != 4)
spastor 0:1c358ea10753 249 {
spastor 0:1c358ea10753 250 connector_request_id_t request_id;
spastor 0:1c358ea10753 251 request_id.remote_config_request = connector_request_id_remote_config_group_process;
spastor 0:1c358ea10753 252 notify_error_status(rci->service_data->connector_ptr->callback, connector_class_id_remote_config, request_id, connector_invalid_data_range);
spastor 0:1c358ea10753 253 rci->status = rci_status_error;
spastor 0:1c358ea10753 254 overflow = connector_false;
spastor 0:1c358ea10753 255 connector_debug_printf("Invalid IPv4 \"%s\"\n", string);
spastor 0:1c358ea10753 256 goto done;
spastor 0:1c358ea10753 257 }
spastor 0:1c358ea10753 258
spastor 0:1c358ea10753 259 message_store_u8(rci_ber_u32, opcode, sizeof ipv4);
spastor 0:1c358ea10753 260 message_store_be32(rci_ber_u32, value, ipv4);
spastor 0:1c358ea10753 261
spastor 0:1c358ea10753 262 rci_buffer_advance(output, record_bytes(rci_ber_u32));
spastor 0:1c358ea10753 263
spastor 0:1c358ea10753 264 overflow = connector_false;
spastor 0:1c358ea10753 265 }
spastor 0:1c358ea10753 266
spastor 0:1c358ea10753 267 done:
spastor 0:1c358ea10753 268 return overflow;
spastor 0:1c358ea10753 269 }
spastor 0:1c358ea10753 270 #endif
spastor 0:1c358ea10753 271
spastor 0:1c358ea10753 272 static connector_bool_t rci_output_uint8(rci_t * const rci, uint8_t const value)
spastor 0:1c358ea10753 273 {
spastor 0:1c358ea10753 274 uint8_t const data = value;
spastor 0:1c358ea10753 275 rci_buffer_t * const output = &rci->buffer.output;
spastor 0:1c358ea10753 276
spastor 0:1c358ea10753 277 return rci_output_data(rci, output, &data, sizeof data);
spastor 0:1c358ea10753 278 }
spastor 0:1c358ea10753 279
spastor 0:1c358ea10753 280 #if defined RCI_PARSER_USES_FLOAT
spastor 0:1c358ea10753 281 static connector_bool_t rci_output_float(rci_t * const rci, float const value)
spastor 0:1c358ea10753 282 {
spastor 0:1c358ea10753 283 float const float_value = value;
spastor 0:1c358ea10753 284 uint32_t float_integer;
spastor 0:1c358ea10753 285
spastor 0:1c358ea10753 286 ASSERT(sizeof value == sizeof float_integer);
spastor 0:1c358ea10753 287
spastor 0:1c358ea10753 288 memcpy(&float_integer, &float_value, sizeof float_integer);
spastor 0:1c358ea10753 289
spastor 0:1c358ea10753 290 return rci_output_uint32(rci, float_integer);
spastor 0:1c358ea10753 291 }
spastor 0:1c358ea10753 292 #endif
spastor 0:1c358ea10753 293
spastor 0:1c358ea10753 294 #define rci_output_no_value(rci) rci_output_uint8((rci), BINARY_RCI_NO_VALUE)
spastor 0:1c358ea10753 295 #define rci_output_terminator(rci) rci_output_uint8((rci), BINARY_RCI_TERMINATOR)
spastor 0:1c358ea10753 296
spastor 0:1c358ea10753 297 static void rci_output_command_id(rci_t * const rci)
spastor 0:1c358ea10753 298 {
spastor 0:1c358ea10753 299 connector_remote_config_t const * const remote_config = &rci->shared.callback_data;
spastor 0:1c358ea10753 300 uint32_t command_id = 0;
spastor 0:1c358ea10753 301
spastor 0:1c358ea10753 302 switch (rci->shared.callback_data.group.type)
spastor 0:1c358ea10753 303 {
spastor 0:1c358ea10753 304 case connector_remote_group_setting:
spastor 0:1c358ea10753 305 switch (rci->shared.callback_data.action)
spastor 0:1c358ea10753 306 {
spastor 0:1c358ea10753 307 case connector_remote_action_set:
spastor 0:1c358ea10753 308 command_id = rci_command_set_setting;
spastor 0:1c358ea10753 309 break;
spastor 0:1c358ea10753 310 case connector_remote_action_query:
spastor 0:1c358ea10753 311 command_id = rci_command_query_setting;
spastor 0:1c358ea10753 312 break;
spastor 0:1c358ea10753 313 }
spastor 0:1c358ea10753 314 break;
spastor 0:1c358ea10753 315 case connector_remote_group_state:
spastor 0:1c358ea10753 316 switch (rci->shared.callback_data.action)
spastor 0:1c358ea10753 317 {
spastor 0:1c358ea10753 318 case connector_remote_action_set:
spastor 0:1c358ea10753 319 command_id = rci_command_set_state;
spastor 0:1c358ea10753 320 break;
spastor 0:1c358ea10753 321 case connector_remote_action_query:
spastor 0:1c358ea10753 322 command_id = rci_command_query_state;
spastor 0:1c358ea10753 323 break;
spastor 0:1c358ea10753 324 }
spastor 0:1c358ea10753 325 break;
spastor 0:1c358ea10753 326 }
spastor 0:1c358ea10753 327
spastor 0:1c358ea10753 328 {
spastor 0:1c358ea10753 329 connector_bool_t const overflow = rci_output_uint32(rci, command_id);
spastor 0:1c358ea10753 330
spastor 0:1c358ea10753 331 if (!overflow)
spastor 0:1c358ea10753 332 {
spastor 0:1c358ea10753 333 if (remote_config->error_id != connector_success)
spastor 0:1c358ea10753 334 state_call(rci, rci_parser_state_error);
spastor 0:1c358ea10753 335 else
spastor 0:1c358ea10753 336 state_call(rci, rci_parser_state_traverse);
spastor 0:1c358ea10753 337 }
spastor 0:1c358ea10753 338 }
spastor 0:1c358ea10753 339
spastor 0:1c358ea10753 340 return;
spastor 0:1c358ea10753 341 }
spastor 0:1c358ea10753 342
spastor 0:1c358ea10753 343 static void rci_output_group_id(rci_t * const rci)
spastor 0:1c358ea10753 344 {
spastor 0:1c358ea10753 345 connector_remote_config_t const * const remote_config = &rci->shared.callback_data;
spastor 0:1c358ea10753 346 uint32_t encoding_data;
spastor 0:1c358ea10753 347
spastor 0:1c358ea10753 348 if (!have_group_id(rci))
spastor 0:1c358ea10753 349 {
spastor 0:1c358ea10753 350 state_call(rci, rci_parser_state_error);
spastor 0:1c358ea10753 351 goto done;
spastor 0:1c358ea10753 352 }
spastor 0:1c358ea10753 353
spastor 0:1c358ea10753 354 encoding_data = encode_group_id(get_group_id(rci));
spastor 0:1c358ea10753 355
spastor 0:1c358ea10753 356 if (get_group_index(rci) > 1)
spastor 0:1c358ea10753 357 encoding_data |= BINARY_RCI_ATTRIBUTE_BIT;
spastor 0:1c358ea10753 358
spastor 0:1c358ea10753 359 {
spastor 0:1c358ea10753 360 connector_bool_t const overflow = rci_output_uint32(rci, encoding_data);
spastor 0:1c358ea10753 361
spastor 0:1c358ea10753 362 if (!overflow)
spastor 0:1c358ea10753 363 {
spastor 0:1c358ea10753 364 if (remote_config->error_id != connector_success)
spastor 0:1c358ea10753 365 state_call(rci, rci_parser_state_error);
spastor 0:1c358ea10753 366 else
spastor 0:1c358ea10753 367 set_rci_output_state(rci, rci_output_state_group_attribute);
spastor 0:1c358ea10753 368 }
spastor 0:1c358ea10753 369 }
spastor 0:1c358ea10753 370
spastor 0:1c358ea10753 371 done:
spastor 0:1c358ea10753 372 return;
spastor 0:1c358ea10753 373 }
spastor 0:1c358ea10753 374
spastor 0:1c358ea10753 375 static connector_bool_t encode_attribute(rci_t * const rci, unsigned int const index)
spastor 0:1c358ea10753 376 {
spastor 0:1c358ea10753 377 uint32_t encoding_data;
spastor 0:1c358ea10753 378 connector_bool_t overflow = connector_false;
spastor 0:1c358ea10753 379
spastor 0:1c358ea10753 380 if (index > 1)
spastor 0:1c358ea10753 381 {
spastor 0:1c358ea10753 382 /* attribute output
spastor 0:1c358ea10753 383 * bit |7 | 6 5 | 4 3 2 1 0|
spastor 0:1c358ea10753 384 * |x | 0 1 | - index -|
spastor 0:1c358ea10753 385 */
spastor 0:1c358ea10753 386 #define BINARY_RCI_ATTRIBUTE_INDEX_MAX 31
spastor 0:1c358ea10753 387 #define BINARY_RCI_ATTRIBUTE_TYPE_INDEX 0x20
spastor 0:1c358ea10753 388
spastor 0:1c358ea10753 389 ASSERT(index <= BINARY_RCI_ATTRIBUTE_INDEX_MAX);
spastor 0:1c358ea10753 390 encoding_data = index | BINARY_RCI_ATTRIBUTE_TYPE_INDEX;
spastor 0:1c358ea10753 391
spastor 0:1c358ea10753 392 overflow = rci_output_uint32(rci, encoding_data);
spastor 0:1c358ea10753 393 }
spastor 0:1c358ea10753 394
spastor 0:1c358ea10753 395 return overflow;
spastor 0:1c358ea10753 396 }
spastor 0:1c358ea10753 397
spastor 0:1c358ea10753 398 static void rci_output_group_attribute(rci_t * const rci)
spastor 0:1c358ea10753 399 {
spastor 0:1c358ea10753 400 unsigned int const index = get_group_index(rci);
spastor 0:1c358ea10753 401 connector_bool_t overflow = encode_attribute(rci, index);
spastor 0:1c358ea10753 402
spastor 0:1c358ea10753 403 if (!overflow)
spastor 0:1c358ea10753 404 state_call(rci, rci_parser_state_traverse);
spastor 0:1c358ea10753 405 }
spastor 0:1c358ea10753 406
spastor 0:1c358ea10753 407
spastor 0:1c358ea10753 408 static void rci_output_field_id(rci_t * const rci)
spastor 0:1c358ea10753 409 {
spastor 0:1c358ea10753 410 connector_remote_config_t const * const remote_config = &rci->shared.callback_data;
spastor 0:1c358ea10753 411
spastor 0:1c358ea10753 412 if (!have_element_id(rci))
spastor 0:1c358ea10753 413 {
spastor 0:1c358ea10753 414 state_call(rci, rci_parser_state_error);
spastor 0:1c358ea10753 415 goto done;
spastor 0:1c358ea10753 416 }
spastor 0:1c358ea10753 417
spastor 0:1c358ea10753 418 {
spastor 0:1c358ea10753 419 /* output field id */
spastor 0:1c358ea10753 420 uint32_t id = encode_element_id(get_element_id(rci));
spastor 0:1c358ea10753 421
spastor 0:1c358ea10753 422 if (remote_config->error_id != connector_success) id |= BINARY_RCI_FIELD_TYPE_INDICATOR_BIT;
spastor 0:1c358ea10753 423
spastor 0:1c358ea10753 424 {
spastor 0:1c358ea10753 425 connector_bool_t const overflow = rci_output_uint32(rci, id);
spastor 0:1c358ea10753 426
spastor 0:1c358ea10753 427 if (overflow) goto done;
spastor 0:1c358ea10753 428
spastor 0:1c358ea10753 429 if (remote_config->error_id != connector_success)
spastor 0:1c358ea10753 430 state_call(rci, rci_parser_state_error);
spastor 0:1c358ea10753 431 else
spastor 0:1c358ea10753 432 set_rci_output_state(rci, rci_output_state_field_value);
spastor 0:1c358ea10753 433 }
spastor 0:1c358ea10753 434
spastor 0:1c358ea10753 435 }
spastor 0:1c358ea10753 436
spastor 0:1c358ea10753 437 done:
spastor 0:1c358ea10753 438 return;
spastor 0:1c358ea10753 439 }
spastor 0:1c358ea10753 440
spastor 0:1c358ea10753 441
spastor 0:1c358ea10753 442 static void rci_output_field_value(rci_t * const rci)
spastor 0:1c358ea10753 443 {
spastor 0:1c358ea10753 444 connector_group_element_t const * const element = get_current_element(rci);
spastor 0:1c358ea10753 445 connector_element_value_type_t const type = element->type;
spastor 0:1c358ea10753 446
spastor 0:1c358ea10753 447 connector_bool_t overflow = connector_false;
spastor 0:1c358ea10753 448
spastor 0:1c358ea10753 449
spastor 0:1c358ea10753 450 switch (rci->shared.callback_data.action)
spastor 0:1c358ea10753 451 {
spastor 0:1c358ea10753 452 case connector_remote_action_set:
spastor 0:1c358ea10753 453 overflow = rci_output_no_value(rci);
spastor 0:1c358ea10753 454 goto done;
spastor 0:1c358ea10753 455
spastor 0:1c358ea10753 456 case connector_remote_action_query:
spastor 0:1c358ea10753 457 break;
spastor 0:1c358ea10753 458 }
spastor 0:1c358ea10753 459
spastor 0:1c358ea10753 460 switch (type)
spastor 0:1c358ea10753 461 {
spastor 0:1c358ea10753 462 #if defined RCI_PARSER_USES_STRINGS
spastor 0:1c358ea10753 463
spastor 0:1c358ea10753 464 #if defined RCI_PARSER_USES_STRING
spastor 0:1c358ea10753 465 case connector_element_type_string:
spastor 0:1c358ea10753 466 #endif
spastor 0:1c358ea10753 467
spastor 0:1c358ea10753 468 #if defined RCI_PARSER_USES_MULTILINE_STRING
spastor 0:1c358ea10753 469 case connector_element_type_multiline_string:
spastor 0:1c358ea10753 470 #endif
spastor 0:1c358ea10753 471
spastor 0:1c358ea10753 472 #if defined RCI_PARSER_USES_PASSWORD
spastor 0:1c358ea10753 473 case connector_element_type_password:
spastor 0:1c358ea10753 474 #endif
spastor 0:1c358ea10753 475
spastor 0:1c358ea10753 476 #if defined RCI_PARSER_USES_FQDNV4
spastor 0:1c358ea10753 477 case connector_element_type_fqdnv4:
spastor 0:1c358ea10753 478 #endif
spastor 0:1c358ea10753 479
spastor 0:1c358ea10753 480 #if defined RCI_PARSER_USES_FQDNV6
spastor 0:1c358ea10753 481 case connector_element_type_fqdnv6:
spastor 0:1c358ea10753 482 #endif
spastor 0:1c358ea10753 483
spastor 0:1c358ea10753 484 #if defined RCI_PARSER_USES_DATETIME
spastor 0:1c358ea10753 485 case connector_element_type_datetime:
spastor 0:1c358ea10753 486 #endif
spastor 0:1c358ea10753 487 ASSERT(rci->shared.value.string_value != NULL);
spastor 0:1c358ea10753 488 overflow = rci_output_string(rci, rci->shared.value.string_value, strlen(rci->shared.value.string_value));
spastor 0:1c358ea10753 489 break;
spastor 0:1c358ea10753 490 #endif
spastor 0:1c358ea10753 491
spastor 0:1c358ea10753 492 #if defined RCI_PARSER_USES_IPV4
spastor 0:1c358ea10753 493 case connector_element_type_ipv4:
spastor 0:1c358ea10753 494 ASSERT(rci->shared.value.string_value != NULL);
spastor 0:1c358ea10753 495 overflow = rci_output_ipv4(rci, rci->shared.value.string_value);
spastor 0:1c358ea10753 496 break;
spastor 0:1c358ea10753 497 #endif
spastor 0:1c358ea10753 498
spastor 0:1c358ea10753 499 #if defined RCI_PARSER_USES_INT32
spastor 0:1c358ea10753 500 case connector_element_type_int32:
spastor 0:1c358ea10753 501 overflow = rci_output_uint32(rci, rci->shared.value.signed_integer_value);
spastor 0:1c358ea10753 502 break;
spastor 0:1c358ea10753 503 #endif
spastor 0:1c358ea10753 504
spastor 0:1c358ea10753 505 #if (defined RCI_PARSER_USES_UNSIGNED_INTEGER)
spastor 0:1c358ea10753 506 #if defined RCI_PARSER_USES_UINT32
spastor 0:1c358ea10753 507 case connector_element_type_uint32:
spastor 0:1c358ea10753 508 #endif
spastor 0:1c358ea10753 509
spastor 0:1c358ea10753 510 #if defined RCI_PARSER_USES_HEX32
spastor 0:1c358ea10753 511 case connector_element_type_hex32:
spastor 0:1c358ea10753 512 #endif
spastor 0:1c358ea10753 513
spastor 0:1c358ea10753 514 #if defined RCI_PARSER_USES_0X_HEX32
spastor 0:1c358ea10753 515 case connector_element_type_0x_hex32:
spastor 0:1c358ea10753 516 #endif
spastor 0:1c358ea10753 517
spastor 0:1c358ea10753 518 overflow = rci_output_uint32(rci, rci->shared.value.unsigned_integer_value);
spastor 0:1c358ea10753 519 break;
spastor 0:1c358ea10753 520 #endif
spastor 0:1c358ea10753 521
spastor 0:1c358ea10753 522 #if defined RCI_PARSER_USES_FLOAT
spastor 0:1c358ea10753 523 case connector_element_type_float:
spastor 0:1c358ea10753 524 overflow = rci_output_float(rci, rci->shared.value.float_value);
spastor 0:1c358ea10753 525 break;
spastor 0:1c358ea10753 526 #endif
spastor 0:1c358ea10753 527
spastor 0:1c358ea10753 528 #if defined RCI_PARSER_USES_ENUM
spastor 0:1c358ea10753 529 case connector_element_type_enum:
spastor 0:1c358ea10753 530 overflow = rci_output_uint32(rci, rci->shared.value.enum_value);
spastor 0:1c358ea10753 531 break;
spastor 0:1c358ea10753 532 #endif
spastor 0:1c358ea10753 533
spastor 0:1c358ea10753 534 #if defined RCI_PARSER_USES_ON_OFF
spastor 0:1c358ea10753 535 case connector_element_type_on_off:
spastor 0:1c358ea10753 536 overflow = rci_output_uint32(rci, rci->shared.value.on_off_value);
spastor 0:1c358ea10753 537 break;
spastor 0:1c358ea10753 538 #endif
spastor 0:1c358ea10753 539
spastor 0:1c358ea10753 540 #if defined RCI_PARSER_USES_BOOLEAN
spastor 0:1c358ea10753 541 case connector_element_type_boolean:
spastor 0:1c358ea10753 542 overflow = rci_output_uint32(rci, rci->shared.value.boolean_value);
spastor 0:1c358ea10753 543 break;
spastor 0:1c358ea10753 544 #endif
spastor 0:1c358ea10753 545 }
spastor 0:1c358ea10753 546
spastor 0:1c358ea10753 547 done:
spastor 0:1c358ea10753 548 if (!overflow)
spastor 0:1c358ea10753 549 state_call(rci, rci_parser_state_traverse);
spastor 0:1c358ea10753 550
spastor 0:1c358ea10753 551 }
spastor 0:1c358ea10753 552
spastor 0:1c358ea10753 553 static void rci_output_field_terminator(rci_t * const rci)
spastor 0:1c358ea10753 554 {
spastor 0:1c358ea10753 555 connector_remote_config_t const * const remote_config = &rci->shared.callback_data;
spastor 0:1c358ea10753 556
spastor 0:1c358ea10753 557 connector_bool_t const overflow = rci_output_terminator(rci);
spastor 0:1c358ea10753 558 if (!overflow)
spastor 0:1c358ea10753 559 {
spastor 0:1c358ea10753 560 invalidate_element_id(rci);
spastor 0:1c358ea10753 561
spastor 0:1c358ea10753 562 if (remote_config->error_id != connector_success)
spastor 0:1c358ea10753 563 state_call(rci, rci_parser_state_error);
spastor 0:1c358ea10753 564 else
spastor 0:1c358ea10753 565 state_call(rci, rci_parser_state_traverse);
spastor 0:1c358ea10753 566 }
spastor 0:1c358ea10753 567 return;
spastor 0:1c358ea10753 568 }
spastor 0:1c358ea10753 569
spastor 0:1c358ea10753 570 static void rci_output_group_terminator(rci_t * const rci)
spastor 0:1c358ea10753 571 {
spastor 0:1c358ea10753 572 connector_remote_config_t const * const remote_config = &rci->shared.callback_data;
spastor 0:1c358ea10753 573
spastor 0:1c358ea10753 574 if (remote_config->error_id != connector_success)
spastor 0:1c358ea10753 575 {
spastor 0:1c358ea10753 576 state_call(rci, rci_parser_state_error);
spastor 0:1c358ea10753 577 }
spastor 0:1c358ea10753 578 else
spastor 0:1c358ea10753 579 {
spastor 0:1c358ea10753 580 connector_bool_t const overflow = rci_output_terminator(rci);
spastor 0:1c358ea10753 581 if (overflow) goto done;
spastor 0:1c358ea10753 582
spastor 0:1c358ea10753 583 set_rci_output_state(rci, rci_output_state_response_done);
spastor 0:1c358ea10753 584 }
spastor 0:1c358ea10753 585
spastor 0:1c358ea10753 586 invalidate_group_id(rci);
spastor 0:1c358ea10753 587
spastor 0:1c358ea10753 588 done:
spastor 0:1c358ea10753 589 return;
spastor 0:1c358ea10753 590 }
spastor 0:1c358ea10753 591
spastor 0:1c358ea10753 592 static void rci_generate_output(rci_t * const rci)
spastor 0:1c358ea10753 593 {
spastor 0:1c358ea10753 594 rci_buffer_t * const output = &rci->buffer.output;
spastor 0:1c358ea10753 595
spastor 0:1c358ea10753 596 if ((rci_buffer_remaining(output) != 0))
spastor 0:1c358ea10753 597 {
spastor 0:1c358ea10753 598 rci_debug_printf("output: %s\n", rci_output_state_t_as_string(rci->output.state));
spastor 0:1c358ea10753 599
spastor 0:1c358ea10753 600 switch (rci->output.state)
spastor 0:1c358ea10753 601 {
spastor 0:1c358ea10753 602 case rci_output_state_command_id:
spastor 0:1c358ea10753 603 rci_output_command_id(rci);
spastor 0:1c358ea10753 604 break;
spastor 0:1c358ea10753 605
spastor 0:1c358ea10753 606 case rci_output_state_group_id:
spastor 0:1c358ea10753 607 rci_output_group_id(rci);
spastor 0:1c358ea10753 608 break;
spastor 0:1c358ea10753 609
spastor 0:1c358ea10753 610 case rci_output_state_group_attribute:
spastor 0:1c358ea10753 611 rci_output_group_attribute(rci);
spastor 0:1c358ea10753 612 break;
spastor 0:1c358ea10753 613
spastor 0:1c358ea10753 614 case rci_output_state_field_id:
spastor 0:1c358ea10753 615 rci_output_field_id(rci);
spastor 0:1c358ea10753 616 break;
spastor 0:1c358ea10753 617
spastor 0:1c358ea10753 618 case rci_output_state_field_value:
spastor 0:1c358ea10753 619 rci_output_field_value(rci);
spastor 0:1c358ea10753 620 break;
spastor 0:1c358ea10753 621
spastor 0:1c358ea10753 622 case rci_output_state_field_terminator:
spastor 0:1c358ea10753 623 rci_output_field_terminator(rci);
spastor 0:1c358ea10753 624 break;
spastor 0:1c358ea10753 625
spastor 0:1c358ea10753 626 case rci_output_state_group_terminator:
spastor 0:1c358ea10753 627 rci_output_group_terminator(rci);
spastor 0:1c358ea10753 628 break;
spastor 0:1c358ea10753 629
spastor 0:1c358ea10753 630 case rci_output_state_response_done:
spastor 0:1c358ea10753 631
spastor 0:1c358ea10753 632 if (get_rci_input_state(rci) == rci_input_state_done)
spastor 0:1c358ea10753 633 {
spastor 0:1c358ea10753 634 trigger_rci_callback(rci, connector_request_id_remote_config_session_end);
spastor 0:1c358ea10753 635 set_rci_output_state(rci, rci_output_state_done);
spastor 0:1c358ea10753 636 }
spastor 0:1c358ea10753 637 else
spastor 0:1c358ea10753 638 {
spastor 0:1c358ea10753 639 state_call(rci, rci_parser_state_input);
spastor 0:1c358ea10753 640 set_rci_input_state(rci, rci_input_state_command_id);
spastor 0:1c358ea10753 641 }
spastor 0:1c358ea10753 642 break;
spastor 0:1c358ea10753 643
spastor 0:1c358ea10753 644 case rci_output_state_done:
spastor 0:1c358ea10753 645 {
spastor 0:1c358ea10753 646 connector_remote_config_t const * const remote_config = &rci->shared.callback_data;
spastor 0:1c358ea10753 647 if (remote_config->error_id != connector_success)
spastor 0:1c358ea10753 648 state_call(rci, rci_parser_state_error);
spastor 0:1c358ea10753 649 else
spastor 0:1c358ea10753 650 rci->status = rci_status_complete;
spastor 0:1c358ea10753 651 break;
spastor 0:1c358ea10753 652 }
spastor 0:1c358ea10753 653 }
spastor 0:1c358ea10753 654 }
spastor 0:1c358ea10753 655 else if ((rci_buffer_used(&rci->buffer.output) > 0) && (rci->status == rci_status_busy))
spastor 0:1c358ea10753 656 {
spastor 0:1c358ea10753 657 /* We are here since we have no space left for more output data and we have output data waiting to be sent.
spastor 0:1c358ea10753 658 So set up the state to send out the output data and come back to rci */
spastor 0:1c358ea10753 659
spastor 0:1c358ea10753 660 rci->status = rci_status_flush_output;
spastor 0:1c358ea10753 661 }
spastor 0:1c358ea10753 662
spastor 0:1c358ea10753 663
spastor 0:1c358ea10753 664 #if defined RCI_DEBUG
spastor 0:1c358ea10753 665 {
spastor 0:1c358ea10753 666 size_t const bytes = rci_buffer_used(&rci->buffer.output);
spastor 0:1c358ea10753 667 if (bytes > 0)
spastor 0:1c358ea10753 668 {
spastor 0:1c358ea10753 669 connector_debug_hexvalue("Response", rci->buffer.output.start, bytes);
spastor 0:1c358ea10753 670 }
spastor 0:1c358ea10753 671 }
spastor 0:1c358ea10753 672 #endif
spastor 0:1c358ea10753 673
spastor 0:1c358ea10753 674 return;
spastor 0:1c358ea10753 675 }
spastor 0:1c358ea10753 676
spastor 0:1c358ea10753 677