summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2003-12-18 22:22:24 +0000
committerLennart Poettering <lennart@poettering.net>2003-12-18 22:22:24 +0000
commit51c0330ea15a28d2d7c83a746458dfd5cf1770bc (patch)
tree886bab27438137f7083990d7c3ff8eae1cb79168
parentc79399f437e9268203768ab65b32c20f29093b27 (diff)
further work
git-svn-id: file:///home/lennart/svn/public/ivam2/trunk@8 dbf6933d-3bce-0310-9bcc-ed052ba35b35
-rw-r--r--src/buffio.c100
-rw-r--r--src/buffio.h9
-rw-r--r--src/modem.c59
3 files changed, 130 insertions, 38 deletions
diff --git a/src/buffio.c b/src/buffio.c
index 1e13b4d..2c3a7fb 100644
--- a/src/buffio.c
+++ b/src/buffio.c
@@ -15,13 +15,16 @@ struct buffio buffio_new(int fd) {
memset(b, 0, sizeof(struct buffio));
b->fd = fd;
- b->input_buf = malloc(BUFSIZE);
+
+ b->input_buf = malloc(b->input_max_length = BUFSIZE);
assert(b->input_buf);
- b->input_buf_len = 0;
-
- b->output_buf = malloc(BUFSIZE);
+ b->input_buf_len = b->input_index = 0;
+ b->input_watermark = 2; /* Read some more data if 2 or less bytes are in the input buffer */
+
+ b->output_buf = malloc(b->output_max_length = BUFSIZE);
assert(b->output_buf);
- b->output_buf_len = 0;
+ b->output_length = b->output_index = 0;
+ b->output_watermark = 1; /* Write some data if 1 or more bytes are in the output buffer */
buffio_set_callbacks(b);
@@ -56,15 +59,15 @@ static void* buffio_read_cb(oop_source *source, int fd, oop_event event, void *u
struct buffio *b = user;
assert(source && b && b->fd == fd && event == OOP_READ);
- if (b->input_length < BUFSIZE) {
+ if (b->input_length < b->input_max_length) {
ssize_t s;
size_t m, l;
- i = (b->input_index + b->input_length) % BUFSIZE;
+ i = (b->input_index + b->input_length) % b->input_max_length;
- m = BUFSIZE-b->input_length;
- if (m > BUFSIZE-i)
- m = BUFSIZE-i;
+ m = b->input_max_length-b->input_length;
+ if (m > b->input_max_length-i)
+ m = b->input_max_length-i;
if ((s = read(fd, b->input_buf+i, m)) < 0) {
daemon_log(LOG_ERR, "Failed to read from file descriptor: %s", strerror(errno));
@@ -82,7 +85,12 @@ static void* buffio_read_cb(oop_source *source, int fd, oop_event event, void *u
b->input_length += s;
}
- buffio_set_callbacks(b);
+ buffio_normalize(b);
+ buffio_set_input_callbacks(b);
+
+ if (b->input_length && b->input_ready_cb)
+ b->input_ready_cb(b, b->user);
+
return OOP_CONTINUE;
}
@@ -95,8 +103,8 @@ static void* buffio_write_cb(oop_source *source, int fd, oop_event event, void *
size_t m;
m = b->output_length;
- if (m > BUFSIZE-b->output_index)
- m = BUFSIZE-b->output_index;
+ if (m > b->output_max_length-b->output_index)
+ m = b->output_max_length-b->output_index;
if ((s = write(fd, b->output_buf+b->output_index, m)) < 0) {
daemon_log(LOG_ERR, "Failed to write to file descriptor: %s", strerror(errno));
@@ -111,19 +119,24 @@ static void* buffio_write_cb(oop_source *source, int fd, oop_event event, void *
}
assert(s <= m);
- b->output_index = (b->output_index + s) % BUFSIZE;
+ b->output_index = (b->output_index + s) % b->output_max_length;
b->ouput_length -= s;
}
+
+ buffio_normalize(b);
+ buffio_set_output_callbacks(b);
+
+ if (!b->output_length && b->output_empty_cb)
+ b->output_empty_cb(b, b->user);
- buffio_set_callbacks(b);
return OOP_CONTINUE;
}
-static void buffio_set_callbacks(struct buffio *b) {
+static void buffio_set_input_callbacks(struct buffio *b) {
assert(b && b->fd >= 0 && event_source);
- if (b->input_length < BUFSIZE) {
+ if (b->input_length <= b->input_watermark) {
if (!b->b_read_cb) { /* Enable the callback */
event_source->on_fd(event_source, b->fd, OOP_READ, buffio_read_cb, b);
b->b_read_cb = 1;
@@ -134,8 +147,12 @@ static void buffio_set_callbacks(struct buffio *b) {
b->read_cb = 0;
}
}
+}
- if (b->output_length > 0) {
+static void buffio_set_output_callbacks(struct buffio *b) {
+ assert(b && b->fd >= 0 && event_source);
+
+ if (b->output_length >= b->output_watermark) {
if (!b->b_write_cb) { /* Enable the callback */
event_source->on_fd(event_source, b->fd, OOP_WRITE, buffio_write_cb, b);
b->b_write_cb = 1;
@@ -146,24 +163,23 @@ static void buffio_set_callbacks(struct buffio *b) {
b->b_write_cb = 0;
}
}
-
}
int buffio_write(struct buffio *b, const uint8_t *d, size_t l) {
assert(b && s && l);
- if (l < BUFFSIZE - b->output_length) {
+ if (l < b->output_max_length - b->output_length) {
daemon_log(LOG_ERR, "buffio_write() with too much data called");
return -1;
}
while (l >= 0) {
- i = (b->ouput_index + b->ouput_length) % BUFSIZE;
+ i = (b->ouput_index + b->ouput_length) % b->ouput_max_length;
- m = BUFSIZE-b->output_length;
- if (m > BUFSIZE-i)
- m = BUFSIZE-i;
+ m = b->ouput_max_length-b->output_length;
+ if (m > b->output_max_length-i)
+ m = b->output_max_length-i;
memcpy(b->output_buf+i, d, m);
@@ -171,7 +187,8 @@ int buffio_write(struct buffio *b, const uint8_t *d, size_t l) {
b->output_length += m;
}
- buffio_set_callbacks(b);
+ buffio_set_output_callbacks(b);
+ buffio_normalize();
return 0;
}
@@ -195,8 +212,39 @@ void buffio_flush_input(struct buffio *b) {
buffio_set_callbacks(b);
}
+
+static void buffio_normalize(struct buffio *b) {
+ assert(b);
+
+ assert(b->input_index < b->input_max_length);
+ assert(b->input_length <= b->input_max_length);
+
+ if (!b->input_length) /* This will optimize throughput a bit */
+ b->input_index = 0;
+}
+
int buffio_find_input(struct buffio *b, const char *c) {
- assert(b && c);
+ size_t l, cl, j;
+ assert(b && c && *c);
+ cl = strlen(c);
+
+ for (i = b->input_index, l = b->input_length; l >= cl; i = (i+1) % b->input_max_length, l--) {
+ char *p;
+ size_t i;
+
+ for (j = i, p = c; *p && *p == b->input_buf[j]; p++, j = (j+1) % b->input_max_length);
+
+ if (!*p) { /* Found! */
+ b->input_index = j;
+ b->input_length = l-cl;
+
+ buffio_normalize(b);
+ return 1;
+ }
+ }
+
+ return 0;
}
+
diff --git a/src/buffio.h b/src/buffio.h
index 461bff9..a340385 100644
--- a/src/buffio.h
+++ b/src/buffio.h
@@ -5,17 +5,18 @@ struct buffio {
int fd;
uint8_t *input_buf;
- size_t input_index, input_length;
+ size_t input_max_length, input_index, input_length;
uint8_t *output_buf;
- size_t output_index, output_length;
+ size_t output_max_length, output_index, output_length;
int b_read_cb, b_write_cb;
void *user;
+
void (*eof_cb) (struct buffio *b, void *user);
- void (*output_cb) (struct buffio *b, void *user);
- void (*input_cb) (struct buffio *b, void *user);
+ void (*output_empty_cb) (struct buffio *b, void *user);
+ void (*input_ready_cb) (struct buffio *b, void *user);
};
struct buffio buffio_new(int fd);
diff --git a/src/modem.c b/src/modem.c
index ef1d7fd..1269fbb 100644
--- a/src/modem.c
+++ b/src/modem.c
@@ -55,11 +55,12 @@ struct modem *modem_open(const char *dev) {
assert(m->dev);
m->buffio = buffio_new(fd);
assert(m->buffio);
- m->state = MODEM_STATE_INIT;
+ m->buffio->output_empty_cb = modem_output_empty_cb;
+ m->buffio->input_ready_cb = modem_output_ready_cb;
+
m->child_pid = -1;
- modem_timeout(m, 10);
- modem_next_command(m);
+ modem_init(m);
return m;
@@ -195,11 +196,10 @@ static const char* const init_at_commands[INIT_AT_COMMANDS*2] = {
-static void modem_input_init_cb(struct buffio *b, void *user) {
+static void modem_input_ready_cb(struct buffio *b, void *user) {
struct modem *m = user;
assert(b && m && m->buffio == b);
-
switch (m->state) {
case MODEM_STATE_INIT: {
@@ -213,6 +213,7 @@ static void modem_input_init_cb(struct buffio *b, void *user) {
if (m->command_index >= INIT_AT_COMMANDS) {
m->state = MODEM_STATE_CALLER_NUMBER_EXPECT;
+ modem_timeout(m, 0);
modem_input_init_cb(b, user);
} else
modem_next_command(m);
@@ -294,15 +295,49 @@ static void modem_input_init_cb(struct buffio *b, void *user) {
break;
case MODEM_STATE_CONNECTION:
+
+ m->state = MODEM_STATE_HANGUP;
break;
- case MODEM_STATE_DONE:
+ case MODEM_STATE_HANGUP: {
+
+ modem_send_command(m, { DLE, DC4, DLE, ETX, 0 });
+ m->state = MODEM_STATE_FORCE_HANGUP;
break;
+ }
+ }
+}
+
+
+static void modem_output_empty_cb(struct buffio *b, void *user) {
+ struct modem *m = user;
+ assert(b && m && m->buffio == b);
+
+ switch (m->state) {
+ case MODEM_STATE_FORCE_HANGUP:
+ modem_force_hangup(m);
+ modem_init(m);
+ break;
}
-
}
+void modem_force_hangup(struct modem *m) {
+ struct termios pts;
+ assert(m && m->buffio);
+
+ tcgetattr(m->buffio->fd, &pts);
+ cfsetospeed(&pts, B0);
+ cfsetispeed(&pts, B0);
+ tcsetattr(m->buffio->fd, TCSANOW, &pts);
+
+ tcgetattr(m->buffio->fd, &pts);
+ cfsetospeed(&pts, BAUD_RATE);
+ cfsetispeed(&pts, BAUD_RATE);
+ tcsetattr(m->buffio->fd, TCSANOW, &pts);
+}
+
+
static void modem_send_command(struct modem *m, const char *p) {
assert(m && m->buffio);
@@ -328,6 +363,14 @@ static void modem_next_command(struct modem *m) {
m->buffio->input_cb = modem_input_cb;
buffio_command(m->buffio, p);
+
}
-// { DLE, DC4, DLE, ETX, 'A', 'T', 'H', '\n', "AT&F\n" },
+static void modem_init(struct modem *m) {
+ assert(m);
+ m->state = MODEM_STATE_INIT;
+ m->command_index = 0;
+
+ modem_timeout(m, 10);
+ modem_next_command(m);
+}