Merge branch 'gnss_cleanup' into 'master'

Fix various small issues in the gnss assistance data upload code

Closes #20

See merge request mobian1/devices/eg25-manager!29
This commit is contained in:
Arnaud Ferraris
2021-09-29 21:05:08 +00:00

View File

@@ -8,8 +8,13 @@
#include "manager.h"
#include "at.h"
#include <sys/sendfile.h>
#include <sys/stat.h>
#include <errno.h>
#define BUFFER_SIZE 256
#define UPLOAD_DELAY 100000
#define UPLOAD_DELAY_US 10000
#define UPLOAD_TIMEOUT_S 10
#define RESCHEDULE_IN_SECS 30
static void gnss_step(struct EG25Manager *manager);
@@ -195,71 +200,71 @@ static void state_at_gnss(struct EG25Manager *manager)
static void fetch_assistance_data(struct EG25Manager *manager)
{
CURL *curl;
CURLcode response;
long status_code;
gchar *url = NULL;
curl_off_t downloaded;
CURL *curl = NULL;
g_autofree gchar *url = NULL;
FILE *tmp_file = NULL;
long int size;
gchar errbuf[CURL_ERROR_SIZE];
errbuf[0] = 0;
/* Fetch assistance data with curl */
tmp_file = fdopen(manager->gnss_assistance_fd, "wb+");
if (tmp_file == NULL) {
g_critical("Unable to open file to save assistance data: %s",
g_strerror(errno));
goto bail;
}
lseek(manager->gnss_assistance_fd, 0, SEEK_SET);
ftruncate(manager->gnss_assistance_fd, 0);
url = g_strconcat(manager->gnss_assistance_url, "/",
manager->gnss_assistance_file, NULL);
curl = curl_easy_init();
if (!curl)
g_error ("Unable to initialize curl");
if (!curl) {
g_critical("Unable to initialize curl");
goto bail;
}
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, NULL);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, tmp_file);
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L);
response = curl_easy_perform(curl);
if (response == CURLE_HTTP_RETURNED_ERROR) {
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &status_code);
curl_easy_cleanup(curl);
g_warning ("Unable to fetch GNSS assistance data from %s (HTTP %ld)",
url, status_code);
/* Restart upload on HTTP error status code */
g_message ("Rescheduling upload because of failure in %ds",
RESCHEDULE_IN_SECS);
manager->gnss_assistance_step = EG25_GNSS_STEP_LAST;
g_timeout_add_seconds(RESCHEDULE_IN_SECS,
G_SOURCE_FUNC(gnss_upload_assistance_data),
manager);
return;
response = curl_easy_perform(curl);
if (response != CURLE_OK) {
g_warning("Unable to fetch GNSS assistance data from %s: %s",
url, strlen(errbuf) ? errbuf : curl_easy_strerror(response));
goto bail;
}
/* Get file size in bytes */
size = (long int)lseek(manager->gnss_assistance_fd, 0, SEEK_END);
lseek(manager->gnss_assistance_fd, 0, SEEK_SET);
if (size <= 0) {
g_warning ("GNSS assistance data contains 0 bytes,"
"check network connection.");
/*
* Restart upload when file does not contain any data,
* mostly because of no network connection.
*/
g_message ("Rescheduling upload because of failure in %ds",
RESCHEDULE_IN_SECS);
manager->gnss_assistance_step = EG25_GNSS_STEP_LAST;
g_timeout_add_seconds(RESCHEDULE_IN_SECS,
G_SOURCE_FUNC(gnss_upload_assistance_data),
manager);
return;
response = curl_easy_getinfo(curl, CURLINFO_SIZE_DOWNLOAD_T, &downloaded);
if (response) {
g_critical("Unable to get number of downloaded bytes from curl");
goto bail;
} else if (downloaded <= 0) {
g_warning("Downloaded empty assistance data file");
goto bail;
}
g_message("Fetching GNSS assistance data from %s was successfull", url);
fflush(tmp_file);
curl_easy_cleanup(curl);
g_free(url);
/* Go to the next step */
manager->gnss_assistance_step++;
gnss_step(manager);
return;
bail:
if (curl != NULL)
curl_easy_cleanup(curl);
manager->gnss_assistance_step = EG25_GNSS_STEP_LAST;
}
/******************************************************************************/
@@ -279,18 +284,24 @@ static void init_assistance_data_upload_start(struct EG25Manager *manager,
const char *response)
{
gchar value[BUFFER_SIZE];
long int size;
off_t size;
/* Process AT response */
at_process_result(manager, response);
/* Get file size in bytes */
size = (long int)lseek(manager->gnss_assistance_fd, 0, SEEK_END);
size = lseek(manager->gnss_assistance_fd, 0, SEEK_END);
if (size == -1) {
g_critical("gnss: unable to read size of xtra data file: %s", g_strerror(errno));
manager->gnss_assistance_step = EG25_GNSS_STEP_LAST;
return;
}
lseek(manager->gnss_assistance_fd, 0, SEEK_SET);
/* Start upload */
g_snprintf(value, BUFFER_SIZE, "\"RAM:%s\",%ld\r\n",
manager->gnss_assistance_file, size);
g_snprintf(value, BUFFER_SIZE, "\"RAM:%s\",%ld,%d",
manager->gnss_assistance_file, size, UPLOAD_TIMEOUT_S);
g_message("Initiate GNSS assistance data upload: %s", value);
at_append_command(manager, "QFUPL", NULL, value, NULL,
init_assistance_data_upload_ready);
@@ -310,39 +321,39 @@ static void init_assistance_data_upload(struct EG25Manager *manager)
static void upload_assistance_data(struct EG25Manager *manager)
{
char buffer[2*BUFFER_SIZE];
gint len;
gboolean success = TRUE;
gint error;
glong written_total = 0;
gint ret;
struct stat sb;
/* Copy downloaded XTRA assistance data to the modem over serial */
while((len = read(manager->gnss_assistance_fd, buffer, 2*BUFFER_SIZE)) > 0)
{
len = write(manager->at_fd, buffer, len);
if (len < 0) {
success = FALSE;
g_error("Writing GNSS assistance data failed: %d", len);
break;
}
usleep(UPLOAD_DELAY);
g_message("Uploaded %d bytes", len);
if (fstat(manager->gnss_assistance_fd, &sb) != 0) {
g_critical("gnss: unable to stat xtra data file: %s", g_strerror(errno));
/* Make sure the upload times out and the modem goes back to AT command mode */
sleep(UPLOAD_TIMEOUT_S + 1);
manager->gnss_assistance_step = EG25_GNSS_STEP_LAST;
return;
}
do {
errno = 0;
/* Copy downloaded XTRA assistance data to the modem over serial */
ret = sendfile(manager->at_fd, manager->gnss_assistance_fd, &written_total, sb.st_size);
error = errno;
usleep(UPLOAD_DELAY_US);
} while ((!error && written_total < sb.st_size) || (ret == -1 && error == EAGAIN));
/* Clear QFUPL AT command and process next */
at_next_command(manager);
/* Go to the next step if successful */
if (success) {
if (!error) {
g_message("Successfully uploaded %ld bytes to the modem", written_total);
manager->gnss_assistance_step++;
gnss_step(manager);
}
/* Restart upload */
else {
g_message ("Rescheduling upload because of failure in %ds",
RESCHEDULE_IN_SECS);
} else {
g_critical("Unable to upload xtra data: %s", g_strerror(error));
manager->gnss_assistance_step = EG25_GNSS_STEP_LAST;
g_timeout_add_seconds(RESCHEDULE_IN_SECS,
G_SOURCE_FUNC(gnss_upload_assistance_data),
manager);
}
}
@@ -385,9 +396,9 @@ static void finish_assistance_data_upload(struct EG25Manager *manager)
#ifdef HAVE_MMGLIB
static void enable_mm_gnss(struct EG25Manager *manager)
{
MMModemLocationSource sources;
gboolean signal_location;
g_autoptr (GError) error = NULL;
MMModemLocationSource sources = mm_modem_location_get_enabled(manager->mm_location);
gboolean signal_location = mm_modem_location_signals_location(manager->mm_location);
if (manager->gnss_sources & EG25_GNSS_SOURCE_UNMANAGED)
sources |= MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED;
@@ -396,8 +407,6 @@ static void enable_mm_gnss(struct EG25Manager *manager)
if (manager->gnss_sources & EG25_GNSS_SOURCE_RAW)
sources |= MM_MODEM_LOCATION_SOURCE_GPS_RAW;
sources = mm_modem_location_get_enabled(manager->mm_location);
signal_location = mm_modem_location_signals_location(manager->mm_location);
mm_modem_location_setup_sync(manager->mm_location, sources,
signal_location, NULL, &error);
if (error != NULL)