summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWolfgang Wiedmeyer <wolfgit@wiedmeyer.de>2017-07-19 00:56:25 +0200
committerWolfgang Wiedmeyer <wolfgit@wiedmeyer.de>2017-07-19 01:28:33 +0200
commit63058d5bdb8a50fe650a7b91f6c6e29bdaf583b9 (patch)
tree8f6421038b0ff586cc0e99981ed35109c55cc736
parent9af74e1e2707bee3dcbf1008682566d330418d8a (diff)
downloadi9305_modem-63058d5bdb8a50fe650a7b91f6c6e29bdaf583b9.zip
i9305_modem-63058d5bdb8a50fe650a7b91f6c6e29bdaf583b9.tar.gz
i9305_modem-63058d5bdb8a50fe650a7b91f6c6e29bdaf583b9.tar.bz2
various fixes and improvements, mostly for EFS sync
EFS data is sometimes successfully received and the modem stays online because the reset after the sync works (even if the EFS sync itself fails). EFS data is not yet written to the partition. This needs to be implemented. When EFS data is read, timeouts are now checked and the data is read in chunks which mirrors the behaviour of the kickstart tool. Strangely enough, occasionally after receiving the first package, that is below the maximum size, a timeout happens and the complete data is never received during all runs. Either the modem is not sending the complete data for whatever reason or there is still something wrong with the command chain. Signed-off-by: Wolfgang Wiedmeyer <wolfgit@wiedmeyer.de>
-rw-r--r--boot.c5
-rw-r--r--i9305.h1
-rw-r--r--sahara.c98
-rw-r--r--sahara.h4
4 files changed, 80 insertions, 28 deletions
diff --git a/boot.c b/boot.c
index d22de18..4198f90 100644
--- a/boot.c
+++ b/boot.c
@@ -53,7 +53,7 @@ int configure_tty(int *tty_fd, time_t timeout_sec, long int timeout_usec)
timeout.tv_sec = timeout_sec;
timeout.tv_usec = timeout_usec;
- rc = select(tty_dev+1, NULL, &fds, NULL, &timeout);
+ rc = select(tty_dev+1, &fds, NULL, NULL, &timeout);
if (rc <= 0) {
printf("failed to set timeout\n");
return -1;
@@ -69,6 +69,7 @@ int main()
int mdm_dev, tty_dev;
int mode;
struct sah_data_end_ack data_end_ack;
+ int hellos = 0;
int rc;
mdm_dev = open(MDM_DEVICE, O_RDONLY | O_NONBLOCK);
@@ -141,7 +142,7 @@ int main()
}
while (1) {
- rc = handle_memory_debug(tty_dev);
+ rc = handle_memory_debug(tty_dev, &hellos);
if (rc < 0) {
printf("error during modem operation\n");
return -1;
diff --git a/i9305.h b/i9305.h
index e374ef8..f11f7c2 100644
--- a/i9305.h
+++ b/i9305.h
@@ -28,6 +28,7 @@
#define WAIT_FOR_RESTART _IOR(CHARM_CODE, 7, int)
#define MAX_DATA_SEND_SIZE 1*1024*1024
+#define MAX_MEMORY_CHUNK_SIZE 16383
// files to upload
#define FILE_APPS "/firmware/image/apps.mbn"
diff --git a/sahara.c b/sahara.c
index 2533759..6d93ad1 100644
--- a/sahara.c
+++ b/sahara.c
@@ -37,31 +37,41 @@ int check_mode(int mode_recv, int mode_expected)
return -1;
}
-int hello_response(int tty_fd, int mode)
+int read_hello_data(int tty_fd, int mode, struct sah_hello_req *hello_req)
{
- struct sah_hello_req hello_req;
- struct sah_hello_resp hello_resp;
int rc;
- rc = read(tty_fd, &hello_req, sizeof(hello_req));
+ rc = read(tty_fd, hello_req, sizeof(*hello_req));
if (rc < (int) sizeof(hello_req)) {
printf("error receiving hello, wrong packet size\n");
return -1;
}
- rc = check_mode(hello_req.mode, mode);
+ rc = check_mode(hello_req->mode, mode);
if (rc < 0) {
printf("mode %d is not the expected mode %d\n",
- hello_req.mode, mode);
+ hello_req->mode, mode);
return -1;
}
+ return 0;
+}
+
+int hello_response(int tty_fd, int mode)
+{
+ struct sah_hello_req hello_req;
+ struct sah_hello_resp hello_resp;
+ int rc;
+
+ read_hello_data(tty_fd, mode, &hello_req);
+
hello_resp.header.command = SAH_COMMAND_HELLO_RESP;
hello_resp.header.packet_size = sizeof(hello_resp);
hello_resp.version = hello_req.version;
hello_resp.min_version = hello_req.min_version;
hello_resp.status = 0;
hello_resp.mode = hello_req.mode;
+ memcpy(hello_resp.appended, hello_req.appended, sizeof(hello_req.appended));
rc = write(tty_fd, &hello_resp, sizeof(hello_resp));
if (rc < (int) sizeof(hello_resp)) {
@@ -260,7 +270,12 @@ int check_efs_file_request(unsigned char name[20])
int request_efs_data(int tty_fd,
struct sah_memory_read_req memory_read_req)
{
+ char chunk_data[MAX_MEMORY_CHUNK_SIZE];
char file_data[MAX_DATA_SEND_SIZE];
+ unsigned int size_read = 0;
+ fd_set fds;
+ struct timeval timeout;
+ int size;
int rc;
rc = write(tty_fd, &memory_read_req, sizeof(memory_read_req));
@@ -269,10 +284,33 @@ int request_efs_data(int tty_fd,
return -1;
}
- rc = read(tty_fd, &file_data, memory_read_req.size);
- if (rc < (int) memory_read_req.size) {
- printf("failed to read memory table data\n");
- return -1;
+ FD_ZERO(&fds);
+ FD_SET(tty_fd, &fds);
+
+ while (size_read < memory_read_req.size) {
+ if (memory_read_req.size - size_read > MAX_MEMORY_CHUNK_SIZE)
+ size = MAX_MEMORY_CHUNK_SIZE;
+ else
+ size = memory_read_req.size - size_read;
+
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 500000;
+ rc = select(tty_fd+1, &fds, NULL, NULL, &timeout);
+ if (rc <= 0) {
+ printf("failed to set timeout\n");
+ return -1;
+ }
+ rc = read(tty_fd, &chunk_data, size);
+ if (rc < 1) {
+ printf("failed to read memory table data\n");
+ printf("received %d out of %d\n", rc, size);
+ printf("%d of %d read so far\n", size_read,
+ memory_read_req.size);
+ return -1;
+ }
+
+ memcpy(&file_data[size_read], chunk_data, rc);
+ size_read += rc;
}
printf("successfully received EFS data\n");
@@ -312,9 +350,9 @@ int efs_sync(int tty_fd)
return -1;
}
- printf("requested file %s with address %d and size %d\n",
- memory_table.file, memory_table.address,
- memory_table.size);
+ printf("requested file %s (alt file name '%s') with address %d and size %d\n",
+ memory_table.file, memory_table.empty,
+ memory_table.address, memory_table.size);
rc = check_efs_file_request(memory_table.file);
if (rc < 0) {
@@ -331,8 +369,8 @@ int efs_sync(int tty_fd)
memory_read_req.size = memory_table.size;
do {
rc = request_efs_data(tty_fd, memory_read_req);
- // abort after 3 retries
- if (i++ > 2)
+ // abort after 5 retries
+ if (i++ > 4 && rc < 0)
break;
} while (rc < 0);
@@ -350,16 +388,17 @@ int efs_sync(int tty_fd)
return -1;
} else if (header.command != SAH_COMMAND_RESET_RESP) {
printf("received command %d instead of reset response\n",
- header.command);
+ header.command);
return -1;
}
return 0;
}
-int handle_memory_debug(int tty_fd)
+int handle_memory_debug(int tty_fd, int *hellos)
{
struct sah_header header;
+ struct sah_hello_req hello_req;
int rc;
rc = read(tty_fd, &header, sizeof(header));
@@ -371,12 +410,25 @@ int handle_memory_debug(int tty_fd)
switch (header.command) {
case SAH_COMMAND_HELLO_REQ:
printf("received hello\n");
- rc = hello_response(tty_fd, SAH_MODE_MEMORY_DEBUG);
- if (rc < 0) {
- printf("failed to send hello response\n");
- return -1;
+ // Modem doesn't like it if the second hello is
+ // answered, so only read data and keep quiet.
+ if (++(*hellos) == 2) {
+ rc = read_hello_data(tty_fd,
+ SAH_MODE_MEMORY_DEBUG,
+ &hello_req);
+ if (rc < 0) {
+ printf("failed to read hello data\n");
+ return -1;
+ }
+ } else {
+ rc = hello_response(tty_fd,
+ SAH_MODE_MEMORY_DEBUG);
+ if (rc < 0) {
+ printf("failed to send hello response\n");
+ return -1;
+ }
+ printf("sent hello response\n");
}
- printf("sent hello response\n");
break;
case SAH_COMMAND_MEMORY_DEBUG_REQ:
printf("received memory debug command\n");
@@ -385,7 +437,7 @@ int handle_memory_debug(int tty_fd)
printf("failed to receive EFS data\n");
return -1;
}
- printf("successful EFS sync\n");
+ printf("finished EFS sync\n");
break;
default:
printf("received unknown command %d with size %d\n",
diff --git a/sahara.h b/sahara.h
index b4b0e7b..f7efc3d 100644
--- a/sahara.h
+++ b/sahara.h
@@ -98,9 +98,7 @@ struct sah_memory_table {
unsigned char file[20];
} __attribute__((__packed__));
-int hello_response(int tty_fd, int mode);
-int hello_handshake(int tty_fd, int mode);
int send_file(int tty_fd, struct sah_data_end_ack *data_end_ack);
-int handle_memory_debug(int tty_fd);
+int handle_memory_debug(int tty_fd, int *hellos);
#endif