diff --git a/Makefile.am b/Makefile.am index fcf6771b..6d0f3be9 100644 --- a/Makefile.am +++ b/Makefile.am @@ -42,7 +42,7 @@ gdbus_sources = gdbus/gdbus.h gdbus/mainloop.c gdbus/object.c gdbus/watch.c gisi_sources = gisi/phonet.h gisi/modem.h gisi/netlink.h gisi/netlink.c \ gisi/socket.h gisi/socket.c gisi/client.h gisi/client.c \ gisi/pep.h gisi/pep.c gisi/pipe.h gisi/pipe.c gisi/iter.h \ - gisi/iter.c + gisi/iter.c gisi/verify.c gatchat_sources = gatchat/gatchat.h gatchat/gatchat.c \ gatchat/gatresult.h gatchat/gatresult.c \ diff --git a/gisi/client.c b/gisi/client.c index b3f685be..c592c3c9 100644 --- a/gisi/client.c +++ b/gisi/client.c @@ -41,6 +41,10 @@ struct _GIsiClient { uint8_t resource; + struct { + int major; + int minor; + } version; GIsiModem *modem; /* Requests */ @@ -100,6 +104,8 @@ GIsiClient *g_isi_client_create(GIsiModem *modem, uint8_t resource) abort(); cl = ptr; cl->resource = resource; + cl->version.major = -1; + cl->version.minor = -1; cl->modem = modem; cl->debug_func = NULL; memset(cl->timeout, 0, sizeof(cl->timeout)); @@ -132,6 +138,43 @@ GIsiClient *g_isi_client_create(GIsiModem *modem, uint8_t resource) return cl; } +/** + * Set the ISI resource version of @a client. + * @param client client for the resource + * @param major ISI major version + * @param minor ISI minor version + */ +void g_isi_version_set(GIsiClient *client, int major, int minor) +{ + if (!client) + return; + + client->version.major = major; + client->version.minor = minor; +} + +/** + * Returns the ISI major version of the resource associated with @a + * client. + * @param client client for the resource + * @return major version, -1 if not available + */ +int g_isi_version_major(GIsiClient *client) +{ + return client->version.major; +} + +/** + * Returns the ISI minor version of the resource associated with @a + * client. + * @param client client for the resource + * @return minor version, -1 if not available + */ +int g_isi_version_minor(GIsiClient *client) +{ + return client->version.minor; +} + /** * Returns the resource associated with @a client * @param client client for the resource diff --git a/gisi/client.h b/gisi/client.h index 448f9e5c..d0c0c4b5 100644 --- a/gisi/client.h +++ b/gisi/client.h @@ -38,6 +38,8 @@ typedef struct _GIsiClient GIsiClient; struct _GIsiRequest; typedef struct _GIsiRequest GIsiRequest; +typedef void (*GIsiVerifyFunc)(GIsiClient *client, bool alive, void *opaque); + typedef bool (*GIsiResponseFunc)(GIsiClient *client, const void *restrict data, size_t len, uint16_t object, void *opaque); @@ -51,8 +53,15 @@ typedef void (*GIsiDebugFunc) (const void *restrict data, size_t len, GIsiClient *g_isi_client_create(GIsiModem *modem, uint8_t resource); +GIsiRequest *g_isi_verify(GIsiClient *client, GIsiVerifyFunc func, + void *opaque); + uint8_t g_isi_client_resource(GIsiClient *client); +void g_isi_version_set(GIsiClient *client, int major, int minor); +int g_isi_version_major(GIsiClient *client); +int g_isi_version_minor(GIsiClient *client); + void g_isi_client_set_debug(GIsiClient *client, GIsiDebugFunc func, void *opaque); diff --git a/gisi/verify.c b/gisi/verify.c new file mode 100644 index 00000000..f94aeea9 --- /dev/null +++ b/gisi/verify.c @@ -0,0 +1,106 @@ +/* + * This file is part of oFono - Open Source Telephony + * + * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). + * + * Contact: RĂ©mi Denis-Courmont + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include "client.h" + +#define VERSION_TIMEOUT 5 + +#define COMMON_MESSAGE 0xF0 +#define COMM_ISI_VERSION_GET_REQ 0x12 +#define COMM_ISI_VERSION_GET_RESP 0x13 +#define COMM_ISA_ENTITY_NOT_REACHABLE_RESP 0x14 + +struct verify_data { + void *func; + void *data; +}; + +static bool verify_cb(GIsiClient *client, const void *restrict data, + size_t len, uint16_t object, void *opaque) +{ + const uint8_t *msg = data; + struct verify_data *vd = opaque; + GIsiVerifyFunc func = vd->func; + + bool alive = false; + + if(!msg) + goto out; + + if (len < 4 || msg[0] != COMMON_MESSAGE) + goto out; + + if (msg[1] == COMM_ISI_VERSION_GET_RESP) { + g_isi_version_set(client, msg[2], msg[3]); + alive = true; + goto out; + } + + if (msg[1] != COMM_ISA_ENTITY_NOT_REACHABLE_RESP) + alive = true; + +out: + if (func) + func(client, alive, vd->data); + g_free(vd); + return true; +} + +/** + * Verifies reachability of @a client with its resource. As a side + * effect of this liveliness check, the ISI version of the client + * resource will be made available via g_isi_client_version(). + * @param client client to verify + * @param func callback to process outcome + * @param opaque user data + * @return NULL on error (see errno), GIsiRequest pointer on success. + */ +GIsiRequest *g_isi_verify(GIsiClient *client, GIsiVerifyFunc func, + void *opaque) +{ + struct verify_data *data = g_try_new0(struct verify_data, 1); + GIsiRequest *req = NULL; + uint8_t msg[] = { + COMMON_MESSAGE, + COMM_ISI_VERSION_GET_REQ, + 0x00 /* Filler */ + }; + + data->func = func; + data->data = opaque; + + req = g_isi_request_make(client, msg, sizeof(msg), VERSION_TIMEOUT, + verify_cb, data); + if (!req) + g_free(data); + + return req; +}