Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ppp_service_if.cpp Source File

ppp_service_if.cpp

00001 /*
00002  * Copyright (c) 2019 ARM Limited
00003  * SPDX-License-Identifier: Apache-2.0
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License");
00006  * you may not use this file except in compliance with the License.
00007  * You may obtain a copy of the License at
00008  *
00009  *     http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 
00018 #include <stdlib.h>
00019 #include <stdio.h>
00020 #include "mbed_interface.h"
00021 #include "mbed_trace.h"
00022 #include "netsocket/nsapi_types.h"
00023 #include "mbed_shared_queues.h"
00024 #include "mbed_poll.h"
00025 #include "ip4string.h"
00026 #include "ip6string.h"
00027 #include "ppp_service.h"
00028 #include "ppp_impl.h"
00029 
00030 #if PPP_SUPPORT
00031 
00032 #define TRACE_GROUP "ppp_serv_if"
00033 
00034 typedef void (*ppp_sys_timeout_handler)(void *arg);
00035 
00036 // Number of timers running simultaneous
00037 #define PPP_TIMER_NUM            5
00038 // Number of simultaneous memory buffers
00039 #define PPP_PBUF_HANDLE_NUM      10
00040 
00041 typedef struct {
00042     ppp_service *ppp_drv;
00043     ppp_sys_timeout_handler handler;
00044     void *arg;
00045     int equeue_id;
00046     uint8_t id;
00047 } ppp_sys_timeout_t;
00048 
00049 static ppp_sys_timeout_t *timeout[PPP_TIMER_NUM];
00050 static SingletonPtr<PlatformMutex>  ppp_service_if_mutex;
00051 static uint8_t ppp_service_sys_timeout_id = 0;
00052 static pbuf pbuf_handles[PPP_PBUF_HANDLE_NUM];
00053 
00054 #if PPP_TRACE_ENABLE
00055 #define OUTPUT_BUFFER           0
00056 #define INPUT_BUFFER            1
00057 
00058 #define BUFFER_SIZE             5000
00059 
00060 typedef struct  {
00061     char buffer[BUFFER_SIZE];
00062     int buffer_index = 0;
00063     int line_len = 0;
00064 } trace_buf_t;
00065 
00066 static trace_buf_t output_trace_buffer;
00067 static trace_buf_t input_trace_buffer;
00068 
00069 #if PPP_TRACE_BUFFER_SIZE > 0
00070 static char cont_trace_buffer[PPP_TRACE_BUFFER_SIZE];
00071 static int cont_trace_buffer_index = 0;
00072 #endif
00073 #endif
00074 
00075 #if BYTE_ORDER == LITTLE_ENDIAN
00076 #if !defined(ppp_htons)
00077 /**
00078  * Convert an u16_t from host- to network byte order.
00079  *
00080  * @param n u16_t in host byte order
00081  * @return n in network byte order
00082  */
00083 uint16_t ppp_htons(uint16_t n)
00084 {
00085     return PP_HTONS(n);
00086 }
00087 #endif /* ppp_htons */
00088 
00089 #if !defined(ppp_htonl)
00090 /**
00091  * Convert an u32_t from host- to network byte order.
00092  *
00093  * @param n u32_t in host byte order
00094  * @return n in network byte order
00095  */
00096 uint32_t ppp_htonl(uint32_t n)
00097 {
00098     return PP_HTONL(n);
00099 }
00100 #endif /* ppp_htonl */
00101 
00102 #endif /* BYTE_ORDER == LITTLE_ENDIAN */
00103 
00104 extern "C" {
00105 
00106     void ppp_ip4_addr_set(nsapi_addr_t *addr, uint32_t *src)
00107     {
00108         memset(addr->bytes, 0, NSAPI_IP_BYTES);
00109         memcpy(addr->bytes, src, 4);
00110         addr->version = NSAPI_IPv4 ;
00111     }
00112 
00113     struct netif *ppp_netif_add(struct netif *netif, void *state, netif_init_fn init)
00114     {
00115 #if PPP_IPV4_SUPPORT
00116         netif->output = NULL;
00117         netif->ipv4_up = false;
00118 #endif /* PPP_IPV4_SUPPORT */
00119 #if PPP_IPV6_SUPPORT
00120         netif->output_ip6 = NULL;
00121         netif->ipv6_up = false;
00122 #endif
00123         netif->mtu = 0;
00124         netif->input = NULL;
00125         netif->state = state;
00126 
00127         /* call user specified initialization function for netif */
00128         if (init(netif) != ERR_OK) {
00129             return NULL;
00130         }
00131 
00132         return netif;
00133     }
00134 
00135     err_t ppp_ip_input(struct pbuf *p, struct netif *inp)
00136     {
00137         ppp_service *ppp_service_ptr = static_cast<ppp_service *>(inp->service_ptr);
00138         void *buffer = ppp_memory_buffer_convert_from(p);
00139         ppp_service_ptr->link_input(static_cast<net_stack_mem_buf_t *>(buffer));
00140         return ERR_OK;
00141     }
00142 
00143     void ppp_set_link_up(struct netif *netif)
00144     {
00145         ppp_service *ppp_service_ptr = static_cast<ppp_service *>(netif->service_ptr);
00146         ppp_service_ptr->link_state(true);
00147     }
00148 
00149     void ppp_set_link_down(struct netif *netif)
00150     {
00151         ppp_service *ppp_service_ptr = static_cast<ppp_service *>(netif->service_ptr);
00152         ppp_service_ptr->link_state(false);
00153     }
00154 
00155     err_t ppp_call_callback(void *service_ptr, ppp_service_cb callback, void *arg)
00156     {
00157         ppp_service *ppp_service_ptr = static_cast<ppp_service *>(service_ptr);
00158 
00159         int unique_id = ppp_service_ptr->event_queue_get()->call(mbed::callback(callback, arg));
00160         if (unique_id == 0) {
00161             return ERR_MEM;
00162         }
00163 
00164         return ERR_OK;
00165     }
00166 
00167     pbuf *ppp_memory_buffer_allocate(void *memory_manager, uint16_t size, ppp_buf_type_e type)
00168     {
00169         ppp_service_if_mutex->lock();
00170 
00171         int8_t free_index = -1;
00172         for (int8_t index = 0; index < PPP_PBUF_HANDLE_NUM; index++) {
00173             if (pbuf_handles[index].buffer == NULL) {
00174                 free_index = index;
00175                 break;
00176             }
00177         }
00178 
00179         if (free_index < 0) {
00180             ppp_service_if_mutex->unlock();
00181             return NULL;
00182         }
00183 
00184         NetStackMemoryManager *mem_mngr = static_cast<NetStackMemoryManager *>(memory_manager);
00185 
00186         void *buffer;
00187         if (type == PPP_BUF_HEAP) {
00188             buffer = mem_mngr->alloc_heap(size, 0);
00189         } else {
00190             buffer = mem_mngr->alloc_pool(size, 0);
00191         }
00192 
00193         if (!buffer) {
00194             ppp_service_if_mutex->unlock();
00195             return NULL;
00196         }
00197 
00198         // Must be continuous buffer from pool on alloc
00199         if (mem_mngr->get_next(buffer) != NULL) {
00200             mem_mngr->free(buffer);
00201             ppp_service_if_mutex->unlock();
00202             return NULL;
00203         }
00204 
00205         pbuf_handles[free_index].next = NULL;
00206         pbuf_handles[free_index].buffer = buffer;
00207         pbuf_handles[free_index].memory_manager = memory_manager;
00208         pbuf_handles[free_index].payload = static_cast<uint8_t *>(mem_mngr->get_ptr(buffer));
00209         pbuf_handles[free_index].len = size;
00210         pbuf_handles[free_index].tot_len = size;
00211         pbuf_handles[free_index].payload_start = pbuf_handles[free_index].payload;
00212 
00213         ppp_service_if_mutex->unlock();
00214 
00215         return &pbuf_handles[free_index];
00216     }
00217 
00218     void ppp_memory_buffer_free(pbuf *buffer)
00219     {
00220         ppp_service_if_mutex->lock();
00221 
00222         int8_t buffer_index = -1;
00223         for (int8_t index = 0; index < PPP_PBUF_HANDLE_NUM; index++) {
00224             if (&pbuf_handles[index] == buffer) {
00225                 buffer_index = index;
00226                 break;
00227             }
00228         }
00229 
00230         if (buffer_index < 0) {
00231             ppp_service_if_mutex->unlock();
00232             return;
00233         }
00234 
00235         if (pbuf_handles[buffer_index].buffer != NULL) {
00236             NetStackMemoryManager *mem_mngr = static_cast<NetStackMemoryManager *>(pbuf_handles[buffer_index].memory_manager);
00237             mem_mngr->free(pbuf_handles[buffer_index].buffer);
00238         }
00239 
00240         memset(&pbuf_handles[buffer_index], 0, sizeof(pbuf));
00241 
00242         ppp_service_if_mutex->unlock();
00243     }
00244 
00245     uint16_t ppp_memory_buffer_pool_alloc_unit_get(void *memory_manager)
00246     {
00247         NetStackMemoryManager *mem_mngr = static_cast<NetStackMemoryManager *>(memory_manager);
00248         return mem_mngr->get_pool_alloc_unit(0);
00249     }
00250 
00251     void ppp_memory_buffer_cat(void *memory_manager, pbuf *to_buf, pbuf *cat_buf)
00252     {
00253         for (struct pbuf *buf = to_buf; buf != NULL; buf = buf->next) {
00254             if (buf->next == NULL) {
00255                 buf->next = cat_buf;
00256                 break;
00257             }
00258         }
00259     }
00260 
00261     void ppp_memory_buffer_set_len(void *memory_manager, pbuf *buf, uint16_t len)
00262     {
00263         NetStackMemoryManager *mem_mngr = static_cast<NetStackMemoryManager *>(memory_manager);
00264         mem_mngr->set_len(buf->buffer, len);
00265     }
00266 
00267     struct pbuf *ppp_memory_buffer_convert_to(void *memory_manager, net_stack_mem_buf_t *mem_buf)
00268     {
00269         ppp_service_if_mutex->lock();
00270 
00271         int8_t free_index = -1;
00272         for (int8_t index = 0; index < PPP_PBUF_HANDLE_NUM; index++) {
00273             if (pbuf_handles[index].buffer == NULL) {
00274                 free_index = index;
00275                 break;
00276             }
00277         }
00278 
00279         if (free_index < 0) {
00280             ppp_service_if_mutex->unlock();
00281             return NULL;
00282         }
00283 
00284         NetStackMemoryManager *mem_mngr = static_cast<NetStackMemoryManager *>(memory_manager);
00285 
00286         pbuf_handles[free_index].buffer = mem_buf;
00287         pbuf_handles[free_index].memory_manager = memory_manager;
00288         pbuf_handles[free_index].payload = mem_mngr->get_ptr(mem_buf);
00289         pbuf_handles[free_index].len = mem_mngr->get_len(mem_buf);
00290         pbuf_handles[free_index].tot_len =  mem_mngr->get_total_len(mem_buf);
00291         pbuf_handles[free_index].payload_start = pbuf_handles[free_index].payload;
00292 
00293         ppp_service_if_mutex->unlock();
00294 
00295         return &pbuf_handles[free_index];
00296     }
00297 
00298     net_stack_mem_buf_t *ppp_memory_buffer_convert_from(struct pbuf *p)
00299     {
00300         NetStackMemoryManager *mem_mngr = static_cast<NetStackMemoryManager *>(p->memory_manager);
00301 
00302         net_stack_mem_buf_t *first_buffer = p->buffer;
00303 
00304         struct pbuf *buf_next;
00305         for (struct pbuf *buf = p; buf != NULL; buf = buf_next) {
00306 
00307             // Set actual memory buffer length
00308             mem_mngr->set_len(buf->buffer, buf->len);
00309 
00310             // Trim the headroom away from buffer if set
00311             if (buf->payload_start < buf->payload) {
00312                 memmove(buf->payload_start, buf->payload, buf->len);
00313             }
00314 
00315             buf_next = buf->next;
00316 
00317             // If not first buffer cat to first buffer and free
00318             if (buf->buffer != first_buffer) {
00319                 mem_mngr->cat(first_buffer, buf->buffer);
00320                 buf->buffer = NULL;
00321                 ppp_memory_buffer_free(buf);
00322             }
00323         }
00324 
00325         // Going to upper levels, do not deallocate the actual buffer
00326         p->buffer = NULL;
00327         ppp_memory_buffer_free(p);
00328 
00329         return first_buffer;
00330     }
00331 
00332     uint8_t ppp_memory_buffer_remove_header(pbuf *buffer, uint16_t header_len)
00333     {
00334         uint8_t *payload = static_cast<uint8_t *>(buffer->payload);
00335         payload += header_len;
00336         buffer->payload = payload;
00337         buffer->len -= header_len;
00338         return 0;
00339     }
00340 
00341     uint8_t ppp_memory_buffer_add_header(struct pbuf *buffer, uint16_t header_len)
00342     {
00343         uint32_t payload_headroom_len = static_cast<uint8_t *>(buffer->payload) - static_cast<uint8_t *>(buffer->payload_start);
00344 
00345         if (payload_headroom_len < header_len) {
00346             return 1; // failure
00347         }
00348 
00349         buffer->payload = static_cast<uint8_t *>(buffer->payload) - header_len;
00350         buffer->len += header_len;
00351 
00352         return 0;
00353     }
00354 
00355     uint32_t ppp_sys_now(void)
00356     {
00357         return osKernelGetTickCount();
00358     }
00359 
00360     uint32_t ppp_sys_jiffies(void)
00361     {
00362         return ppp_sys_now();
00363     }
00364 
00365     sys_prot_t ppp_sys_arch_protect(void *service_ptr)
00366     {
00367         ppp_service *ppp_service_ptr = static_cast<ppp_service *>(service_ptr);
00368         ppp_service_ptr->resource_lock();
00369 
00370         return (sys_prot_t) 1;
00371     }
00372 
00373     void ppp_sys_arch_unprotect(void *service_ptr, sys_prot_t p)
00374     {
00375         ppp_service *ppp_service_ptr = static_cast<ppp_service *>(service_ptr);
00376         ppp_service_ptr->resource_unlock();
00377     }
00378 
00379 #if PPP_TRACE_ENABLE
00380     void ppp_trace_to_ascii_hex_dump(int buffer, int len, char *data)
00381     {
00382         char prefix[10];
00383         trace_buf_t *trace_buffer = NULL;
00384         if (buffer == OUTPUT_BUFFER) {
00385             strcpy(prefix, "O:");
00386             trace_buffer = &output_trace_buffer;
00387         } else if (buffer == INPUT_BUFFER) {
00388             strcpy(prefix, "I:");
00389             trace_buffer = &input_trace_buffer;
00390         }
00391 
00392         static char line[100];
00393         memset(line, 0, 100);
00394         int index = 0;
00395 
00396         bool add_prefix = false;
00397         if (trace_buffer->buffer_index == 0) {
00398             index += sprintf(&line[index], "\n %" PRIi32 " len: %i buffer index %i line len %i \n", ppp_sys_now(), len, trace_buffer->buffer_index, trace_buffer->line_len);
00399             add_prefix = true;
00400         }
00401 
00402         for (int i = 0; i < len; i++) {
00403             if ((trace_buffer->line_len % 16) == 0) {
00404                 if (trace_buffer->line_len != 0) {
00405                     index += sprintf(&line[index], "\n");
00406                     trace_buffer->buffer_index += sprintf(&trace_buffer->buffer[trace_buffer->buffer_index], "%s", line);
00407                     index = 0;
00408                 }
00409 
00410                 bool add_ppp_flag = false;
00411                 if (add_prefix) {
00412                     if (data[i] == 0xff || (data[i] == 0x57 && (data[i + 1] == 0x60 || data[i + 1] == 0x6a))) {
00413                         add_ppp_flag = true;
00414                     }
00415                 }
00416 
00417                 index += sprintf(&line[index], "%s %06x%s%s", prefix, trace_buffer->line_len, add_prefix ? " 00 00 88 81" : "", add_ppp_flag ? " 7e" : "");
00418                 if (add_prefix) {
00419                     trace_buffer->line_len += 4;
00420                 }
00421                 if (add_ppp_flag) {
00422                     trace_buffer->line_len += 1;
00423                 }
00424                 add_prefix = false;
00425             }
00426             trace_buffer->line_len++;
00427             index += sprintf(&line[index], " %02x", data[i]);
00428         }
00429 
00430         trace_buffer->buffer_index += sprintf(&trace_buffer->buffer[trace_buffer->buffer_index], "%s", line);
00431     }
00432 
00433     void ppp_trace_to_ascii_hex_dump_print(int buffer)
00434     {
00435         trace_buf_t *trace_buffer = NULL;
00436         if (buffer == OUTPUT_BUFFER) {
00437             trace_buffer = &output_trace_buffer;
00438         } else if (buffer == INPUT_BUFFER) {
00439             trace_buffer = &input_trace_buffer;
00440         }
00441 
00442 #if PPP_TRACE_BUFFER_SIZE == 0
00443         tr_info("%s", trace_buffer->buffer);
00444 #endif
00445 
00446 #if PPP_TRACE_BUFFER_SIZE > 0
00447         cont_trace_buffer_index += sprintf(&cont_trace_buffer[cont_trace_buffer_index], "%s", trace_buffer->buffer);
00448         memset(trace_buffer->buffer, 0, BUFFER_SIZE);
00449 
00450         if (cont_trace_buffer_index > (PPP_TRACE_BUFFER_SIZE - PPP_TRACE_BUFFER_SIZE / 5)) {
00451             cont_trace_buffer_index = 0;
00452         }
00453 #endif
00454 
00455         trace_buffer->buffer_index = 0;
00456         trace_buffer->line_len = 0;
00457     }
00458 
00459 #endif
00460 
00461     void ppp_sys_timeout_callback(void *cb_ptr)
00462     {
00463         ppp_service_if_mutex->lock();
00464 
00465         int id = reinterpret_cast<int>(cb_ptr);
00466 
00467         ppp_sys_timeout_handler handler = NULL;
00468         void *arg = NULL;
00469 
00470         for (int8_t i = 0; i < PPP_TIMER_NUM; i++) {
00471             if (timeout[i] && timeout[i]->id == id) {
00472                 handler = timeout[i]->handler;
00473                 arg = timeout[i]->arg;
00474                 free(timeout[i]);
00475                 timeout[i] = NULL;
00476                 //tr_info("sys timer timeout, i: %i h/a: %p %p, id: %i", i, handler, arg, timeout[i]->equeue_id);
00477             }
00478         }
00479 
00480         ppp_service_if_mutex->unlock();
00481 
00482         if (handler) {
00483             handler(arg);
00484         } else {
00485             tr_error("Cancelled timeout");
00486         }
00487     }
00488 
00489     void ppp_sys_timeout(void *service_ptr, u32_t msecs, ppp_sys_timeout_handler handler, void *arg)
00490     {
00491         ppp_service *ppp_service_ptr = static_cast<ppp_service *>(service_ptr);
00492 
00493         ppp_service_if_mutex->lock();
00494 
00495         int8_t free_index = -1;
00496 
00497         for (int8_t i = 0; i < PPP_TIMER_NUM; i++) {
00498             if (timeout[i] == NULL && free_index < 0) {
00499                 free_index = i;
00500             } else if (timeout[i] != NULL && timeout[i]->handler == handler && timeout[i]->arg == arg) {
00501                 tr_error("Timeout already set");
00502                 ppp_service_if_mutex->unlock();
00503                 return;
00504             }
00505         }
00506 
00507         if (free_index < 0) {
00508             tr_error("No free timeouts");
00509             ppp_service_if_mutex->unlock();
00510         }
00511 
00512         timeout[free_index] = static_cast<ppp_sys_timeout_t *>(malloc(sizeof(ppp_sys_timeout_t)));
00513         if (!timeout[free_index]) {
00514             tr_error("No free memory for timeout");
00515             ppp_service_if_mutex->unlock();
00516             return;
00517         }
00518 
00519         void *cb_ptr = reinterpret_cast<void *>(ppp_service_sys_timeout_id);
00520         int unique_id = ppp_service_ptr->event_queue_get()->call_in(msecs, mbed::callback(ppp_sys_timeout_callback, cb_ptr));
00521         if (unique_id == 0) {
00522             tr_error("No free memory for timeout equeue");
00523             ppp_service_if_mutex->unlock();
00524             return;
00525         }
00526 
00527         timeout[free_index]->ppp_drv = ppp_service_ptr;
00528         timeout[free_index]->handler = handler;
00529         timeout[free_index]->arg = arg;
00530         timeout[free_index]->equeue_id = unique_id;
00531         timeout[free_index]->id = ppp_service_sys_timeout_id++;
00532 
00533         //tr_info("sys timer start, i: %i h/a: %p %p, t: %" PRIx32 " id: %i", free_index, handler, arg, msecs, unique_id);
00534 
00535         ppp_service_if_mutex->unlock();
00536     }
00537 
00538     void ppp_sys_untimeout(ppp_sys_timeout_handler handler, void *arg)
00539     {
00540         ppp_service_if_mutex->lock();
00541 
00542         for (int8_t i = 0; i < PPP_TIMER_NUM; i++) {
00543             if (timeout[i] != NULL && timeout[i]->handler == handler && timeout[i]->arg == arg) {
00544                 int unique_id = timeout[i]->equeue_id;
00545                 timeout[i]->ppp_drv->event_queue_get()->cancel(unique_id);
00546                 //tr_info("sys timer cancel, i: %i h/a: %p %p, id: %i", i, timeout[i]->handler, timeout[i]->arg, unique_id);
00547                 free(timeout[i]);
00548                 timeout[i] = NULL;
00549             }
00550         }
00551 
00552         ppp_service_if_mutex->unlock();
00553     }
00554 
00555 } // extern "C"
00556 
00557 #if PPP_TRACE_ENABLE && PPP_TRACE_BUFFER_SIZE > 0
00558 void ppp_trace_to_ascii_hex_dump_print_final(void)
00559 {
00560     int start_i = 0;
00561 
00562     for (int i = 0; i < PPP_TRACE_BUFFER_SIZE; i++) {
00563         if (cont_trace_buffer[i] == '\n' || cont_trace_buffer[i] == '\0') {
00564             memcpy(output_trace_buffer.buffer, &cont_trace_buffer[start_i], i - start_i);
00565             output_trace_buffer.buffer[i - start_i] = 0;
00566 
00567             tr_info("%s", output_trace_buffer.buffer);
00568 
00569             if (cont_trace_buffer[i] == '\0') {
00570                 break;
00571             }
00572 
00573             start_i = i + 1;
00574         }
00575     }
00576 }
00577 #endif
00578 
00579 #endif