summaryrefslogtreecommitdiffstats
path: root/gisi
diff options
context:
space:
mode:
authorAki Niemi <aki.niemi@nokia.com>2010-11-16 17:06:11 +0200
committerAki Niemi <aki.niemi@nokia.com>2010-12-22 17:13:47 +0200
commit50f6b061054d1aa323521fa25c5e6c9576712f72 (patch)
treece7724af8e02f09b19413275c3188919e9d71e30 /gisi
parenta1d8fb8c72813186b4fbb0e67bd819574ddcb074 (diff)
downloadofono-50f6b061054d1aa323521fa25c5e6c9576712f72.tar.bz2
gisi: Split indication to use separate socket
Some resources send INDs with non-zero unique transaction ID, which can conflict with pending RESPs. To fix this, we use two sockets, one dedicated for INDs, and one dedicated to REQs, NTFs and RESPs.
Diffstat (limited to 'gisi')
-rw-r--r--gisi/modem.c63
1 files changed, 42 insertions, 21 deletions
diff --git a/gisi/modem.c b/gisi/modem.c
index 72b90047..55d69af3 100644
--- a/gisi/modem.c
+++ b/gisi/modem.c
@@ -56,8 +56,10 @@ struct _GIsiModem {
unsigned index;
GHashTable *services;
gboolean subs_pending;
- int fd;
- guint source;
+ int req_fd;
+ int ind_fd;
+ guint req_watch;
+ guint ind_watch;
GIsiNotifyFunc debug;
void *ddata;
};
@@ -134,7 +136,8 @@ static void pending_dispatch(GIsiPending *pend, GIsiMessage *msg)
pend->notify(msg, pend->data);
}
-static void service_dispatch(GIsiServiceMux *mux, GIsiMessage *msg)
+static void service_dispatch(GIsiServiceMux *mux, GIsiMessage *msg,
+ gboolean is_indication)
{
uint8_t msgid = g_isi_msg_id(msg);
uint8_t utid = g_isi_msg_utid(msg);
@@ -166,7 +169,7 @@ static void service_dispatch(GIsiServiceMux *mux, GIsiMessage *msg)
pending_dispatch(pend, msg);
} else if (pend->type == GISI_MESSAGE_TYPE_RESP &&
- pend->utid == utid) {
+ !is_indication && pend->utid == utid) {
pending_dispatch(pend, msg);
pend->notify = NULL;
@@ -230,12 +233,14 @@ static gboolean isi_callback(GIOChannel *channel, GIOCondition cond,
{
GIsiModem *modem = data;
int len;
+ int fd;
if (cond & (G_IO_NVAL|G_IO_HUP)) {
g_warning("Unexpected event on PhoNet channel %p", channel);
return FALSE;
}
+ fd = g_io_channel_unix_get_fd(channel);
len = g_isi_phonet_peek_length(channel);
if (len > 0) {
@@ -273,7 +278,7 @@ static gboolean isi_callback(GIOChannel *channel, GIOCondition cond,
if (g_isi_msg_id(&msg) == COMMON_MESSAGE)
common_message_decode(mux, &msg);
- service_dispatch(mux, &msg);
+ service_dispatch(mux, &msg, fd == modem->ind_fd);
}
return TRUE;
}
@@ -281,7 +286,8 @@ static gboolean isi_callback(GIOChannel *channel, GIOCondition cond,
GIsiModem *g_isi_modem_create(unsigned index)
{
GIsiModem *modem;
- GIOChannel *channel;
+ GIOChannel *inds;
+ GIOChannel *reqs;
if (index == 0) {
errno = ENODEV;
@@ -294,17 +300,25 @@ GIsiModem *g_isi_modem_create(unsigned index)
return NULL;
}
- channel = g_isi_phonet_new(index);
- if (!channel) {
+ inds = g_isi_phonet_new(index);
+ reqs = g_isi_phonet_new(index);
+
+ if (!inds || !reqs) {
g_free(modem);
return NULL;
}
- modem->fd = g_io_channel_unix_get_fd(channel);
- modem->source = g_io_add_watch(channel,
+ modem->req_fd = g_io_channel_unix_get_fd(reqs);
+ modem->req_watch = g_io_add_watch(reqs,
+ G_IO_IN|G_IO_ERR|G_IO_HUP|G_IO_NVAL,
+ isi_callback, modem);
+ modem->ind_fd = g_io_channel_unix_get_fd(inds);
+ modem->ind_watch = g_io_add_watch(inds,
G_IO_IN|G_IO_ERR|G_IO_HUP|G_IO_NVAL,
isi_callback, modem);
- g_io_channel_unref(channel);
+
+ g_io_channel_unref(reqs);
+ g_io_channel_unref(inds);
modem->index = index;
modem->services = g_hash_table_new_full(g_int_hash, g_int_equal,
@@ -328,7 +342,7 @@ static void service_name_register(GIsiServiceMux *mux)
};
uint16_t object = 0;
- if (ioctl(mux->modem->fd, SIOCPNGETOBJECT, &object) < 0) {
+ if (ioctl(mux->modem->req_fd, SIOCPNGETOBJECT, &object) < 0) {
g_warning("ioctl(SIOCPNGETOBJECT): %s", strerror(errno));
return;
}
@@ -337,8 +351,8 @@ static void service_name_register(GIsiServiceMux *mux)
msg[8] = object >> 8;
msg[9] = object & 0xFF;
- sendto(mux->modem->fd, msg, sizeof(msg), MSG_NOSIGNAL, (void *)&namesrv,
- sizeof(namesrv));
+ sendto(mux->modem->req_fd, msg, sizeof(msg), MSG_NOSIGNAL,
+ (void *)&namesrv, sizeof(namesrv));
}
static void service_name_deregister(GIsiServiceMux *mux)
@@ -348,8 +362,8 @@ static void service_name_deregister(GIsiServiceMux *mux)
0, 0, 0, mux->resource,
};
- sendto(mux->modem->fd, msg, sizeof(msg), MSG_NOSIGNAL, (void *)&namesrv,
- sizeof(namesrv));
+ sendto(mux->modem->req_fd, msg, sizeof(msg), MSG_NOSIGNAL,
+ (void *)&namesrv, sizeof(namesrv));
}
static gboolean modem_subs_update(gpointer data)
@@ -376,7 +390,7 @@ static gboolean modem_subs_update(gpointer data)
}
msg[2] = count;
- sendto(modem->fd, msg, 3 + msg[2], MSG_NOSIGNAL, (void *)&commgr,
+ sendto(modem->ind_fd, msg, 3 + msg[2], MSG_NOSIGNAL, (void *)&commgr,
sizeof(commgr));
modem->subs_pending = FALSE;
@@ -485,6 +499,13 @@ void g_isi_modem_destroy(GIsiModem *modem)
g_hash_table_foreach_remove(modem->services, service_finalize, modem);
g_hash_table_unref(modem->services);
+
+ if (modem->ind_watch)
+ g_source_remove(modem->ind_watch);
+
+ if (modem->req_watch)
+ g_source_remove(modem->req_watch);
+
g_free(modem);
}
@@ -641,7 +662,7 @@ GIsiPending *g_isi_request_vsendto(GIsiModem *modem, struct sockaddr_pn *dst,
if (modem->debug)
vdebug(dst, _iov, 1 + iovlen, len, modem->debug, modem->ddata);
- ret = sendmsg(modem->fd, &msg, MSG_NOSIGNAL);
+ ret = sendmsg(modem->req_fd, &msg, MSG_NOSIGNAL);
if (ret == -1)
goto error;
@@ -866,7 +887,7 @@ int g_isi_modem_vsendto(GIsiModem *modem, struct sockaddr_pn *dst,
if (modem->debug)
vdebug(dst, iov, iovlen, len, modem->debug, modem->ddata);
- ret = sendmsg(modem->fd, &msg, MSG_NOSIGNAL);
+ ret = sendmsg(modem->req_fd, &msg, MSG_NOSIGNAL);
if (ret == -1)
return -errno;
@@ -903,8 +924,8 @@ static int version_get_send(GIsiModem *modem, GIsiPending *ping)
if (g_slist_find_custom(mux->pending, ping, utid_equal))
return -EBUSY;
- ret = sendto(modem->fd, msg, sizeof(msg), MSG_NOSIGNAL, (void *)&dst,
- sizeof(dst));
+ ret = sendto(modem->req_fd, msg, sizeof(msg), MSG_NOSIGNAL,
+ (void *)&dst, sizeof(dst));
if (ret == -1)
return -errno;