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
spastor 0:1c358ea10753 13 typedef enum
spastor 0:1c358ea10753 14 {
spastor 0:1c358ea10753 15 data_service_opcode_put_request,
spastor 0:1c358ea10753 16 data_service_opcode_put_response,
spastor 0:1c358ea10753 17 data_service_opcode_device_request,
spastor 0:1c358ea10753 18 data_service_opcode_device_response
spastor 0:1c358ea10753 19 } data_service_opcode_t;
spastor 0:1c358ea10753 20
spastor 0:1c358ea10753 21 typedef struct
spastor 0:1c358ea10753 22 {
spastor 0:1c358ea10753 23 void * callback_context;
spastor 0:1c358ea10753 24 connector_request_data_service_send_t const * header;
spastor 0:1c358ea10753 25 connector_bool_t dp_request;
spastor 0:1c358ea10753 26 connector_request_id_data_service_t request_type;
spastor 0:1c358ea10753 27 } data_service_context_t;
spastor 0:1c358ea10753 28
spastor 0:1c358ea10753 29 static void set_data_service_error(msg_service_request_t * const service_request, connector_session_error_t const error_code)
spastor 0:1c358ea10753 30 {
spastor 0:1c358ea10753 31 service_request->error_value = error_code;
spastor 0:1c358ea10753 32 service_request->service_type = msg_service_type_error;
spastor 0:1c358ea10753 33 }
spastor 0:1c358ea10753 34
spastor 0:1c358ea10753 35
spastor 0:1c358ea10753 36 static connector_status_t call_ds_receive_callback(connector_data_t * const connector_ptr,
spastor 0:1c358ea10753 37 data_service_context_t * const data_service,
spastor 0:1c358ea10753 38 void * const data)
spastor 0:1c358ea10753 39 {
spastor 0:1c358ea10753 40 connector_status_t result = connector_working;
spastor 0:1c358ea10753 41 connector_request_id_t request_id;
spastor 0:1c358ea10753 42
spastor 0:1c358ea10753 43 request_id.data_service_request = data_service->request_type;
spastor 0:1c358ea10753 44 switch (request_id.data_service_request)
spastor 0:1c358ea10753 45 {
spastor 0:1c358ea10753 46 case connector_request_id_data_service_receive_reply_length:
spastor 0:1c358ea10753 47 request_id.data_service_request = connector_request_id_data_service_receive_reply_data;
spastor 0:1c358ea10753 48 /* fall thru for error (not-handle) response data */
spastor 0:1c358ea10753 49 case connector_request_id_data_service_receive_target:
spastor 0:1c358ea10753 50 case connector_request_id_data_service_receive_data:
spastor 0:1c358ea10753 51 case connector_request_id_data_service_receive_status:
spastor 0:1c358ea10753 52 case connector_request_id_data_service_receive_reply_data:
spastor 0:1c358ea10753 53 {
spastor 0:1c358ea10753 54 connector_callback_status_t const status = connector_callback(connector_ptr->callback, connector_class_id_data_service, request_id, data);
spastor 0:1c358ea10753 55 switch (status)
spastor 0:1c358ea10753 56 {
spastor 0:1c358ea10753 57 case connector_callback_continue:
spastor 0:1c358ea10753 58 break;
spastor 0:1c358ea10753 59 case connector_callback_error:
spastor 0:1c358ea10753 60 data_service->request_type = connector_request_id_data_service_receive_reply_length;
spastor 0:1c358ea10753 61 break;
spastor 0:1c358ea10753 62 case connector_callback_busy:
spastor 0:1c358ea10753 63 result = connector_pending;
spastor 0:1c358ea10753 64 break;
spastor 0:1c358ea10753 65 default:
spastor 0:1c358ea10753 66 result = connector_abort;
spastor 0:1c358ea10753 67 break;
spastor 0:1c358ea10753 68
spastor 0:1c358ea10753 69 }
spastor 0:1c358ea10753 70 break;
spastor 0:1c358ea10753 71 }
spastor 0:1c358ea10753 72
spastor 0:1c358ea10753 73 default:
spastor 0:1c358ea10753 74 ASSERT(connector_false);
spastor 0:1c358ea10753 75 break;
spastor 0:1c358ea10753 76 }
spastor 0:1c358ea10753 77
spastor 0:1c358ea10753 78 return result;
spastor 0:1c358ea10753 79 }
spastor 0:1c358ea10753 80
spastor 0:1c358ea10753 81 static connector_status_t process_ds_receive_target(connector_data_t * const connector_ptr,
spastor 0:1c358ea10753 82 data_service_context_t * const data_service,
spastor 0:1c358ea10753 83 uint8_t const * const data,
spastor 0:1c358ea10753 84 size_t * const data_length)
spastor 0:1c358ea10753 85 {
spastor 0:1c358ea10753 86 /* 1st message so let's parse message-start packet:
spastor 0:1c358ea10753 87 *
spastor 0:1c358ea10753 88 * Data Service Device request format:
spastor 0:1c358ea10753 89 * -------------------------------------------------------------------------------------------------------
spastor 0:1c358ea10753 90 * | 0 | 1 | 2+N | +1 | +1 | +1 | +M | ... | +P |
spastor 0:1c358ea10753 91 * -------------------------------------------------------------------------------------------------------
spastor 0:1c358ea10753 92 * | Opcode | Target | Target | Parameter | Parameter 1 | Parameter 1 | Parameter 1 | Additional | Payload |
spastor 0:1c358ea10753 93 * | | length | string | count | ID | data length | data | parameters | |
spastor 0:1c358ea10753 94 * -------------------------------------------------------------------------------------------------------
spastor 0:1c358ea10753 95 *
spastor 0:1c358ea10753 96 */
spastor 0:1c358ea10753 97 enum {
spastor 0:1c358ea10753 98 field_define(ds_device_request, opcode, uint8_t),
spastor 0:1c358ea10753 99 field_define(ds_device_request, target_length, uint8_t),
spastor 0:1c358ea10753 100 record_end(ds_device_request_header)
spastor 0:1c358ea10753 101 };
spastor 0:1c358ea10753 102
spastor 0:1c358ea10753 103 enum {
spastor 0:1c358ea10753 104 field_define(ds_device_request, parameter_count, uint8_t)
spastor 0:1c358ea10753 105 };
spastor 0:1c358ea10753 106
spastor 0:1c358ea10753 107 enum {
spastor 0:1c358ea10753 108 field_define(ds_device_request, parameter_id, uint8_t),
spastor 0:1c358ea10753 109 field_define(ds_device_request, parameter_length, uint8_t),
spastor 0:1c358ea10753 110 record_end(ds_device_request_parameter)
spastor 0:1c358ea10753 111 };
spastor 0:1c358ea10753 112
spastor 0:1c358ea10753 113 connector_status_t result = connector_working;
spastor 0:1c358ea10753 114 uint8_t const * ds_device_request = data;
spastor 0:1c358ea10753 115
spastor 0:1c358ea10753 116 char * target_string = NULL;
spastor 0:1c358ea10753 117 uint8_t const target_length = message_load_u8(ds_device_request, target_length);
spastor 0:1c358ea10753 118
spastor 0:1c358ea10753 119 size_t const min_data_length = (size_t)(target_length +
spastor 0:1c358ea10753 120 record_bytes(ds_device_request_header) +
spastor 0:1c358ea10753 121 field_named_data(ds_device_request, parameter_count, size));
spastor 0:1c358ea10753 122
spastor 0:1c358ea10753 123 ASSERT_GOTO((message_load_u8(ds_device_request, opcode) == data_service_opcode_device_request), done);
spastor 0:1c358ea10753 124 ASSERT_GOTO(*data_length >= min_data_length, done);
spastor 0:1c358ea10753 125
spastor 0:1c358ea10753 126 ds_device_request += record_bytes(ds_device_request_header);
spastor 0:1c358ea10753 127
spastor 0:1c358ea10753 128 target_string = (char *)ds_device_request;
spastor 0:1c358ea10753 129 ds_device_request += target_length;
spastor 0:1c358ea10753 130
spastor 0:1c358ea10753 131 {
spastor 0:1c358ea10753 132 /* TODO: Parse and process each parameter in the future.
spastor 0:1c358ea10753 133 * Ignore all parameters now.
spastor 0:1c358ea10753 134 */
spastor 0:1c358ea10753 135
spastor 0:1c358ea10753 136 uint8_t const parameter_count = message_load_u8(ds_device_request, parameter_count);
spastor 0:1c358ea10753 137 uint8_t i;
spastor 0:1c358ea10753 138
spastor 0:1c358ea10753 139 ds_device_request += field_named_data(ds_device_request, parameter_count, size);
spastor 0:1c358ea10753 140
spastor 0:1c358ea10753 141 for (i=0; i < parameter_count; i++)
spastor 0:1c358ea10753 142 {
spastor 0:1c358ea10753 143 unsigned int const parameter_length = message_load_u8(ds_device_request, parameter_length);
spastor 0:1c358ea10753 144 size_t const min_parameter_length = min_data_length + record_bytes(ds_device_request_parameter) + parameter_length;
spastor 0:1c358ea10753 145 ASSERT_GOTO(*data_length >= min_parameter_length, done);
spastor 0:1c358ea10753 146
spastor 0:1c358ea10753 147 ds_device_request += record_bytes(ds_device_request_parameter); /* skip id and length */
spastor 0:1c358ea10753 148 ds_device_request += parameter_length;
spastor 0:1c358ea10753 149
spastor 0:1c358ea10753 150 }
spastor 0:1c358ea10753 151 }
spastor 0:1c358ea10753 152
spastor 0:1c358ea10753 153 *data_length = (ds_device_request - data);
spastor 0:1c358ea10753 154
spastor 0:1c358ea10753 155 /* Add NUL to the target string. Must NULL-terminate it after parsing all parameters.
spastor 0:1c358ea10753 156 * The NUL char is on parameter_count field in the request.
spastor 0:1c358ea10753 157 */
spastor 0:1c358ea10753 158 target_string[target_length] = '\0';
spastor 0:1c358ea10753 159
spastor 0:1c358ea10753 160 switch (data_service->request_type)
spastor 0:1c358ea10753 161 {
spastor 0:1c358ea10753 162 case connector_request_id_data_service_receive_target:
spastor 0:1c358ea10753 163 {
spastor 0:1c358ea10753 164
spastor 0:1c358ea10753 165 connector_data_service_receive_target_t device_request;
spastor 0:1c358ea10753 166
spastor 0:1c358ea10753 167 device_request.transport = connector_transport_tcp;
spastor 0:1c358ea10753 168 device_request.user_context = data_service->callback_context;
spastor 0:1c358ea10753 169 device_request.target = target_string;
spastor 0:1c358ea10753 170 device_request.response_required = connector_true;
spastor 0:1c358ea10753 171
spastor 0:1c358ea10753 172 result = call_ds_receive_callback(connector_ptr, data_service, &device_request);
spastor 0:1c358ea10753 173 data_service->callback_context = device_request.user_context;
spastor 0:1c358ea10753 174 break;
spastor 0:1c358ea10753 175 }
spastor 0:1c358ea10753 176 default:
spastor 0:1c358ea10753 177 /* just skip the header and return */
spastor 0:1c358ea10753 178 break;
spastor 0:1c358ea10753 179 }
spastor 0:1c358ea10753 180
spastor 0:1c358ea10753 181 done:
spastor 0:1c358ea10753 182 return result;
spastor 0:1c358ea10753 183 }
spastor 0:1c358ea10753 184
spastor 0:1c358ea10753 185 static connector_status_t process_ds_receive_data(connector_data_t * const connector_ptr,
spastor 0:1c358ea10753 186 data_service_context_t * const data_service,
spastor 0:1c358ea10753 187 uint8_t const * const data,
spastor 0:1c358ea10753 188 size_t const data_length,
spastor 0:1c358ea10753 189 unsigned int const flags)
spastor 0:1c358ea10753 190 {
spastor 0:1c358ea10753 191 connector_status_t result;
spastor 0:1c358ea10753 192
spastor 0:1c358ea10753 193 connector_data_service_receive_data_t device_request;
spastor 0:1c358ea10753 194 device_request.transport = connector_transport_tcp;
spastor 0:1c358ea10753 195 device_request.user_context = data_service->callback_context;
spastor 0:1c358ea10753 196 device_request.buffer = data;
spastor 0:1c358ea10753 197 device_request.bytes_used = data_length;
spastor 0:1c358ea10753 198 device_request.more_data = MsgIsLastData(flags) ? connector_false : connector_true;
spastor 0:1c358ea10753 199
spastor 0:1c358ea10753 200 result = call_ds_receive_callback(connector_ptr, data_service, &device_request);
spastor 0:1c358ea10753 201 data_service->callback_context = device_request.user_context;
spastor 0:1c358ea10753 202
spastor 0:1c358ea10753 203 return result;
spastor 0:1c358ea10753 204 }
spastor 0:1c358ea10753 205 static connector_status_t process_data_service_device_request(connector_data_t * const connector_ptr,
spastor 0:1c358ea10753 206 msg_service_request_t * const service_request)
spastor 0:1c358ea10753 207 {
spastor 0:1c358ea10753 208 connector_status_t result = connector_working;
spastor 0:1c358ea10753 209 msg_session_t * const session = service_request->session;
spastor 0:1c358ea10753 210 data_service_context_t * data_service = session->service_context;
spastor 0:1c358ea10753 211 msg_service_data_t * const service_data = service_request->have_data;
spastor 0:1c358ea10753 212
spastor 0:1c358ea10753 213 uint8_t const * ds_device_request = service_data->data_ptr;
spastor 0:1c358ea10753 214 size_t ds_device_request_length = service_data->length_in_bytes;
spastor 0:1c358ea10753 215
spastor 0:1c358ea10753 216 connector_bool_t const isFirstRequest = connector_bool(MsgIsStart(service_data->flags));
spastor 0:1c358ea10753 217
spastor 0:1c358ea10753 218 if (isFirstRequest)
spastor 0:1c358ea10753 219 {
spastor 0:1c358ea10753 220 if (data_service == NULL)
spastor 0:1c358ea10753 221 {
spastor 0:1c358ea10753 222 /* 1st time here so let's allocate service context memory for device request service */
spastor 0:1c358ea10753 223 void * ptr;
spastor 0:1c358ea10753 224
spastor 0:1c358ea10753 225 result = malloc_data_buffer(connector_ptr, sizeof *data_service, named_buffer_id(msg_service), &ptr);
spastor 0:1c358ea10753 226 if (result != connector_working)
spastor 0:1c358ea10753 227 {
spastor 0:1c358ea10753 228 goto done;
spastor 0:1c358ea10753 229 }
spastor 0:1c358ea10753 230
spastor 0:1c358ea10753 231 data_service = ptr;
spastor 0:1c358ea10753 232 session->service_context = data_service;
spastor 0:1c358ea10753 233 data_service->callback_context = NULL;
spastor 0:1c358ea10753 234 data_service->dp_request = connector_false;
spastor 0:1c358ea10753 235 data_service->request_type = connector_request_id_data_service_receive_target;
spastor 0:1c358ea10753 236 }
spastor 0:1c358ea10753 237 }
spastor 0:1c358ea10753 238
spastor 0:1c358ea10753 239 switch (data_service->request_type)
spastor 0:1c358ea10753 240 {
spastor 0:1c358ea10753 241 case connector_request_id_data_service_receive_target:
spastor 0:1c358ea10753 242 ds_device_request_length = service_data->length_in_bytes;
spastor 0:1c358ea10753 243
spastor 0:1c358ea10753 244 result = process_ds_receive_target(connector_ptr, data_service, ds_device_request, &ds_device_request_length);
spastor 0:1c358ea10753 245
spastor 0:1c358ea10753 246 switch (result)
spastor 0:1c358ea10753 247 {
spastor 0:1c358ea10753 248 case connector_working:
spastor 0:1c358ea10753 249 if (data_service->request_type == connector_request_id_data_service_receive_target)
spastor 0:1c358ea10753 250 data_service->request_type = connector_request_id_data_service_receive_data;
spastor 0:1c358ea10753 251 /* make it return busy so it comes here to skip parsing the header for the 1st data block */
spastor 0:1c358ea10753 252 result = connector_pending;
spastor 0:1c358ea10753 253 break;
spastor 0:1c358ea10753 254 default:
spastor 0:1c358ea10753 255 break;
spastor 0:1c358ea10753 256 }
spastor 0:1c358ea10753 257 break;
spastor 0:1c358ea10753 258
spastor 0:1c358ea10753 259 case connector_request_id_data_service_receive_data:
spastor 0:1c358ea10753 260 if (isFirstRequest)
spastor 0:1c358ea10753 261 {
spastor 0:1c358ea10753 262 /* skip the header; just get the point to data */
spastor 0:1c358ea10753 263 result = process_ds_receive_target(connector_ptr, data_service, ds_device_request, &ds_device_request_length);
spastor 0:1c358ea10753 264 if (result != connector_working) goto done;
spastor 0:1c358ea10753 265 ds_device_request += ds_device_request_length;
spastor 0:1c358ea10753 266 }
spastor 0:1c358ea10753 267 {
spastor 0:1c358ea10753 268 size_t const data_length = (size_t)(ds_device_request - (uint8_t *)service_data->data_ptr);
spastor 0:1c358ea10753 269 ds_device_request_length = service_data->length_in_bytes - data_length;
spastor 0:1c358ea10753 270
spastor 0:1c358ea10753 271 result = process_ds_receive_data(connector_ptr, data_service, ds_device_request, ds_device_request_length, service_data->flags);
spastor 0:1c358ea10753 272 switch (result)
spastor 0:1c358ea10753 273 {
spastor 0:1c358ea10753 274 case connector_working:
spastor 0:1c358ea10753 275 /* data_service->request_type may have been changed inside process_ds_receive_data() */
spastor 0:1c358ea10753 276 switch (data_service->request_type)
spastor 0:1c358ea10753 277 {
spastor 0:1c358ea10753 278 case connector_request_id_data_service_receive_reply_length:
spastor 0:1c358ea10753 279 break;
spastor 0:1c358ea10753 280
spastor 0:1c358ea10753 281 default:
spastor 0:1c358ea10753 282 if (MsgIsLastData(service_data->flags))
spastor 0:1c358ea10753 283 data_service->request_type = connector_request_id_data_service_receive_reply_data;
spastor 0:1c358ea10753 284 break;
spastor 0:1c358ea10753 285 }
spastor 0:1c358ea10753 286 break;
spastor 0:1c358ea10753 287 default:
spastor 0:1c358ea10753 288 break;
spastor 0:1c358ea10753 289 }
spastor 0:1c358ea10753 290 break;
spastor 0:1c358ea10753 291 }
spastor 0:1c358ea10753 292 case connector_request_id_data_service_receive_reply_length:
spastor 0:1c358ea10753 293 /* We set this when callback returns error.
spastor 0:1c358ea10753 294 * We need to respond with an error after receiving all request data.
spastor 0:1c358ea10753 295 */
spastor 0:1c358ea10753 296 break;
spastor 0:1c358ea10753 297
spastor 0:1c358ea10753 298 default:
spastor 0:1c358ea10753 299 ASSERT(connector_false);
spastor 0:1c358ea10753 300 goto done;
spastor 0:1c358ea10753 301 }
spastor 0:1c358ea10753 302
spastor 0:1c358ea10753 303 done:
spastor 0:1c358ea10753 304 return result;
spastor 0:1c358ea10753 305 }
spastor 0:1c358ea10753 306
spastor 0:1c358ea10753 307 static connector_status_t process_data_service_device_response(connector_data_t * const connector_ptr,
spastor 0:1c358ea10753 308 msg_service_request_t * const service_request)
spastor 0:1c358ea10753 309 {
spastor 0:1c358ea10753 310 /* Data Service Device response format:
spastor 0:1c358ea10753 311 * ---------------------------------
spastor 0:1c358ea10753 312 * | 0 | 1 | 2... |
spastor 0:1c358ea10753 313 * ---------------------------------
spastor 0:1c358ea10753 314 * | Opcode | status | Response Data |
spastor 0:1c358ea10753 315 * ---------------------------------
spastor 0:1c358ea10753 316 */
spastor 0:1c358ea10753 317 enum {
spastor 0:1c358ea10753 318 field_define(ds_device_response, opcode, uint8_t),
spastor 0:1c358ea10753 319 field_define(ds_device_response, status, uint8_t),
spastor 0:1c358ea10753 320 record_end(ds_device_response_header)
spastor 0:1c358ea10753 321 };
spastor 0:1c358ea10753 322
spastor 0:1c358ea10753 323 connector_status_t result = connector_working;
spastor 0:1c358ea10753 324 msg_service_data_t * const service_data = service_request->need_data;
spastor 0:1c358ea10753 325 msg_session_t * const session = service_request->session;
spastor 0:1c358ea10753 326 data_service_context_t * const data_service = session->service_context;
spastor 0:1c358ea10753 327 connector_bool_t const isFirstResponse = connector_bool(MsgIsStart(service_data->flags));
spastor 0:1c358ea10753 328
spastor 0:1c358ea10753 329 /* save some room for response header on 1st response data */
spastor 0:1c358ea10753 330 size_t const header_length = isFirstResponse == connector_true ? record_bytes(ds_device_response_header) : 0;
spastor 0:1c358ea10753 331 uint8_t * const data_ptr = service_data->data_ptr;
spastor 0:1c358ea10753 332
spastor 0:1c358ea10753 333
spastor 0:1c358ea10753 334 connector_data_service_receive_reply_data_t device_request;
spastor 0:1c358ea10753 335
spastor 0:1c358ea10753 336 device_request.transport = connector_transport_tcp;
spastor 0:1c358ea10753 337 device_request.user_context = data_service->callback_context;
spastor 0:1c358ea10753 338 device_request.buffer = data_ptr + header_length;
spastor 0:1c358ea10753 339 device_request.bytes_available = service_data->length_in_bytes - header_length;
spastor 0:1c358ea10753 340 device_request.bytes_used = 0;
spastor 0:1c358ea10753 341 device_request.more_data = connector_false;
spastor 0:1c358ea10753 342
spastor 0:1c358ea10753 343 {
spastor 0:1c358ea10753 344 connector_request_id_data_service_t const request_type = data_service->request_type;
spastor 0:1c358ea10753 345
spastor 0:1c358ea10753 346 switch (request_type)
spastor 0:1c358ea10753 347 {
spastor 0:1c358ea10753 348 case connector_request_id_data_service_receive_reply_length:
spastor 0:1c358ea10753 349 /* We got here because callback returns error for request data.
spastor 0:1c358ea10753 350 * Just get the replay data.
spastor 0:1c358ea10753 351 */
spastor 0:1c358ea10753 352 /* fall thru */
spastor 0:1c358ea10753 353 case connector_request_id_data_service_receive_reply_data:
spastor 0:1c358ea10753 354 {
spastor 0:1c358ea10753 355
spastor 0:1c358ea10753 356 result = call_ds_receive_callback(connector_ptr, data_service, &device_request);
spastor 0:1c358ea10753 357 data_service->callback_context = device_request.user_context;
spastor 0:1c358ea10753 358 if (request_type != data_service->request_type &&
spastor 0:1c358ea10753 359 data_service->request_type == connector_request_id_data_service_receive_reply_length)
spastor 0:1c358ea10753 360 {
spastor 0:1c358ea10753 361 /* callback returns error on reply data
spastor 0:1c358ea10753 362 * We need to cancel the message in messaging layer.
spastor 0:1c358ea10753 363 */
spastor 0:1c358ea10753 364 device_request.bytes_used = 0;
spastor 0:1c358ea10753 365 device_request.more_data = connector_false;
spastor 0:1c358ea10753 366 set_data_service_error(service_request, connector_session_error_cancel);
spastor 0:1c358ea10753 367 }
spastor 0:1c358ea10753 368 break;
spastor 0:1c358ea10753 369 }
spastor 0:1c358ea10753 370 default:
spastor 0:1c358ea10753 371 /* should be here */
spastor 0:1c358ea10753 372 ASSERT(connector_false);
spastor 0:1c358ea10753 373 goto done;
spastor 0:1c358ea10753 374 }
spastor 0:1c358ea10753 375 }
spastor 0:1c358ea10753 376 if (isFirstResponse)
spastor 0:1c358ea10753 377 {
spastor 0:1c358ea10753 378
spastor 0:1c358ea10753 379 enum {
spastor 0:1c358ea10753 380 connector_data_service_device_success,
spastor 0:1c358ea10753 381 connector_data_service_device_not_handled
spastor 0:1c358ea10753 382 };
spastor 0:1c358ea10753 383
spastor 0:1c358ea10753 384 /* Add header for 1st response message */
spastor 0:1c358ea10753 385 uint8_t * const ds_device_response = service_data->data_ptr;
spastor 0:1c358ea10753 386 uint8_t const target_status = (data_service->request_type == connector_request_id_data_service_receive_reply_length) ?
spastor 0:1c358ea10753 387 connector_data_service_device_not_handled: connector_data_service_device_success;
spastor 0:1c358ea10753 388
spastor 0:1c358ea10753 389 message_store_u8(ds_device_response, opcode, data_service_opcode_device_response);
spastor 0:1c358ea10753 390 message_store_u8(ds_device_response, status, target_status);
spastor 0:1c358ea10753 391 }
spastor 0:1c358ea10753 392
spastor 0:1c358ea10753 393 if (!device_request.more_data)
spastor 0:1c358ea10753 394 {
spastor 0:1c358ea10753 395 data_service->dp_request = connector_true;
spastor 0:1c358ea10753 396 MsgSetLastData(service_data->flags);
spastor 0:1c358ea10753 397 }
spastor 0:1c358ea10753 398 service_data->length_in_bytes = device_request.bytes_used + header_length;
spastor 0:1c358ea10753 399
spastor 0:1c358ea10753 400 done:
spastor 0:1c358ea10753 401 return result;
spastor 0:1c358ea10753 402 }
spastor 0:1c358ea10753 403
spastor 0:1c358ea10753 404
spastor 0:1c358ea10753 405 static connector_status_t process_data_service_device_error(connector_data_t * const connector_ptr,
spastor 0:1c358ea10753 406 msg_service_request_t * const service_request)
spastor 0:1c358ea10753 407 {
spastor 0:1c358ea10753 408 connector_status_t result = connector_working;
spastor 0:1c358ea10753 409
spastor 0:1c358ea10753 410 msg_session_t * const session = service_request->session;
spastor 0:1c358ea10753 411 data_service_context_t * const data_service = session->service_context;
spastor 0:1c358ea10753 412 connector_data_service_status_t device_request;
spastor 0:1c358ea10753 413
spastor 0:1c358ea10753 414
spastor 0:1c358ea10753 415 device_request.transport = connector_transport_tcp;
spastor 0:1c358ea10753 416 device_request.user_context = data_service->callback_context;
spastor 0:1c358ea10753 417 data_service->request_type = connector_request_id_data_service_receive_status;
spastor 0:1c358ea10753 418
spastor 0:1c358ea10753 419 switch (service_request->error_value)
spastor 0:1c358ea10753 420 {
spastor 0:1c358ea10753 421 case connector_session_error_none:
spastor 0:1c358ea10753 422 device_request.status = connector_data_service_status_complete;
spastor 0:1c358ea10753 423 break;
spastor 0:1c358ea10753 424
spastor 0:1c358ea10753 425 case connector_session_error_cancel:
spastor 0:1c358ea10753 426 device_request.status = connector_data_service_status_cancel;
spastor 0:1c358ea10753 427 break;
spastor 0:1c358ea10753 428
spastor 0:1c358ea10753 429 case connector_session_error_timeout:
spastor 0:1c358ea10753 430 device_request.status = connector_data_service_status_timeout;
spastor 0:1c358ea10753 431 break;
spastor 0:1c358ea10753 432
spastor 0:1c358ea10753 433 default:
spastor 0:1c358ea10753 434 device_request.status = connector_data_service_status_session_error;
spastor 0:1c358ea10753 435 device_request.session_error = service_request->error_value;
spastor 0:1c358ea10753 436 break;
spastor 0:1c358ea10753 437 }
spastor 0:1c358ea10753 438
spastor 0:1c358ea10753 439 result = call_ds_receive_callback(connector_ptr, data_service, &device_request);
spastor 0:1c358ea10753 440
spastor 0:1c358ea10753 441 data_service->callback_context = device_request.user_context;
spastor 0:1c358ea10753 442
spastor 0:1c358ea10753 443 return result;
spastor 0:1c358ea10753 444 }
spastor 0:1c358ea10753 445
spastor 0:1c358ea10753 446 static connector_status_t data_service_device_request_callback(connector_data_t * const connector_ptr, msg_service_request_t * const service_request)
spastor 0:1c358ea10753 447 {
spastor 0:1c358ea10753 448 connector_status_t status = connector_working;
spastor 0:1c358ea10753 449
spastor 0:1c358ea10753 450 switch (service_request->service_type)
spastor 0:1c358ea10753 451 {
spastor 0:1c358ea10753 452 case msg_service_type_need_data:
spastor 0:1c358ea10753 453 status = process_data_service_device_response(connector_ptr, service_request);
spastor 0:1c358ea10753 454 break;
spastor 0:1c358ea10753 455
spastor 0:1c358ea10753 456 case msg_service_type_have_data:
spastor 0:1c358ea10753 457 status = process_data_service_device_request(connector_ptr, service_request);
spastor 0:1c358ea10753 458 break;
spastor 0:1c358ea10753 459
spastor 0:1c358ea10753 460 case msg_service_type_error:
spastor 0:1c358ea10753 461 {
spastor 0:1c358ea10753 462 msg_session_t * const session = service_request->session;
spastor 0:1c358ea10753 463 session->error = service_request->error_value;
spastor 0:1c358ea10753 464 status = process_data_service_device_error(connector_ptr, service_request);
spastor 0:1c358ea10753 465 break;
spastor 0:1c358ea10753 466 }
spastor 0:1c358ea10753 467
spastor 0:1c358ea10753 468 case msg_service_type_free:
spastor 0:1c358ea10753 469 {
spastor 0:1c358ea10753 470 msg_session_t * const session = service_request->session;
spastor 0:1c358ea10753 471 #if (CONNECTOR_VERSION >= 0x02010000)
spastor 0:1c358ea10753 472 if (session->error == connector_session_error_none)
spastor 0:1c358ea10753 473 {
spastor 0:1c358ea10753 474 /* If there is no error, call the user to inform that session is done */
spastor 0:1c358ea10753 475 status = process_data_service_device_error(connector_ptr, service_request);
spastor 0:1c358ea10753 476 if (status != connector_working)
spastor 0:1c358ea10753 477 break;
spastor 0:1c358ea10753 478 }
spastor 0:1c358ea10753 479 #endif
spastor 0:1c358ea10753 480 status = free_data_buffer(connector_ptr, named_buffer_id(msg_service), session->service_context);
spastor 0:1c358ea10753 481 break;
spastor 0:1c358ea10753 482 }
spastor 0:1c358ea10753 483
spastor 0:1c358ea10753 484 default:
spastor 0:1c358ea10753 485 ASSERT(connector_false);
spastor 0:1c358ea10753 486 break;
spastor 0:1c358ea10753 487 }
spastor 0:1c358ea10753 488
spastor 0:1c358ea10753 489 return status;
spastor 0:1c358ea10753 490 }
spastor 0:1c358ea10753 491
spastor 0:1c358ea10753 492 static size_t fill_put_request_header(connector_request_data_service_send_t const * const request, uint8_t * const data)
spastor 0:1c358ea10753 493 {
spastor 0:1c358ea10753 494 uint8_t * ptr = data;
spastor 0:1c358ea10753 495
spastor 0:1c358ea10753 496 *ptr++ = data_service_opcode_put_request;
spastor 0:1c358ea10753 497
spastor 0:1c358ea10753 498 /* fill path */
spastor 0:1c358ea10753 499 if (request->path != NULL)
spastor 0:1c358ea10753 500 {
spastor 0:1c358ea10753 501 uint8_t const bytes = (uint8_t) strlen(request->path);
spastor 0:1c358ea10753 502
spastor 0:1c358ea10753 503 ASSERT(strlen(request->path) <= UCHAR_MAX);
spastor 0:1c358ea10753 504 *ptr++ = bytes;
spastor 0:1c358ea10753 505 memcpy(ptr, request->path, bytes);
spastor 0:1c358ea10753 506 ptr += bytes;
spastor 0:1c358ea10753 507 }
spastor 0:1c358ea10753 508
spastor 0:1c358ea10753 509 /* fill parameters */
spastor 0:1c358ea10753 510 {
spastor 0:1c358ea10753 511 connector_bool_t const have_type = connector_bool(request->content_type != NULL);
spastor 0:1c358ea10753 512 uint8_t const parameter_requested = 1;
spastor 0:1c358ea10753 513 uint8_t params = have_type ? 1 : 0;
spastor 0:1c358ea10753 514
spastor 0:1c358ea10753 515 enum
spastor 0:1c358ea10753 516 {
spastor 0:1c358ea10753 517 parameter_id_content_type,
spastor 0:1c358ea10753 518 parameter_id_archive,
spastor 0:1c358ea10753 519 parameter_id_append,
spastor 0:1c358ea10753 520 parameter_id_transient
spastor 0:1c358ea10753 521 };
spastor 0:1c358ea10753 522
spastor 0:1c358ea10753 523 if (request->option != connector_data_service_send_option_overwrite) params++;
spastor 0:1c358ea10753 524
spastor 0:1c358ea10753 525 *ptr++ = params;
spastor 0:1c358ea10753 526
spastor 0:1c358ea10753 527 if (have_type)
spastor 0:1c358ea10753 528 {
spastor 0:1c358ea10753 529 uint8_t const bytes = (uint8_t) strlen(request->content_type);
spastor 0:1c358ea10753 530
spastor 0:1c358ea10753 531 ASSERT(strlen(request->content_type) <= UCHAR_MAX);
spastor 0:1c358ea10753 532 *ptr++ = parameter_id_content_type;
spastor 0:1c358ea10753 533 *ptr++ = bytes;
spastor 0:1c358ea10753 534 memcpy(ptr, request->content_type, bytes);
spastor 0:1c358ea10753 535 ptr += bytes;
spastor 0:1c358ea10753 536 }
spastor 0:1c358ea10753 537
spastor 0:1c358ea10753 538 switch(request->option)
spastor 0:1c358ea10753 539 {
spastor 0:1c358ea10753 540 case connector_data_service_send_option_archive:
spastor 0:1c358ea10753 541 *ptr++ = parameter_id_archive;
spastor 0:1c358ea10753 542 *ptr++ = parameter_requested;
spastor 0:1c358ea10753 543 break;
spastor 0:1c358ea10753 544
spastor 0:1c358ea10753 545 case connector_data_service_send_option_append:
spastor 0:1c358ea10753 546 *ptr++ = parameter_id_append;
spastor 0:1c358ea10753 547 *ptr++ = parameter_requested;
spastor 0:1c358ea10753 548 break;
spastor 0:1c358ea10753 549
spastor 0:1c358ea10753 550 case connector_data_service_send_option_transient:
spastor 0:1c358ea10753 551 *ptr++ = parameter_id_transient;
spastor 0:1c358ea10753 552 *ptr++ = parameter_requested;
spastor 0:1c358ea10753 553 break;
spastor 0:1c358ea10753 554
spastor 0:1c358ea10753 555 default:
spastor 0:1c358ea10753 556 break;
spastor 0:1c358ea10753 557 }
spastor 0:1c358ea10753 558 }
spastor 0:1c358ea10753 559
spastor 0:1c358ea10753 560 return (size_t)(ptr - data);
spastor 0:1c358ea10753 561 }
spastor 0:1c358ea10753 562
spastor 0:1c358ea10753 563 static connector_status_t call_put_request_user(connector_data_t * const connector_ptr, msg_service_request_t * const service_request, connector_request_id_data_service_t const request_id, void * const cb_data)
spastor 0:1c358ea10753 564 {
spastor 0:1c358ea10753 565 connector_status_t status = connector_working;
spastor 0:1c358ea10753 566 msg_session_t * const session = service_request->session;
spastor 0:1c358ea10753 567 data_service_context_t * const context = (session != NULL) ? session->service_context : NULL;
spastor 0:1c358ea10753 568 connector_callback_status_t callback_status = connector_callback_continue;
spastor 0:1c358ea10753 569
spastor 0:1c358ea10753 570 if ((context == NULL) || (context->dp_request == connector_false))
spastor 0:1c358ea10753 571 {
spastor 0:1c358ea10753 572 connector_request_id_t request;
spastor 0:1c358ea10753 573
spastor 0:1c358ea10753 574 request.data_service_request = request_id;
spastor 0:1c358ea10753 575 callback_status = connector_callback(connector_ptr->callback, connector_class_id_data_service, request, cb_data);
spastor 0:1c358ea10753 576 }
spastor 0:1c358ea10753 577 #if (defined CONNECTOR_DATA_POINTS)
spastor 0:1c358ea10753 578 else
spastor 0:1c358ea10753 579 {
spastor 0:1c358ea10753 580 callback_status = dp_handle_callback(connector_ptr, request_id, cb_data);
spastor 0:1c358ea10753 581 }
spastor 0:1c358ea10753 582 #endif
spastor 0:1c358ea10753 583
spastor 0:1c358ea10753 584 switch (callback_status)
spastor 0:1c358ea10753 585 {
spastor 0:1c358ea10753 586 case connector_callback_continue:
spastor 0:1c358ea10753 587 status = connector_working;
spastor 0:1c358ea10753 588 break;
spastor 0:1c358ea10753 589
spastor 0:1c358ea10753 590 case connector_callback_error:
spastor 0:1c358ea10753 591 set_data_service_error(service_request, connector_session_error_cancel);
spastor 0:1c358ea10753 592 status = connector_working;
spastor 0:1c358ea10753 593 break;
spastor 0:1c358ea10753 594
spastor 0:1c358ea10753 595 case connector_callback_busy:
spastor 0:1c358ea10753 596 status = connector_pending;
spastor 0:1c358ea10753 597 break;
spastor 0:1c358ea10753 598
spastor 0:1c358ea10753 599 default:
spastor 0:1c358ea10753 600 status = connector_abort;
spastor 0:1c358ea10753 601 break;
spastor 0:1c358ea10753 602 }
spastor 0:1c358ea10753 603
spastor 0:1c358ea10753 604 return status;
spastor 0:1c358ea10753 605 }
spastor 0:1c358ea10753 606
spastor 0:1c358ea10753 607 static connector_status_t process_send_request(connector_data_t * const connector_ptr, msg_service_request_t * const service_request, data_service_context_t * const ds_ptr)
spastor 0:1c358ea10753 608 {
spastor 0:1c358ea10753 609 connector_status_t status = connector_working;
spastor 0:1c358ea10753 610 msg_service_data_t * const service_data = service_request->need_data;
spastor 0:1c358ea10753 611 connector_data_service_send_data_t user_data;
spastor 0:1c358ea10753 612
spastor 0:1c358ea10753 613 user_data.transport = connector_transport_tcp;
spastor 0:1c358ea10753 614 user_data.user_context = ds_ptr->callback_context;
spastor 0:1c358ea10753 615 user_data.bytes_used = 0;
spastor 0:1c358ea10753 616 user_data.more_data = connector_false;
spastor 0:1c358ea10753 617
spastor 0:1c358ea10753 618 if (MsgIsStart(service_data->flags))
spastor 0:1c358ea10753 619 {
spastor 0:1c358ea10753 620 uint8_t * dptr = service_data->data_ptr;
spastor 0:1c358ea10753 621 size_t const bytes = fill_put_request_header(ds_ptr->header, dptr);
spastor 0:1c358ea10753 622
spastor 0:1c358ea10753 623 if (bytes >= service_data->length_in_bytes)
spastor 0:1c358ea10753 624 {
spastor 0:1c358ea10753 625 connector_debug_printf("process_send_request: required bytes [%" PRIsize "] is more than available [%" PRIsize "]\n", bytes, service_data->length_in_bytes);
spastor 0:1c358ea10753 626 goto error;
spastor 0:1c358ea10753 627 }
spastor 0:1c358ea10753 628
spastor 0:1c358ea10753 629 user_data.buffer = dptr + bytes;
spastor 0:1c358ea10753 630 user_data.bytes_available = service_data->length_in_bytes - bytes;
spastor 0:1c358ea10753 631 service_data->length_in_bytes = bytes;
spastor 0:1c358ea10753 632 }
spastor 0:1c358ea10753 633 else
spastor 0:1c358ea10753 634 {
spastor 0:1c358ea10753 635 user_data.buffer = service_data->data_ptr;
spastor 0:1c358ea10753 636 user_data.bytes_available = service_data->length_in_bytes;
spastor 0:1c358ea10753 637 service_data->length_in_bytes = 0;
spastor 0:1c358ea10753 638 }
spastor 0:1c358ea10753 639
spastor 0:1c358ea10753 640 status = call_put_request_user(connector_ptr, service_request, connector_request_id_data_service_send_data, &user_data);
spastor 0:1c358ea10753 641 if (status == connector_working)
spastor 0:1c358ea10753 642 {
spastor 0:1c358ea10753 643 service_data->flags = 0;
spastor 0:1c358ea10753 644 service_data->length_in_bytes += user_data.bytes_used;
spastor 0:1c358ea10753 645 if (user_data.more_data == connector_false)
spastor 0:1c358ea10753 646 MsgSetLastData(service_data->flags);
spastor 0:1c358ea10753 647 }
spastor 0:1c358ea10753 648 goto done;
spastor 0:1c358ea10753 649
spastor 0:1c358ea10753 650 error:
spastor 0:1c358ea10753 651 set_data_service_error(service_request, connector_session_error_format);
spastor 0:1c358ea10753 652
spastor 0:1c358ea10753 653 done:
spastor 0:1c358ea10753 654 return status;
spastor 0:1c358ea10753 655 }
spastor 0:1c358ea10753 656
spastor 0:1c358ea10753 657 static connector_status_t process_send_response(connector_data_t * const connector_ptr, msg_service_request_t * const service_request, data_service_context_t * const ds_ptr)
spastor 0:1c358ea10753 658 {
spastor 0:1c358ea10753 659 connector_status_t status = connector_working;
spastor 0:1c358ea10753 660 connector_data_service_send_response_t user_data;
spastor 0:1c358ea10753 661
spastor 0:1c358ea10753 662 /* Data Service put response format:
spastor 0:1c358ea10753 663 * ---------------------------------
spastor 0:1c358ea10753 664 * | 0 | 1 | 2... |
spastor 0:1c358ea10753 665 * ---------------------------------
spastor 0:1c358ea10753 666 * | Opcode | status | Response Data |
spastor 0:1c358ea10753 667 * ---------------------------------
spastor 0:1c358ea10753 668 */
spastor 0:1c358ea10753 669 enum
spastor 0:1c358ea10753 670 {
spastor 0:1c358ea10753 671 field_define(put_response, opcode, uint8_t),
spastor 0:1c358ea10753 672 field_define(put_response, status, uint8_t),
spastor 0:1c358ea10753 673 record_end(put_response)
spastor 0:1c358ea10753 674 };
spastor 0:1c358ea10753 675
spastor 0:1c358ea10753 676 enum
spastor 0:1c358ea10753 677 {
spastor 0:1c358ea10753 678 ds_data_success,
spastor 0:1c358ea10753 679 ds_data_bad_request,
spastor 0:1c358ea10753 680 ds_data_service_unavailable,
spastor 0:1c358ea10753 681 ds_data_cloud_error
spastor 0:1c358ea10753 682 };
spastor 0:1c358ea10753 683
spastor 0:1c358ea10753 684 msg_service_data_t * const service_data = service_request->have_data;
spastor 0:1c358ea10753 685 uint8_t * const put_response = service_data->data_ptr;
spastor 0:1c358ea10753 686 uint8_t const opcode = message_load_u8(put_response, opcode);
spastor 0:1c358ea10753 687 uint8_t const result = message_load_u8(put_response, status);
spastor 0:1c358ea10753 688
spastor 0:1c358ea10753 689 ASSERT_GOTO(MsgIsStart(service_data->flags), error);
spastor 0:1c358ea10753 690 ASSERT_GOTO(opcode == data_service_opcode_put_response, error);
spastor 0:1c358ea10753 691
spastor 0:1c358ea10753 692 user_data.transport = connector_transport_tcp;
spastor 0:1c358ea10753 693 user_data.user_context = ds_ptr->callback_context;
spastor 0:1c358ea10753 694 if (service_data->length_in_bytes > record_end(put_response))
spastor 0:1c358ea10753 695 {
spastor 0:1c358ea10753 696 int const max_hint_length = (MSG_MAX_RECV_PACKET_SIZE - PACKET_EDP_HEADER_SIZE - record_end(start_packet) - record_end(put_response));
spastor 0:1c358ea10753 697 uint8_t * const hint_start = put_response + record_end(put_response);
spastor 0:1c358ea10753 698 uint8_t * const hint_end = put_response + service_data->length_in_bytes;
spastor 0:1c358ea10753 699 size_t hint_length = (hint_end - hint_start) < max_hint_length ? hint_end - hint_start : max_hint_length;
spastor 0:1c358ea10753 700 char * const hint = (char *)hint_start;
spastor 0:1c358ea10753 701
spastor 0:1c358ea10753 702 /* Add a null-terminator only if necessary */
spastor 0:1c358ea10753 703 if (hint[hint_length - 1] != '\0')
spastor 0:1c358ea10753 704 hint[hint_length] = '\0';
spastor 0:1c358ea10753 705 user_data.hint = hint;
spastor 0:1c358ea10753 706 }
spastor 0:1c358ea10753 707 else
spastor 0:1c358ea10753 708 {
spastor 0:1c358ea10753 709 user_data.hint = NULL;
spastor 0:1c358ea10753 710 }
spastor 0:1c358ea10753 711
spastor 0:1c358ea10753 712 switch (result)
spastor 0:1c358ea10753 713 {
spastor 0:1c358ea10753 714 case ds_data_success:
spastor 0:1c358ea10753 715 user_data.response = connector_data_service_send_response_success;
spastor 0:1c358ea10753 716 break;
spastor 0:1c358ea10753 717
spastor 0:1c358ea10753 718 case ds_data_bad_request:
spastor 0:1c358ea10753 719 user_data.response = connector_data_service_send_response_bad_request;
spastor 0:1c358ea10753 720 break;
spastor 0:1c358ea10753 721
spastor 0:1c358ea10753 722 case ds_data_service_unavailable:
spastor 0:1c358ea10753 723 user_data.response = connector_data_service_send_response_unavailable;
spastor 0:1c358ea10753 724 break;
spastor 0:1c358ea10753 725
spastor 0:1c358ea10753 726 case ds_data_cloud_error:
spastor 0:1c358ea10753 727 user_data.response = connector_data_service_send_response_cloud_error;
spastor 0:1c358ea10753 728 break;
spastor 0:1c358ea10753 729
spastor 0:1c358ea10753 730 default:
spastor 0:1c358ea10753 731 ASSERT(connector_false);
spastor 0:1c358ea10753 732 break;
spastor 0:1c358ea10753 733 }
spastor 0:1c358ea10753 734
spastor 0:1c358ea10753 735 status = call_put_request_user(connector_ptr, service_request, connector_request_id_data_service_send_response, &user_data);
spastor 0:1c358ea10753 736 goto done;
spastor 0:1c358ea10753 737
spastor 0:1c358ea10753 738 error:
spastor 0:1c358ea10753 739 set_data_service_error(service_request, connector_session_error_format);
spastor 0:1c358ea10753 740
spastor 0:1c358ea10753 741 done:
spastor 0:1c358ea10753 742 return status;
spastor 0:1c358ea10753 743 }
spastor 0:1c358ea10753 744
spastor 0:1c358ea10753 745 static connector_status_t process_send_error(connector_data_t * const connector_ptr, msg_service_request_t * const service_request, void * const cb_context)
spastor 0:1c358ea10753 746 {
spastor 0:1c358ea10753 747 connector_status_t status = connector_working;
spastor 0:1c358ea10753 748 connector_data_service_status_t user_data;
spastor 0:1c358ea10753 749
spastor 0:1c358ea10753 750 user_data.transport = connector_transport_tcp;
spastor 0:1c358ea10753 751 user_data.user_context = cb_context;
spastor 0:1c358ea10753 752 user_data.session_error = connector_session_error_none;
spastor 0:1c358ea10753 753
spastor 0:1c358ea10753 754 switch (service_request->error_value)
spastor 0:1c358ea10753 755 {
spastor 0:1c358ea10753 756 case connector_session_error_none:
spastor 0:1c358ea10753 757 user_data.status = connector_data_service_status_complete;
spastor 0:1c358ea10753 758 break;
spastor 0:1c358ea10753 759
spastor 0:1c358ea10753 760 case connector_session_error_cancel:
spastor 0:1c358ea10753 761 user_data.status = connector_data_service_status_cancel;
spastor 0:1c358ea10753 762 break;
spastor 0:1c358ea10753 763
spastor 0:1c358ea10753 764 case connector_session_error_timeout:
spastor 0:1c358ea10753 765 user_data.status = connector_data_service_status_timeout;
spastor 0:1c358ea10753 766 break;
spastor 0:1c358ea10753 767
spastor 0:1c358ea10753 768 default:
spastor 0:1c358ea10753 769 user_data.status = connector_data_service_status_session_error;
spastor 0:1c358ea10753 770 user_data.session_error = service_request->error_value;
spastor 0:1c358ea10753 771 break;
spastor 0:1c358ea10753 772 }
spastor 0:1c358ea10753 773
spastor 0:1c358ea10753 774 status = call_put_request_user(connector_ptr, service_request, connector_request_id_data_service_send_status, &user_data);
spastor 0:1c358ea10753 775
spastor 0:1c358ea10753 776 return status;
spastor 0:1c358ea10753 777 }
spastor 0:1c358ea10753 778
spastor 0:1c358ea10753 779 static connector_status_t data_service_put_request_callback(connector_data_t * const connector_ptr, msg_service_request_t * const service_request)
spastor 0:1c358ea10753 780 {
spastor 0:1c358ea10753 781 connector_status_t status;
spastor 0:1c358ea10753 782 msg_session_t * const session = service_request->session;
spastor 0:1c358ea10753 783 data_service_context_t * const ds_ptr = session->service_context;
spastor 0:1c358ea10753 784
spastor 0:1c358ea10753 785 switch (service_request->service_type)
spastor 0:1c358ea10753 786 {
spastor 0:1c358ea10753 787 case msg_service_type_need_data:
spastor 0:1c358ea10753 788 status = process_send_request(connector_ptr, service_request, ds_ptr);
spastor 0:1c358ea10753 789 break;
spastor 0:1c358ea10753 790
spastor 0:1c358ea10753 791 case msg_service_type_have_data:
spastor 0:1c358ea10753 792 status = process_send_response(connector_ptr, service_request, ds_ptr);
spastor 0:1c358ea10753 793 break;
spastor 0:1c358ea10753 794
spastor 0:1c358ea10753 795 case msg_service_type_error:
spastor 0:1c358ea10753 796 {
spastor 0:1c358ea10753 797 msg_session_t * const session = service_request->session;
spastor 0:1c358ea10753 798 session->error = service_request->error_value;
spastor 0:1c358ea10753 799 status = process_send_error(connector_ptr, service_request, ds_ptr->callback_context);
spastor 0:1c358ea10753 800 break;
spastor 0:1c358ea10753 801 }
spastor 0:1c358ea10753 802
spastor 0:1c358ea10753 803 case msg_service_type_free:
spastor 0:1c358ea10753 804 {
spastor 0:1c358ea10753 805 #if (CONNECTOR_VERSION >= 0x02010000)
spastor 0:1c358ea10753 806 msg_session_t * const session = service_request->session;
spastor 0:1c358ea10753 807 if (session->error == connector_session_error_none)
spastor 0:1c358ea10753 808 {
spastor 0:1c358ea10753 809 /* If there is no error, call the user to inform that session is done */
spastor 0:1c358ea10753 810 status = process_send_error(connector_ptr, service_request, ds_ptr->callback_context);
spastor 0:1c358ea10753 811 if (status != connector_working)
spastor 0:1c358ea10753 812 break;
spastor 0:1c358ea10753 813 }
spastor 0:1c358ea10753 814 #endif
spastor 0:1c358ea10753 815 if (ds_ptr != NULL)
spastor 0:1c358ea10753 816 status = free_data_buffer(connector_ptr, named_buffer_id(put_request), ds_ptr);
spastor 0:1c358ea10753 817 else
spastor 0:1c358ea10753 818 status = connector_working;
spastor 0:1c358ea10753 819 break;
spastor 0:1c358ea10753 820 }
spastor 0:1c358ea10753 821 default:
spastor 0:1c358ea10753 822 status = connector_idle;
spastor 0:1c358ea10753 823 ASSERT(connector_false);
spastor 0:1c358ea10753 824 break;
spastor 0:1c358ea10753 825 }
spastor 0:1c358ea10753 826
spastor 0:1c358ea10753 827 return status;
spastor 0:1c358ea10753 828 }
spastor 0:1c358ea10753 829
spastor 0:1c358ea10753 830 static connector_status_t data_service_put_request_init(connector_data_t * const connector_ptr, msg_service_request_t * const service_request)
spastor 0:1c358ea10753 831 {
spastor 0:1c358ea10753 832 connector_status_t status = connector_working;
spastor 0:1c358ea10753 833 connector_session_error_t result = service_request->error_value;
spastor 0:1c358ea10753 834 msg_session_t * const session = service_request->session;
spastor 0:1c358ea10753 835 connector_request_data_service_send_t * send_ptr = (void *)service_request->have_data;
spastor 0:1c358ea10753 836 data_service_context_t * ds_ptr = NULL;
spastor 0:1c358ea10753 837
spastor 0:1c358ea10753 838 if (send_ptr != NULL)
spastor 0:1c358ea10753 839 {
spastor 0:1c358ea10753 840 void * ptr;
spastor 0:1c358ea10753 841
spastor 0:1c358ea10753 842 if ((result != connector_session_error_none) || (session == NULL)) goto error;
spastor 0:1c358ea10753 843
spastor 0:1c358ea10753 844 status = malloc_data_buffer(connector_ptr, sizeof *ds_ptr, named_buffer_id(put_request), &ptr);
spastor 0:1c358ea10753 845 if (status != connector_working)
spastor 0:1c358ea10753 846 goto error;
spastor 0:1c358ea10753 847
spastor 0:1c358ea10753 848 ds_ptr = ptr;
spastor 0:1c358ea10753 849 }
spastor 0:1c358ea10753 850 else
spastor 0:1c358ea10753 851 {
spastor 0:1c358ea10753 852 status = connector_invalid_data;
spastor 0:1c358ea10753 853 ASSERT_GOTO(connector_false, done);
spastor 0:1c358ea10753 854 }
spastor 0:1c358ea10753 855
spastor 0:1c358ea10753 856 ds_ptr->header = send_ptr;
spastor 0:1c358ea10753 857 ds_ptr->callback_context = send_ptr->user_context;
spastor 0:1c358ea10753 858 ds_ptr->request_type = connector_request_id_data_service_send_data;
spastor 0:1c358ea10753 859 ds_ptr->dp_request = connector_false;
spastor 0:1c358ea10753 860 session->service_context = ds_ptr;
spastor 0:1c358ea10753 861
spastor 0:1c358ea10753 862 #if (defined CONNECTOR_DATA_POINTS)
spastor 0:1c358ea10753 863 {
spastor 0:1c358ea10753 864 char const data_point_prefix[] = "DataPoint/";
spastor 0:1c358ea10753 865
spastor 0:1c358ea10753 866 ds_ptr->dp_request = connector_bool(!strncmp(ds_ptr->header->path, data_point_prefix, strlen(data_point_prefix)));
spastor 0:1c358ea10753 867 }
spastor 0:1c358ea10753 868 #endif
spastor 0:1c358ea10753 869
spastor 0:1c358ea10753 870 goto done;
spastor 0:1c358ea10753 871
spastor 0:1c358ea10753 872 error:
spastor 0:1c358ea10753 873 set_data_service_error(service_request, result);
spastor 0:1c358ea10753 874 process_send_error(connector_ptr, service_request, send_ptr->user_context);
spastor 0:1c358ea10753 875
spastor 0:1c358ea10753 876 done:
spastor 0:1c358ea10753 877 return status;
spastor 0:1c358ea10753 878 }
spastor 0:1c358ea10753 879
spastor 0:1c358ea10753 880 static connector_status_t data_service_callback(connector_data_t * const connector_ptr, msg_service_request_t * const service_request)
spastor 0:1c358ea10753 881 {
spastor 0:1c358ea10753 882 connector_status_t status = connector_idle;
spastor 0:1c358ea10753 883 msg_session_t * session;
spastor 0:1c358ea10753 884 data_service_context_t * ds_ptr;
spastor 0:1c358ea10753 885
spastor 0:1c358ea10753 886 ASSERT_GOTO(connector_ptr != NULL, done);
spastor 0:1c358ea10753 887 ASSERT_GOTO(service_request != NULL, done);
spastor 0:1c358ea10753 888
spastor 0:1c358ea10753 889 session = service_request->session;
spastor 0:1c358ea10753 890
spastor 0:1c358ea10753 891 if (service_request->service_type == msg_service_type_pending_request || session == NULL)
spastor 0:1c358ea10753 892 {
spastor 0:1c358ea10753 893 status = data_service_put_request_init(connector_ptr, service_request);
spastor 0:1c358ea10753 894 goto done;
spastor 0:1c358ea10753 895 }
spastor 0:1c358ea10753 896
spastor 0:1c358ea10753 897 ds_ptr = session->service_context;
spastor 0:1c358ea10753 898
spastor 0:1c358ea10753 899 if (ds_ptr == NULL)
spastor 0:1c358ea10753 900 {
spastor 0:1c358ea10753 901 status = data_service_device_request_callback(connector_ptr, service_request);
spastor 0:1c358ea10753 902 goto done;
spastor 0:1c358ea10753 903 }
spastor 0:1c358ea10753 904
spastor 0:1c358ea10753 905 switch (ds_ptr->request_type)
spastor 0:1c358ea10753 906 {
spastor 0:1c358ea10753 907 case connector_request_id_data_service_send_length:
spastor 0:1c358ea10753 908 case connector_request_id_data_service_send_data:
spastor 0:1c358ea10753 909 case connector_request_id_data_service_send_status:
spastor 0:1c358ea10753 910 case connector_request_id_data_service_send_response:
spastor 0:1c358ea10753 911 status = data_service_put_request_callback(connector_ptr, service_request);
spastor 0:1c358ea10753 912 break;
spastor 0:1c358ea10753 913
spastor 0:1c358ea10753 914 case connector_request_id_data_service_receive_target:
spastor 0:1c358ea10753 915 case connector_request_id_data_service_receive_data:
spastor 0:1c358ea10753 916 case connector_request_id_data_service_receive_status:
spastor 0:1c358ea10753 917 case connector_request_id_data_service_receive_reply_length:
spastor 0:1c358ea10753 918 case connector_request_id_data_service_receive_reply_data:
spastor 0:1c358ea10753 919 status = data_service_device_request_callback(connector_ptr, service_request);
spastor 0:1c358ea10753 920 break;
spastor 0:1c358ea10753 921
spastor 0:1c358ea10753 922 default:
spastor 0:1c358ea10753 923 ASSERT(connector_false);
spastor 0:1c358ea10753 924 break;
spastor 0:1c358ea10753 925 }
spastor 0:1c358ea10753 926
spastor 0:1c358ea10753 927 done:
spastor 0:1c358ea10753 928 return status;
spastor 0:1c358ea10753 929 }
spastor 0:1c358ea10753 930
spastor 0:1c358ea10753 931 static connector_status_t connector_facility_data_service_cleanup(connector_data_t * const connector_ptr)
spastor 0:1c358ea10753 932 {
spastor 0:1c358ea10753 933 return msg_cleanup_all_sessions(connector_ptr, msg_service_id_data);
spastor 0:1c358ea10753 934 }
spastor 0:1c358ea10753 935
spastor 0:1c358ea10753 936 static connector_status_t connector_facility_data_service_delete(connector_data_t * const data_ptr)
spastor 0:1c358ea10753 937 {
spastor 0:1c358ea10753 938 return msg_delete_facility(data_ptr, msg_service_id_data);
spastor 0:1c358ea10753 939 }
spastor 0:1c358ea10753 940
spastor 0:1c358ea10753 941 static connector_status_t connector_facility_data_service_init(connector_data_t * const data_ptr, unsigned int const facility_index)
spastor 0:1c358ea10753 942 {
spastor 0:1c358ea10753 943 return msg_init_facility(data_ptr, facility_index, msg_service_id_data, data_service_callback);
spastor 0:1c358ea10753 944 }
spastor 0:1c358ea10753 945
spastor 0:1c358ea10753 946 static connector_status_t data_service_initiate(connector_data_t * const connector_ptr, void const * request)
spastor 0:1c358ea10753 947 {
spastor 0:1c358ea10753 948 connector_status_t status = connector_invalid_data;
spastor 0:1c358ea10753 949
spastor 0:1c358ea10753 950 ASSERT_GOTO(request != NULL, error);
spastor 0:1c358ea10753 951
spastor 0:1c358ea10753 952 status = msg_initiate_request(connector_ptr, request) == connector_true ? connector_success : connector_service_busy;
spastor 0:1c358ea10753 953
spastor 0:1c358ea10753 954 error:
spastor 0:1c358ea10753 955 return status;
spastor 0:1c358ea10753 956 }
spastor 0:1c358ea10753 957
spastor 0:1c358ea10753 958
spastor 0:1c358ea10753 959