[PATCH 2/4] Add handle the case when write buffer is full
If current write_buf is fulled, put it into the full list and fetch a new ring buffer from the free list. --- gatchat/gatserver.c | 63 -- 1 files changed, 60 insertions(+), 3 deletions(-) diff --git a/gatchat/gatserver.c b/gatchat/gatserver.c index 6b40084..b5ac91e 100644 --- a/gatchat/gatserver.c +++ b/gatchat/gatserver.c @@ -130,13 +130,70 @@ static gboolean alloc_free_list(GAtServer *server) return TRUE; } +static gboolean replace_write_buf(GAtServer *server) +{ + struct ring_buffer *free_buf; + + /* Add current buffer into full list and replace current buffer +* by a new free buffer */ + server-full_list = g_slist_append(server-full_list, + server-write_buf); + + /* All free lists are exhausted. Allocate more free lists */ + if (!server-free_list) { + if (!alloc_free_list(server)) { + /* Failed so shutdown the socket */ + g_at_server_shutdown(server); + + return FALSE; + } + } + + free_buf = server-free_list-data; + + server-free_list = g_slist_remove(server-free_list, free_buf); + + server-write_buf = free_buf; + + return TRUE; +} + static void send_common(GAtServer *server, const char *buf) { gsize avail = ring_buffer_avail(server-write_buf); - gsize len = strlen(buf); + gsize towrite = strlen(buf); + gsize bytes_written; + gsize offset = 0; + + if (avail towrite) { + ring_buffer_write(server-write_buf, buf, towrite); - if (avail = len) - ring_buffer_write(server-write_buf, buf, len); + g_at_server_wakeup_writer(server); + + return; + } + + /* Write as much as we can */ + bytes_written = ring_buffer_write(server-write_buf, buf, avail); + towrite -= bytes_written; + offset = bytes_written; + + /* If current write buf is full, replace it with next free buffer */ + if (!replace_write_buf(server)) + return; + + bytes_written = ring_buffer_write(server-write_buf, buf + offset, + towrite); + while (bytes_written towrite) { + /* The next free buf is full, replace with next free one */ + if (!replace_write_buf(server)) + return; + + towrite -= bytes_written; + offset += bytes_written; + bytes_written = ring_buffer_write(server-write_buf, + buf + offset, towrite); + } g_at_server_wakeup_writer(server); } -- 1.6.6.1 ___ ofono mailing list ofono@ofono.org http://lists.ofono.org/listinfo/ofono
[PATCH] Add support of Huawei EM770 modem
Hi, This patch is to enable Huawei EM770 modem, which is a full feature modem that supports voicecall, phonebook, call forwarding, call barring, etc. There are two known parts of code that may have problem and need your comments. 1. Once connecting this modem to PC via USB, we can get 5 tty ports: ttyUSB0, ttyUSB1, ttyUSB2, ttyUSB3 and ttyUSB4. The correct way to talk to this modem is using ttyUSB2. I'm not sure if I handled this correctly in file udev.c. 2. When creating the modem, a global modem id will be appended to the name of it while constructing the path. This modem has name huawei_em770, thus the path becomes things like /huawei_em7700 or /huawei_em7701. This looks strange. Need I change the name of this modem, or can we use some smarter way to append the modem id? There is also one known issue for this modem: The return of CSMS=? from this modem is not compatible with spec. This is deemed as a modem issue, so the sms wouldn't work before this hardware issue get solved. Comments are welcome! Regards, -Yang 0001-Add-support-of-Huawei-EM770-modem.patch Description: 0001-Add-support-of-Huawei-EM770-modem.patch ___ ofono mailing list ofono@ofono.org http://lists.ofono.org/listinfo/ofono
Re: [PATCH 3/4] Add ring_buffer_read_advance for partial write
Hi Zhenhua, These two patches are for server side partial write. When server writes data into non-blocking IO, we first get the read pointer of write_buf and write data as much as we can. Then we advance the read_ptr according to the real bytes written. --- gatchat/ringbuffer.c |8 gatchat/ringbuffer.h |7 +++ 2 files changed, 15 insertions(+), 0 deletions(-) diff --git a/gatchat/ringbuffer.c b/gatchat/ringbuffer.c index 42d5b68..e17c1fa 100644 --- a/gatchat/ringbuffer.c +++ b/gatchat/ringbuffer.c @@ -130,6 +130,14 @@ int ring_buffer_read(struct ring_buffer *buf, void *data, unsigned int len) return len; } +int ring_buffer_read_advance(struct ring_buffer *buf, unsigned int len) +{ + len = MIN(len, buf-in - buf-out); + buf-out += len; + + return len; +} + ring_buffer_drain already does this, that is the one you want to use. Regards, -Denis ___ ofono mailing list ofono@ofono.org http://lists.ofono.org/listinfo/ofono
Re: [PATCH] Add support of Huawei EM770 modem
Hi Yang, There are two known parts of code that may have problem and need your comments. 1. Once connecting this modem to PC via USB, we can get 5 tty ports: ttyUSB0, ttyUSB1, ttyUSB2, ttyUSB3 and ttyUSB4. The correct way to talk to this modem is using ttyUSB2. I'm not sure if I handled this correctly in file udev.c. 2. When creating the modem, a global modem id So Andrew had it exactly correct, you can't just use ttyUSB2 here. Most devices have other udev attributes you can examine for what type of port it is, to help you pick the right one. Perhaps examination of 'udevadm info -- attribute-walk --path=device' might be in order? will be appended to the name of it while constructing the path. This modem has name huawei_em770, thus the path becomes things like /huawei_em7700 or /huawei_em7701. This looks strange. Need I change the name of this modem, or can we use some smarter way to append the modem id? We should be using the udev short serial from the device. For some reason this seems to be failing on the EM770. Can you check whether get_serial returns NULL for this device? Regards, -Denis ___ ofono mailing list ofono@ofono.org http://lists.ofono.org/listinfo/ofono
Re: [PATCH 1/4] Rename buf to read_buf in GAtServer
Hi Zhenhua, Because we may introduce write_buf for sever response buffer. --- This patch has been applied, thanks. Regards, -Denis ___ ofono mailing list ofono@ofono.org http://lists.ofono.org/listinfo/ofono
RFC: Neighbouring Cell Info, take 2
Hi, Revisited proposal for neighbouring cell info based on previous feedback: - Low-level driver API instead of oFono.org DBUS API - Polling based, no automatic periodic updates - Follows definitions in OMA SUPL v2.0 I'm not particular fond of the nested list - wcdma. measured_results_list[].cell_measured_results[], maybe flatten that into a single list? Cheers, Waldo /* * * oFono - Open Source Telephony * * Copyright (C) 2010 Intel Corporation. * * 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 * */ #ifndef __OFONO_CELL_INFO_H #define __OFONO_CELL_INFO_H #ifdef __cplusplus extern C { #endif #include ofono/types.h struct ofono_cell_info; enum ofono_cell_info_type { OFONO_CELL_INFO_GSM = 0, OFONO_CELL_INFO_WCDMA = 1, }; struct ofono_cell_info_results { enum ofono_cell_info_type rat; char mcc[OFONO_MAX_MCC_LENGTH + 1]; char mnc[OFONO_MAX_MNC_LENGTH + 1]; union { struct { int lac;/* Location Area Code (0.65535) */ int ci; /* Cell Identity (0..65535) */ int ta; /* Timing Advance (0..255), -1 = unsupported */ int no_cells; /* Number of valid nmr entries (1..15) */ struct { int arfcn; /* ARFCN of the channel (0..1023) */ int bsic; /* BSIC of the channel (0..63) */ int rxlev; /* Measured power of the channel (0..63) Subtract 110 to get power in dBm */ } nmr[15]; } gsm; struct { int uc; /* Cell Identity, composed of RNC-ID and C-ID (0..268435455) */ int dl_frequency; /* (0..16383), -1 = unsupported */ int ul_frequency; /* (0..16383), -1 = unsupported */ int scrambling_code;/* Primary scrambling code (0..511) */ int no_freq;/* Number of valid measured_results_list entries (1..8) */ struct { int dl_frequency; /* (0..16383), -1 = unsupported */ int ul_frequency; /* (0..16383), -1 = unsupported */ int rssi; /* UTRA-CarrierRSSI (0..76), -1 = unsupported */ int no_cells; /* Number of valid cell_measured_results entries (0..32) */ struct { int ci; /* Cell Identity (0..268435455), -1 = unsupported */ int scrambling_code; /* Primary scrambling code (0..511) */ int ecn0; /* (0..49), -1 = unsupported */ int rscp; /* cpich-RSCP per [3GPP RRC] (0..127), -1 = unsupported */ int pathloss; /* (46..158), -1 = unsupported */ } cell_measured_results[32]; } measured_results_list[8]; } wcdma; }; }; typedef void (*ofono_cell_info_query_cb_t)(const struct ofono_error *error, const struct ofono_cell_info_results results, void *data); struct ofono_cell_info_driver { const char *name; int (*probe)(struct ofono_cell_info *ci, unsigned int vendor, void *data); void (*remove)(struct ofono_cell_info *ci); void (*query)(struct ofono_cell_info *ci, ofono_cell_info_query_cb_t cb, void *data); }; void ofono_cell_info_query(struct ofono_cell_info *ci, ofono_cell_info_query_cb_t cb, void *data); int ofono_cell_info_driver_register(const struct ofono_cell_info_driver *d); void ofono_cel_info_driver_unregister(const struct ofono_cell_info_driver *d); struct ofono_cell_info *ofono_cell_info_create(struct ofono_modem *modem, unsigned int vendor,
Re: [PATCH 1/4] Add write ring buffer for non-blocking write
Hi Padovan, On 02/11/2010 01:23 AM, Gustavo F. Padovan wrote: * Zhenhua Zhangzhenhua.zh...@intel.com [2010-02-10 16:13:40 +0800]: + + for (i = 0; i MAX_BUFFER_NUM; i++) { +#ifdef WRITE_SCHEDULER_DEBUG + buf = ring_buffer_new(4); +#else + buf = ring_buffer_new(4096); +#endif Why not a macro to define buf size? So you don't need to use ifdef everytime #ifdef WRITE_SCHEDULER_DEBUG BUF_SIZE = 4 #else BUF_SIZE = 4096 #endif Good suggestion. We can use a macro to define the buffer size. + if (!buf) + return FALSE; + + server-free_list = g_slist_prepend(server-free_list, buf); + } + + return TRUE; +} + +static void free_ring_buffer(struct ring_buffer *buf) +{ + ring_buffer_free(buf); +} This seems pointless to me. It just remind me to call ring_buffer_free. Yes. I can remove it and call ring_buffer_free in g_slist_foreach() directly. + static void g_at_server_cleanup(GAtServer *server) { /* Cleanup all received data */ ring_buffer_free(server-read_buf); server-read_buf = NULL; + /* Cleanup pending data to write */ + ring_buffer_free(server-write_buf); + server-write_buf = NULL; + + if (server-full_list) + g_slist_foreach(server-full_list, (GFunc)free_ring_buffer, + NULL); + + if (server-free_list) + g_slist_foreach(server-free_list, (GFunc)free_ring_buffer, + NULL); + server-channel = NULL; } @@ -446,8 +507,6 @@ static void read_watcher_destroy_notify(GAtServer *server) g_at_server_cleanup(server); server-read_watch = 0; - server-channel = NULL; - if (server-user_disconnect) server-user_disconnect(server-user_disconnect_data); @@ -455,6 +514,23 @@ static void read_watcher_destroy_notify(GAtServer *server) g_free(server); } +static void write_watcher_destroy_notify(GAtServer *server) +{ + server-write_watch = 0; +} + +static void g_at_server_wakeup_writer(GAtServer *server) +{ + if (server-write_watch != 0) + return; + + server-write_watch = g_io_add_watch_full(server-channel, + G_PRIORITY_DEFAULT, + G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL, + can_write_data, server, + (GDestroyNotify)write_watcher_destroy_notify); +} + static void v250_settings_create(struct v250_settings *v250) { v250-s3 = '\r'; @@ -483,11 +559,22 @@ GAtServer *g_at_server_new(GIOChannel *io) v250_settings_create(server-v250); server-channel = io; server-read_buf = ring_buffer_new(4096); - server-max_read_attempts = 3; - if (!server-read_buf) goto error; +#ifdef WRITE_SCHEDULER_DEBUG + server-write_buf = ring_buffer_new(4); +#else + server-write_buf = ring_buffer_new(4096); +#endif + if (!server-write_buf) + goto error; + + if (!alloc_free_list(server)) + goto error; + + server-max_read_attempts = 3; + if (!g_at_util_setup_io(server-channel, G_IO_FLAG_NONBLOCK)) goto error; @@ -502,6 +589,13 @@ error: if (server-read_buf) ring_buffer_free(server-read_buf); + if (server-write_buf) + ring_buffer_free(server-write_buf); + + if (server-free_list) + g_slist_foreach(server-free_list, (GFunc)free_ring_buffer, + NULL); + if (server) g_free(server); @@ -552,6 +646,9 @@ gboolean g_at_server_shutdown(GAtServer *server) server-user_disconnect = NULL; server-user_disconnect_data = NULL; + if (server-write_watch) + g_source_remove(server-write_watch); + if (server-read_watch) g_source_remove(server-read_watch); -- 1.6.6.1 ___ ofono mailing list ofono@ofono.org http://lists.ofono.org/listinfo/ofono ___ ofono mailing list ofono@ofono.org http://lists.ofono.org/listinfo/ofono
[PATCH 2/3] Add handle the case when write buffer is full
If current write_buf is fulled, put it into the full list and fetch a new ring buffer from the free list. --- gatchat/gatserver.c | 63 -- 1 files changed, 60 insertions(+), 3 deletions(-) diff --git a/gatchat/gatserver.c b/gatchat/gatserver.c index 6e76016..2c160bf 100644 --- a/gatchat/gatserver.c +++ b/gatchat/gatserver.c @@ -132,13 +132,70 @@ static gboolean alloc_free_list(GAtServer *server) return TRUE; } +static gboolean replace_write_buf(GAtServer *server) +{ + struct ring_buffer *free_buf; + + /* Add current buffer into full list and replace current buffer +* by a new free buffer */ + server-full_list = g_slist_append(server-full_list, + server-write_buf); + + /* All free lists are exhausted. Allocate more free lists */ + if (!server-free_list) { + if (!alloc_free_list(server)) { + /* Failed so shutdown the socket */ + g_at_server_shutdown(server); + + return FALSE; + } + } + + free_buf = server-free_list-data; + + server-free_list = g_slist_remove(server-free_list, free_buf); + + server-write_buf = free_buf; + + return TRUE; +} + static void send_common(GAtServer *server, const char *buf) { gsize avail = ring_buffer_avail(server-write_buf); - gsize len = strlen(buf); + gsize towrite = strlen(buf); + gsize bytes_written; + gsize offset = 0; + + if (avail towrite) { + ring_buffer_write(server-write_buf, buf, towrite); - if (avail = len) - ring_buffer_write(server-write_buf, buf, len); + g_at_server_wakeup_writer(server); + + return; + } + + /* Write as much as we can */ + bytes_written = ring_buffer_write(server-write_buf, buf, avail); + towrite -= bytes_written; + offset = bytes_written; + + /* If current write buf is full, replace it with next free buffer */ + if (!replace_write_buf(server)) + return; + + bytes_written = ring_buffer_write(server-write_buf, buf + offset, + towrite); + while (bytes_written towrite) { + /* The next free buf is full, replace with next free one */ + if (!replace_write_buf(server)) + return; + + towrite -= bytes_written; + offset += bytes_written; + bytes_written = ring_buffer_write(server-write_buf, + buf + offset, towrite); + } g_at_server_wakeup_writer(server); } -- 1.6.6.1 ___ ofono mailing list ofono@ofono.org http://lists.ofono.org/listinfo/ofono
[PATCH 1/3] Add write ring buffer for non-blocking write
Use two layers to cache server side response data to client. 1. A fixed-length ring buffer. 2. A list of free ring buffers and a list of empty full ring buffer. If current ring buffer is full, put it into full buffer list and fetch a free buffer frome free list. --- gatchat/gatserver.c | 106 +++ 1 files changed, 98 insertions(+), 8 deletions(-) diff --git a/gatchat/gatserver.c b/gatchat/gatserver.c index bf7e847..6e76016 100644 --- a/gatchat/gatserver.c +++ b/gatchat/gatserver.c @@ -32,6 +32,15 @@ #include ringbuffer.h #include gatserver.h +#define MAX_BUFFER_NUM 5 +#define READ_BUF_SIZE 4096 +/* #define WRITE_SCHEDULER_DEBUG 1 */ +#ifdef WRITE_SCHEDULER_DEBUG +#define WRITE_BUF_SIZE 4 +#else +#define WRITE_BUF_SIZE 4096 +#endif + enum ParserState { PARSER_STATE_IDLE, PARSER_STATE_A, @@ -90,17 +99,50 @@ struct _GAtServer { struct v250_settings v250; /* V.250 command setting */ GIOChannel *channel;/* Server IO */ guint read_watch; /* GSource read id, 0 if none */ + guint write_watch; /* GSource write id, 0 if none */ guint read_so_far; /* Number of bytes processed */ GAtDisconnectFunc user_disconnect; /* User disconnect func */ gpointer user_disconnect_data; /* User disconnect data */ GAtDebugFunc debugf;/* Debugging output function */ gpointer debug_data;/* Data to pass to debug func */ struct ring_buffer *read_buf; /* Current read buffer */ + struct ring_buffer *write_buf; /* Current write buffer */ + GSList *full_list; /* List of full ring buffer */ + GSList *free_list; /* List of free ring buffer */ guint max_read_attempts;/* Max reads per select */ enum ParserState parser_state; gboolean destroyed; /* Re-entrancy guard */ }; +static void g_at_server_wakeup_writer(GAtServer *server); + +static gboolean alloc_free_list(GAtServer *server) +{ + struct ring_buffer *buf; + guint i; + + for (i = 0; i MAX_BUFFER_NUM; i++) { + buf = ring_buffer_new(WRITE_BUF_SIZE); + if (!buf) + return FALSE; + + server-free_list = g_slist_prepend(server-free_list, buf); + } + + return TRUE; +} + +static void send_common(GAtServer *server, const char *buf) +{ + gsize avail = ring_buffer_avail(server-write_buf); + gsize len = strlen(buf); + + if (avail = len) + ring_buffer_write(server-write_buf, buf, len); + + g_at_server_wakeup_writer(server); +} + static void g_at_server_send_result(GAtServer *server, GAtServerResult result) { struct v250_settings v250 = server-v250; @@ -108,7 +150,6 @@ static void g_at_server_send_result(GAtServer *server, GAtServerResult result) char buf[1024]; char t = v250.s3; char r = v250.s4; - gsize wbuf; if (v250.quiet) return; @@ -125,8 +166,7 @@ static void g_at_server_send_result(GAtServer *server, GAtServerResult result) g_at_util_debug_chat(FALSE, buf, strlen(buf), server-debugf, server-debug_data); - g_io_channel_write(server-channel, (char *) buf, strlen(buf), - wbuf); + send_common(server, buf); } static inline gboolean is_at_command_prefix(const char c) @@ -432,12 +472,30 @@ static gboolean received_data(GIOChannel *channel, GIOCondition cond, return TRUE; } +static gboolean can_write_data(GIOChannel *channel, GIOCondition cond, + gpointer data) +{ + return FALSE; +} + static void g_at_server_cleanup(GAtServer *server) { /* Cleanup all received data */ ring_buffer_free(server-read_buf); server-read_buf = NULL; + /* Cleanup pending data to write */ + ring_buffer_free(server-write_buf); + server-write_buf = NULL; + + if (server-full_list) + g_slist_foreach(server-full_list, (GFunc)ring_buffer_free, + NULL); + + if (server-free_list) + g_slist_foreach(server-free_list, (GFunc)ring_buffer_free, + NULL); + server-channel = NULL; } @@ -446,8 +504,6 @@ static void read_watcher_destroy_notify(GAtServer *server) g_at_server_cleanup(server); server-read_watch = 0; - server-channel = NULL; - if (server-user_disconnect) server-user_disconnect(server-user_disconnect_data); @@ -455,6 +511,23 @@ static void read_watcher_destroy_notify(GAtServer *server) g_free(server); }
RE: [PATCH] Add support of Huawei EM770 modem
Hi, Andrew and Denis, -Original Message- From: ofono-boun...@ofono.org [mailto:ofono-boun...@ofono.org] On Behalf Of Denis Kenzior Sent: Thursday, February 11, 2010 6:38 AM To: ofono@ofono.org Subject: Re: [PATCH] Add support of Huawei EM770 modem Hi Yang, There are two known parts of code that may have problem and need your comments. 1. Once connecting this modem to PC via USB, we can get 5 tty ports: ttyUSB0, ttyUSB1, ttyUSB2, ttyUSB3 and ttyUSB4. The correct way to talk to this modem is using ttyUSB2. I'm not sure if I handled this correctly in file udev.c. 2. When creating the modem, a global modem id So Andrew had it exactly correct, you can't just use ttyUSB2 here. Most devices have other udev attributes you can examine for what type of port it is, to help you pick the right one. Perhaps examination of 'udevadm info -- attribute-walk --path=device' might be in order? The check of ttyUSB2 in my code is not the same as you see in /dev directory. Below is the output of this modem along its path (not a full path and I removed some unimportant attributes in each path): looking at device '/devices/pci:00/:00:1a.7/usb1/1-3/1-3:1.2/ttyUSB2/tty/ttyUSB2': (device1) KERNEL==ttyUSB2 SUBSYSTEM==tty DRIVER== looking at parent device '/devices/pci:00/:00:1a.7/usb1/1-3/1-3:1.2/ttyUSB2': (device2) KERNELS==ttyUSB2 SUBSYSTEMS==usb-serial DRIVERS==option1 ATTRS{port_number}==0 looking at parent device '/devices/pci:00/:00:1a.7/usb1/1-3/1-3:1.2': (device3) KERNELS==1-3:1.2 SUBSYSTEMS==usb DRIVERS==option ATTRS{bInterfaceNumber}==02 ATTRS{modalias}==usb:v12D1p1404ddc00dsc00dp00icFFiscFFipFF ATTRS{supports_autosuspend}==0 looking at parent device '/devices/pci:00/:00:1a.7/usb1/1-3':(device4) KERNELS==1-3 ATTRS{configuration}==Huawei Configuration ATTRS{bNumInterfaces}== 5 ATTRS{idVendor}==12d1 ATTRS{idProduct}==1404 ATTRS{manufacturer}==HUAWEI Technology ATTRS{product}==HUAWEI Mobile In oFono code, device4 represents the modem, while device1 is the udev_device when calling function add_huawei_em770(modem, udev_device). When I check if it's ttyUSB2 or not in my code, I think I'm checking the device1 and its sysname (Showed as KERNEL in device1, but not the one showed in /dev directory), and in the context of this modem (device4). I do believe there may be some other ttyUSB2 in the system, for example, we have another em770 modem pluged in. But these two ttyUSB2 are in different context. I ever tried to change the name showed in /dev directory by writing some udev rules, but this sysname (KERNEL) seems stable (It's still ttyUSB2). Is it possible this sysname gets changed under some circumstance expect the kernel or driver changes? If not, I still think it's safe and convenient to check this value here. Maybe we can use another attribute bInterfaceNumber. But this attribute is udev_device's parent's parent (device3), so the code could become more complicated. What's your opinion? will be appended to the name of it while constructing the path. This modem has name huawei_em770, thus the path becomes things like /huawei_em7700 or /huawei_em7701. This looks strange. Need I change the name of this modem, or can we use some smarter way to append the modem id? We should be using the udev short serial from the device. For some reason this seems to be failing on the EM770. Can you check whether get_serial returns NULL for this device? Yes. get_serial() will return NULL, and we just use its type as name. Regards, -Denis ___ ofono mailing list ofono@ofono.org http://lists.ofono.org/listinfo/ofono Regards, -Yang ___ ofono mailing list ofono@ofono.org http://lists.ofono.org/listinfo/ofono
Re: RFC: Neighbouring Cell Info, take 2
to, 2010-02-11 kello 01:23 +0100, ext Bastian, Waldo kirjoitti: Revisited proposal for neighbouring cell info based on previous feedback: - Low-level driver API instead of oFono.org DBUS API - Polling based, no automatic periodic updates - Follows definitions in OMA SUPL v2.0 I like it. I'm not particular fond of the nested list - wcdma. measured_results_list[].cell_measured_results[], maybe flatten that into a single list? I agree it's ugly, but I'd keep it like that in the driver API, and possibly flatten it in the D-Bus API if necessary. struct ofono_cell_info_driver { const char *name; int (*probe)(struct ofono_cell_info *ci, unsigned int vendor, void *data); void (*remove)(struct ofono_cell_info *ci); void (*query)(struct ofono_cell_info *ci, ofono_cell_info_query_cb_t cb, void *data); }; void ofono_cell_info_query(struct ofono_cell_info *ci, ofono_cell_info_query_cb_t cb, void *data); What's this for? Cheers, Aki ___ ofono mailing list ofono@ofono.org http://lists.ofono.org/listinfo/ofono