OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [net/] [lwip_tcpip/] [current/] [src/] [netif/] [ppp/] [chat.c] - Blame information for rev 865

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
/**
2
 * @file
3
 * Chat implementation
4
 *
5
 */
6
 
7
/*
8
 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
9
 * All rights reserved.
10
 *
11
 * Redistribution and use in source and binary forms, with or without
12
 * modification, are permitted provided that the following conditions
13
 * are met:
14
 * 1. Redistributions of source code must retain the above copyright
15
 *    notice, this list of conditions and the following disclaimer.
16
 * 2. Redistributions in binary form must reproduce the above copyright
17
 *    notice, this list of conditions and the following disclaimer in the
18
 *    documentation and/or other materials provided with the distribution.
19
 * 3. Neither the name of the Institute nor the names of its contributors
20
 *    may be used to endorse or promote products derived from this software
21
 *    without specific prior written permission.
22
 *
23
 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33
 * SUCH DAMAGE.
34
 *
35
 * Author: Simon Kallweit <simon.kallweit(at)intefo.ch>
36
 */
37
 
38
/*
39
 * This is an arch independent chat implementation. The specific serial hooks
40
 * must be provided by another file. They are sio_open, sio_recv and sio_send.
41
 */
42
 
43
#include "netif/ppp/chat.h"
44
#include "lwip/opt.h"
45
 
46
#include "lwip/sys.h"
47
#include "lwip/mem.h"
48
#include "lwip/sio.h"
49
 
50
#define BUFSIZE 64
51
 
52
/** Chat states */
53
enum chat_state {
54
  STATE_INITIAL,    /**< Initial state, checks the current item, executes it
55
                         directly or transitions to a new state to handle the
56
                         item. */
57
  STATE_WAIT,       /**< Waits for an answer from the modem. */
58
  STATE_SLEEP,      /**< Sleep for at least 1 second. */
59
  STATE_NEXT_ITEM,  /**< Moves to the next item. */
60
  STATE_IDLE,       /**< Chat finished. */
61
};
62
 
63
/** Chat */
64
struct chat {
65
  struct chat *next;        /**< Pointer to the next chat instance */
66
  /* Settings */
67
  sio_fd_t sd;              /**< Serial device descriptor */
68
  const struct chat_item const *items; /**< Chat items */
69
  int timeout;              /**< Default timeout in seconds */
70
  chat_cb_t chat_cb;        /**< Chat callback function */
71
  chat_send_cb_t send_cb;   /**< Chat send callback function */
72
  void *arg;                /**< Argument for callback function */
73
  /* State */
74
  enum chat_state state;    /**< Current state */
75
  const struct chat_item *item; /**< Current chat item */
76
  char buf[BUFSIZE + 1];   /**< Receive buffer */
77
  int recvd;                /**< Received bytes */
78
  int timeleft;             /**< Seconds left until timeout */
79
};
80
 
81
/** Linked list of chats */
82
static struct chat *chats;
83
 
84
static void chat_send(struct chat *chat, const struct chat_item *item);
85
static void chat_send_cb(struct chat *chat, const struct chat_item *item);
86
static int chat_wait(struct chat *chat, const struct chat_item *item);
87
 
88
/*
89
 * Creates a new chat. The chat is further processed by calling chat_poll().
90
 * The result of the chat is posted by the chat_cb() callback function.
91
 */
92
chat_t chat_new(sio_fd_t sd, const struct chat_item const *items, int timeout,
93
                chat_cb_t chat_cb, chat_send_cb_t send_cb, void *arg)
94
{
95
  struct chat *chat;
96
  const struct chat_item *item;
97
 
98
  /* Some sanity checks */
99
  LWIP_ASSERT("chat_new: sd != NULL", sd != NULL);
100
  LWIP_ASSERT("chat_new: items != NULL", items != NULL);
101
  LWIP_ASSERT("chat_new: chat_cb != NULL", chat_cb != NULL);
102
 
103
  /* Check for correct chat items */
104
  for (item = items; item->cmd != CHAT_LAST; item++)
105
    LWIP_ASSERT("chat_new: invalid chat item or CHAT_LAST missing",
106
                item->cmd >= CHAT_ABORT && item->cmd < CHAT_LAST);
107
 
108
  /* Allocate chat */
109
  chat = mem_malloc(sizeof(struct chat));
110
  if (!chat)
111
    return NULL;
112
 
113
  /* Iinitialize chat */
114
  chat->sd = sd;
115
  chat->items = items;
116
  chat->timeout = timeout * 1000 + 1;
117
  chat->chat_cb = chat_cb;
118
  chat->send_cb = send_cb;
119
  chat->arg = arg;
120
 
121
  /* Reset state */
122
  chat->state = STATE_INITIAL;
123
  chat->item = items;
124
  chat->recvd = 0;
125
 
126
  /* Add chat to list */
127
  chat->next = chats;
128
  chats = chat;
129
 
130
  return chat;
131
}
132
 
133
/*
134
 * Frees a chat.
135
 */
136
void chat_free(struct chat *chat)
137
{
138
  struct chat *t;
139
 
140
  if (!chat)
141
    return;
142
 
143
  /* Remove chat from list */
144
  if (chat == chats) {
145
    chats = chat->next;
146
  } else {
147
    for (t = chats; t->next; t = t->next)
148
      if (t->next == chat) {
149
        t->next = chat->next;
150
        break;
151
      }
152
  }
153
 
154
  mem_free(chat);
155
}
156
 
157
/*
158
 * Processes the chat. This needs to be called iteratively until the chat_cb()
159
 * callback function posts success or an error.
160
 */
161
void chat_poll(struct chat *chat)
162
{
163
  int done = 0;
164
  int err;
165
 
166
  LWIP_ASSERT("chat_poll: chat != NULL", chat != NULL);
167
 
168
  while (!done) {
169
    switch (chat->state) {
170
    case STATE_INITIAL:
171
      /* Check item command */
172
      switch (chat->item->cmd) {
173
      case CHAT_ABORT:
174
        chat->state = STATE_NEXT_ITEM;
175
        break;
176
      case CHAT_SAY:
177
        LWIP_DEBUGF(PPP_DEBUG, ("chat_poll: SAY '%s'\n", chat->item->arg));
178
        chat->state = STATE_NEXT_ITEM;
179
        break;
180
      case CHAT_SEND:
181
        LWIP_DEBUGF(PPP_DEBUG, ("chat_poll: SEND '%s'\n", chat->item->arg));
182
        chat_send(chat, chat->item);
183
        chat->state = STATE_NEXT_ITEM;
184
        break;
185
      case CHAT_SEND_CB:
186
        LWIP_DEBUGF(PPP_DEBUG, ("chat_poll: SEND_CB '%d'\n", (int) chat->item->arg));
187
        chat_send_cb(chat, chat->item);
188
        chat->state = STATE_NEXT_ITEM;
189
        break;
190
      case CHAT_WAIT:
191
        LWIP_DEBUGF(PPP_DEBUG, ("chat_poll: WAIT '%s'\n", chat->item->arg));
192
        chat->timeleft = chat->timeout;
193
        chat->state = STATE_WAIT;
194
        break;
195
      case CHAT_SLEEP:
196
        LWIP_DEBUGF(PPP_DEBUG, ("chat_poll: SLEEP\n"));
197
        chat->timeleft = 1000 + 1;
198
        if (chat->item->arg)
199
          chat->timeleft = (int) chat->item->arg + 1;
200
        chat->state = STATE_SLEEP;
201
        break;
202
      case CHAT_LAST:
203
        LWIP_DEBUGF(PPP_DEBUG, ("chat_poll: SUCCESS\n"));
204
        chat->chat_cb(chat, CHAT_ERR_OK, chat->arg);
205
        chat->state = STATE_IDLE;
206
        break;
207
      }
208
      break;
209
    case STATE_WAIT:
210
      err = chat_wait(chat, chat->item);
211
      if (err == -1) {
212
        done = 1;
213
      } else if (err == CHAT_ERR_OK) {
214
        chat->state = STATE_NEXT_ITEM;
215
      } else {
216
        chat->chat_cb(chat, err, chat->arg);
217
        chat->state = STATE_IDLE;
218
      }
219
      break;
220
    case STATE_SLEEP:
221
      if (chat->timeleft == 0)
222
        chat->state = STATE_NEXT_ITEM;
223
      else
224
        done = 1;
225
      break;
226
    case STATE_NEXT_ITEM:
227
      chat->item++;
228
      chat->state = STATE_INITIAL;
229
      break;
230
    case STATE_IDLE:
231
      done = 1;
232
      break;
233
    }
234
  }
235
}
236
 
237
/*
238
 * This should be called every CHAT_TMR_INTERVAL milliseconds.
239
 */
240
void chat_tmr(void)
241
{
242
  struct chat *chat;
243
 
244
  LWIP_DEBUGF(PPP_DEBUG, ("chat_tmr\n"));
245
 
246
  for (chat = chats; chat; chat = chat->next) {
247
    if (chat->timeleft > CHAT_TMR_INTERVAL)
248
      chat->timeleft -= CHAT_TMR_INTERVAL;
249
    else
250
      chat->timeleft = 0;
251
    LWIP_DEBUGF(PPP_DEBUG, ("chat_tmr: %d\n", chat->timeleft));
252
  }
253
}
254
 
255
 
256
/**
257
 * Sends a chat message to the modem.
258
 * @param chat Chat
259
 * @param item Item to send
260
 */
261
static void chat_send(struct chat *chat, const struct chat_item *item)
262
{
263
  sio_write(chat->sd, (u8_t *) item->arg, strlen(item->arg));
264
  chat->recvd = 0;
265
}
266
 
267
/**
268
 * Sends a chat message to the modem. Gets the send string via a callback.
269
 * @param chat Chat
270
 * @param item Item to send
271
 */
272
static void chat_send_cb(struct chat *chat, const struct chat_item *item)
273
{
274
  LWIP_ASSERT("chat_poll: chat->send_cb != NULL", chat->send_cb != NULL);
275
 
276
  // Get the command to send
277
  chat->send_cb(chat, (int) item->arg, chat->buf, BUFSIZE, chat->arg);
278
  chat->buf[BUFSIZE] = '\0';
279
 
280
  // Send command
281
  sio_write(chat->sd, (u8_t *) chat->buf, strlen(chat->buf));
282
  chat->recvd = 0;
283
}
284
 
285
/**
286
 * Waits for an response from the modem. This function returns:
287
 *   -1: when no more data could be read from the serial (polling)
288
 *   CHAT_ERR_OK: when the correct response was received
289
 *   CHAT_ERR_ABORT: when an abort response was received
290
 *   CHAT_ERR_TIMEOUT: when a timeout occured
291
 * @param chat Chat
292
 * @param item Item to wait for
293
 * @return See above.
294
 */
295
static int chat_wait(struct chat *chat, const struct chat_item *item)
296
{
297
  int count;
298
  const struct chat_item *abort;
299
 
300
  while (chat->recvd < BUFSIZE) {
301
    /* Receive data from serial */
302
    if ((count = sio_read(chat->sd, (u8_t *) &chat->buf[chat->recvd],
303
                          BUFSIZE - chat->recvd)) < 1)
304
      break;
305
    chat->recvd += count;
306
    chat->buf[chat->recvd] = '\0';
307
 
308
    /* Check abort strings */
309
    for (abort = chat->items; abort->cmd != CHAT_LAST; abort++) {
310
      if (abort->cmd != CHAT_ABORT)
311
        continue;
312
      if (strstr(chat->buf, abort->arg)) {
313
        LWIP_DEBUGF(PPP_DEBUG, ("chat_wait: ABORT '%s'\n", abort->arg));
314
        return CHAT_ERR_ABORT;
315
      }
316
    }
317
 
318
    /* Check wait string */
319
    if (strstr(chat->buf, item->arg)) {
320
      LWIP_DEBUGF(PPP_DEBUG, ("chat_wait: SUCCESS\n"));
321
      return CHAT_ERR_OK;
322
    }
323
  }
324
 
325
  /* Check for timeout */
326
  if (chat->timeleft == 0) {
327
    LWIP_DEBUGF(PPP_DEBUG, ("chat_wait: TIMEOUT\n"));
328
    return CHAT_ERR_TIMEOUT;
329
  }
330
 
331
  return -1;
332
}

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.