BA
/
BaBoRo1
Embed:
(wiki syntax)
Show/hide line numbers
thread_diagnostic.c
00001 /* 00002 * Copyright (c) 2016-2017, Arm Limited and affiliates. 00003 * SPDX-License-Identifier: BSD-3-Clause 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions are met: 00007 * 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 3. Neither the name of the copyright holder nor the 00014 * names of its contributors may be used to endorse or promote products 00015 * derived from this software without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00018 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00019 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00020 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 00021 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00022 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00023 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00024 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00025 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00026 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00027 * POSSIBILITY OF SUCH DAMAGE. 00028 */ 00029 #include "nsconfig.h" 00030 #ifdef HAVE_THREAD 00031 #include <string.h> 00032 #include <ns_types.h> 00033 #include <ns_list.h> 00034 #include <ns_trace.h> 00035 #include "nsdynmemLIB.h" 00036 #include "net_interface.h" 00037 #include "thread_management_if.h" 00038 #include "thread_common.h" 00039 #include "thread_joiner_application.h" 00040 #include "thread_leader_service.h" 00041 #include "thread_router_bootstrap.h" 00042 #include "MLE/mle.h" 00043 #include "6LoWPAN/Thread/thread_router_bootstrap.h" 00044 #include "thread_config.h" 00045 #include "thread_network_data_storage.h" 00046 #include "NWK_INTERFACE/Include/protocol.h" 00047 #include "thread_diagcop_lib.h" 00048 #include "common_functions.h" 00049 #include "6LoWPAN/MAC/mac_helper.h" 00050 #include "mac_api.h" 00051 00052 00053 #define TRACE_GROUP "TdiaC" 00054 00055 00056 #include "coap_service_api.h" 00057 00058 00059 typedef struct thread_diagnostic_command { 00060 int8_t interface_id; 00061 int8_t coap_service_id; 00062 ns_list_link_t link; 00063 } thread_diagnostic_command_t; 00064 00065 static NS_LIST_DEFINE(instance_list, thread_diagnostic_command_t, link); 00066 00067 static thread_diagnostic_command_t *thread_diagnostic_command_find(int8_t interface_id) 00068 { 00069 thread_diagnostic_command_t *this = NULL; 00070 ns_list_foreach(thread_diagnostic_command_t, cur_ptr, &instance_list) { 00071 if (cur_ptr->interface_id == interface_id) { 00072 this = cur_ptr; 00073 break; 00074 } 00075 } 00076 return this; 00077 } 00078 00079 static thread_diagnostic_command_t *thread_diagnostic_find_by_service(int8_t service_id) 00080 { 00081 thread_diagnostic_command_t *this = NULL; 00082 ns_list_foreach(thread_diagnostic_command_t, cur_ptr, &instance_list) { 00083 if (cur_ptr->coap_service_id == service_id) { 00084 this = cur_ptr; 00085 break; 00086 } 00087 } 00088 return this; 00089 } 00090 00091 static uint8_t *thread_diagnostic_child_table_tlv_build(uint8_t *data_ptr, protocol_interface_info_entry_t *cur) 00092 { 00093 uint8_t child_count = 0; 00094 uint8_t calculated_timeout; 00095 00096 mle_neigh_table_list_t *mle_table = mle_class_active_list_get(cur->id); 00097 if (!mle_table) { 00098 return data_ptr; 00099 } 00100 00101 child_count = thread_router_bootstrap_child_count_get(cur); 00102 00103 *data_ptr++ = DIAGCOP_TLV_CHILD_TABLE; // Type 00104 *data_ptr++ = (3 * child_count); // Length 00105 00106 ns_list_foreach(mle_neigh_table_entry_t, cur_entry, mle_table) { 00107 if (cur_entry->threadNeighbor && thread_router_addr_from_addr(cur_entry->short_adr) == mac_helper_mac16_address_get(cur)){ 00108 /* |0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|6|7|8|9|0|1|2|3| */ 00109 /* |Timeout |Rsv| Child ID | Mode | */ 00110 calculated_timeout = thread_log2_aprx((cur_entry->timeout_rx-1)*MLE_TIMER_TICKS_SECONDS) + 4; 00111 tr_debug("Write child table TLV entry: %d - %d - %d", calculated_timeout, cur_entry->short_adr, cur_entry->mode); 00112 *data_ptr = 0x00; //reserved bytes to zero 00113 *data_ptr = calculated_timeout << 3; 00114 00115 if(cur_entry->short_adr & 0x0100){ 00116 *data_ptr = *data_ptr | 0x01; 00117 } 00118 data_ptr++; 00119 *data_ptr++ = (uint8_t)(cur_entry->short_adr & 0x00ff); 00120 *data_ptr++ = cur_entry->mode; 00121 } 00122 } 00123 00124 return data_ptr; 00125 } 00126 00127 uint8_t thread_diag_mode_get_by_interface_ptr(protocol_interface_info_entry_t *cur) 00128 { 00129 uint8_t mle_mode = 0; 00130 if (!thread_info(cur)) { 00131 return 0; 00132 } 00133 if (!(cur->lowpan_info & INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE)) { 00134 mle_mode |= MLE_RX_ON_IDLE; 00135 } 00136 00137 if (thread_info(cur)->requestFullNetworkData) { 00138 mle_mode |= (MLE_THREAD_REQ_FULL_DATA_SET); 00139 } 00140 00141 /* We always send secured data requests */ 00142 mle_mode |= MLE_THREAD_SECURED_DATA_REQUEST; 00143 00144 switch (thread_info(cur)->thread_device_mode) { 00145 case THREAD_DEVICE_MODE_ROUTER: 00146 case THREAD_DEVICE_MODE_FULL_END_DEVICE: 00147 mle_mode |= MLE_FFD_DEV; 00148 break; 00149 00150 default: 00151 break; 00152 } 00153 00154 00155 return mle_mode; 00156 } 00157 00158 static int thread_diagnostic_configuration_calc(protocol_interface_info_entry_t *cur, uint8_t *tlv_list, uint16_t list_len) 00159 { 00160 int payload_len = 0; 00161 uint16_t address_count = 0; 00162 00163 if(!tlv_list || list_len < 1) { 00164 return 0; 00165 } 00166 00167 while(list_len --){ 00168 switch (*tlv_list){ 00169 case DIAGCOP_TLV_EXTENDED_MAC_ADDRESS: 00170 payload_len += 2 + 8; 00171 break; 00172 00173 case DIAGCOP_TLV_ADDRESS16: 00174 payload_len += 2 + 2; 00175 break; 00176 00177 case DIAGCOP_TLV_MODE: 00178 payload_len += 2 + 1; 00179 break; 00180 00181 case DIAGCOP_TLV_TIMEOUT: 00182 if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_SLEEPY_END_DEVICE || 00183 cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_END_DEVICE ) { 00184 payload_len += 2 + 4; 00185 } 00186 break; 00187 00188 case DIAGCOP_TLV_CONNECTIVITY: 00189 payload_len += 2 + 10; 00190 break; 00191 00192 case DIAGCOP_TLV_ROUTE64: 00193 payload_len += thread_route_option_size(cur); 00194 break; 00195 00196 case DIAGCOP_TLV_LEADER_DATA: 00197 payload_len += 2 + 8; // TLV header + uint16 pan id 00198 break; 00199 00200 case DIAGCOP_TLV_NETWORK_DATA: 00201 payload_len += 2; // TLV header 00202 payload_len += thread_network_data_tlv_size(cur,1); 00203 break; 00204 00205 case DIAGCOP_TLV_IPV6_ADDRESS_LIST: 00206 arm_net_interface_address_list_size(cur->id, &address_count); 00207 payload_len += 2 + (address_count * 16); 00208 break; 00209 00210 case DIAGCOP_TLV_MAC_COUNTERS: 00211 payload_len += 2+36; 00212 break; 00213 case DIAGCOP_TLV_BATTERY_LEVEL: 00214 payload_len += 2 + 1; 00215 break; 00216 00217 case DIAGCOP_TLV_SUPPLY_VOLTAGE: 00218 payload_len += 2 + 2; 00219 break; 00220 00221 case DIAGCOP_TLV_CHILD_TABLE: 00222 /* Value length = Type + Length + 3 * child count */ 00223 payload_len += 2 + (3 * thread_router_bootstrap_child_count_get(cur)); 00224 break; 00225 00226 case DIAGCOP_TLV_CHANNEL_PAGES: 00227 payload_len += 2+1; 00228 break; 00229 00230 default: 00231 // todo: Other TLV's not supported atm 00232 break; 00233 } 00234 00235 tlv_list++; 00236 } 00237 return payload_len; 00238 } 00239 00240 static uint8_t *thread_diagnostic_get_build(protocol_interface_info_entry_t *cur, uint8_t *response_ptr, uint8_t *tlv_list, uint16_t list_len) 00241 { 00242 00243 if(!tlv_list || list_len < 1) { 00244 // Request all 00245 return response_ptr; 00246 } 00247 if (!thread_info(cur)) { 00248 return response_ptr; 00249 } 00250 // the following are some tlvs that need to be implemented correctly, this is only dummy data for the moment 00251 uint8_t dummy_data[36] = {0}; 00252 uint8_t *ptr; 00253 int written_address_count = 0; 00254 uint16_t ipv6_address_count = 0; 00255 uint8_t extended_address[8] = {0}; 00256 00257 arm_net_interface_address_list_size(cur->id, &ipv6_address_count); 00258 00259 // 16 bytes for each ipv6 address 00260 uint8_t ipv6_address_list[ipv6_address_count * 16]; 00261 00262 tr_debug("tlv list length %d", list_len); 00263 while(list_len --){ 00264 switch (*tlv_list){ 00265 00266 case DIAGCOP_TLV_EXTENDED_MAC_ADDRESS: 00267 if (cur->mac_api) { 00268 //Read dynamicaly generated current extented address from MAC. 00269 cur->mac_api->mac64_get(cur->mac_api,MAC_EXTENDED_DYNAMIC, extended_address); 00270 } 00271 response_ptr = thread_diagcop_tlv_data_write(response_ptr, DIAGCOP_TLV_EXTENDED_MAC_ADDRESS, 8, extended_address); 00272 break; 00273 00274 case DIAGCOP_TLV_ADDRESS16: 00275 response_ptr = thread_diagcop_tlv_data_write_uint16(response_ptr, DIAGCOP_TLV_ADDRESS16, mac_helper_mac16_address_get(cur)); 00276 break; 00277 00278 case DIAGCOP_TLV_MODE: 00279 response_ptr = thread_diagcop_tlv_data_write_uint8(response_ptr, DIAGCOP_TLV_MODE, thread_diag_mode_get_by_interface_ptr(cur)); 00280 break; 00281 00282 case DIAGCOP_TLV_TIMEOUT: 00283 //must be sleeping poll rate 00284 if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_SLEEPY_END_DEVICE || 00285 cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_END_DEVICE ) { 00286 response_ptr = thread_diagcop_tlv_data_write_uint32(response_ptr, DIAGCOP_TLV_TIMEOUT, cur->thread_info->host_link_timeout); 00287 } 00288 break; 00289 00290 case DIAGCOP_TLV_CONNECTIVITY: 00291 ptr = response_ptr; 00292 response_ptr = thread_connectivity_tlv_write(response_ptr, cur, 0x0f); 00293 if (ptr != response_ptr) { 00294 ptr[0]=DIAGCOP_TLV_CONNECTIVITY; 00295 } 00296 break; 00297 00298 case DIAGCOP_TLV_ROUTE64: 00299 ptr = response_ptr; 00300 response_ptr = thread_route_option_write(cur,response_ptr); 00301 if (ptr != response_ptr) { 00302 ptr[0]=DIAGCOP_TLV_ROUTE64; 00303 } 00304 break; 00305 00306 case DIAGCOP_TLV_LEADER_DATA: 00307 ptr = response_ptr; 00308 response_ptr = thread_leader_data_tlv_write(response_ptr,cur); 00309 if (ptr != response_ptr) { 00310 ptr[0]=DIAGCOP_TLV_LEADER_DATA; 00311 } 00312 break; 00313 00314 case DIAGCOP_TLV_NETWORK_DATA: 00315 ptr = response_ptr; 00316 response_ptr = thread_network_data_tlv_write(cur, response_ptr, true); 00317 if (ptr != response_ptr) { 00318 ptr[0]=DIAGCOP_TLV_NETWORK_DATA; 00319 } 00320 break; 00321 00322 case DIAGCOP_TLV_IPV6_ADDRESS_LIST: 00323 arm_net_address_list_get(cur->id, ipv6_address_count * 16,ipv6_address_list,&written_address_count); 00324 response_ptr = thread_diagcop_tlv_data_write(response_ptr, DIAGCOP_TLV_IPV6_ADDRESS_LIST, ipv6_address_count*16, ipv6_address_list); 00325 break; 00326 00327 case DIAGCOP_TLV_MAC_COUNTERS: 00328 /* The following elements from [RFC 2863] are included in this order: 00329 * ifInUnknownProtos (4), ifInErrors (4), ifOutErrors (4), ifInUcastPkts (4), 00330 * ifInBroadcastPkts (4), ifInDiscards (4), ifOutUcastPkts (4), ifOutBroadcastPkts (4), ifOutDiscards (4) */ 00331 response_ptr = thread_diagcop_tlv_data_write(response_ptr, DIAGCOP_TLV_MAC_COUNTERS, 36, dummy_data); 00332 break; 00333 00334 case DIAGCOP_TLV_BATTERY_LEVEL: 00335 response_ptr = thread_diagcop_tlv_data_write_uint8(response_ptr, DIAGCOP_TLV_BATTERY_LEVEL, 0); 00336 break; 00337 00338 case DIAGCOP_TLV_SUPPLY_VOLTAGE: 00339 response_ptr = thread_diagcop_tlv_data_write_uint16(response_ptr, DIAGCOP_TLV_SUPPLY_VOLTAGE, 0); 00340 break; 00341 00342 case DIAGCOP_TLV_CHILD_TABLE: 00343 if (thread_router_bootstrap_child_count_get(cur)) { 00344 response_ptr = thread_diagnostic_child_table_tlv_build(response_ptr, cur); 00345 } 00346 break; 00347 00348 case DIAGCOP_TLV_CHANNEL_PAGES: 00349 // Only supporting channel page 0 00350 response_ptr = thread_diagcop_tlv_data_write_uint8(response_ptr, DIAGCOP_TLV_CHANNEL_PAGES, 0); 00351 break; 00352 00353 default: 00354 00355 break; 00356 } 00357 00358 tlv_list++; 00359 } 00360 return response_ptr; 00361 } 00362 /** 00363 * Thread diagnostics request d/dg 00364 */ 00365 static int thread_diagnostic_command_request_cb(int8_t service_id, uint8_t source_address[16], uint16_t source_port, sn_coap_hdr_s *request_ptr) 00366 { 00367 (void) source_address; 00368 (void) source_port; 00369 00370 thread_diagnostic_command_t *this = thread_diagnostic_find_by_service(service_id); 00371 protocol_interface_info_entry_t *cur; 00372 uint8_t *ptr = NULL; 00373 uint8_t *request_tlv_ptr = NULL; 00374 uint16_t request_tlv_len; 00375 int response_len; 00376 uint8_t *response_ptr = NULL; 00377 sn_coap_msg_code_e return_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; 00378 00379 if (!this) {//check if there is request 00380 return -1; 00381 } 00382 cur = protocol_stack_interface_info_get_by_id(this->interface_id); 00383 if (!cur) { 00384 return -1; 00385 } 00386 00387 tr_debug("Thread diagnostic command get request"); 00388 00389 request_tlv_len = thread_diagcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, DIAGCOP_TLV_TYPE_LIST, &request_tlv_ptr); 00390 00391 // the following function calculates the total memory that is needed to be allocated for response. 00392 // If the request_tlv_len is 0 then the memory allocated is for all the diagnostic command tlvs 00393 response_len = thread_diagnostic_configuration_calc(cur,request_tlv_ptr, request_tlv_len); 00394 if(response_len < 1){ 00395 if (request_tlv_len > 0) { 00396 // TLV was ommitted but ok request. respond with ok status 00397 goto send_response; 00398 } 00399 goto failure; 00400 } 00401 ptr = response_ptr = ns_dyn_mem_alloc(response_len); 00402 if (!response_ptr) { 00403 return_code = COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR; 00404 goto failure; 00405 } 00406 00407 ptr = thread_diagnostic_get_build(cur, ptr, request_tlv_ptr, 00408 request_tlv_len); 00409 00410 send_response: 00411 coap_service_response_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, 00412 request_ptr, COAP_MSG_CODE_RESPONSE_CHANGED, COAP_CT_OCTET_STREAM, 00413 response_ptr,ptr - response_ptr ); 00414 ns_dyn_mem_free(response_ptr); 00415 return 0; 00416 00417 failure: 00418 coap_service_response_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, request_ptr, return_code, COAP_CT_NONE, NULL, 0); 00419 return 0; 00420 } 00421 /** 00422 * Thread diagnostics reset d/dr 00423 */ 00424 static int thread_diagnostic_command_reset_cb(int8_t service_id, uint8_t source_address[16], uint16_t source_port, sn_coap_hdr_s *request_ptr) 00425 { 00426 (void) source_address; 00427 (void) source_port; 00428 00429 thread_diagnostic_command_t *this = thread_diagnostic_find_by_service(service_id); 00430 if (!this) {//check if there is request 00431 return -1; 00432 } 00433 00434 tr_debug("Thread diagnostic command reset request"); 00435 00436 coap_service_response_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, 00437 request_ptr, COAP_MSG_CODE_RESPONSE_CHANGED, COAP_CT_TEXT_PLAIN, NULL, 0); 00438 return 0; 00439 } 00440 00441 /** 00442 * Thread diagnostics query d/dq 00443 */ 00444 static int thread_diagnostic_command_query_cb(int8_t service_id, uint8_t source_address[16], uint16_t source_port, sn_coap_hdr_s *request_ptr) 00445 { 00446 uint8_t address_copy[16]; 00447 protocol_interface_info_entry_t *cur; 00448 uint8_t *response_ptr = NULL; 00449 uint8_t *ptr = NULL; 00450 uint8_t *request_tlv_ptr; 00451 uint16_t response_len; 00452 uint16_t request_tlv_len; 00453 sn_coap_msg_code_e return_code = COAP_MSG_CODE_EMPTY; 00454 int8_t response = -1; 00455 00456 /* Source_address is freed when calling coap_service_response_send(). 00457 * Anyhow, We need to use it when sending request, so let's make a copy! */ 00458 memcpy(address_copy, source_address, 16); 00459 00460 thread_diagnostic_command_t *this = thread_diagnostic_find_by_service(service_id); 00461 if (!this) {//check if there is request 00462 return -1; 00463 } 00464 cur = protocol_stack_interface_info_get_by_id(this->interface_id); 00465 if (!cur) { 00466 return -1; 00467 } 00468 00469 tr_debug("Thread diagnostic command query request from %s:%d", trace_array(source_address, 16), source_port); 00470 // build response 00471 request_tlv_len = thread_diagcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, DIAGCOP_TLV_TYPE_LIST, &request_tlv_ptr); 00472 00473 // the following function calculates the total memory that is needed to be allocated for response. 00474 // If the request_tlv_len is 0 then the memory allocated is for all the diagnostic command tlvs 00475 response_len = thread_diagnostic_configuration_calc(cur, request_tlv_ptr, request_tlv_len); 00476 if(response_len < 1){ 00477 if (request_tlv_len > 0) { 00478 // TLV was ommitted but ok request. respond with ok status 00479 goto send_response; 00480 } 00481 return_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; 00482 goto failure; 00483 } 00484 ptr = response_ptr = ns_dyn_mem_alloc(response_len); 00485 if (!response_ptr) { 00486 return_code = COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR; 00487 goto failure; 00488 } 00489 00490 ptr = thread_diagnostic_get_build(cur, response_ptr, request_tlv_ptr, request_tlv_len); 00491 00492 /* Send ACK to confirmable request */ 00493 if(request_ptr->msg_type == COAP_MSG_TYPE_CONFIRMABLE){ 00494 coap_service_response_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, request_ptr, return_code, COAP_CT_NONE, NULL, 0); 00495 response = 0; 00496 } 00497 00498 /* Send reply to d/da */ 00499 send_response: 00500 coap_service_request_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, address_copy, source_port, COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, 00501 THREAD_URI_DIAGNOSTIC_ANSWER, COAP_CT_OCTET_STREAM, response_ptr, ptr - response_ptr, NULL); 00502 00503 ns_dyn_mem_free(response_ptr); 00504 00505 return response; 00506 00507 failure: 00508 if(request_ptr->msg_type == COAP_MSG_TYPE_CONFIRMABLE){ 00509 coap_service_response_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, request_ptr, return_code, COAP_CT_NONE, NULL, 0); 00510 response = 0; 00511 } 00512 return response; 00513 } 00514 00515 /** 00516 * Public interface functions 00517 */ 00518 int thread_diagnostic_init(int8_t interface_id) 00519 { 00520 00521 thread_diagnostic_command_t *this = thread_diagnostic_command_find(interface_id); 00522 if (this) { 00523 return 0; 00524 } 00525 00526 this = ns_dyn_mem_alloc(sizeof(thread_diagnostic_command_t)); 00527 if (!this) { 00528 return -2; 00529 } 00530 00531 this->interface_id = interface_id; 00532 00533 this->coap_service_id = coap_service_initialize(this->interface_id, THREAD_MANAGEMENT_PORT, COAP_SERVICE_OPTIONS_NONE, NULL, NULL); 00534 if (this->coap_service_id < 0) { 00535 tr_error("Thread diagnostic init failed"); 00536 ns_dyn_mem_free(this); 00537 return -3; 00538 } 00539 /** 00540 * Thread Management uri registration 00541 */ 00542 coap_service_register_uri(this->coap_service_id, THREAD_URI_DIAGNOSTIC_REQUEST, COAP_SERVICE_ACCESS_POST_ALLOWED, thread_diagnostic_command_request_cb); 00543 coap_service_register_uri(this->coap_service_id, THREAD_URI_DIAGNOSTIC_RESET, COAP_SERVICE_ACCESS_POST_ALLOWED, thread_diagnostic_command_reset_cb); 00544 coap_service_register_uri(this->coap_service_id, THREAD_URI_DIAGNOSTIC_QUERY, COAP_SERVICE_ACCESS_POST_ALLOWED, thread_diagnostic_command_query_cb); 00545 ns_list_add_to_start(&instance_list, this); 00546 00547 return 0; 00548 } 00549 00550 int thread_diagnostic_delete(int8_t interface_id) 00551 { 00552 thread_diagnostic_command_t *this = thread_diagnostic_command_find(interface_id); 00553 00554 if (!this) { 00555 return -1; 00556 } 00557 00558 coap_service_delete(this->coap_service_id); 00559 ns_list_remove(&instance_list, this); 00560 ns_dyn_mem_free(this); 00561 return 0; 00562 } 00563 00564 #endif
Generated on Tue Jul 12 2022 12:22:25 by
