diff options
author | Wolfgang Wiedmeyer <wolfgit@wiedmeyer.de> | 2017-07-19 00:56:25 +0200 |
---|---|---|
committer | Wolfgang Wiedmeyer <wolfgit@wiedmeyer.de> | 2017-07-19 01:28:33 +0200 |
commit | 63058d5bdb8a50fe650a7b91f6c6e29bdaf583b9 (patch) | |
tree | 8f6421038b0ff586cc0e99981ed35109c55cc736 | |
parent | 9af74e1e2707bee3dcbf1008682566d330418d8a (diff) | |
download | i9305_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.c | 5 | ||||
-rw-r--r-- | i9305.h | 1 | ||||
-rw-r--r-- | sahara.c | 98 | ||||
-rw-r--r-- | sahara.h | 4 |
4 files changed, 80 insertions, 28 deletions
@@ -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; @@ -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" @@ -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", @@ -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 |