summaryrefslogtreecommitdiffstats
path: root/src/server/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/util.c')
-rw-r--r--src/server/util.c142
1 files changed, 142 insertions, 0 deletions
diff --git a/src/server/util.c b/src/server/util.c
index bb494c8..4aee886 100644
--- a/src/server/util.c
+++ b/src/server/util.c
@@ -18,12 +18,32 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <gtk/gtk.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <time.h>
+#include <endian.h>
#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
#include "util.h"
#include "net.h"
+#include "gtk.h"
+
+struct child_data {
+ char **argv;
+ int fd;
+ char *buf;
+};
static float digest_temp(const short int rawtemp);
static float digest_volt(const short int rawvolt);
+static int find_settings_region(char *start, char *end, char *buf, size_t n);
+static int flash(char *buf, size_t address, size_t size, char* port);
+void reap_dead_children(int pid, int status, void *data);
/*
* raw data is in 0.1°K per 1. Subtract 2730 to get Celsius.
@@ -57,3 +77,125 @@ int refresh_data(int nd, struct tempmodule_state *state)
return ret;
}
+
+
+int write_settings(char *imagename, const struct configuration * const conf)
+{
+ /* the largest flash size supported by ESP-8266 is 16MiB, so let's just use that. */
+ static const size_t flash_size = 16 * 1024 * 1024;
+ char pattern_a[4] = PADDING_START;
+ char pattern_b[4] = PADDING_END;
+ ssize_t buf_used;
+ ssize_t offset;
+ char *buf = NULL;
+ int fd;
+ int ret = ERROR;
+
+ fd = open(imagename, O_RDONLY);
+ if (fd < 0) {
+ goto fail;
+ }
+ buf = malloc(flash_size);
+ buf_used = read(fd, buf, flash_size);
+ close(fd);
+ if (buf_used < sizeof(struct configuration)) {
+ goto fail;
+ }
+
+ offset = find_settings_region(pattern_a, pattern_b, buf, buf_used);
+ if (offset == ERROR) {
+ goto fail;
+ };
+
+ memcpy(buf + offset, conf, sizeof(struct configuration));
+ /* make sure the block written is aligned on 4k boundry
+ * and is 4k of size.
+ *
+ * see:
+ * https://github.com/espressif/esptool/issues/306
+ */
+ offset &= ~(0xfff);
+ ret = flash(buf + offset, offset, 4 * 1024, NULL);
+
+fail:
+ free(buf);
+ return ret;
+}
+
+static int find_settings_region(char *start, char *end, char *buf, size_t n)
+{
+ int ret = ERROR;
+ char *a;
+
+ if (!(a = memmem(buf, n, start, 4))) {
+ goto fail;
+ }
+
+ if ((a - buf + sizeof(struct configuration)) > n) {
+ goto fail;
+ }
+
+ if (memcmp(a + sizeof(struct configuration) - 4, end, 4)) {
+ goto fail;
+ }
+
+ ret = a - buf;
+fail:
+ return ret;
+}
+
+static int flash(char *buf, size_t address, size_t size, char* port)
+{
+ static const char esptool[] = "esptool.py";
+ static const char command[] = "write_flash";
+ struct child_data *cdata;
+ char tmpfn[] = "espXXXXXX"; /* temporary file name template */
+ char *fifn; /* flash image file name */
+ char textbuf[32];
+ char *argv[7] = {0};
+ int ret = ERROR;
+ pid_t pid;
+ int fd;
+ size_t i = 1;
+
+ fd = mkstemp(tmpfn);
+ write(fd, buf, size);
+ fifn = malloc(0x100);
+ memset(fifn, '\0', 0x100);
+ sprintf(textbuf, "/proc/self/fd/%d", fd);
+ if (readlink(textbuf, fifn, 0x100) == -1) {
+ exit(TMPFILE);
+ }
+
+ argv[0] = strdup(esptool);
+ if (port) {
+ argv[i++] = strdup("--port");
+ argv[i++] = strdup(port);
+ }
+ argv[i++] = strdup(command);
+ sprintf(textbuf, "%#.4lx", address);
+ argv[i++] = strdup(textbuf);
+ argv[i++] = strdup(fifn);
+ argv[i] = NULL;
+
+ cdata = malloc(sizeof(*cdata));
+ cdata->argv = argv;
+ cdata->fd = fd;
+ cdata->buf = fifn;
+
+ g_spawn_async_with_pipes(NULL, argv, NULL, G_SPAWN_SEARCH_PATH | G_SPAWN_LEAVE_DESCRIPTORS_OPEN | G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, &pid, NULL, NULL, NULL, NULL);
+ g_child_watch_add(pid, reap_dead_children, cdata);
+ return ret;
+}
+
+void reap_dead_children(int pid, int status, void *data)
+{
+ struct child_data *a;
+
+ a = data;
+ free(a->buf);
+ close(a->fd);
+ free(data);
+ g_spawn_close_pid(pid);
+ gtkui_dialog_done(status);
+}