Start using new implementation of thor protocol 76/68776/5
authorKrzysztof Opasiak <k.opasiak@samsung.com>
Thu, 2 Jun 2016 09:43:22 +0000 (11:43 +0200)
committerKrzysztof Opasiak <k.opasiak@samsung.com>
Thu, 7 Jul 2016 15:08:54 +0000 (17:08 +0200)
Drop all legacy stuff which used cdc-acm kernel driver
and start using new implementation provided by libthor.

Change-Id: If3ee224b4905778d39c8b049f38353f499cd9f9f
Signed-off-by: Krzysztof Opasiak <k.opasiak@samsung.com>
99-lthor.rules
CMakeLists.txt
lthor.c
thor-proto.h [deleted file]

index dcd694d85bddd1346c1e0105322bfd76f2ba17fd..47ee167023536a3f4c84c1e1f11e3ef62e54846f 100644 (file)
@@ -1,2 +1 @@
-SUBSYSTEM=="tty", KERNEL=="ttyACM*", MODE="0666"
-SUBSYSTEM=="tty", KERNEL=="ttyACM*", ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="685d", ENV{ID_MM_CANDIDATE}="null"
+SUBSYSTEM=="usb", ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="685d", MODE="0666"
index fda3bcf322f6d8a454caa7fa6a0ef9c967f579e1..c6678716a37e5a8e222cb9e0eaf86d4bf2a43724 100755 (executable)
@@ -1,11 +1,19 @@
 CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
 PROJECT(lthor C)
 
+SET(LIBTHOR_SRCS
+       libthor/thor_acm.c
+       libthor/thor.c
+       libthor/thor_raw_file.c
+       libthor/thor_tar.c
+       libthor/thor_usb.c
+)
+
 SET(SRCS
        lthor.c
 )
 
-INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/.)
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/libthor)
 
 SET(VENDOR "samsung")
 SET(PACKAGE ${PROJECT_NAME})
@@ -25,6 +33,7 @@ MESSAGE("Build type: ${CMAKE_BUILD_TYPE}")
 INCLUDE(FindPkgConfig)
 pkg_check_modules(pkgs REQUIRED 
        libarchive
+       libusb-1.0>=1.0.17
 )
 
 FOREACH(flag ${pkgs_CFLAGS})
@@ -45,12 +54,16 @@ ADD_DEFINITIONS("-DPACKAGE_VERSION=\"${PACKAGE_VERSION}\"")
 #SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed")
 IF(APPLE)
        SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}")
+       INCLUDE_DIRECTORIES("/usr/include/machine")
 ELSE()
        SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--as-needed")
 ENDIF()
 
+ADD_LIBRARY(libthor ${LIBTHOR_SRCS})
+
 ADD_EXECUTABLE(${PROJECT_NAME} ${SRCS})
-TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS})
+
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} libthor ${pkgs_LDFLAGS})
 
 
 INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${BINDIR})
diff --git a/lthor.c b/lthor.c
index 5ebc35718dd8444fd776be1f2fb2faa74a96c01f..b4e6b3df4f23cfd874a4fc1de939d53e441e990e 100644 (file)
--- a/lthor.c
+++ b/lthor.c
  * limitations under the License.
  */
 
-#include <stdio.h>
 #include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <fcntl.h>
-#include <termios.h>
-#include <stdlib.h>
+#include <stdio.h>
+#include <getopt.h>
 #include <unistd.h>
-#include <string.h>
-#include <assert.h>
-#include <sys/mman.h>
-#include <poll.h>
+#include <stdlib.h>
 #include <errno.h>
-#include <dirent.h>
-#include <libgen.h>
-#include <getopt.h>
-
-#include <archive.h>
-#include <archive_entry.h>
+#include <string.h>
+#include <stdint.h>
+#include <sys/time.h>
 
-#include "thor-proto.h"
+#include "thor.h"
 
 #define KB                     (1024)
 #define MB                     (1024*KB)
-#define DEFAULT_PKT_SIZE       (1*MB)
-#define DEFAULT_TIMEOUT        (60000)                 /* 1 minute */
-
-/* data abstraction */
-struct data_src {
-       size_t (*get_data_length)(struct data_src *src);
-       size_t (*get_data_block)(struct data_src *src, void *data, size_t len);
-       const char* (*get_data_name)(struct data_src *src);
-};
-
-int opt_verbose = 0;
-int opt_test = 0;
-size_t trans_unit_size = DEFAULT_PKT_SIZE;
-
-static void dump(const char *msg, void *bytes, int len)
-{
-       int i;
-
-       if (!opt_verbose)
-               return;
-
-       fprintf(stderr, "%s :", msg);
-       for (i=0; i<len; i++) {
-               if (i && (0==i%16))
-                       fprintf(stderr, "      ");
-               fprintf(stderr, "%02x%c", ((unsigned char*)bytes)[i],
-                               ((len == i+1) || (i+1)%16==0) ? '\n': ' ');
-       }
-}
-
-static off_t file_size(const char *filename)
-{
-       struct stat st;
-       if (stat(filename, &st) < 0)
-               return -1;
-
-       return st.st_size;
-}
-
-int serial_read(int fd, void *addr, size_t len, int timeout)
-{
-       unsigned char *p = addr;
-       int n = 0, r;
-
-       while (n < len) {
-               struct pollfd fds;
-               fds.fd = fd;
-               fds.events = POLLIN;
-               fds.revents = 0;
-               r = poll(&fds, 1, timeout);
-               if (r < 0) {
-                       fprintf(stderr, "line %d: poll failed\n", __LINE__);
-                       return -1;
-               }
-
-               if (r == 0) {
-                       if (opt_verbose)
-                               fprintf(stderr, "line %d: timeout after reading %d bytes\n", __LINE__, n);
-                       return n;
-               }
-
-               if (!(fds.revents & POLLIN)) {
-                       fprintf(stderr, "line %d: poll returned non-read event %08x\n", __LINE__, fds.revents);
-                       continue;
-               }
-
-               r = read(fd, &p[n], len - n);
-               if (r < 0) {
-                       fprintf(stderr, "line %d: read failed\n", __LINE__);
-                       return -1;
-               }
-
-               n += r;
-       }
-
-       return n;
-}
-
-static double timediff (struct timeval *atv, struct timeval *btv)
-{
-       double diff;
-
-       if (btv->tv_usec < atv->tv_usec) {
-               diff = btv->tv_sec - atv->tv_sec - 1;
-               diff += (double)(1*1000*1000 - atv->tv_usec +
-                               btv->tv_usec)/(1000*1000);
-       } else {
-               diff = btv->tv_sec - atv->tv_sec;
-               diff += (double)(btv->tv_usec - atv->tv_usec)/(1000*1000);
-       }
-
-       return diff;
-}
-
-int send_chunks(int fd, struct data_src *senddata, size_t size)
-{
-       unsigned char *chunk;
-       struct data_res_pkt resp;
-       size_t n = 0;
-       int chunksize, chunk_number = 1;
-       struct timeval stv, etv, ltv;
-       int r;
-
-       chunk = malloc(trans_unit_size);
-       if (chunk == NULL) {
-               fprintf(stderr, "Unable to allocate memory.\n");
-               return -1;
-       }
-
-       if (opt_verbose)
-               fprintf(stderr, "Downloading: %zd bytes\n", size);
-
-       gettimeofday(&stv, NULL);
-       memcpy(&ltv, &stv, sizeof(struct timeval));
-
-       while (n < size) {
-               if (size - n >= trans_unit_size)
-                       chunksize = trans_unit_size;
-               else
-                       chunksize = size - n;
-
-               chunksize = senddata->get_data_block(senddata, chunk, chunksize);
-               if (chunksize <= 0) {
-                       fprintf(stderr, "\nline %d: Broken tar archive - check download!\n", __LINE__);
-                       exit(1);
-               }
-
-               if (opt_verbose)
-                       fprintf(stderr, "read %d bytes\n", chunksize);
-
-               assert(chunksize > 0 && chunksize <= trans_unit_size);
-               memset(&chunk[chunksize], 0, trans_unit_size - chunksize);
-
-               if (opt_verbose)
-                       fprintf(stderr, "sending %zd/%zd\n", n + chunksize, size);
-
-               r = write(fd, chunk, trans_unit_size);
-               if (r != trans_unit_size) {
-                       if (opt_verbose) {
-                               if (r > 0)
-                                       fprintf(stderr, "line %d: %d bytes requested, %d written\n",
-                                                       __LINE__, trans_unit_size, r);
-                               fprintf(stderr, "line %d: failed to send data\n", __LINE__);
-                       }
-                       free(chunk);
-                       return -1;
-               }
-
-               memset(&resp, 0, DATA_RES_PKT_SIZE);
-               r = serial_read(fd, &resp, DATA_RES_PKT_SIZE, DEFAULT_TIMEOUT);
-               if (r != DATA_RES_PKT_SIZE) {
-                       fprintf(stderr, "line %d: read failed %d\n", __LINE__, r);
-                       free(chunk);
-                       return -1;
-               }
-
-               if (resp.cnt != chunk_number) {
-                       printf("\nsending %zd/%zd : sequence wrong %08x, expected %08x\n",
-                               n, size, resp.cnt, chunk_number);
-                       //return -1;
-               }
-
-               n += chunksize;
-
-               if (opt_verbose) {
-                       printf("response %08x %08x\n", resp.ack, resp.cnt);
-
-               } else {
-                       int now = n/KB;
-                       int total = size/KB;
-                       char progress [4] = { '-', '\\', '|', '/' };
-                       char c = progress[(now/30)%4];
-                       double elaps;
-
-                       gettimeofday(&etv, NULL);
-                       if (n >= size) {
-                               elaps = timediff(&stv, &etv);
-                               fprintf(stderr, "\x1b[1A\x1b[16C%c sending %6dk/%6dk %3d%% block %-6d", 
-                                               c, now, total, ((now*100)/total), chunk_number);
-                               fprintf(stderr, " [avg %.2f MB/s]\n", (double)(size/elaps)/(MB));
-                       } else {
-                               elaps = timediff(&ltv, &etv);
-                               memcpy(&ltv, &etv, sizeof(struct timeval));
-                               fprintf(stderr, "\x1b[1A\x1b[16C%c sending %6dk/%6dk %3d%% block %-6d", 
-                                               c, now, total, ((now*100)/total), chunk_number);
-                               fprintf(stderr, " [%.2f MB/s]\n", (double)(chunksize/elaps)/(MB));
-                       }
-               }
-               chunk_number++;
-       }
-
-       free(chunk);
-
-       return 0;
-}
-
-/*
- * function that doesn't wait for response data, used by standard requests and
- * REQ_PIT_DATA_START, which doesn't want a response
- */
-int write_request(int fd, request_type req_id, int req_sub_id,
-       int *idata, int icnt, char **sdata, int scnt)
-{
-       struct rqt_pkt req;
-       int r, i;
-
-       assert(icnt <= sizeof(req.int_data)/sizeof(req.int_data[0]));
-       assert(icnt >= 0);
-       assert(scnt <= sizeof(req.str_data)/sizeof(req.str_data[0]));
-       assert(scnt >= 0);
-
-       memset(&req, 0, sizeof(req));
-
-       req.id = req_id;
-       req.sub_id = req_sub_id;
-
-       if (idata) {
-               for (i=0; i<icnt; i++)
-                       req.int_data[i] = idata[i];
-       }
-
-       if (sdata) {
-               for (i=0; i<scnt; i++)
-                       strcpy(req.str_data[i],sdata[i]);
-       }
-
-       dump("send", &req, 0x20);
-
-       r = write(fd, &req, RQT_PKT_SIZE);
-       if (r != RQT_PKT_SIZE) {
-               fprintf(stderr, "line %d: failed to send data r = %d\n",
-                               __LINE__, r);
-               return -1;
-       }
-
-       return 0;
-}
-
-int send_request_timeout(int fd, request_type req_id, int req_sub_id,
-       int *idata, int icnt, char **sdata, int scnt, struct res_pkt *pres, int timeout)
-{
-       struct res_pkt resp;
-       int r;
-
-       r = write_request(fd, req_id, req_sub_id, idata, icnt, sdata, scnt);
-       if (r < 0) {
-               fprintf(stderr, "line %d: failed to write request r = %d\n",
-                               __LINE__, r);
-               return -1;
-       }
-
-       r = serial_read(fd, &resp, sizeof resp, timeout);
-       if (r >= 0)
-               dump("recv", &resp, sizeof resp);
-       if (r != sizeof resp) {
-               fprintf(stderr, "line %d: failed to receive data r = %d\n",
-                               __LINE__, r);
-               return -1;
-       }
-
-       if (pres)
-               memcpy(pres, &resp, RES_PKT_SIZE);
-
-       if (resp.ack != 0) {
-               if (opt_verbose) {
-                       fprintf(stderr, "\x1b[0;31;1mMissmatch\x1b[0m\n");
-                       fprintf(stderr, "line %d: ack reports fail. ack = %d\n",
-                                       __LINE__, resp.ack);
-               } else {
-                       fprintf(stderr, "\x1b[1A\x1b[16C\x1b[0;31;1mMissmatch\x1b[0m\n");
-               }
-               return -2;
-       }
-
-       return resp.ack;
-}
 
-int send_request(int fd, request_type req_id, int req_sub_id, int *idata, int icnt)
-{
-       return send_request_timeout(fd, req_id, req_sub_id, idata, icnt,
-               NULL, 0, NULL, DEFAULT_TIMEOUT);
-}
+struct helper {
+       struct thor_data_src *data;
+       enum thor_data_type type;
+       const char *name;
+};
 
-int request_reboot(int fd)
-{
-       int r;
-       r = send_request(fd, RQT_CMD, RQT_CMD_REBOOT, NULL, 0);
-       if (r)
-               fprintf(stderr, "RQT_CMD_REBOOT,   status = %08x\n", r);
-       return r;
-}
+struct time_data {
+       struct timeval start_time;
+       struct timeval last_time;
+       int last_sent;
+};
 
-int thor_handshake(int fd, int timeout, int log_on)
+static int test_tar_file_list(char **tarfilelist)
 {
-       char buffer[4];
-       int r;
-
-       r = write(fd, "THOR", 4);
-       if (r != 4) {
-               if (log_on)
-                       fprintf(stderr, "line %d: failed to write signature bytes\n",
-                                       __LINE__);
-               return -1;
-       }
+       struct thor_data_src *data;
+       int ret;
 
-       r = serial_read(fd, buffer, 4, timeout);
-       if (r != 4) {
-               if (log_on)
-                       fprintf(stderr, "line %d: failed to read signature bytes\n",
-                                       __LINE__);
-               return -1;
-       }
+       while (*tarfilelist) {
+               ret = thor_get_data_src(*tarfilelist, THOR_FORMAT_TAR, &data);
+               if (ret)
+                       goto error;
 
-       if (memcmp(buffer, "ROHT", 4)) {
-               if (log_on)
-                       fprintf(stderr, "line %d: signature byte mismatch\n",
-                                       __LINE__);
-               return -1;
+               ret = thor_send_data(NULL, data, THOR_NORMAL_DATA,
+                                    NULL, NULL, NULL, NULL);
+               thor_release_data_src(data);
+               if (ret)
+                       goto error;
        }
 
        return 0;
-}
-
-int getfile(const char *devpath, char *buffer, size_t bufsize)
-{
-       int fd, r = 0;
-
-       fd = open(devpath, O_RDONLY);
-       if (fd >= 0) {
-               r = read(fd, buffer, bufsize - 1);
-               if (r < 0)
-                       r = 0;
-               close(fd);
-       }
-       else if (opt_verbose)
-               fprintf(stderr, "failed to open %s\n", devpath);
-       if (r && buffer[r - 1] == '\n')
-               r--;
-       buffer[r] = 0;
-       return r;
-}
-
-/*
- * Given USB path, return tty name
- * FIXME: probably should look up the /dev from device major:minor
- * There seems to be two styles of device name:
- *  1. /sys/bus/usb/devices/1-2/1-2\:2.0/tty/ttyACM0/dev
- *  2. /sys/bus/usb/devices/1-2/1-2\:2.0/tty:ttyACM0
- */
-char *device_from_usb_tty_directory(const char *usbpath)
-{
-       static char ttypath[0x400];
-       static char devpath[0x400];
-       char *ret = NULL;
-       DIR *d;
-
-       strcpy(ttypath, usbpath);
-       strcat(ttypath, "/tty");
-
-       d = opendir(ttypath);
-       if (d) {
-               if (opt_verbose)
-                       fprintf(stderr, "listing %s:\n", ttypath);
-
-               /* device name is under tty directory */
-               while (!ret) {
-                       struct dirent *de;
-
-                       de = readdir(d);
-                       if (!de)
-                               break;
-
-                       if (opt_verbose)
-                               fprintf(stderr, "%s\n", de->d_name);
-
-                       if (de->d_name[0] == '.')
-                               continue;
-
-                       strcpy(devpath, "/dev/");
-                       strcat(devpath, de->d_name);
-
-                       ret = devpath;
-               }
-       } else  {
-               /* device name is in directory */
-               d = opendir(usbpath);
-               if (!d)
-                       return NULL;
-
-               if (opt_verbose)
-                       fprintf(stderr, "listing %s:\n", usbpath);
-
-               while (!ret) {
-                       struct dirent *de;
-
-                       de = readdir(d);
-                       if (!de)
-                               break;
-
-                       if (opt_verbose)
-                               fprintf(stderr, "%s\n", de->d_name);
-
-                       if (strncmp(de->d_name, "tty:", 4))
-                               continue;
-
-                       strcpy(devpath, "/dev/");
-                       strcat(devpath, &de->d_name[4]);
-
-                       ret = devpath;
-               }
-       }
-
-       closedir(d);
-
+error:
+       fprintf(stderr, "Unable to load file %s: %d\n", *tarfilelist, ret);
        return ret;
 }
 
-int find_usb_device(void)
+/* Check if LHOR protocol is in working state */
+static int check_proto(struct thor_device_id *dev_id)
 {
-       DIR *usb_dir;
-       DIR *usb_dir_in;
-       char *p;
-       char buffer[11];
-       const char *dirname = "/sys/bus/usb/devices";
-       char usbpath[0x400];
-       char usbdir[0x100];
-       char *tty = NULL;
-       int fd, r;
-
-       usb_dir = opendir(dirname);
-       if (!usb_dir)
-               return -1;
-
-       while (1) {
-               struct dirent *de;
-
-               de = readdir(usb_dir);
-               if (!de)
-                       break;
-
-               if (de->d_name[0] == '.')
-                       continue;
-
-               strcpy(usbdir, de->d_name);
-               strcpy(usbpath, dirname);
-               strcat(usbpath, "/");
-               strcat(usbpath, usbdir);
-               strcat(usbpath, "/");
-               p = &usbpath[strlen(usbpath)];
-               p[0] = 0x00;
-
-               usb_dir_in = opendir(usbpath);
-               if (opt_verbose)
-                       fprintf(stderr, "at %s\n", usbpath);
-
-               while ((de = readdir(usb_dir_in))) {
-                       if (strlen(de->d_name) < strlen(usbdir))
-                               continue;
-
-                       if (de->d_type != DT_DIR)
-                               continue;
-
-                       if (strncmp(de->d_name, usbdir, strlen(usbdir)))
-                               continue;
-
-                       strcpy(p, de->d_name);
-                       if (opt_verbose)
-                               fprintf(stderr, "search for tty on %s\n", usbpath);
-
-                       tty = device_from_usb_tty_directory(usbpath);
-                       if (tty) {
-                               fd = get_termios(tty);
-                               if (fd < 0)
-                                       continue;
-
-                               r = thor_handshake(fd, 2000, 0);
-                               if (r < 0) {
-                                       close(fd);
-                                       continue;
-                               }
-
-                               closedir(usb_dir_in);
-                               return fd;
-                       }
-               }
-
-               closedir(usb_dir_in);
-       }
-
-       closedir(usb_dir);
+       thor_device_handle *handle;
+       int ret;
 
-       if (opt_verbose)
-               fprintf(stderr, "No USB device found with matching\n");
+       ret = thor_open(dev_id, 0, &handle);
+       if (ret)
+               fprintf(stderr, "Unable to open device: %d\n", ret);
+       else
+               thor_close(handle);
 
-       return -1;
+       return ret;
 }
 
-int get_termios(const char *portname)
+static int count_files(char **list)
 {
-       struct termios tios;
-       int fd, r;
-
-       /* On OS X open serial port with O_NONBLOCK flag */
-       fd = open(portname, O_RDWR | O_NONBLOCK);
-
-       if (fd == -1) {
-               perror("port open error!!\n");
-               return -1;
-       }
-
-       /*now clear the O_NONBLOCK flag to enable writing big data chunks at once*/
-       if (fcntl(fd, F_SETFL, 0)) {
-               printf("line %d: error clearing O_NONBLOCK\n", __LINE__);
-               return -1;
-       }
+       int i = 0;
 
-       r = tcgetattr(fd, &tios);
-       if (r < 0) {
-               fprintf(stderr, "line %d: tcgetattr failed\n", __LINE__);
-               close(fd);
-               return -1;
-       }
-
-       /*
-        * Firmware BUG alert!!!
-        * Flow control (RTS/CTS) should be disabled, because
-        * the firmware doesn't deal with it properly.
-        */
-        cfmakeraw(&tios);
-       r = tcsetattr(fd, TCSANOW, &tios);
-       if (r < 0) {
-               fprintf(stderr, "line %d: tcsetattr failed\n", __LINE__);
-               close(fd);
-               return -1;
-       }
+       while (list && list[i])
+               ++i;
 
-       r = tcflush(fd, TCIOFLUSH);
-       if (r < 0) {
-               fprintf(stderr, "line %d: tcflush failed\n", __LINE__);
-               close(fd);
-               return -1;
-       }
-
-       return fd;
+       return i;
 }
 
-int open_port(const char *portname, int wait)
+static int init_data_parts(const char *pitfile, char **tarfilelist,
+                   struct helper *data_parts)
 {
-       int once = 0;
-       int fd, r;
-
-       if (opt_test)
-               return open("/dev/null", O_RDWR);
-
-       while (1) {
-               if (!portname) {
-                       fd = find_usb_device();
-                       if (fd >= 0)
-                               return fd;
-
-               } else {
-                       fd = get_termios(portname);
-                       if (fd < 0) {
-                               fprintf(stderr, "USB port is "
-                                       "\x1b[0;31;1mnot\x1b[0m detected !\n\n");
-                               return fd;
-                       }
-
-                       r = thor_handshake(fd, DEFAULT_TIMEOUT, 1);
-                       if (r < 0) {
-                               close(fd);
-                               return -1;
-                       }
-
-                       return fd;
-               }
-
-               if (!wait) {
-                       fprintf(stderr, "line %d: device not found\n", __LINE__);
-                       return -1;
-               }
+       int i;
+       int entry = 0;
+       int ret;
 
-               if (!once) {
-                       if (!wait)
-                           return -1;
-                       printf("\nUSB port is not detected yet... \n");
-                       printf("Make sure phone(device) should be in a download mode \n");
-                       printf("before connecting phone to PC with USB cable.\n");
-                       printf("(How to enter download mode : press <volume-down> + <power> key)\n\n");
-                       once = 1;
+       if (pitfile) {
+               data_parts[0].type = THOR_PIT_DATA;
+               data_parts[0].name = pitfile;
+               ret = thor_get_data_src(pitfile, THOR_FORMAT_RAW,
+                                       &(data_parts[0].data));
+               if (ret) {
+                       fprintf(stderr, "Unable to open pit file %s : %d\n",
+                               pitfile, ret);
+                       return -EINVAL;
                }
-               sleep(1);
+               ++entry;
        }
-}
 
-int wait_and_open_port(const char *portname)
-{
-       return open_port(portname, 1);
-}
-
-/*
- * Write a data source (file) into a partition
- *
- * data_src abstraction provided so sending a single file
- * from a non-tar source is possible one day
- */
-int download_single_file(int fd, struct data_src *senddata, int filetype)
-{
-       int r;
-       size_t filesize;
-       const char *filename;
-       struct res_pkt resp;
-       int32_t int_data[2];
-
-       filesize = senddata->get_data_length(senddata);
-       filename = senddata->get_data_name(senddata);
-
-       int_data[0] = filetype;
-       int_data[1] = filesize;
-       r = send_request_timeout(fd, RQT_DL, RQT_DL_FILE_INFO, int_data, 2,
-               (char **)&filename, 1, &resp, DEFAULT_TIMEOUT);
-       if (r < 0) {
-               if (opt_verbose)
-                       fprintf(stderr, "RQT_DL_FILE_INFO, status = %08x\n", r);
-               return r;
-       }
-       trans_unit_size = resp.int_data[0];
-
-       r = send_request(fd, RQT_DL, RQT_DL_FILE_START, NULL, 0);
-       if (r < 0) {
-               fprintf(stderr, "RQT_DL_FILE_START, status = %08x\n", r);
-               return -1;
-       }
-
-       r = send_chunks(fd, senddata, filesize);
-       if (r < 0) {
-               fprintf(stderr, "send_chunks(), status = %08x\n", r);
-               return -1;
-       }
+       while (*tarfilelist) {
+               printf("\x1b[0;33;1m%s :\x1b[0m\n", *tarfilelist);
+               data_parts[entry].type = THOR_NORMAL_DATA;
+               data_parts[0].name = *tarfilelist;
+               ret = thor_get_data_src(*tarfilelist, THOR_FORMAT_TAR,
+                                       &(data_parts[entry].data));
+               if (ret) {
+                       fprintf(stderr, "Unable to open file %s : %d\n",
+                               *tarfilelist, ret);
+                       goto err_cleanup_parts;
+               }
 
-       r = send_request(fd, RQT_DL, RQT_DL_FILE_END, NULL, 0);
-       if (r < 0) {
-               fprintf(stderr, "RQT_DL_FILE_END, status = %08x\n", r);
-               return -1;
+               ++entry;
+               ++tarfilelist;
        }
 
-       return 0;
-}
-
-struct file_data_src {
-       struct data_src src;
-       int fd;
-       const char* filename;
-       size_t filesize;
-};
-
-size_t file_get_data_length(struct data_src *src)
-{
-       struct file_data_src *filedata = (struct file_data_src *) src;
-
-       return filedata->filesize;
-}
-
-size_t file_get_data_block(struct data_src *src, void *data, size_t len)
-{
-       struct file_data_src *filedata = (struct file_data_src *) src;
-
-       return read(filedata->fd, data, len);
-}
-
-const char *file_get_data_name(struct data_src *src)
-{
-       struct file_data_src *filedata = (struct file_data_src *) src;
-
-       return filedata->filename;
-}
-
-int filedata_open(struct file_data_src *filedata, const char *filename)
-{
-       int r;
-       char *basefile;
-
-       if (!filedata)
-               return -1;
-
-       memset((void*)filedata, 0x00, sizeof(struct file_data_src));
-
-       r = open(filename, O_RDONLY);
-       if (r < 0)
-               return r;
-
-       filedata->fd = r;
-
-       /* According to the man page basename() might modify the argument or
-        * return a pointer to statically allocated memory. Thus two strdup()s */
-       basefile = strdup(filename);
-       filedata->filename = strdup(basename(basefile));
-       free(basefile);
-
-       filedata->filesize = lseek(filedata->fd, 0, SEEK_END);
-       lseek(filedata->fd, 0, SEEK_SET);
-
-       filedata->src.get_data_length = &file_get_data_length;
-       filedata->src.get_data_block = &file_get_data_block;
-       filedata->src.get_data_name = &file_get_data_name;
-
-       return r;
-}
-
-int filedata_close(struct file_data_src *filedata)
-{
-       close(filedata->fd);
-       free((void *)filedata->filename);
-       return 0;
-}
-
-struct tar_data_src {
-       struct data_src src;
-       struct archive *ar;
-       struct archive_entry *ae;
-};
-
-size_t te_get_data_length(struct data_src *src)
-{
-       struct tar_data_src *tardata = (struct tar_data_src *) src;
-
-       return archive_entry_size(tardata->ae);
+       return entry;
+err_cleanup_parts:
+       for (i = 0; i < entry; ++i)
+               thor_release_data_src(data_parts[i].data);
+       return ret;
 }
 
-size_t te_get_data_block(struct data_src *src, void *data, size_t len)
+static void init_time_data(struct time_data *tdata)
 {
-       struct tar_data_src *tardata = (struct tar_data_src *) src;
-
-       return archive_read_data(tardata->ar, data, len);
+       gettimeofday(&tdata->start_time, NULL);
+       memcpy(&tdata->last_time, &tdata->start_time, sizeof(tdata->start_time));
+       tdata->last_sent = 0;
 }
 
-const char *te_get_data_name(struct data_src *src)
+static void report_next_entry(thor_device_handle *th,
+                             struct thor_data_src *data, void *user_data)
 {
-       struct tar_data_src *tardata = (struct tar_data_src *) src;
+       struct time_data *tdata = user_data;
 
-       return archive_entry_pathname(tardata->ae);
+       printf("[\x1b[0;32;1m%s\x1b[0m]\n", data->get_name(data));
+       init_time_data(tdata);
 }
 
-int tardata_open(struct tar_data_src *tardata, const char *tarfile)
+static double timediff(struct timeval *atv, struct timeval *btv)
 {
-       int r;
-
-       /* open the tar archive */
-       tardata->ar = archive_read_new();
-
-       archive_read_support_format_tar(tardata->ar);
-       archive_read_support_compression_gzip(tardata->ar);
-       archive_read_support_compression_bzip2(tardata->ar);
-
-       if (!strcmp(tarfile, "-"))
-               r = archive_read_open_FILE(tardata->ar, stdin);
-       else
-               r = archive_read_open_filename(tardata->ar, tarfile, 512);
+       double diff;
 
-       if (r) {
-               fprintf(stderr, "line %d: failed to open %s\n", __LINE__, tarfile);
-               return r;
+       if (btv->tv_usec < atv->tv_usec) {
+               diff = btv->tv_sec - atv->tv_sec - 1;
+               diff += (double)(1*1000*1000 - atv->tv_usec +
+                               btv->tv_usec)/(1000*1000);
+       } else {
+               diff = btv->tv_sec - atv->tv_sec;
+               diff += (double)(btv->tv_usec - atv->tv_usec)/(1000*1000);
        }
 
-       tardata->src.get_data_length = &te_get_data_length;
-       tardata->src.get_data_block = &te_get_data_block;
-       tardata->src.get_data_name = &te_get_data_name;
-       tardata->ae = NULL;
-
-       return r;
+       return diff;
 }
 
-const char *tardata_next(struct tar_data_src *tardata)
+static void report_progress(thor_device_handle *th, struct thor_data_src *data,
+                           int sent, int left, int chunk_nmb, void *user_data)
 {
-       int64_t partsize;
-       int r;
-
-       r = archive_read_next_header(tardata->ar, &tardata->ae);
-       if (r == ARCHIVE_EOF)
-               return NULL;
-
-       if (r != ARCHIVE_OK) {
-               fprintf(stderr, "line %d: archive_read_next_header error %d\n",
-                               __LINE__, r);
-               return NULL;
-       }
-
-       partsize = archive_entry_size(tardata->ae);
-       if (partsize > SIZE_MAX) {
-               /*
-                * FIXME: fix source (and maybe firmware) to deal with files
-                * bigger than 4G
-                */
-               fprintf(stderr, "line %d: Large file %llx (>4GB) is not"
-                               " supported\n", __LINE__, (unsigned long long)
-                               partsize);
-               return NULL;
+       struct time_data *tdata = user_data;
+       struct timeval *start_time = &tdata->start_time;
+       struct timeval *last_time = &tdata->last_time;
+       struct timeval current_time;
+       double diff;
+       int sent_kb = sent/KB;
+       int total_kb = (sent + left)/KB;
+       char progress [4] = { '-', '\\', '|', '/' };
+       char c = progress[(sent_kb/30)%4];
+
+       fprintf(stderr, "\x1b[1A\x1b[16C%c sending %6dk/%6dk %3d%% block %-6d",
+               c, sent_kb, total_kb, ((sent_kb*100)/total_kb), chunk_nmb);
+
+       gettimeofday(&current_time, NULL);
+
+       if (left != 0) {
+               diff = timediff(last_time, &current_time);
+               fprintf(stderr, " [%.2f MB/s]\n",
+                       (double)((sent - tdata->last_sent)/diff)/(MB));
+               tdata->last_sent = sent;
+               *last_time = current_time;
+       } else {
+               diff = timediff(start_time, &current_time);
+               fprintf(stderr, " [avg %.2f MB/s]\n",
+                       (double)(sent/diff)/(MB));
        }
-
-       return archive_entry_pathname(tardata->ae);
 }
 
-int tardata_close(struct tar_data_src *tardata)
+static int do_download(thor_device_handle *th, struct helper *data_parts,
+                      int entries, size_t total_size)
 {
-       archive_read_close(tardata->ar);
-       archive_read_finish(tardata->ar);
-       return 0;
-}
+       struct time_data tdata;
+       int i;
+       int ret;
 
-int get_entry_size_in_tar(const char *tarfile, unsigned long long *total)
-{
-       struct tar_data_src tardata;
-       const char *filename;
-       int r;
-
-       r = tardata_open(&tardata, tarfile);
-       if (r < 0) {
-               fprintf(stderr, "line %d: failed to open %s\n", __LINE__,
-                               tarfile);
-               return r;
+       ret = thor_start_session(th, total_size);
+       if (ret) {
+               fprintf(stderr, "Unable to start download session: %d\n", ret);
+               goto out;
        }
 
-       *total = 0;
-
-       while (1) {
-               size_t size = 0;
-
-               filename = tardata_next(&tardata);
-               if (!filename)
+       for (i = 0; i < entries; ++i) {
+               switch (data_parts[i].type) {
+               case THOR_PIT_DATA:
+                       fprintf(stderr, "\nDownload PIT file : %s\n\n",
+                               data_parts[i].name);
                        break;
-
-               size = tardata.src.get_data_length(&tardata.src);
-               printf("[\x1b[0;32;1m%s\x1b[0m]\t%zuk\n", filename, size/KB);
-
-               *total += size;
-       }
-
-       tardata_close(&tardata);
-
-       return 0;
-}
-
-int download_pitfile(int fd, const char *pitfile)
-{
-       struct file_data_src filedata;
-       int r;
-
-       r = filedata_open(&filedata, pitfile);
-       if (r < 0) {
-               fprintf(stderr, "line %d: failed to open %s\n", __LINE__, pitfile);
-               return r;
-       }
-
-
-       printf("[\x1b[0;32;1m%s\x1b[0m]\n", pitfile);
-       r = download_single_file(fd, &filedata.src, BINARY_TYPE_PIT);
-       if (r < 0) {
-               fprintf(stderr, "line %d: failed to download %s\n", __LINE__,
-                               pitfile);
-               filedata_close(&filedata);
-               return r;
-       }
-
-       fprintf(stderr, "\n%s completed\n", pitfile);
-
-       filedata_close(&filedata);
-
-       return r;
-}
-
-int download_single_tarfile(int fd, const char *tarfile)
-{
-       struct tar_data_src tardata;
-       const char *filename;
-       int r;
-
-       r = tardata_open(&tardata, tarfile);
-       if (r < 0) {
-               fprintf(stderr, "line %d: failed to open %s\n", __LINE__, tarfile);
-               return r;
-       }
-
-       while (1) {
-               filename = tardata_next(&tardata);
-               if (!filename)
+               case THOR_NORMAL_DATA:
+                       fprintf(stderr, "\nDownload files from %s\n\n",
+                               data_parts[i].name);
                        break;
-
-               printf("[\x1b[0;32;1m%s\x1b[0m]\n", filename);
-               r = download_single_file(fd, &tardata.src, BINARY_TYPE_NORMAL);
-               if (r == -1) {
-                       fprintf(stderr, "line %d: failed to download %s\n", __LINE__, filename);
-                       fprintf(stderr, "\nIn some cases, lthor needs enough memory\n");
-                       fprintf(stderr, "Please check free memory in your Host PC ");
-                       fprintf(stderr, "and unload some heavy applications\n");
-                       tardata_close(&tardata);
-                       return r;
-               }
-       }
-
-       fprintf(stderr, "\n%s completed\n", tarfile);
-
-       tardata_close(&tardata);
-
-       return 0;
-}
-
-int process_download(const char *portname, const char *pitfile, char **tarfilelist)
-{
-       int r;
-       char **tfl;
-       off_t pit_length = 0;
-       int fd;
-       unsigned long long total;
-
-       /* now connect to the target */
-       fd = wait_and_open_port(portname);
-       if (fd < 0) {
-               fprintf(stderr, "line %d: failed to open port %s\n", __LINE__,
-                               portname);
-               return -1;
-       }
-
-       total = 0;
-       tfl = tarfilelist;
-       while (tfl && *tfl) {
-               unsigned long long len = 0;
-               printf("\x1b[0;33;1m%s :\x1b[0m\n", *tfl);
-               if (get_entry_size_in_tar(*tfl, &len) < 0) {
-                       perror("Error");
-                       close(fd);
-                       return -1;
-               }
-               total += len;
-               tfl++;
-       }
-
-       if (pitfile) {
-               pit_length = file_size(pitfile);
-               if (pit_length < 0) {
-                       fprintf(stderr, "line %d: failed to get pit length\n"
-                               , __LINE__);
-                       close(fd);
-                       return -1;
                }
-               total += pit_length;
-               printf("\x1b[0;33;1m%s : \x1b[0m%zuk\n", pitfile,
-                       (size_t)pit_length/KB);
-       }
-       printf("-------------------------\n");
-       printf("\t\x1b[0;33;1mtotal\x1b[0m :\t%.2fMB\n\n", (double)total/MB);
-
-       /* for updating progress bar in the target */
-       r = send_request(fd, RQT_DL, RQT_DL_INIT, (int*)&total, 1);
-       /*
-        * FIXME : if total > SIZE_MAX then DL_INIT must change it's protocol to
-        * send/receive 64bit size data.
-        */
-       if (r) {
-               fprintf(stderr, "RQT_DL_INIT, status = %08x\n", r);
-               close(fd);
-               return -1;
-       }
 
-       if (pitfile) {
-               fprintf(stderr, "\nDownload PIT file : %s\n\n", pitfile);
-               r = download_pitfile(fd, pitfile);
-               if (r < 0) {
-                       fprintf(stderr, "\nfailed to download %s\n", pitfile);
-                       close(fd);
-                       return r;
+               ret = thor_send_data(th, data_parts[i].data, data_parts[i].type,
+                                    report_progress, &tdata, report_next_entry,
+                                    &tdata);
+               if (ret) {
+                       fprintf(stderr, "\nfailed to download %s: %d\n",
+                               data_parts[i].name, ret);
+                       goto out;
                }
-       }
 
-       while (tarfilelist && *tarfilelist) {
-               fprintf(stderr, "\nDownload files from %s\n\n", *tarfilelist);
-               r = download_single_tarfile(fd, *tarfilelist);
-               if (r < 0) {
-                       fprintf(stderr, "\nfailed to download %s\n", *tarfilelist);
-                       close(fd);
-                       return r;
-               }
-               tarfilelist++;
        }
 
-       r = send_request(fd, RQT_DL, RQT_DL_EXIT, NULL, 0);
-       if (r) {
+       ret = thor_end_session(th);
+       if (ret)
                fprintf(stderr, "\x1b[0;33;1mmissing RQT_DL_EXIT response "
                        "from broken bootloader\x1b[0m\n");
-       }
 
        fprintf(stderr, "\nrequest target reboot : ");
 
-       r = request_reboot(fd);
-       if (r)
+       ret = thor_reboot(th);
+       if (ret) {
                fprintf(stderr, "\x1b[0;31;1mfailed\x1b[0m\n");
-       else
+               goto out;
+       } else {
                fprintf(stderr, "\x1b[0;32;1msuccess\x1b[0m\n");
-
-       close(fd);
-
-       return 0;
+       }
+out:
+       return ret;
 }
 
-/* Check if LHOR protocol is in working state */
-int check_proto(const char *portname)
+static int process_download(struct thor_device_id *dev_id, const char *pitfile,
+                    char **tarfilelist)
 {
-       int fd;
-       /* int r;
-        struct res_pkt resp;*/
-
-       /* connect to the target */
-       fd = open_port(portname, 0);
-        if (fd < 0)
-               return -1;
-
-       /* Below I commented out my attempt to check if LHOR protocol is enabled
-        * by quering protocol version.
-        * The main problem is that I didn't find a way to 'close' the session,
-        * to put protocol into previous state.
-        * */
-
-       /*
-       r = thor_handshake(fd);
-       if (r < 0) {
-               fprintf(stderr, "line %d: handshake failed\n", __LINE__);
-               return -1;
-        }
-
-       r = send_request_timeout(fd, RQT_INFO, RQT_INFO_VER_PROTOCOL, NULL, 0, NULL, 0, &resp, DEFAULT_TIMEOUT);
-        if (r) {
-               fprintf(stderr, "RQT_INFO_VER_PROTOCOL, status = %08x\n", r);
-               return -1;
-       } */
-
-       /* Here should be some code, which closes protocol session, resets it somehow */
-       
-       close(fd);
-
-       return 0;
-}
+       thor_device_handle *th;
+       size_t total_size = 0;
+       struct helper *data_parts;
+       int nfiles;
+       int entries = 0;
+       int i;
+       int ret;
 
-int test_tar_entry(struct data_src *tardata)
-{
-       static unsigned char *chunk;
-       size_t n = 0, size;
-       int chunksize;
-
-       chunk = (unsigned char*)malloc(trans_unit_size);
-       if (chunk == NULL) {
-               fprintf(stderr, "Unable to allocate memory.\n");
-               return -1;
+       ret = thor_open(dev_id, 1, &th);
+       if (ret) {
+               fprintf(stderr, "Unable to open device: %d\n", ret);
+               return ret;
        }
 
-       size = tardata->get_data_length(tardata);
-       while (n < size) {
-               if (size - n >= trans_unit_size)
-                       chunksize = trans_unit_size;
-               else
-                       chunksize = size - n;
-
-               chunksize = tardata->get_data_block(tardata, chunk, chunksize);
-               if (chunksize <= 0) {
-                       free(chunk);
-                       return -1;
-               }
-
-               if (!(chunksize <= trans_unit_size && chunksize > 0)) {
-                       free(chunk);
-                       return -1;
-               }
-
-               if ((n/chunksize)%4 == 0)
-                       fprintf(stderr, ".");
+       nfiles = count_files(tarfilelist) + (pitfile ? 1 : 0);
 
-               n += chunksize;
+       data_parts = calloc(nfiles, sizeof(*data_parts));
+       if (!data_parts) {
+               ret = -ENOMEM;
+               goto close_dev;
        }
 
-       free(chunk);
-
-       return 0;
-}
-
-int test_tar_file(const char *tarfile)
-{
-       struct tar_data_src tardata;
-       const char *filename;
-       int r = 0;
-
-       fprintf(stderr, "tar %s\n", tarfile);
-
-       r = tardata_open(&tardata, tarfile);
-       if (r < 0) {
-               fprintf(stderr, "line %d: failed to open %s\n", __LINE__, tarfile);
-               return r;
+       entries = init_data_parts(pitfile, tarfilelist, data_parts);
+       if (entries < 0) {
+               ret = entries;
+               goto free_data_parts;
        }
 
-       while (1) {
-               filename = tardata_next(&tardata);
-               if (!filename)
-                       break;
-
-               fprintf(stderr, " entry %s ", filename);
+       /* Count the total size of data */
+       for (i = 0; i < entries; ++i) {
+               size_t size = data_parts[i].data->get_size(data_parts[i].data);
 
-               r = test_tar_entry(&tardata.src);
-               if (r) {
-                       fprintf(stderr, "bad\n");
+               switch (data_parts[i].type) {
+               case THOR_PIT_DATA:
+                       printf("\x1b[0;33;1m%s : \x1b[0m%zuk\n",
+                              data_parts[i].name, size/KB);
+                       break;
+               case THOR_NORMAL_DATA:
+               default:
                        break;
                }
-
-               fprintf(stderr, "\n");
+               total_size += size;
        }
 
-       tardata_close(&tardata);
+       printf("-------------------------\n");
+       printf("\t\x1b[0;33;1mtotal\x1b[0m :\t%.2fMB\n\n",
+              (double)total_size/MB);
 
-       return r;
-}
+       ret = do_download(th, data_parts, entries, total_size);
 
+       for (i = 0; i < entries; ++i)
+               thor_release_data_src(data_parts[i].data);
 
-int test_tar_file_list(char **tarfilelist)
-{
-       int r;
+free_data_parts:
+       free(data_parts);
+close_dev:
+       thor_close(th);
 
-       while (*tarfilelist) {
-               char *tarfile = *tarfilelist;
-
-               r = test_tar_file(tarfile);
-               if (r < 0)
-                       fprintf(stderr, "failed to load %s\n", *tarfilelist);
-               tarfilelist++;
-       }
-
-       return 0;
+       return ret;
 }
 
-void usage(const char *exename)
+static void usage(const char *exename)
 {
        fprintf(stderr,
                "Usage: %s: [options] [-d port] [-p pitfile] [tar] [tar] ..\n"
@@ -1181,26 +322,55 @@ void usage(const char *exename)
                "  -t, --test                         Don't flash, just check if given tar files are correct\n"
                "  -v, --verbose                      Be more verbose\n"
                "  -c, --check                        Don't flash, just check if given tty port is thor capable\n"
-               "  -d=<port>, --port=<port>           Use specific tty port for communication\n"
                "  -p=<pitfile>, --pitfile=<pitfile>  Flash new partition table\n"
+               "  -b=<busid>, --busid=<busid>        Flash device with given busid\n"
+               "  --vendor-id=<vid>                  Flash device with given Vendor ID\n"
+               "  --product-id=<pid>                 Flash device with given Product ID\n"
+               "  --serial=<serialno>                Flash device with given Serial Number\n"
                "  --help                             Print this help message\n",
                exename);
        exit(1);
 }
 
+static void d_opt_obsolete()
+{
+       fprintf(stderr,
+               "--port, -p options are obsolete.\n"
+               "Instead you may use:"
+               "  -b=<busid>, --busid=<busid>        Flash device with given busid\n"
+               "  --vendor-id=<vid>                  Flash device with given Vendor ID\n"
+               "  --product-id=<pid>                 Flash device with given Product ID\n"
+               "  --serial=<serialno>                Flash device with given Serial Number\n");
+       exit(1);
+}
+
 int main(int argc, char **argv)
 {
-       const char *exename = NULL, *portname = NULL, *pitfile = NULL;
+       const char *exename = NULL, *pitfile = NULL;
        int opt;
+       int opt_test = 0;
        int opt_check = 0;
+       int opt_verbose = 0; /* unused for now */
        int optindex;
+       int ret;
+       struct thor_device_id dev_id = {
+               .busid = NULL,
+               .vid = -1,
+               .pid = -1,
+               .serial = NULL,
+       };
+
        struct option opts[] = {
                {"test", no_argument, 0, 't'},
                {"verbose", no_argument, 0, 'v'},
                {"check", no_argument, 0, 'c'},
                {"port", required_argument, 0, 'd'},
                {"pitfile", required_argument, 0, 'p'},
-               {"help", no_argument, 0, 1},
+               {"busid", required_argument, 0, 'b'},
+               {"vendor-id", required_argument, 0, 1},
+               {"product-id", required_argument, 0, 2},
+               {"serial", required_argument, 0, 3},
+               {"help", no_argument, 0, 0},
                {0, 0, 0, 0}
        };
 
@@ -1211,8 +381,14 @@ int main(int argc, char **argv)
 
        exename = argv[0];
 
+       ret = thor_init();
+       if (ret) {
+               fprintf(stderr, "Unable to init io backend: %d\n", ret);
+               exit(-1);
+       }
+
        while (1) {
-               opt = getopt_long(argc, argv, "tvcd:p:", opts, &optindex);
+               opt = getopt_long(argc, argv, "tvcd:p:b:", opts, &optindex);
                if (opt == -1)
                        break;
 
@@ -1227,31 +403,81 @@ int main(int argc, char **argv)
                        opt_check = 1;
                        break;
                case 'd':
-                       portname = optarg;
+                       d_opt_obsolete();
                        break;
                case 'p':
                        pitfile = optarg;
                        break;
+               case 'b':
+                       dev_id.busid = optarg;
+                       break;
                case 1:
+               {
+                       unsigned long int val;
+                       char *endptr = NULL;
+
+                       val = strtoul(optarg, &endptr, 0);
+                       if (*optarg == '\0'
+                           || (endptr && *endptr != '\0')) {
+                               fprintf(stderr,
+                                       "Invalid value type for --vendor-id option.\n"
+                                       "Expected a number but got: %s", optarg);
+                               exit(-1);
+                       }
+
+                       if (val > UINT16_MAX) {
+                               fprintf(stderr,
+                                       "Value of --vendor-id out of range\n");
+                               exit(-1);
+                       }
+
+                       dev_id.vid = (int)val;
+                       break;
+               }
+               case 2:
+               {
+                       unsigned long int val;
+                       char *endptr = NULL;
+
+                       val = strtoul(optarg, &endptr, 0);
+                       if (*optarg == '\0'
+                           || (endptr && *endptr != '\0')) {
+                               fprintf(stderr,
+                                       "Invalid value type for --product-id option.\n"
+                                       "Expected a number but got: %s", optarg);
+                               exit(-1);
+                       }
+
+                       if (val > UINT16_MAX) {
+                               fprintf(stderr,
+                                       "Value of --product-id out of range\n");
+                               exit(-1);
+                       }
+
+                       dev_id.vid = (int)val;
+                       break;
+               }
+               case 3:
+                       dev_id.serial = optarg;
+                       break;
+               case 0:
                default:
                        usage(exename);
                        return 0;
                }
        }
 
+       ret = 0;
        if (opt_test)
-               return test_tar_file_list(&(argv[optind]));
-
-       if (opt_check)
-               return check_proto(portname);
-
-       if (pitfile && !argv[optind])
-               return process_download(portname, pitfile, NULL);
-
-       if (argv[optind])
-               return process_download(portname, pitfile, &(argv[optind]));
+               ret = test_tar_file_list(&(argv[optind]));
+       else if (opt_check)
+               ret = check_proto(&dev_id);
+       else if (pitfile || argv[optind])
+               ret = process_download(&dev_id, pitfile, &(argv[optind]));
+       else
+               usage(exename);
 
-       usage(exename);
-       return 0;
+       thor_cleanup();
+       return ret;
 }
 
diff --git a/thor-proto.h b/thor-proto.h
deleted file mode 100644 (file)
index 0b8ee39..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-#ifndef __THOR_PROTO_H__
-#define __THOR_PROTO_H__
-
-typedef enum {
-       RQT_INFO = 200, 
-       RQT_CMD,
-       RQT_DL,
-       RQT_UL,
-} request_type;
-
-/* Request Data */
-/* RQT_INFO */
-enum {
-       RQT_INFO_VER_PROTOCOL = 1,
-       RQT_INFO_VER_HW,
-       RQT_INFO_VER_BOOT,
-       RQT_INFO_VER_KERNEL,
-       RQT_INFO_VER_PLATFORM,
-       RQT_INFO_VER_CSC,
-};
-
-/* RQT_CMD */
-enum {
-       RQT_CMD_REBOOT = 1,
-       RQT_CMD_POWEROFF,
-};
-
-/* RQT_DL */
-enum {
-       RQT_DL_INIT = 1,
-       RQT_DL_FILE_INFO,
-       RQT_DL_FILE_START,
-       RQT_DL_FILE_END,
-       RQT_DL_EXIT,
-};
-
-/* RQT_UL */
-enum {
-       RQT_UL_INIT = 1,
-       RQT_UL_START,
-       RQT_UL_END,
-       RQT_UL_EXIT,
-};
-
-enum __binary_type {
-       BINARY_TYPE_NORMAL = 0,
-       BINARY_TYPE_PIT,
-};
-
-struct rqt_pkt {
-       int32_t id;                     /* Request Group ID. */
-       int32_t sub_id;                 /* Request Data ID. */
-       int32_t int_data[14];           /* Int. Datas. */
-       char    str_data[5][32];        /* Str. Data. */
-       char    md5[32];                /* MD5 Checksum. */
-};
-
-
-struct res_pkt {
-       int32_t id;                     /* Response Group ID == Request Group ID. */
-       int32_t sub_id;                 /* Response Data ID == Request Data ID. */
-       int32_t ack;                    /* Ack. */
-       int32_t int_data[5];            /* Int. Datas. */
-       char    str_data[3][32];        /* Str. Data. */
-};
-
-
-struct data_res_pkt {
-       int32_t ack;                    /* Ack. */
-       int32_t cnt;                    /* Int. Datas. */
-};
-
-
-#define RQT_PKT_SIZE           sizeof(struct rqt_pkt)
-#define RES_PKT_SIZE           sizeof(struct res_pkt)
-#define DATA_RES_PKT_SIZE      sizeof(struct data_res_pkt)
-
-#endif /* __THOR_PROTO_H__ */