Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
layer.h
00001 /* 00002 * Copyright (c) 2013 Digi International Inc., 00003 * All rights not expressly granted are reserved. 00004 * 00005 * This Source Code Form is subject to the terms of the Mozilla Public 00006 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 00007 * You can obtain one at http://mozilla.org/MPL/2.0/. 00008 * 00009 * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343 00010 * ======================================================================= 00011 */ 00012 00013 00014 #define MANDATORY_FACILITY (connector_request_id_config_t)-1 00015 00016 #define SET_FACILITY_SUPPORT(i) (UINT32_C(0x01) << (i)) 00017 #define IS_FACILITY_SUPPORTED(connector_ptr, table_index) (connector_ptr->edp_data.facilities.supported_mask & SET_FACILITY_SUPPORT(table_index)) 00018 00019 typedef connector_status_t (* connector_facility_service_init_cb_t)(struct connector_data * const connector_ptr, unsigned int const facility_index); 00020 typedef connector_status_t (* connector_facility_service_delete_cb_t)(struct connector_data * const connector_ptr); 00021 typedef connector_status_t (* connector_facility_service_process_cb_t )(struct connector_data * const connector_ptr, 00022 void * const facility_data, 00023 uint8_t * const packet, 00024 unsigned int * const receive_timeout); 00025 00026 typedef struct { 00027 connector_request_id_t request_id; 00028 connector_facility_service_init_cb_t init_cb; 00029 connector_facility_service_delete_cb_t delete_cb; 00030 connector_facility_service_delete_cb_t cleanup_cb; 00031 connector_facility_service_process_cb_t discovery_cb; 00032 connector_facility_service_process_cb_t process_cb; 00033 } connector_facility_service_t; 00034 00035 /* Table of all supported facilities. 00036 * 00037 * The connector will call the callback to see whether it supports each optional facility. 00038 * It will call init_cb to initialize the facility and delete_cb to remove the facility. 00039 * The init_cb must call add_facility_data() to add the facility into the facility list. 00040 * The delete_cb is called to delete the facility from the facility list when user terminates the connector. 00041 */ 00042 static connector_facility_service_t const connector_supported_service_table[] = { 00043 /* mandatory facilities */ 00044 {{MANDATORY_FACILITY}, connector_facility_cc_init, connector_facility_cc_delete, connector_facility_cc_cleanup, cc_discovery, cc_process}, 00045 00046 /* list of optional facilities */ 00047 #if (defined CONNECTOR_FIRMWARE_SERVICE) || (defined CONNECTOR_RCI_SERVICE) 00048 #if (defined CONNECTOR_FIRMWARE_SUPPORT) || (defined CONNECTOR_RCI_SERVICE) 00049 {{MANDATORY_FACILITY}, connector_facility_firmware_init, connector_facility_firmware_delete, NULL, fw_discovery, fw_process}, 00050 #else 00051 {{connector_request_id_config_firmware_facility}, connector_facility_firmware_init, connector_facility_firmware_delete, NULL, fw_discovery, fw_process}, 00052 #endif 00053 #endif 00054 #if (defined CONNECTOR_DATA_SERVICE) 00055 #if (defined CONNECTOR_DATA_SERVICE_SUPPORT) 00056 {{MANDATORY_FACILITY}, connector_facility_data_service_init, connector_facility_data_service_delete, connector_facility_data_service_cleanup, msg_discovery, msg_process}, 00057 #else 00058 {{connector_request_id_config_data_service}, connector_facility_data_service_init, connector_facility_data_service_delete, connector_facility_data_service_cleanup, msg_discovery, msg_process}, 00059 #endif 00060 #endif 00061 #if (defined CONNECTOR_FILE_SYSTEM) 00062 #if (defined CONNECTOR_FILE_SYSTEM_SUPPORT) 00063 {{MANDATORY_FACILITY}, connector_facility_file_system_init, connector_facility_file_system_delete, connector_facility_file_system_cleanup, msg_discovery, msg_process}, 00064 #else 00065 {{connector_request_id_config_file_system}, connector_facility_file_system_init, connector_facility_file_system_delete, connector_facility_file_system_cleanup, msg_discovery, msg_process}, 00066 #endif 00067 #endif 00068 00069 #if (defined CONNECTOR_RCI_SERVICE) 00070 #if (defined CONNECTOR_REMOTE_CONFIGURATION_SUPPORT) 00071 {{MANDATORY_FACILITY}, connector_facility_rci_service_init, connector_facility_rci_service_delete, connector_facility_rci_service_cleanup, msg_discovery, msg_process} 00072 #else 00073 {{connector_request_id_config_remote_configuration}, connector_facility_rci_service_init, connector_facility_rci_service_delete, connector_facility_rci_service_cleanup, msg_discovery, msg_process} 00074 #endif 00075 #endif 00076 }; 00077 00078 static size_t const connector_facility_count = asizeof(connector_supported_service_table); 00079 00080 00081 static connector_status_t layer_remove_facilities(connector_data_t * const connector_ptr, connector_supported_facility_cb_index_t cb_index) 00082 { 00083 connector_status_t result = connector_idle; 00084 size_t i; 00085 00086 for (i=0; (i < connector_facility_count) && ((result == connector_idle) || (result == connector_working)); i++) 00087 { 00088 if (IS_FACILITY_SUPPORTED(connector_ptr,i)) 00089 { 00090 switch (cb_index) 00091 { 00092 case facility_callback_delete: 00093 if (connector_supported_service_table[i].delete_cb != NULL) 00094 { 00095 result = connector_supported_service_table[i].delete_cb(connector_ptr); 00096 } 00097 break; 00098 case facility_callback_cleanup: 00099 if (connector_supported_service_table[i].cleanup_cb != NULL) 00100 { 00101 result = connector_supported_service_table[i].cleanup_cb(connector_ptr); 00102 } 00103 break; 00104 } 00105 ASSERT(result != connector_pending); 00106 } 00107 } 00108 return result; 00109 } 00110 00111 00112 00113 static connector_status_t layer_discovery_facility(connector_data_t * const connector_ptr) 00114 { 00115 connector_status_t result = connector_idle; 00116 connector_facility_t * fac_ptr; 00117 00118 /* invoke any facility that needs to send any message to Device Cloud 00119 * during initialization phase at discovery layer. 00120 */ 00121 fac_ptr = (connector_ptr->edp_data.facilities.current == NULL)? connector_ptr->edp_data.facilities.list: connector_ptr->edp_data.facilities.current; 00122 00123 for (;fac_ptr != NULL && result == connector_idle; fac_ptr = fac_ptr->next) 00124 { 00125 unsigned int const i = fac_ptr->service_index; 00126 00127 if (connector_supported_service_table[i].discovery_cb != NULL) 00128 { /* function to send facility discovery */ 00129 result = connector_supported_service_table[i].discovery_cb(connector_ptr, fac_ptr->facility_data, 00130 NULL, &connector_ptr->edp_data.receive_packet.timeout); 00131 connector_ptr->edp_data.facilities.current = (result == connector_pending) ? fac_ptr : fac_ptr->next; 00132 } 00133 } 00134 00135 if (result == connector_working || result == connector_idle) 00136 { 00137 if (connector_ptr->edp_data.facilities.current == NULL) 00138 { 00139 /* done all facilities */ 00140 result = connector_working; 00141 } 00142 else if (result == connector_working) 00143 { 00144 /* continue next facility */ 00145 result = connector_idle; 00146 } 00147 } 00148 return result; 00149 } 00150 00151 00152 static connector_status_t edp_layer_get_supported_facilities(connector_data_t * const connector_ptr) 00153 { 00154 #define NUMBER_FACILITY_PER_BYTE CHAR_BIT 00155 connector_status_t result = connector_working; 00156 unsigned int i; 00157 00158 connector_ptr->edp_data.facilities.supported_mask = 0; 00159 00160 ASSERT(CHAR_BIT == 8); 00161 ASSERT(connector_facility_count <= (sizeof connector_ptr->edp_data.facilities.supported_mask * NUMBER_FACILITY_PER_BYTE)); 00162 00163 /* connector_supported_service_table[] table includes a list of supported facilities. 00164 * Call callback to see which facility is supported. 00165 */ 00166 00167 for (i=0; i < connector_facility_count; i++) 00168 { 00169 connector_request_id_t const request_id = connector_supported_service_table[i].request_id; 00170 connector_config_supported_t config_status; 00171 00172 config_status.supported = connector_bool(request_id.config_request == MANDATORY_FACILITY); 00173 00174 if (request_id.config_request != MANDATORY_FACILITY) 00175 { /* this is optional facility so ask application whether it supports this facility */ 00176 connector_callback_status_t status; 00177 00178 status = connector_callback(connector_ptr->callback, connector_class_id_config, request_id, &config_status); 00179 switch (status) 00180 { 00181 case connector_callback_busy: 00182 /* not allowed to returned busy */ 00183 connector_debug_printf("edp_layer_get_supported_facilities: callback returns connector_callback_busy which is not allowed\n"); 00184 result = connector_abort; 00185 goto error; 00186 case connector_callback_abort: 00187 case connector_callback_error: 00188 result = connector_abort; 00189 goto done; 00190 case connector_callback_unrecognized: 00191 config_status.supported = connector_false; 00192 break; 00193 case connector_callback_continue: 00194 break; 00195 } 00196 } 00197 00198 switch (config_status.supported) 00199 { 00200 case connector_true: 00201 connector_ptr->edp_data.facilities.supported_mask |= (uint16_t)SET_FACILITY_SUPPORT(i); 00202 break; 00203 case connector_false: 00204 break; 00205 default: 00206 result = connector_invalid_data_range; 00207 goto error; 00208 } 00209 00210 } 00211 00212 error: 00213 if (result != connector_working) 00214 { 00215 connector_request_id_t const request_id = connector_supported_service_table[i].request_id; 00216 if (notify_error_status(connector_ptr->callback, connector_class_id_config, request_id, result) != connector_working) 00217 result = connector_abort; 00218 } 00219 00220 done: 00221 return result; 00222 } 00223 00224 static connector_status_t edp_layer_initialize_facilities(connector_data_t * const connector_ptr) 00225 { 00226 connector_status_t result = connector_working; 00227 size_t i; 00228 00229 for (i=0; i < connector_facility_count; i++) 00230 { 00231 if (IS_FACILITY_SUPPORTED(connector_ptr,i) && 00232 connector_supported_service_table[i].init_cb != NULL) 00233 { 00234 result = connector_supported_service_table[i].init_cb(connector_ptr, i); 00235 if ( result != connector_working) goto done; 00236 } 00237 } 00238 00239 { 00240 connector_facility_t * fac_ptr; 00241 /* initialize packet pointer for each facility */ 00242 for (fac_ptr = connector_ptr->edp_data.facilities.list; fac_ptr != NULL; fac_ptr = fac_ptr->next) 00243 { 00244 fac_ptr->packet_buffer = NULL; 00245 } 00246 } 00247 00248 done: 00249 return result; 00250 } 00251 00252 static connector_status_t layer_facility_process(connector_data_t * const connector_ptr) 00253 { 00254 connector_status_t result = connector_idle; 00255 connector_facility_t * fac_ptr; 00256 00257 00258 /* Invoke facility process. 00259 * 00260 * Run all facilities. But each starting facility 00261 * will be alternated. 00262 */ 00263 fac_ptr = (connector_ptr->edp_data.facilities.current != NULL) ? connector_ptr->edp_data.facilities.current : connector_ptr->edp_data.facilities.list; 00264 connector_ptr->edp_data.facilities.current = fac_ptr; 00265 do 00266 { 00267 /* We want to run all facilities processes */ 00268 unsigned int const i = fac_ptr->service_index; 00269 00270 if (connector_supported_service_table[i].process_cb) 00271 { 00272 uint8_t * const packet = (fac_ptr->packet_buffer != NULL) ? fac_ptr->packet_buffer->buffer: NULL; 00273 00274 result = connector_supported_service_table[i].process_cb(connector_ptr, fac_ptr->facility_data, 00275 packet, &connector_ptr->edp_data.receive_packet.timeout); 00276 00277 if (result != connector_pending && result != connector_active && fac_ptr->packet_buffer != NULL) 00278 { /* release the packet when it's done */ 00279 tcp_release_receive_packet(connector_ptr, fac_ptr->packet_buffer); 00280 fac_ptr->packet_buffer = NULL; 00281 } 00282 fac_ptr = (fac_ptr->next != NULL) ? fac_ptr->next : connector_ptr->edp_data.facilities.list; 00283 } 00284 00285 } while (result == connector_idle && fac_ptr != connector_ptr->edp_data.facilities.current); 00286 00287 /* setup next starting facility process */ 00288 connector_ptr->edp_data.facilities.current = (connector_ptr->edp_data.facilities.current != NULL) ? connector_ptr->edp_data.facilities.current->next : connector_ptr->edp_data.facilities.list; 00289 00290 if (result == connector_abort) edp_set_close_status(connector_ptr, connector_close_status_abort); 00291 00292 return result; 00293 } 00294
Generated on Tue Jul 12 2022 19:18:38 by
1.7.2