diff options
Diffstat (limited to 'packages/gsm/files/0001-Introduce-ports.patch')
-rw-r--r-- | packages/gsm/files/0001-Introduce-ports.patch | 710 |
1 files changed, 710 insertions, 0 deletions
diff --git a/packages/gsm/files/0001-Introduce-ports.patch b/packages/gsm/files/0001-Introduce-ports.patch new file mode 100644 index 0000000000..b3ba3cb957 --- /dev/null +++ b/packages/gsm/files/0001-Introduce-ports.patch @@ -0,0 +1,710 @@ +From 516d67c679101d1503dbd4c0613bcd6ff1b604e4 Mon Sep 17 00:00:00 2001 +From: Andrzej Zaborowski <balrog@zabor.org> +Date: Wed, 19 Sep 2007 14:03:28 +0200 +Subject: [PATCH] Introduce ports. + +--- + include/gsmd/atcmd.h | 2 +- + include/gsmd/gsmd.h | 7 +- + include/gsmd/uart.h | 28 ++++++ + include/gsmd/vendorplugin.h | 4 +- + src/gsmd/Makefile.am | 2 +- + src/gsmd/atcmd.c | 177 +++++++++++++++++--------------------- + src/gsmd/gsmd.c | 64 ++------------ + src/gsmd/uart.c | 202 +++++++++++++++++++++++++++++++++++++++++++ + 8 files changed, 328 insertions(+), 158 deletions(-) + create mode 100644 include/gsmd/uart.h + create mode 100644 src/gsmd/uart.c + +diff --git a/include/gsmd/atcmd.h b/include/gsmd/atcmd.h +index 0d6c62a..a1af6a0 100644 +--- a/include/gsmd/atcmd.h ++++ b/include/gsmd/atcmd.h +@@ -9,7 +9,7 @@ typedef int atcmd_cb_t(struct gsmd_atcmd *cmd, void *ctx, char *resp); + + extern struct gsmd_atcmd *atcmd_fill(const char *cmd, int rlen, atcmd_cb_t *cb, void *ctx, u_int16_t id); + extern int atcmd_submit(struct gsmd *g, struct gsmd_atcmd *cmd); +-extern int atcmd_init(struct gsmd *g, int sockfd); ++extern int atcmd_init(struct gsmd *g, struct gsmd_port *port); + extern void atcmd_drain(int fd); + + #endif /* __GSMD__ */ +diff --git a/include/gsmd/gsmd.h b/include/gsmd/gsmd.h +index ed334f1..4afdf66 100644 +--- a/include/gsmd/gsmd.h ++++ b/include/gsmd/gsmd.h +@@ -10,6 +10,7 @@ + #include <gsmd/machineplugin.h> + #include <gsmd/vendorplugin.h> + #include <gsmd/select.h> ++#include <gsmd/uart.h> + #include <gsmd/state.h> + + void *gsmd_tallocs; +@@ -52,6 +53,7 @@ enum llparse_state { + #define MLPARSE_BUF_SIZE 65535 + + struct llparser { ++ struct gsmd_port *port; + enum llparse_state state; + unsigned int len; + unsigned int flags; +@@ -70,7 +72,7 @@ struct gsmd; + struct gsmd { + unsigned int flags; + int interpreter_ready; +- struct gsmd_fd gfd_uart; ++ struct gsmd_uart uart; + struct gsmd_fd gfd_sock; + struct llparser llp; + struct llist_head users; +@@ -81,9 +83,10 @@ struct gsmd { + struct gsmd_device_state dev_state; + + struct llist_head operators; /* cached list of operator names */ +- unsigned char *mlbuf; /* ml_parse buffer */ ++ char *mlbuf; /* ml_parse buffer */ + unsigned int mlbuf_len; + int mlunsolicited; ++ int clear_to_send; + }; + + struct gsmd_user { +diff --git a/include/gsmd/uart.h b/include/gsmd/uart.h +new file mode 100644 +index 0000000..a006fa7 +--- /dev/null ++++ b/include/gsmd/uart.h +@@ -0,0 +1,28 @@ ++#ifndef __GSMD_UART_H ++#define __GSMD_UART_H ++ ++#ifdef __GSMD__ ++ ++struct gsmd_port { ++ int (*write)(struct gsmd_port *port, const char data[], int len); ++ int (*set_break)(struct gsmd_port *port, int state); ++ /* more parameters here */ ++ int (*newdata_cb)(void *opaque, const char data[], int len); ++ void *newdata_opaque; ++}; ++ ++struct gsmd_uart { ++ struct gsmd_port port; ++ struct gsmd_fd gfd; ++ char txfifo[2048]; ++ int tx_start; ++ int tx_len; ++}; ++ ++extern int set_baudrate(int fd, int baudrate, int hwflow); ++extern void uart_drain(int fd); ++extern int uart_init(struct gsmd_uart *uart, int sockfd); ++ ++#endif /* __GSMD__ */ ++ ++#endif +diff --git a/include/gsmd/vendorplugin.h b/include/gsmd/vendorplugin.h +index 1911fef..1c82790 100644 +--- a/include/gsmd/vendorplugin.h ++++ b/include/gsmd/vendorplugin.h +@@ -11,8 +11,8 @@ struct gsmd_unsolicit; + + struct gsmd_vendor_plugin { + struct llist_head list; +- unsigned char *name; +- unsigned char *ext_chars; ++ char *name; ++ char *ext_chars; + unsigned int num_unsolicit; + const struct gsmd_unsolicit *unsolicit; + int (*detect)(struct gsmd *g); +diff --git a/src/gsmd/Makefile.am b/src/gsmd/Makefile.am +index 9ac45ee..110b757 100644 +--- a/src/gsmd/Makefile.am ++++ b/src/gsmd/Makefile.am +@@ -13,7 +13,7 @@ sbin_PROGRAMS = gsmd + gsmd_CFLAGS = -D PLUGINDIR=\"$(plugindir)\" + gsmd_SOURCES = gsmd.c atcmd.c select.c machine.c vendor.c unsolicited.c log.c \ + usock.c talloc.c timer.c operator_cache.c ext_response.c \ +- sms_cb.c sms_pdu.c ++ sms_cb.c sms_pdu.c uart.c + gsmd_LDADD = -ldl + gsmd_LDFLAGS = -Wl,--export-dynamic + +diff --git a/src/gsmd/atcmd.c b/src/gsmd/atcmd.c +index 2ef6a10..27dfa41 100644 +--- a/src/gsmd/atcmd.c ++++ b/src/gsmd/atcmd.c +@@ -159,7 +159,8 @@ static int llparse_byte(struct llparser *llp, char byte) + return ret; + } + +-static int llparse_string(struct llparser *llp, char *buf, unsigned int len) ++static int llparse_string(struct llparser *llp, const char *buf, ++ unsigned int len) + { + while (len--) { + int rc = llparse_byte(llp, *(buf++)); +@@ -187,6 +188,55 @@ static int llparse_init(struct llparser *llp) + return 0; + } + ++/* See if we can now send more commands to the port */ ++static void atcmd_wake_queue(struct gsmd *g) ++{ ++ int len, rc; ++ char *cr; ++ ++ /* write pending commands to UART */ ++ while (g->interpreter_ready && g->clear_to_send) { ++ struct gsmd_atcmd *pos, *pos2; ++ llist_for_each_entry_safe(pos, pos2, &g->pending_atcmds, list) { ++ cr = strchr(pos->cur, '\n'); ++ if (cr) ++ len = cr - pos->cur; ++ else ++ len = pos->buflen; ++ rc = g->llp.port->write(g->llp.port, pos->cur, len); ++ if (rc == 0) { ++ gsmd_log(GSMD_ERROR, ++ "write returns 0, aborting\n"); ++ break; ++ } ++ if (cr && rc == len) ++ rc ++; /* Skip the \n */ ++ pos->buflen -= rc; ++ pos->cur += rc; ++ g->llp.port->write(g->llp.port, "\r", 1); ++ ++ if (!pos->buflen) { ++ /* success: remove from global list of ++ * to-be-sent atcmds */ ++ llist_del(&pos->list); ++ /* append to global list of executing atcmds */ ++ llist_add_tail(&pos->list, &g->busy_atcmds); ++ ++ /* we only send one cmd at the moment */ ++ g->clear_to_send = 0; ++ break; ++ } else { ++ /* The write was short or the atcmd has more ++ * lines to send after a "> ". */ ++ if (rc < len) ++ break; ++ g->clear_to_send = 0; ++ break; ++ } ++ } ++ } ++} ++ + /* mid-level parser */ + + static int parse_final_result(const char *res) +@@ -216,6 +266,7 @@ static int ml_parse(const char *buf, int len, void *ctx) + g->interpreter_ready = 1; + gsmd_initsettings(g); + gmsd_alive_start(g); ++ atcmd_wake_queue(g); + return 0; + } + +@@ -316,6 +367,7 @@ static int ml_parse(const char *buf, int len, void *ctx) + } else { + DEBUGP("Calling cmd->cb()\n"); + cmd->resp = g->mlbuf; ++ g->mlbuf[g->mlbuf_len] = 0; + rc = cmd->cb(cmd, cmd->ctx, cmd->resp); + DEBUGP("Clearing mlbuf\n"); + } +@@ -370,12 +422,15 @@ static int ml_parse(const char *buf, int len, void *ctx) + if (g->mlbuf_len) + g->mlbuf[g->mlbuf_len ++] = '\n'; + DEBUGP("Appending buf to mlbuf\n"); +- if (len > MLPARSE_BUF_SIZE - g->mlbuf_len) ++ if (len > MLPARSE_BUF_SIZE - g->mlbuf_len) { + len = MLPARSE_BUF_SIZE - g->mlbuf_len; ++ gsmd_log(GSMD_NOTICE, "g->mlbuf overrun\n"); ++ } + memcpy(g->mlbuf + g->mlbuf_len, buf, len); + g->mlbuf_len += len; + + if (g->mlunsolicited) { ++ g->mlbuf[g->mlbuf_len] = 0; + rc = unsolicited_parse(g, g->mlbuf, g->mlbuf_len, + strchr(g->mlbuf, ':') + 1); + if (rc == -EAGAIN) { +@@ -422,8 +477,11 @@ final_cb: + + /* if we're finished with current commands, but still have pending + * commands: we want to WRITE again */ +- if (llist_empty(&g->busy_atcmds) && !llist_empty(&g->pending_atcmds)) +- g->gfd_uart.when |= GSMD_FD_WRITE; ++ if (llist_empty(&g->busy_atcmds)) { ++ g->clear_to_send = 1; ++ if (!llist_empty(&g->pending_atcmds)) ++ atcmd_wake_queue(g); ++ } + + return rc; + } +@@ -433,85 +491,23 @@ static int atcmd_prompt(void *data) + { + struct gsmd *g = data; + +- g->gfd_uart.when |= GSMD_FD_WRITE; ++ g->clear_to_send = 1; ++ atcmd_wake_queue(g); + } + + /* callback to be called if [virtual] UART has some data for us */ +-static int atcmd_select_cb(int fd, unsigned int what, void *data) ++static int atcmd_newdata_cb(void *opaque, const char data[], int len) + { +- int len, rc; +- static char rxbuf[1024]; +- struct gsmd *g = data; +- char *cr; +- +- if (what & GSMD_FD_READ) { +- memset(rxbuf, 0, sizeof(rxbuf)); +- while ((len = read(fd, rxbuf, sizeof(rxbuf)))) { +- if (len < 0) { +- if (errno == EAGAIN) +- return 0; +- gsmd_log(GSMD_NOTICE, "ERROR reading from fd %u: %d (%s)\n", fd, len, +- strerror(errno)); +- return len; +- } +- rc = llparse_string(&g->llp, rxbuf, len); +- if (rc < 0) { +- gsmd_log(GSMD_ERROR, "ERROR during llparse_string: %d\n", rc); +- return rc; +- } +- } +- } +- +- /* write pending commands to UART */ +- if ((what & GSMD_FD_WRITE) && g->interpreter_ready) { +- struct gsmd_atcmd *pos, *pos2; +- llist_for_each_entry_safe(pos, pos2, &g->pending_atcmds, list) { +- cr = strchr(pos->cur, '\n'); +- if (cr) +- len = cr - pos->cur; +- else +- len = pos->buflen - 1; /* assuming zero-terminated strings */ +- rc = write(fd, pos->cur, len); +- if (rc == 0) { +- gsmd_log(GSMD_ERROR, "write returns 0, aborting\n"); +- break; +- } else if (rc < 0) { +- gsmd_log(GSMD_ERROR, "error during write to fd %d: %d\n", +- fd, rc); +- return rc; +- } +- if (!cr || rc == len) +- rc ++; /* Skip the \n or \0 */ +- pos->buflen -= rc; +- pos->cur += rc; +- write(fd, "\r", 1); +- +- if (!pos->buflen) { +- /* success: remove from global list of +- * to-be-sent atcmds */ +- llist_del(&pos->list); +- /* append to global list of executing atcmds */ +- llist_add_tail(&pos->list, &g->busy_atcmds); +- +- /* we only send one cmd at the moment */ +- break; +- } else { +- /* The write was short or the atcmd has more +- * lines to send after a "> ". */ +- if (rc < len) +- return 0; +- break; +- } +- } ++ struct gsmd *g = opaque; ++ int rc; + +- /* Either pending_atcmds is empty or a command has to wait */ +- g->gfd_uart.when &= ~GSMD_FD_WRITE; +- } ++ rc = llparse_string(&g->llp, data, len); ++ if (rc < 0) ++ gsmd_log(GSMD_ERROR, "ERROR during llparse_string: %d\n", rc); + +- return 0; ++ return rc; + } + +- + struct gsmd_atcmd *atcmd_fill(const char *cmd, int rlen, + atcmd_cb_t cb, void *ctx, u_int16_t id) + { +@@ -544,36 +540,18 @@ int atcmd_submit(struct gsmd *g, struct gsmd_atcmd *cmd) + { + DEBUGP("submitting command `%s'\n", cmd->buf); + +- if (llist_empty(&g->pending_atcmds)) +- g->gfd_uart.when |= GSMD_FD_WRITE; ++ llist_empty(&g->pending_atcmds); + llist_add_tail(&cmd->list, &g->pending_atcmds); ++ atcmd_wake_queue(g); + + return 0; + } + +-void atcmd_drain(int fd) +-{ +- int rc; +- struct termios t; +- rc = tcflush(fd, TCIOFLUSH); +- rc = tcgetattr(fd, &t); +- DEBUGP("c_iflag = 0x%08x, c_oflag = 0x%08x, c_cflag = 0x%08x, c_lflag = 0x%08x\n", +- t.c_iflag, t.c_oflag, t.c_cflag, t.c_lflag); +- t.c_iflag = t.c_oflag = 0; +- cfmakeraw(&t); +- rc = tcsetattr(fd, TCSANOW, &t); +-} +- + /* init atcmd parser */ +-int atcmd_init(struct gsmd *g, int sockfd) ++int atcmd_init(struct gsmd *g, struct gsmd_port *port) + { + __atcmd_ctx = talloc_named_const(gsmd_tallocs, 1, "atcmds"); + +- g->gfd_uart.fd = sockfd; +- g->gfd_uart.when = GSMD_FD_READ; +- g->gfd_uart.data = g; +- g->gfd_uart.cb = &atcmd_select_cb; +- + INIT_LLIST_HEAD(&g->pending_atcmds); + INIT_LLIST_HEAD(&g->busy_atcmds); + +@@ -581,7 +559,9 @@ int atcmd_init(struct gsmd *g, int sockfd) + + g->mlbuf_len = 0; + g->mlunsolicited = 0; ++ g->clear_to_send = 1; + ++ g->llp.port = port; + g->llp.cur = g->llp.buf; + g->llp.len = sizeof(g->llp.buf); + g->llp.cb = &ml_parse; +@@ -589,5 +569,8 @@ int atcmd_init(struct gsmd *g, int sockfd) + g->llp.ctx = g; + g->llp.flags = LGSM_ATCMD_F_EXTENDED; + +- return gsmd_register_fd(&g->gfd_uart); ++ port->newdata_opaque = g; ++ port->newdata_cb = atcmd_newdata_cb; ++ ++ return 0; + } +diff --git a/src/gsmd/gsmd.c b/src/gsmd/gsmd.c +index 51b4f2c..846bd17 100644 +--- a/src/gsmd/gsmd.c ++++ b/src/gsmd/gsmd.c +@@ -26,7 +26,6 @@ + #include <string.h> + #include <errno.h> + #include <fcntl.h> +-#include <termios.h> + #include <signal.h> + + #define _GNU_SOURCE +@@ -247,56 +246,6 @@ int gsmd_initsettings(struct gsmd *gsmd) + return atcmd_submit(gsmd, cmd); + } + +-struct bdrt { +- int bps; +- u_int32_t b; +-}; +- +-static struct bdrt bdrts[] = { +- { 0, B0 }, +- { 9600, B9600 }, +- { 19200, B19200 }, +- { 38400, B38400 }, +- { 57600, B57600 }, +- { 115200, B115200 }, +- { 230400, B230400 }, +- { 460800, B460800 }, +- { 921600, B921600 }, +-}; +- +-static int set_baudrate(int fd, int baudrate, int hwflow) +-{ +- int i; +- u_int32_t bd = 0; +- struct termios ti; +- +- for (i = 0; i < ARRAY_SIZE(bdrts); i++) { +- if (bdrts[i].bps == baudrate) +- bd = bdrts[i].b; +- } +- if (bd == 0) +- return -EINVAL; +- +- i = tcgetattr(fd, &ti); +- if (i < 0) +- return i; +- +- i = cfsetispeed(&ti, B0); +- if (i < 0) +- return i; +- +- i = cfsetospeed(&ti, bd); +- if (i < 0) +- return i; +- +- if (hwflow) +- ti.c_cflag |= CRTSCTS; +- else +- ti.c_cflag &= ~CRTSCTS; +- +- return tcsetattr(fd, 0, &ti); +-} +- + static int gsmd_initialize(struct gsmd *g) + { + INIT_LLIST_HEAD(&g->users); +@@ -478,14 +427,19 @@ int main(int argc, char **argv) + if (wait >= 0) + g.interpreter_ready = !wait; + +- if (atcmd_init(&g, fd) < 0) { ++ if (uart_init(&g.uart, fd) < 0) { + fprintf(stderr, "can't initialize UART device\n"); + exit(1); + } + +- write(fd, "\r", 1); +- sleep(1); +- atcmd_drain(fd); ++ if (atcmd_init(&g, &g.uart.port) < 0) { ++ fprintf(stderr, "can't initialize AT parser\n"); ++ exit(1); ++ } ++ write(fd, "\r", 1); ++ sleep(1); ++ ++ uart_drain(fd); + + if (usock_init(&g) < 0) { + fprintf(stderr, "can't open unix socket\n"); +diff --git a/src/gsmd/uart.c b/src/gsmd/uart.c +new file mode 100644 +index 0000000..22a4a5c +--- /dev/null ++++ b/src/gsmd/uart.c +@@ -0,0 +1,202 @@ ++/* Wrapper for the physical UART in a struct gsmd_port abstraction. ++ * ++ * Copyright (C) 2007 OpenMoko, Inc. ++ * Written by Andrzej Zaborowski <andrew@openedhand.com> ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of ++ * the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, ++ * MA 02111-1307 USA ++ */ ++ ++#include <string.h> ++#include <fcntl.h> ++#include <termios.h> ++#include <unistd.h> ++#include <errno.h> ++ ++#include "gsmd.h" ++ ++#include <gsmd/gsmd.h> ++ ++void uart_drain(int fd) ++{ ++ int rc; ++ struct termios t; ++ rc = tcflush(fd, TCIOFLUSH); ++ rc = tcgetattr(fd, &t); ++ DEBUGP( ++ "c_iflag = 0x%08x, c_oflag = 0x%08x, " ++ "c_cflag = 0x%08x, c_lflag = 0x%08x\n", ++ t.c_iflag, t.c_oflag, t.c_cflag, t.c_lflag); ++ t.c_iflag = t.c_oflag = 0; ++ cfmakeraw(&t); ++ rc = tcsetattr(fd, TCSANOW, &t); ++} ++ ++struct bdrt { ++ int bps; ++ u_int32_t b; ++}; ++ ++static struct bdrt bdrts[] = { ++ { 0, B0 }, ++ { 9600, B9600 }, ++ { 19200, B19200 }, ++ { 38400, B38400 }, ++ { 57600, B57600 }, ++ { 115200, B115200 }, ++ { 230400, B230400 }, ++ { 460800, B460800 }, ++ { 921600, B921600 }, ++}; ++ ++int set_baudrate(int fd, int baudrate, int hwflow) ++{ ++ int i; ++ u_int32_t bd = 0; ++ struct termios ti; ++ ++ for (i = 0; i < ARRAY_SIZE(bdrts); i++) { ++ if (bdrts[i].bps == baudrate) ++ bd = bdrts[i].b; ++ } ++ if (bd == 0) ++ return -EINVAL; ++ ++ i = tcgetattr(fd, &ti); ++ if (i < 0) ++ return i; ++ ++ i = cfsetispeed(&ti, B0); ++ if (i < 0) ++ return i; ++ ++ i = cfsetospeed(&ti, bd); ++ if (i < 0) ++ return i; ++ ++ if (hwflow) ++ ti.c_cflag |= CRTSCTS; ++ else ++ ti.c_cflag &= ~CRTSCTS; ++ ++ return tcsetattr(fd, 0, &ti); ++} ++ ++static int uart_select_cb(int fd, unsigned int what, void *data) ++{ ++ struct gsmd_uart *uart = (struct gsmd_uart *) data; ++ static char rxbuf[2048]; ++ int rc, len; ++ ++ if ((what & GSMD_FD_READ) && uart->port.newdata_cb) { ++ while ((len = read(fd, rxbuf, sizeof(rxbuf)))) { ++ if (len < 0) { ++ if (errno == EAGAIN || errno == EINTR) ++ return 0; ++ gsmd_log(GSMD_NOTICE, "ERROR reading from " ++ "fd %u: %d (%s)\n", fd, errno, ++ strerror(errno)); ++ return -errno; ++ } ++ ++ rc = uart->port.newdata_cb( ++ uart->port.newdata_opaque, ++ rxbuf, ++ len); ++ if (rc < 0) ++ return rc; ++ } ++ } ++ ++ /* Write pending data to UART. */ ++ if ((what & GSMD_FD_WRITE) && uart->tx_len) { ++ while (uart->tx_start + uart->tx_len >= sizeof(uart->txfifo)) { ++ len = sizeof(uart->txfifo) - uart->tx_start; ++ rc = write(fd, &uart->txfifo[uart->tx_start], len); ++ if (rc < 0 && errno != EINTR) { ++ if (errno == EAGAIN) ++ return 0; ++ gsmd_log(GSMD_NOTICE, "ERROR writing " ++ "fd %u: %d (%s)\n", fd, errno, ++ strerror(errno)); ++ return -errno; ++ } ++ ++ if (rc > 0) { ++ uart->tx_start += rc; ++ uart->tx_len -= rc; ++ } ++ } ++ uart->tx_start &= sizeof(uart->txfifo) - 1; ++ ++ while (uart->tx_len) { ++ rc = write(fd, &uart->txfifo[uart->tx_start], ++ uart->tx_len); ++ if (rc < 0 && errno != EINTR) { ++ if (errno == EAGAIN) ++ return 0; ++ gsmd_log(GSMD_NOTICE, "ERROR writing " ++ "fd %u: %d (%s)\n", fd, errno, ++ strerror(errno)); ++ return -errno; ++ } ++ ++ if (rc > 0) { ++ uart->tx_start += rc; ++ uart->tx_len -= rc; ++ } ++ } ++ ++ /* If we reached here, there's no more data for the moment. */ ++ uart->gfd.when &= ~GSMD_FD_WRITE; ++ } ++ ++ return 0; ++} ++ ++static int uart_write(struct gsmd_port *port, const char data[], int len) ++{ ++ struct gsmd_uart *uart = (struct gsmd_uart *) port; ++ int start = (uart->tx_start + uart->tx_len) & ++ (sizeof(uart->txfifo) - 1); ++ int space = sizeof(uart->txfifo) - start; ++ ++ if (uart->tx_len + len > sizeof(uart->txfifo)) ++ len = sizeof(uart->txfifo) - uart->tx_len; ++ ++ if (len) ++ uart->gfd.when |= GSMD_FD_WRITE; ++ ++ if (len > space) { ++ memcpy(uart->txfifo + start, data, space); ++ memcpy(uart->txfifo, data + space, len - space); ++ } else ++ memcpy(uart->txfifo + start, data, len); ++ ++ uart->tx_len += len; ++ return len; ++} ++ ++int uart_init(struct gsmd_uart *uart, int sockfd) ++{ ++ uart->gfd.fd = sockfd; ++ uart->gfd.when = GSMD_FD_READ; ++ uart->gfd.data = uart; ++ uart->gfd.cb = &uart_select_cb; ++ ++ uart->port.write = uart_write; ++ ++ return gsmd_register_fd(&uart->gfd); ++} +-- +1.5.2.1 + |