takashi kadono / Mbed OS Nucleo446_SSD1331

Dependencies:   ssd1331

Committer:
kadonotakashi
Date:
Wed Oct 10 00:33:53 2018 +0000
Revision:
0:8fdf9a60065b
how to make mbed librry

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kadonotakashi 0:8fdf9a60065b 1 /* mbed Microcontroller Library
kadonotakashi 0:8fdf9a60065b 2 * Copyright (c) 2016 ARM Limited
kadonotakashi 0:8fdf9a60065b 3 *
kadonotakashi 0:8fdf9a60065b 4 * Licensed under the Apache License, Version 2.0 (the "License");
kadonotakashi 0:8fdf9a60065b 5 * you may not use this file except in compliance with the License.
kadonotakashi 0:8fdf9a60065b 6 * You may obtain a copy of the License at
kadonotakashi 0:8fdf9a60065b 7 *
kadonotakashi 0:8fdf9a60065b 8 * http://www.apache.org/licenses/LICENSE-2.0
kadonotakashi 0:8fdf9a60065b 9 *
kadonotakashi 0:8fdf9a60065b 10 * Unless required by applicable law or agreed to in writing, software
kadonotakashi 0:8fdf9a60065b 11 * distributed under the License is distributed on an "AS IS" BASIS,
kadonotakashi 0:8fdf9a60065b 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
kadonotakashi 0:8fdf9a60065b 13 * See the License for the specific language governing permissions and
kadonotakashi 0:8fdf9a60065b 14 * limitations under the License.
kadonotakashi 0:8fdf9a60065b 15 */
kadonotakashi 0:8fdf9a60065b 16
kadonotakashi 0:8fdf9a60065b 17 #include <errno.h>
kadonotakashi 0:8fdf9a60065b 18 #include "platform/FileHandle.h"
kadonotakashi 0:8fdf9a60065b 19 #include "platform/mbed_poll.h"
kadonotakashi 0:8fdf9a60065b 20 #include "events/EventQueue.h"
kadonotakashi 0:8fdf9a60065b 21 #include "mbed_trace.h"
kadonotakashi 0:8fdf9a60065b 22 #define TRACE_GROUP "LPPP"
kadonotakashi 0:8fdf9a60065b 23 #include "rtos/Thread.h"
kadonotakashi 0:8fdf9a60065b 24 #include "lwip/tcpip.h"
kadonotakashi 0:8fdf9a60065b 25 #include "lwip/tcp.h"
kadonotakashi 0:8fdf9a60065b 26 #include "lwip/ip.h"
kadonotakashi 0:8fdf9a60065b 27 #include "lwip/dns.h"
kadonotakashi 0:8fdf9a60065b 28 #include "lwip/pbuf.h"
kadonotakashi 0:8fdf9a60065b 29 extern "C" { // "pppos.h" is missing extern C
kadonotakashi 0:8fdf9a60065b 30 #include "netif/ppp/pppapi.h"
kadonotakashi 0:8fdf9a60065b 31 }
kadonotakashi 0:8fdf9a60065b 32
kadonotakashi 0:8fdf9a60065b 33 #include "nsapi_ppp.h"
kadonotakashi 0:8fdf9a60065b 34 #include "ppp_lwip.h"
kadonotakashi 0:8fdf9a60065b 35 #include "LWIPStack.h"
kadonotakashi 0:8fdf9a60065b 36
kadonotakashi 0:8fdf9a60065b 37 namespace mbed {
kadonotakashi 0:8fdf9a60065b 38
kadonotakashi 0:8fdf9a60065b 39 using rtos::Thread;
kadonotakashi 0:8fdf9a60065b 40 using events::EventQueue;
kadonotakashi 0:8fdf9a60065b 41
kadonotakashi 0:8fdf9a60065b 42 #if LWIP_PPP_API
kadonotakashi 0:8fdf9a60065b 43
kadonotakashi 0:8fdf9a60065b 44 static EventQueue *event_queue;
kadonotakashi 0:8fdf9a60065b 45 static Thread *event_thread;
kadonotakashi 0:8fdf9a60065b 46 static volatile bool event_queued;
kadonotakashi 0:8fdf9a60065b 47 static nsapi_error_t connect_error_code;
kadonotakashi 0:8fdf9a60065b 48
kadonotakashi 0:8fdf9a60065b 49 // Just one interface for now
kadonotakashi 0:8fdf9a60065b 50 static FileHandle *my_stream;
kadonotakashi 0:8fdf9a60065b 51 static LWIP::Interface *my_interface;
kadonotakashi 0:8fdf9a60065b 52 static ppp_pcb *my_ppp_pcb;
kadonotakashi 0:8fdf9a60065b 53 static bool ppp_active = false;
kadonotakashi 0:8fdf9a60065b 54 static bool blocking_connect = true;
kadonotakashi 0:8fdf9a60065b 55 static const char *login;
kadonotakashi 0:8fdf9a60065b 56 static const char *pwd;
kadonotakashi 0:8fdf9a60065b 57 static sys_sem_t ppp_close_sem;
kadonotakashi 0:8fdf9a60065b 58 static Callback<void(nsapi_event_t, intptr_t)> connection_status_cb;
kadonotakashi 0:8fdf9a60065b 59
kadonotakashi 0:8fdf9a60065b 60 static EventQueue *prepare_event_queue()
kadonotakashi 0:8fdf9a60065b 61 {
kadonotakashi 0:8fdf9a60065b 62 if (event_queue) {
kadonotakashi 0:8fdf9a60065b 63 return event_queue;
kadonotakashi 0:8fdf9a60065b 64 }
kadonotakashi 0:8fdf9a60065b 65
kadonotakashi 0:8fdf9a60065b 66 // Should be trying to get a global shared event queue here!
kadonotakashi 0:8fdf9a60065b 67 // Shouldn't have to be making a private thread!
kadonotakashi 0:8fdf9a60065b 68
kadonotakashi 0:8fdf9a60065b 69 // Only need to queue 2 events. new blows on failure.
kadonotakashi 0:8fdf9a60065b 70 event_queue = new EventQueue(2 * EVENTS_EVENT_SIZE, NULL);
kadonotakashi 0:8fdf9a60065b 71 event_thread = new Thread(osPriorityNormal, PPP_THREAD_STACK_SIZE);
kadonotakashi 0:8fdf9a60065b 72
kadonotakashi 0:8fdf9a60065b 73 if (event_thread->start(callback(event_queue, &EventQueue::dispatch_forever)) != osOK) {
kadonotakashi 0:8fdf9a60065b 74 delete event_thread;
kadonotakashi 0:8fdf9a60065b 75 delete event_queue;
kadonotakashi 0:8fdf9a60065b 76 return NULL;
kadonotakashi 0:8fdf9a60065b 77 }
kadonotakashi 0:8fdf9a60065b 78
kadonotakashi 0:8fdf9a60065b 79 return event_queue;
kadonotakashi 0:8fdf9a60065b 80 }
kadonotakashi 0:8fdf9a60065b 81
kadonotakashi 0:8fdf9a60065b 82 static u32_t ppp_output(ppp_pcb *pcb, u8_t *data, u32_t len, void *ctx)
kadonotakashi 0:8fdf9a60065b 83 {
kadonotakashi 0:8fdf9a60065b 84 FileHandle *stream = my_stream;
kadonotakashi 0:8fdf9a60065b 85 if (!stream) {
kadonotakashi 0:8fdf9a60065b 86 return 0;
kadonotakashi 0:8fdf9a60065b 87 }
kadonotakashi 0:8fdf9a60065b 88
kadonotakashi 0:8fdf9a60065b 89 pollfh fhs;
kadonotakashi 0:8fdf9a60065b 90 fhs.fh = stream;
kadonotakashi 0:8fdf9a60065b 91 fhs.events = POLLOUT;
kadonotakashi 0:8fdf9a60065b 92
kadonotakashi 0:8fdf9a60065b 93 // LWIP expects us to block on write
kadonotakashi 0:8fdf9a60065b 94 // File handle will be in non-blocking mode, because of read events.
kadonotakashi 0:8fdf9a60065b 95 // Therefore must use poll to achieve the necessary block for writing.
kadonotakashi 0:8fdf9a60065b 96
kadonotakashi 0:8fdf9a60065b 97 uint32_t written = 0;
kadonotakashi 0:8fdf9a60065b 98 while (len != 0) {
kadonotakashi 0:8fdf9a60065b 99 // Block forever until we're selected - don't care about reason we wake;
kadonotakashi 0:8fdf9a60065b 100 // return from write should tell us what's up.
kadonotakashi 0:8fdf9a60065b 101 poll(&fhs, 1, -1);
kadonotakashi 0:8fdf9a60065b 102 // This write will be non-blocking, but blocking would be fine.
kadonotakashi 0:8fdf9a60065b 103 ssize_t ret = stream->write(data, len);
kadonotakashi 0:8fdf9a60065b 104 if (ret == -EAGAIN) {
kadonotakashi 0:8fdf9a60065b 105 continue;
kadonotakashi 0:8fdf9a60065b 106 } else if (ret < 0) {
kadonotakashi 0:8fdf9a60065b 107 break;
kadonotakashi 0:8fdf9a60065b 108 }
kadonotakashi 0:8fdf9a60065b 109 written += ret;
kadonotakashi 0:8fdf9a60065b 110 data += ret;
kadonotakashi 0:8fdf9a60065b 111 len -= ret;
kadonotakashi 0:8fdf9a60065b 112 }
kadonotakashi 0:8fdf9a60065b 113
kadonotakashi 0:8fdf9a60065b 114 // /tr_debug("> %ld bytes of data written\n", (long) written);
kadonotakashi 0:8fdf9a60065b 115
kadonotakashi 0:8fdf9a60065b 116 return written;
kadonotakashi 0:8fdf9a60065b 117 }
kadonotakashi 0:8fdf9a60065b 118
kadonotakashi 0:8fdf9a60065b 119 static void ppp_link_status(ppp_pcb *pcb, int err_code, void *ctx)
kadonotakashi 0:8fdf9a60065b 120 {
kadonotakashi 0:8fdf9a60065b 121 nsapi_error_t mapped_err_code = NSAPI_ERROR_NO_CONNECTION;
kadonotakashi 0:8fdf9a60065b 122
kadonotakashi 0:8fdf9a60065b 123 switch(err_code) {
kadonotakashi 0:8fdf9a60065b 124 case PPPERR_NONE:
kadonotakashi 0:8fdf9a60065b 125 mapped_err_code = NSAPI_ERROR_OK;
kadonotakashi 0:8fdf9a60065b 126 tr_info("status_cb: Connected");
kadonotakashi 0:8fdf9a60065b 127 #if PPP_IPV4_SUPPORT
kadonotakashi 0:8fdf9a60065b 128 tr_debug(" our_ipaddr = %s", ipaddr_ntoa(&ppp_netif(pcb)->ip_addr));
kadonotakashi 0:8fdf9a60065b 129 tr_debug(" his_ipaddr = %s", ipaddr_ntoa(&ppp_netif(pcb)->gw));
kadonotakashi 0:8fdf9a60065b 130 tr_debug(" netmask = %s", ipaddr_ntoa(&ppp_netif(pcb)->netmask));
kadonotakashi 0:8fdf9a60065b 131 #if LWIP_DNS
kadonotakashi 0:8fdf9a60065b 132 const ip_addr_t *ns;
kadonotakashi 0:8fdf9a60065b 133 ns = dns_getserver(0);
kadonotakashi 0:8fdf9a60065b 134 if (ns) {
kadonotakashi 0:8fdf9a60065b 135 tr_debug(" dns1 = %s", ipaddr_ntoa(ns));
kadonotakashi 0:8fdf9a60065b 136 }
kadonotakashi 0:8fdf9a60065b 137 ns = dns_getserver(1);
kadonotakashi 0:8fdf9a60065b 138 if (ns) {
kadonotakashi 0:8fdf9a60065b 139 tr_debug(" dns2 = %s", ipaddr_ntoa(ns));
kadonotakashi 0:8fdf9a60065b 140 }
kadonotakashi 0:8fdf9a60065b 141 #endif /* LWIP_DNS */
kadonotakashi 0:8fdf9a60065b 142 #endif /* PPP_IPV4_SUPPORT */
kadonotakashi 0:8fdf9a60065b 143 #if PPP_IPV6_SUPPORT
kadonotakashi 0:8fdf9a60065b 144 tr_debug(" our6_ipaddr = %s", ip6addr_ntoa(netif_ip6_addr(ppp_netif(pcb), 0)));
kadonotakashi 0:8fdf9a60065b 145 #endif /* PPP_IPV6_SUPPORT */
kadonotakashi 0:8fdf9a60065b 146 break;
kadonotakashi 0:8fdf9a60065b 147
kadonotakashi 0:8fdf9a60065b 148 case PPPERR_PARAM:
kadonotakashi 0:8fdf9a60065b 149 tr_info("status_cb: Invalid parameter");
kadonotakashi 0:8fdf9a60065b 150 break;
kadonotakashi 0:8fdf9a60065b 151
kadonotakashi 0:8fdf9a60065b 152 case PPPERR_OPEN:
kadonotakashi 0:8fdf9a60065b 153 tr_info("status_cb: Unable to open PPP session");
kadonotakashi 0:8fdf9a60065b 154 break;
kadonotakashi 0:8fdf9a60065b 155
kadonotakashi 0:8fdf9a60065b 156 case PPPERR_DEVICE:
kadonotakashi 0:8fdf9a60065b 157 tr_info("status_cb: Invalid I/O device for PPP");
kadonotakashi 0:8fdf9a60065b 158 break;
kadonotakashi 0:8fdf9a60065b 159
kadonotakashi 0:8fdf9a60065b 160 case PPPERR_ALLOC:
kadonotakashi 0:8fdf9a60065b 161 tr_info("status_cb: Unable to allocate resources");
kadonotakashi 0:8fdf9a60065b 162 break;
kadonotakashi 0:8fdf9a60065b 163
kadonotakashi 0:8fdf9a60065b 164 case PPPERR_USER:
kadonotakashi 0:8fdf9a60065b 165 tr_info("status_cb: User interrupt");
kadonotakashi 0:8fdf9a60065b 166 break;
kadonotakashi 0:8fdf9a60065b 167
kadonotakashi 0:8fdf9a60065b 168 case PPPERR_CONNECT:
kadonotakashi 0:8fdf9a60065b 169 tr_info("status_cb: Connection lost");
kadonotakashi 0:8fdf9a60065b 170 mapped_err_code = NSAPI_ERROR_CONNECTION_LOST;
kadonotakashi 0:8fdf9a60065b 171 break;
kadonotakashi 0:8fdf9a60065b 172
kadonotakashi 0:8fdf9a60065b 173 case PPPERR_AUTHFAIL:
kadonotakashi 0:8fdf9a60065b 174 tr_info("status_cb: Failed authentication challenge");
kadonotakashi 0:8fdf9a60065b 175 mapped_err_code = NSAPI_ERROR_AUTH_FAILURE;
kadonotakashi 0:8fdf9a60065b 176 break;
kadonotakashi 0:8fdf9a60065b 177
kadonotakashi 0:8fdf9a60065b 178 case PPPERR_PROTOCOL:
kadonotakashi 0:8fdf9a60065b 179 tr_info("status_cb: Failed to meet protocol");
kadonotakashi 0:8fdf9a60065b 180 break;
kadonotakashi 0:8fdf9a60065b 181
kadonotakashi 0:8fdf9a60065b 182 case PPPERR_PEERDEAD:
kadonotakashi 0:8fdf9a60065b 183 tr_info("status_cb: Connection timeout");
kadonotakashi 0:8fdf9a60065b 184 mapped_err_code = NSAPI_ERROR_CONNECTION_TIMEOUT;
kadonotakashi 0:8fdf9a60065b 185 break;
kadonotakashi 0:8fdf9a60065b 186
kadonotakashi 0:8fdf9a60065b 187 case PPPERR_IDLETIMEOUT:
kadonotakashi 0:8fdf9a60065b 188 tr_info("status_cb: Idle Timeout");
kadonotakashi 0:8fdf9a60065b 189 break;
kadonotakashi 0:8fdf9a60065b 190
kadonotakashi 0:8fdf9a60065b 191 case PPPERR_CONNECTTIME:
kadonotakashi 0:8fdf9a60065b 192 tr_info("status_cb: Max connect time reached");
kadonotakashi 0:8fdf9a60065b 193 break;
kadonotakashi 0:8fdf9a60065b 194
kadonotakashi 0:8fdf9a60065b 195 case PPPERR_LOOPBACK:
kadonotakashi 0:8fdf9a60065b 196 tr_info("status_cb: Loopback detected");
kadonotakashi 0:8fdf9a60065b 197 break;
kadonotakashi 0:8fdf9a60065b 198
kadonotakashi 0:8fdf9a60065b 199 default:
kadonotakashi 0:8fdf9a60065b 200 tr_info("status_cb: Unknown error code %d", err_code);
kadonotakashi 0:8fdf9a60065b 201 break;
kadonotakashi 0:8fdf9a60065b 202
kadonotakashi 0:8fdf9a60065b 203 }
kadonotakashi 0:8fdf9a60065b 204
kadonotakashi 0:8fdf9a60065b 205 if (err_code == PPPERR_NONE) {
kadonotakashi 0:8fdf9a60065b 206 /* status changes have to be reported */
kadonotakashi 0:8fdf9a60065b 207 if (connection_status_cb) {
kadonotakashi 0:8fdf9a60065b 208 connection_status_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_GLOBAL_UP);
kadonotakashi 0:8fdf9a60065b 209 }
kadonotakashi 0:8fdf9a60065b 210 return;
kadonotakashi 0:8fdf9a60065b 211 }
kadonotakashi 0:8fdf9a60065b 212
kadonotakashi 0:8fdf9a60065b 213 /* If some error happened, we need to properly shutdown the PPP interface */
kadonotakashi 0:8fdf9a60065b 214 if (ppp_active) {
kadonotakashi 0:8fdf9a60065b 215 ppp_active = false;
kadonotakashi 0:8fdf9a60065b 216 connect_error_code = mapped_err_code;
kadonotakashi 0:8fdf9a60065b 217 sys_sem_signal(&ppp_close_sem);
kadonotakashi 0:8fdf9a60065b 218 }
kadonotakashi 0:8fdf9a60065b 219
kadonotakashi 0:8fdf9a60065b 220 /* Alright, PPP interface is down, we need to notify upper layer */
kadonotakashi 0:8fdf9a60065b 221 if (connection_status_cb) {
kadonotakashi 0:8fdf9a60065b 222 connection_status_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_DISCONNECTED);
kadonotakashi 0:8fdf9a60065b 223 }
kadonotakashi 0:8fdf9a60065b 224 }
kadonotakashi 0:8fdf9a60065b 225
kadonotakashi 0:8fdf9a60065b 226 static void handle_modem_hangup()
kadonotakashi 0:8fdf9a60065b 227 {
kadonotakashi 0:8fdf9a60065b 228 if (my_ppp_pcb->phase != PPP_PHASE_DEAD) {
kadonotakashi 0:8fdf9a60065b 229 ppp_close(my_ppp_pcb, 1);
kadonotakashi 0:8fdf9a60065b 230 }
kadonotakashi 0:8fdf9a60065b 231 }
kadonotakashi 0:8fdf9a60065b 232
kadonotakashi 0:8fdf9a60065b 233 #if !PPP_INPROC_IRQ_SAFE
kadonotakashi 0:8fdf9a60065b 234 #error "PPP_INPROC_IRQ_SAFE must be enabled"
kadonotakashi 0:8fdf9a60065b 235 #endif
kadonotakashi 0:8fdf9a60065b 236 static void ppp_input()
kadonotakashi 0:8fdf9a60065b 237 {
kadonotakashi 0:8fdf9a60065b 238 // Allow new events from now, avoiding potential races around the read
kadonotakashi 0:8fdf9a60065b 239 event_queued = false;
kadonotakashi 0:8fdf9a60065b 240
kadonotakashi 0:8fdf9a60065b 241 if (!my_stream) {
kadonotakashi 0:8fdf9a60065b 242 return;
kadonotakashi 0:8fdf9a60065b 243 }
kadonotakashi 0:8fdf9a60065b 244
kadonotakashi 0:8fdf9a60065b 245 // Non-blocking error check handler
kadonotakashi 0:8fdf9a60065b 246 pollfh fhs;
kadonotakashi 0:8fdf9a60065b 247 fhs.fh = my_stream;
kadonotakashi 0:8fdf9a60065b 248 fhs.events = POLLIN;
kadonotakashi 0:8fdf9a60065b 249 poll(&fhs, 1, 0);
kadonotakashi 0:8fdf9a60065b 250 if (fhs.revents & (POLLHUP|POLLERR|POLLNVAL)) {
kadonotakashi 0:8fdf9a60065b 251 handle_modem_hangup();
kadonotakashi 0:8fdf9a60065b 252 return;
kadonotakashi 0:8fdf9a60065b 253 }
kadonotakashi 0:8fdf9a60065b 254
kadonotakashi 0:8fdf9a60065b 255 // Infinite loop, but we assume that we can read faster than the
kadonotakashi 0:8fdf9a60065b 256 // serial, so we will fairly rapidly hit -EAGAIN.
kadonotakashi 0:8fdf9a60065b 257 for (;;) {
kadonotakashi 0:8fdf9a60065b 258 u8_t buffer[16];
kadonotakashi 0:8fdf9a60065b 259 ssize_t len = my_stream->read(buffer, sizeof buffer);
kadonotakashi 0:8fdf9a60065b 260 if (len == -EAGAIN) {
kadonotakashi 0:8fdf9a60065b 261 break;
kadonotakashi 0:8fdf9a60065b 262 } else if (len <= 0) {
kadonotakashi 0:8fdf9a60065b 263 handle_modem_hangup();
kadonotakashi 0:8fdf9a60065b 264 return;
kadonotakashi 0:8fdf9a60065b 265 }
kadonotakashi 0:8fdf9a60065b 266 pppos_input(my_ppp_pcb, buffer, len);
kadonotakashi 0:8fdf9a60065b 267 }
kadonotakashi 0:8fdf9a60065b 268 return;
kadonotakashi 0:8fdf9a60065b 269 }
kadonotakashi 0:8fdf9a60065b 270
kadonotakashi 0:8fdf9a60065b 271 static void stream_cb() {
kadonotakashi 0:8fdf9a60065b 272 if (my_stream && !event_queued) {
kadonotakashi 0:8fdf9a60065b 273 event_queued = true;
kadonotakashi 0:8fdf9a60065b 274 if (event_queue->call(callback(ppp_input)) == 0) {
kadonotakashi 0:8fdf9a60065b 275 event_queued = false;
kadonotakashi 0:8fdf9a60065b 276 }
kadonotakashi 0:8fdf9a60065b 277 }
kadonotakashi 0:8fdf9a60065b 278 }
kadonotakashi 0:8fdf9a60065b 279
kadonotakashi 0:8fdf9a60065b 280 extern "C" err_t ppp_lwip_connect(void *pcb)
kadonotakashi 0:8fdf9a60065b 281 {
kadonotakashi 0:8fdf9a60065b 282 #if PPP_AUTH_SUPPORT
kadonotakashi 0:8fdf9a60065b 283 ppp_set_auth(my_ppp_pcb, PPPAUTHTYPE_ANY, login, pwd);
kadonotakashi 0:8fdf9a60065b 284 #endif //PPP_AUTH_SUPPORT
kadonotakashi 0:8fdf9a60065b 285 ppp_active = true;
kadonotakashi 0:8fdf9a60065b 286 err_t ret = ppp_connect(my_ppp_pcb, 0);
kadonotakashi 0:8fdf9a60065b 287 // lwIP's ppp.txt says input must not be called until after connect
kadonotakashi 0:8fdf9a60065b 288 if (ret == ERR_OK) {
kadonotakashi 0:8fdf9a60065b 289 my_stream->sigio(callback(stream_cb));
kadonotakashi 0:8fdf9a60065b 290 } else {
kadonotakashi 0:8fdf9a60065b 291 ppp_active = false;
kadonotakashi 0:8fdf9a60065b 292 }
kadonotakashi 0:8fdf9a60065b 293 return ret;
kadonotakashi 0:8fdf9a60065b 294 }
kadonotakashi 0:8fdf9a60065b 295
kadonotakashi 0:8fdf9a60065b 296 extern "C" err_t ppp_lwip_disconnect(void *pcb)
kadonotakashi 0:8fdf9a60065b 297 {
kadonotakashi 0:8fdf9a60065b 298 err_t ret = ERR_OK;
kadonotakashi 0:8fdf9a60065b 299 if (ppp_active) {
kadonotakashi 0:8fdf9a60065b 300 ret = ppp_close(my_ppp_pcb, 0);
kadonotakashi 0:8fdf9a60065b 301 if (ret == ERR_OK) {
kadonotakashi 0:8fdf9a60065b 302 /* close call made, now let's catch the response in the status callback */
kadonotakashi 0:8fdf9a60065b 303 sys_arch_sem_wait(&ppp_close_sem, 0);
kadonotakashi 0:8fdf9a60065b 304 }
kadonotakashi 0:8fdf9a60065b 305 ppp_active = false;
kadonotakashi 0:8fdf9a60065b 306 }
kadonotakashi 0:8fdf9a60065b 307 return ret;
kadonotakashi 0:8fdf9a60065b 308 }
kadonotakashi 0:8fdf9a60065b 309
kadonotakashi 0:8fdf9a60065b 310 extern "C" nsapi_error_t ppp_lwip_if_init(void *pcb, struct netif *netif, const nsapi_ip_stack_t stack)
kadonotakashi 0:8fdf9a60065b 311 {
kadonotakashi 0:8fdf9a60065b 312 if (!prepare_event_queue()) {
kadonotakashi 0:8fdf9a60065b 313 return NSAPI_ERROR_NO_MEMORY;
kadonotakashi 0:8fdf9a60065b 314 }
kadonotakashi 0:8fdf9a60065b 315
kadonotakashi 0:8fdf9a60065b 316 if (!my_ppp_pcb) {
kadonotakashi 0:8fdf9a60065b 317 my_ppp_pcb = pppos_create(netif,
kadonotakashi 0:8fdf9a60065b 318 ppp_output, ppp_link_status, NULL);
kadonotakashi 0:8fdf9a60065b 319 if (!my_ppp_pcb) {
kadonotakashi 0:8fdf9a60065b 320 return NSAPI_ERROR_DEVICE_ERROR;
kadonotakashi 0:8fdf9a60065b 321 }
kadonotakashi 0:8fdf9a60065b 322
kadonotakashi 0:8fdf9a60065b 323 sys_sem_new(&ppp_close_sem, 0);
kadonotakashi 0:8fdf9a60065b 324 }
kadonotakashi 0:8fdf9a60065b 325
kadonotakashi 0:8fdf9a60065b 326 #if LWIP_IPV4
kadonotakashi 0:8fdf9a60065b 327 if (stack != IPV6_STACK) {
kadonotakashi 0:8fdf9a60065b 328 ppp_set_usepeerdns(my_ppp_pcb, true);
kadonotakashi 0:8fdf9a60065b 329 }
kadonotakashi 0:8fdf9a60065b 330 #endif
kadonotakashi 0:8fdf9a60065b 331
kadonotakashi 0:8fdf9a60065b 332 #if LWIP_IPV4 && LWIP_IPV6
kadonotakashi 0:8fdf9a60065b 333 if (stack == IPV4_STACK) {
kadonotakashi 0:8fdf9a60065b 334 my_ppp_pcb->ipv6cp_disabled = true;
kadonotakashi 0:8fdf9a60065b 335 } else if (stack == IPV6_STACK) {
kadonotakashi 0:8fdf9a60065b 336 my_ppp_pcb->ipcp_disabled = true;
kadonotakashi 0:8fdf9a60065b 337 }
kadonotakashi 0:8fdf9a60065b 338 #endif
kadonotakashi 0:8fdf9a60065b 339
kadonotakashi 0:8fdf9a60065b 340 return NSAPI_ERROR_OK;
kadonotakashi 0:8fdf9a60065b 341 }
kadonotakashi 0:8fdf9a60065b 342
kadonotakashi 0:8fdf9a60065b 343 nsapi_error_t nsapi_ppp_error_code()
kadonotakashi 0:8fdf9a60065b 344 {
kadonotakashi 0:8fdf9a60065b 345 return connect_error_code;
kadonotakashi 0:8fdf9a60065b 346 }
kadonotakashi 0:8fdf9a60065b 347
kadonotakashi 0:8fdf9a60065b 348 nsapi_error_t nsapi_ppp_set_blocking(bool blocking)
kadonotakashi 0:8fdf9a60065b 349 {
kadonotakashi 0:8fdf9a60065b 350 blocking_connect = blocking;
kadonotakashi 0:8fdf9a60065b 351 return NSAPI_ERROR_OK;
kadonotakashi 0:8fdf9a60065b 352 }
kadonotakashi 0:8fdf9a60065b 353
kadonotakashi 0:8fdf9a60065b 354 nsapi_error_t nsapi_ppp_connect(FileHandle *stream, Callback<void(nsapi_event_t, intptr_t)> cb, const char *uname, const char *password, const nsapi_ip_stack_t stack)
kadonotakashi 0:8fdf9a60065b 355 {
kadonotakashi 0:8fdf9a60065b 356 if (my_stream) {
kadonotakashi 0:8fdf9a60065b 357 return NSAPI_ERROR_PARAMETER;
kadonotakashi 0:8fdf9a60065b 358 }
kadonotakashi 0:8fdf9a60065b 359 my_stream = stream;
kadonotakashi 0:8fdf9a60065b 360 stream->set_blocking(false);
kadonotakashi 0:8fdf9a60065b 361 connection_status_cb = cb;
kadonotakashi 0:8fdf9a60065b 362 login = uname;
kadonotakashi 0:8fdf9a60065b 363 pwd = password;
kadonotakashi 0:8fdf9a60065b 364
kadonotakashi 0:8fdf9a60065b 365 nsapi_error_t retcode;
kadonotakashi 0:8fdf9a60065b 366
kadonotakashi 0:8fdf9a60065b 367 if (!my_interface) {
kadonotakashi 0:8fdf9a60065b 368 LWIP &lwip = LWIP::get_instance();
kadonotakashi 0:8fdf9a60065b 369 retcode = lwip._add_ppp_interface(stream, true, stack, &my_interface);
kadonotakashi 0:8fdf9a60065b 370 if (retcode != NSAPI_ERROR_OK) {
kadonotakashi 0:8fdf9a60065b 371 my_interface = NULL;
kadonotakashi 0:8fdf9a60065b 372 my_stream->set_blocking(true);
kadonotakashi 0:8fdf9a60065b 373 my_stream = NULL;
kadonotakashi 0:8fdf9a60065b 374 connection_status_cb = NULL;
kadonotakashi 0:8fdf9a60065b 375 return retcode;
kadonotakashi 0:8fdf9a60065b 376 }
kadonotakashi 0:8fdf9a60065b 377 }
kadonotakashi 0:8fdf9a60065b 378
kadonotakashi 0:8fdf9a60065b 379 // mustn't start calling input until after connect -
kadonotakashi 0:8fdf9a60065b 380 // attach deferred until ppp_lwip_connect, called from mbed_lwip_bringup
kadonotakashi 0:8fdf9a60065b 381 retcode = my_interface->bringup(false, NULL, NULL, NULL, stack, blocking_connect);
kadonotakashi 0:8fdf9a60065b 382
kadonotakashi 0:8fdf9a60065b 383 if (retcode != NSAPI_ERROR_OK) {
kadonotakashi 0:8fdf9a60065b 384 connection_status_cb = NULL;
kadonotakashi 0:8fdf9a60065b 385 my_stream->sigio(NULL);
kadonotakashi 0:8fdf9a60065b 386 my_stream->set_blocking(true);
kadonotakashi 0:8fdf9a60065b 387 my_stream = NULL;
kadonotakashi 0:8fdf9a60065b 388 }
kadonotakashi 0:8fdf9a60065b 389
kadonotakashi 0:8fdf9a60065b 390 if (retcode != NSAPI_ERROR_OK && connect_error_code != NSAPI_ERROR_OK) {
kadonotakashi 0:8fdf9a60065b 391 return connect_error_code;
kadonotakashi 0:8fdf9a60065b 392 } else {
kadonotakashi 0:8fdf9a60065b 393 return retcode;
kadonotakashi 0:8fdf9a60065b 394 }
kadonotakashi 0:8fdf9a60065b 395 }
kadonotakashi 0:8fdf9a60065b 396
kadonotakashi 0:8fdf9a60065b 397 nsapi_error_t nsapi_ppp_disconnect(FileHandle *stream)
kadonotakashi 0:8fdf9a60065b 398 {
kadonotakashi 0:8fdf9a60065b 399 if (my_stream != stream) {
kadonotakashi 0:8fdf9a60065b 400 return NSAPI_ERROR_NO_CONNECTION;
kadonotakashi 0:8fdf9a60065b 401 }
kadonotakashi 0:8fdf9a60065b 402
kadonotakashi 0:8fdf9a60065b 403 nsapi_error_t retcode = my_interface->bringdown();
kadonotakashi 0:8fdf9a60065b 404
kadonotakashi 0:8fdf9a60065b 405 connection_status_cb = NULL;
kadonotakashi 0:8fdf9a60065b 406 /* Detach callbacks, and put handle back to default blocking mode */
kadonotakashi 0:8fdf9a60065b 407 my_stream->sigio(NULL);
kadonotakashi 0:8fdf9a60065b 408 my_stream->set_blocking(true);
kadonotakashi 0:8fdf9a60065b 409 my_stream = NULL;
kadonotakashi 0:8fdf9a60065b 410
kadonotakashi 0:8fdf9a60065b 411 return retcode;
kadonotakashi 0:8fdf9a60065b 412 }
kadonotakashi 0:8fdf9a60065b 413
kadonotakashi 0:8fdf9a60065b 414 NetworkStack *nsapi_ppp_get_stack()
kadonotakashi 0:8fdf9a60065b 415 {
kadonotakashi 0:8fdf9a60065b 416 return &LWIP::get_instance();
kadonotakashi 0:8fdf9a60065b 417 }
kadonotakashi 0:8fdf9a60065b 418
kadonotakashi 0:8fdf9a60065b 419 const char *nsapi_ppp_get_ip_addr(FileHandle *stream)
kadonotakashi 0:8fdf9a60065b 420 {
kadonotakashi 0:8fdf9a60065b 421 static char ip_addr[IPADDR_STRLEN_MAX];
kadonotakashi 0:8fdf9a60065b 422
kadonotakashi 0:8fdf9a60065b 423 if (stream == my_stream) {
kadonotakashi 0:8fdf9a60065b 424
kadonotakashi 0:8fdf9a60065b 425 if (my_interface->get_ip_address(ip_addr, IPADDR_STRLEN_MAX)) {
kadonotakashi 0:8fdf9a60065b 426 return ip_addr;
kadonotakashi 0:8fdf9a60065b 427 }
kadonotakashi 0:8fdf9a60065b 428 }
kadonotakashi 0:8fdf9a60065b 429
kadonotakashi 0:8fdf9a60065b 430 return NULL;
kadonotakashi 0:8fdf9a60065b 431 }
kadonotakashi 0:8fdf9a60065b 432 const char *nsapi_ppp_get_netmask(FileHandle *stream)
kadonotakashi 0:8fdf9a60065b 433 {
kadonotakashi 0:8fdf9a60065b 434 #if !LWIP_IPV4
kadonotakashi 0:8fdf9a60065b 435 return NULL;
kadonotakashi 0:8fdf9a60065b 436 #endif
kadonotakashi 0:8fdf9a60065b 437
kadonotakashi 0:8fdf9a60065b 438 static char netmask[IPADDR_STRLEN_MAX];
kadonotakashi 0:8fdf9a60065b 439 if (stream == my_stream) {
kadonotakashi 0:8fdf9a60065b 440 if (my_interface->get_netmask(netmask, IPADDR_STRLEN_MAX)) {
kadonotakashi 0:8fdf9a60065b 441 return netmask;
kadonotakashi 0:8fdf9a60065b 442 }
kadonotakashi 0:8fdf9a60065b 443 }
kadonotakashi 0:8fdf9a60065b 444
kadonotakashi 0:8fdf9a60065b 445 return NULL;
kadonotakashi 0:8fdf9a60065b 446 }
kadonotakashi 0:8fdf9a60065b 447 const char *nsapi_ppp_get_gw_addr(FileHandle *stream)
kadonotakashi 0:8fdf9a60065b 448 {
kadonotakashi 0:8fdf9a60065b 449 #if !LWIP_IPV4
kadonotakashi 0:8fdf9a60065b 450 return NULL;
kadonotakashi 0:8fdf9a60065b 451 #endif
kadonotakashi 0:8fdf9a60065b 452
kadonotakashi 0:8fdf9a60065b 453 static char gwaddr[IPADDR_STRLEN_MAX];
kadonotakashi 0:8fdf9a60065b 454 if (stream == my_stream) {
kadonotakashi 0:8fdf9a60065b 455 if (my_interface->get_gateway(gwaddr, IPADDR_STRLEN_MAX)) {
kadonotakashi 0:8fdf9a60065b 456 return gwaddr;
kadonotakashi 0:8fdf9a60065b 457 }
kadonotakashi 0:8fdf9a60065b 458 }
kadonotakashi 0:8fdf9a60065b 459
kadonotakashi 0:8fdf9a60065b 460 return NULL;
kadonotakashi 0:8fdf9a60065b 461 }
kadonotakashi 0:8fdf9a60065b 462
kadonotakashi 0:8fdf9a60065b 463 #endif /* LWIP_PPP_API */
kadonotakashi 0:8fdf9a60065b 464
kadonotakashi 0:8fdf9a60065b 465 } // namespace mbed