Tizen 2.1 base
authorJinkun Jang <jinkun.jang@samsung.com>
Tue, 12 Mar 2013 17:22:03 +0000 (02:22 +0900)
committerJinkun Jang <jinkun.jang@samsung.com>
Tue, 12 Mar 2013 17:22:03 +0000 (02:22 +0900)
14 files changed:
AUTHORS [new file with mode: 0644]
CMakeLists.txt [new file with mode: 0755]
LICENSE.APLv2 [new file with mode: 0644]
NOTICE [new file with mode: 0644]
debian/changelog [new file with mode: 0644]
debian/compat [new file with mode: 0644]
debian/control [new file with mode: 0644]
debian/rules [new file with mode: 0755]
lthor.c [new file with mode: 0755]
packaging/Makefile [new file with mode: 0644]
packaging/lthor.changes [new file with mode: 0644]
packaging/lthor.dsc [new file with mode: 0644]
packaging/lthor.spec [new file with mode: 0644]
thor-proto.h [new file with mode: 0644]

diff --git a/AUTHORS b/AUTHORS
new file mode 100644 (file)
index 0000000..bab8cca
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,5 @@
+YoungJin Lee <yj0701.lee@samsung.com>
+Wonil Choi <wonil22.choi@samsung.com>
+Karol Lewandowski <k.lewandowsk@samsung.com>
+Rafal Krypa <r.krypa@samsung.com>
+Jaehoon You <jaehoon.you@samsung.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..25d7c8f
--- /dev/null
@@ -0,0 +1,52 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+PROJECT(lthor C)
+
+SET(SRCS
+       lthor.c
+)
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/.)
+
+SET(VENDOR "samsung")
+SET(PACKAGE ${PROJECT_NAME})
+SET(PKGNAME "${PACKAGE}")
+SET(PREFIX ${CMAKE_INSTALL_PREFIX})
+SET(BINDIR "${PREFIX}/bin")
+
+SET(PACKAGE_VERSION "1.2")
+
+
+IF("${CMAKE_BUILD_TYPE}" STREQUAL "")
+       SET(CMAKE_BUILD_TYPE "Release")
+ENDIF("${CMAKE_BUILD_TYPE}" STREQUAL "")
+MESSAGE("Build type: ${CMAKE_BUILD_TYPE}")
+
+
+INCLUDE(FindPkgConfig)
+pkg_check_modules(pkgs REQUIRED 
+       libarchive
+)
+
+FOREACH(flag ${pkgs_CFLAGS})
+       SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}")
+SET(CMAKE_C_FLAGS_DEBUG "-O0 -g")
+SET(CMAKE_C_FLAGS_RELEASE "-O2")
+
+
+ADD_DEFINITIONS("-DVENDOR=\"${VENDOR}\"")
+ADD_DEFINITIONS("-DPACKAGE=\"${PACKAGE}\"")
+ADD_DEFINITIONS("-DPACKAGE_NAME=\"${PKGNAME}\"")
+ADD_DEFINITIONS("-DPREFIX=\"${PREFIX}\"")
+ADD_DEFINITIONS("-DPACKAGE_VERSION=\"${PACKAGE_VERSION}\"")
+
+#SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed")
+SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--as-needed")
+
+ADD_EXECUTABLE(${PROJECT_NAME} ${SRCS})
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS})
+
+
+INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${BINDIR})
diff --git a/LICENSE.APLv2 b/LICENSE.APLv2
new file mode 100644 (file)
index 0000000..d645695
--- /dev/null
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/NOTICE b/NOTICE
new file mode 100644 (file)
index 0000000..0e0f016
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,3 @@
+Copyright (c) Samsung Electronics Co., Ltd. All rights reserved.
+Except as noted, this software is licensed under Apache License, Version 2.
+Please, see the LICENSE.APLv2 file for Apache License terms and conditions.
diff --git a/debian/changelog b/debian/changelog
new file mode 100644 (file)
index 0000000..4ab29a4
--- /dev/null
@@ -0,0 +1,5 @@
+lthor (1.0) unstable; urgency=low
+
+  * Initial upload
+
+ -- Ed Bartosh <eduard.bartosh@intel.com>  Mon, 12 Nov 2012 19:08:56 +0200
diff --git a/debian/compat b/debian/compat
new file mode 100644 (file)
index 0000000..7813681
--- /dev/null
@@ -0,0 +1 @@
+5
\ No newline at end of file
diff --git a/debian/control b/debian/control
new file mode 100644 (file)
index 0000000..c1c09bc
--- /dev/null
@@ -0,0 +1,12 @@
+Source: lthor
+Section: net
+Priority: extra
+Maintainer: Ed Bartosh <eduard.bartosh@intel.com>
+Build-Depends: debhelper (>= 5), libc6-dev, pkg-config, cmake, libarchive-dev
+Standards-Version: 0.0.1
+
+Package: lthor
+Architecture: any
+Depends: ${shlibs:Depends}
+Description: Flashing tool for Tizen lunchbox
+
diff --git a/debian/rules b/debian/rules
new file mode 100755 (executable)
index 0000000..abde6ef
--- /dev/null
@@ -0,0 +1,5 @@
+#!/usr/bin/make -f
+
+%:
+       dh $@
+
diff --git a/lthor.c b/lthor.c
new file mode 100755 (executable)
index 0000000..27df43d
--- /dev/null
+++ b/lthor.c
@@ -0,0 +1,1246 @@
+/*
+ * lthor - Tizen Linux Thor Downloader
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * 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 <unistd.h>
+#include <string.h>
+#include <assert.h>
+#include <sys/mman.h>
+#include <poll.h>
+#include <errno.h>
+#include <dirent.h>
+#include <libgen.h>
+
+#include <archive.h>
+#include <archive_entry.h>
+
+#include "thor-proto.h"
+
+#define USB_VENDOR_SAMSUNG "04e8"
+#define USB_DEVICE_Z100 "6601"
+#define USB_DEVICE_Z100_DEVGURU "6860"
+#define USB_DEVICE_DEVGURU "685d"
+#define USB_DEVICE_OLD_DOWNLOADER "1204"
+
+#define KB                     (1024)
+#define MB                     (1024*KB)
+#define DEFAULT_PKT_SIZE       (1*MB)
+#define DEFAULT_TIMEOUT        (60000)                 /* 1 minute */
+#define DEFAULT_PORT           "/dev/ttyACM0"
+
+/* 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) {
+                       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) {
+               fprintf(stderr, "line %d: ack reports fail. ack = %d\n",
+                               __LINE__, resp.ack);
+               return -1;
+       }
+
+       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);
+}
+
+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;
+}
+
+int thor_handshake(int fd)
+{
+       char buffer[4];
+       int r;
+
+       r = write(fd, "THOR", 4);
+       if (r != 4) {
+               fprintf(stderr, "line %d: failed to write signature bytes\n",
+                               __LINE__);
+               return -1;
+       }
+
+       r = serial_read(fd, buffer, 4, DEFAULT_TIMEOUT);
+       if (r != 4) {
+               fprintf(stderr, "line %d: failed to read signature bytes\n",
+                               __LINE__);
+               return -1;
+       }
+
+       if (memcmp(buffer, "ROHT", 4)) {
+               fprintf(stderr, "line %d: signature byte mismatch\n", __LINE__);
+               return -1;
+       }
+
+       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);
+
+       if (ret) {
+               fprintf(stderr, "USB port is detected : %s\n\n", ret);
+       } else {
+               fprintf(stderr, "USB port is "
+                       "\x1b[0;31;1mnot\x1b[0m detected !\n\n", ret);
+       }
+
+       return ret;
+}
+
+const char* find_usb_device(void)
+{
+       DIR *d;
+       char *p;
+       char buffer[11];
+       const char *dirname = "/sys/bus/usb/devices";
+       char usbpath[0x400];
+       char usbdir[0x100];
+       char *tty = NULL;
+
+       d = opendir(dirname);
+       if (!d)
+               return NULL;
+
+       while (1) {
+               struct dirent *de;
+
+               de = readdir(d);
+               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)];
+
+               /* match the vendor ID */
+               strcat(p, "idVendor");
+               getfile(usbpath, buffer, sizeof buffer);
+               if (opt_verbose)
+                       fprintf(stderr, "vendorId = >%s< %zd\n", buffer,
+                                       strlen(buffer));
+               if (strcmp(buffer, USB_VENDOR_SAMSUNG))
+                       continue;
+
+               /* match the product ID */
+               strcpy(p, "idProduct");
+               getfile(usbpath, buffer, sizeof buffer);
+               if (opt_verbose)
+                       fprintf(stderr, "product = >%s< %zd\n", buffer,
+                                       strlen(buffer));
+
+               if (!strcmp(buffer, USB_DEVICE_OLD_DOWNLOADER))
+                       fprintf(stderr, "Old bootloader detected!\n");
+
+               /* supported product ID */
+               if (strcmp(buffer, USB_DEVICE_Z100) &&
+                       strcmp(buffer, USB_DEVICE_Z100_DEVGURU) &&
+                       strcmp(buffer, USB_DEVICE_DEVGURU))
+                       continue;
+
+               if (opt_verbose)
+                       fprintf(stderr, "found %s:%s!\n", USB_VENDOR_SAMSUNG,
+                                       buffer);
+               closedir(d);
+
+               p[0] = 0x00;
+               d = opendir(usbpath);
+               if (opt_verbose)
+                       fprintf(stderr, "at %s\n", usbpath);
+               while ((de = readdir(d))) {
+                       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)
+                               break;
+               }
+
+               closedir(d);
+               if ((opt_verbose) && (!tty))
+                       fprintf(stderr, "idVendor and idProduct are matched"
+                               "but no tty description\n");
+
+               return tty;
+       }
+
+       closedir(d);
+
+       if (opt_verbose)
+               fprintf(stderr, "No USB device found with matching "
+                       "idVendor and idProduct\n" );
+
+       return NULL;
+}
+
+
+int open_port(const char *portname, int wait)
+{
+       int once = 0;
+       int fd;
+       int r;
+       struct termios tios;
+       const char *dev;
+
+       if (opt_test)
+               return open("/dev/null", O_RDWR);
+
+       while (1) {
+               if (!portname)
+                       dev = find_usb_device();
+               else
+                       dev = portname;
+
+               if (!wait && dev == NULL) {
+                       fprintf(stderr, "line %d: device not found\n", __LINE__);
+                       return -1;
+               }
+
+               if (dev) {
+                       fd = open(dev, O_RDWR);
+                       if (fd == -1) {
+                               perror("port open error!!\n");
+                               return -1;
+                       }
+                       break;
+               }
+
+               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;
+               }
+               sleep(1);
+       }
+
+       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;
+       }
+
+       r = tcflush(fd, TCIOFLUSH);
+       if (r < 0) {
+               fprintf(stderr, "line %d: tcflush failed\n", __LINE__);
+               close(fd);
+               return -1;
+       }
+
+       r = thor_handshake(fd);
+       if (r < 0) {
+               fprintf(stderr, "line %d: handshake failed\n", __LINE__);
+               close(fd);
+               return -1;
+       }
+
+       return fd;
+}
+
+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) {
+               fprintf(stderr, "RQT_DL_FILE_INFO, status = %08x\n", r);
+               return -1;
+       }
+       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;
+       }
+
+       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;
+       }
+
+       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);
+}
+
+size_t te_get_data_block(struct data_src *src, void *data, size_t len)
+{
+       struct tar_data_src *tardata = (struct tar_data_src *) src;
+
+       return archive_read_data(tardata->ar, data, len);
+}
+
+const char *te_get_data_name(struct data_src *src)
+{
+       struct tar_data_src *tardata = (struct tar_data_src *) src;
+
+       return archive_entry_pathname(tardata->ae);
+}
+
+int tardata_open(struct tar_data_src *tardata, const char *tarfile)
+{
+       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);
+
+       if (r) {
+               fprintf(stderr, "line %d: failed to open %s\n", __LINE__, tarfile);
+               return r;
+       }
+
+       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;
+}
+
+const char *tardata_next(struct tar_data_src *tardata)
+{
+       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;
+       }
+
+       return archive_entry_pathname(tardata->ae);
+}
+
+int tardata_close(struct tar_data_src *tardata)
+{
+       archive_read_close(tardata->ar);
+       archive_read_finish(tardata->ar);
+       return 0;
+}
+
+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;
+       }
+
+       *total = 0;
+
+       while (1) {
+               size_t size = 0;
+
+               filename = tardata_next(&tardata);
+               if (!filename)
+                       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);
+               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)
+                       break;
+
+               printf("[\x1b[0;32;1m%s\x1b[0m]\n", filename);
+               r = download_single_file(fd, &tardata.src, BINARY_TYPE_NORMAL);
+               if (r < 0) {
+                       fprintf(stderr, "line %d: failed to download %s\n",
+                                       __LINE__, filename);
+                       break;
+               }
+       }
+
+       fprintf(stderr, "\n%s completed\n", tarfile);
+
+       tardata_close(&tardata);
+
+       return r;
+}
+
+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, "failed to download %s\n", pitfile);
+                       close(fd);
+                       return r;
+               }
+       }
+
+       while (tarfilelist && *tarfilelist) {
+               fprintf(stderr, "\nDownload files from %s\n\n", *tarfilelist);
+               r = download_single_tarfile(fd, *tarfilelist);
+               if (r < 0) {
+                       fprintf(stderr, "failed to download %s\n", *tarfilelist);
+                       close(fd);
+                       return r;
+               }
+               tarfilelist++;
+       }
+
+       r = send_request(fd, RQT_DL, RQT_DL_EXIT, NULL, 0);
+       if (r) {
+               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)
+               fprintf(stderr, "\x1b[0;31;1mfailed\x1b[0m\n");
+       else
+               fprintf(stderr, "\x1b[0;32;1msuccess\x1b[0m\n");
+
+       close(fd);
+
+       return 0;
+}
+
+/* Check if LHOR protocol is in working state */
+int check_proto(const char *portname)
+{
+       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;
+}
+
+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;
+       }
+
+       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, ".");
+
+               n += chunksize;
+       }
+
+       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;
+       }
+
+       while (1) {
+               filename = tardata_next(&tardata);
+               if (!filename)
+                       break;
+
+               fprintf(stderr, " entry %s ", filename);
+
+               r = test_tar_entry(&tardata.src);
+               if (r) {
+                       fprintf(stderr, "bad\n");
+                       break;
+               }
+
+               fprintf(stderr, "\n");
+       }
+
+       tardata_close(&tardata);
+
+       return r;
+}
+
+
+int test_tar_file_list(char **tarfilelist)
+{
+       int r;
+
+       while (*tarfilelist) {
+               char *tarfile = *tarfilelist;
+
+               r = test_tar_file(tarfile);
+               if (r < 0)
+                       fprintf(stderr, "failed to load %s\n", *tarfilelist);
+               tarfilelist++;
+       }
+
+       return 0;
+}
+
+void usage(const char *exename)
+{
+       fprintf(stderr, "%s: [-t] [-v] [-i] [-d port] [-p pitfile] [tar] [tar] ..\n",
+                       exename);
+       exit(1);
+}
+
+int main(int argc, char **argv)
+{
+       const char *exename, *portname, *pitfile;
+       int opt;
+       int opt_check = 0;
+
+       exename = argv[0];
+
+       opt = 1;
+
+       pitfile = NULL;
+       portname = NULL;
+
+       printf("\n");
+       printf("Linux Thor downloader, version %s \n", PACKAGE_VERSION);
+       printf("Authors: YoungJin Lee <yj0701.lee@samsung.com>, "
+                       "Jaehoon You <jaehoon.you@samsung.com>\n\n");
+
+       while (opt < argc) {
+               /* check if we're verbose */
+               if (!strcmp(argv[opt], "-v")) {
+                       opt_verbose = 1;
+                       opt++;
+                       continue;
+               }
+
+               if (!strcmp(argv[opt], "-t")) {
+                       opt_test = 1;
+                       opt++;
+                       continue;
+               }
+
+               if  (!strcmp(argv[opt], "-c")) {
+                       opt_check = 1;
+                       opt++;
+                       continue;
+               }
+
+               if (!strcmp(argv[opt], "-p")) {
+                       pitfile = argv[opt+1];
+                       opt += 2;
+                       continue;
+               }
+
+               if (!strcmp(argv[opt], "-d") && (opt+1) < argc) {
+                       portname = argv[opt+1];
+                       opt += 2;
+                       continue;
+               }
+
+               break;
+       }
+
+       if (opt_test)
+               return test_tar_file_list(&argv[opt]);
+
+       if (opt_check)
+               return check_proto(portname);
+
+       if ((pitfile)&&(opt == argc))
+               return process_download(portname, pitfile, NULL);
+
+       if (opt < argc)
+               return process_download(portname, pitfile, &argv[opt]);
+
+       usage(exename);
+       return 0;
+}
+
diff --git a/packaging/Makefile b/packaging/Makefile
new file mode 100644 (file)
index 0000000..4ffb78c
--- /dev/null
@@ -0,0 +1,19 @@
+PKG_NAME := lthor
+SPECFILE = $(addsuffix .spec, $(PKG_NAME))
+PKG_VERSION := $(shell grep '^Version: ' $(SPECFILE)|awk '{print $$2}')
+
+TARBALL := $(PKG_NAME)_$(PKG_VERSION).tar.gz
+
+tarball:
+       @cd .. && git archive --prefix $(PKG_NAME)-$(PKG_VERSION)/ HEAD \
+               | gzip > packaging/$(TARBALL)
+
+dsc: tarball
+       $(eval MD5=$(shell md5sum $(TARBALL) | sed "s/  / $(shell stat -c '%s' $(TARBALL)) /"))
+       @sed  -i 's/^Version:.*/Version: $(PKG_VERSION)/' $(PKG_NAME).dsc
+       @sed  -i 's/ [a-f0-9]\+ [0-9]\+ $(PKG_NAME).*tar.*/ $(MD5)/' $(PKG_NAME).dsc
+
+clean:
+       @rm -f $(PKG_NAME)_*.tar.gz
+
+all: clean tarball dsc
diff --git a/packaging/lthor.changes b/packaging/lthor.changes
new file mode 100644 (file)
index 0000000..26dd435
--- /dev/null
@@ -0,0 +1,5 @@
+-------------------------------------------------------------------
+Tue Nov  6 16:32:56 UTC 2012 - eduard.bartosh@intel.com
+
+- Initial packaging
+
diff --git a/packaging/lthor.dsc b/packaging/lthor.dsc
new file mode 100644 (file)
index 0000000..e4e4e6e
--- /dev/null
@@ -0,0 +1,10 @@
+Format: 1.0
+Source: lthor
+Binary: lthor
+Architecture: any
+Version: 1.0
+Maintainer: Ed Bartosh <eduard.bartosh@intel.com>
+Standards-Version: 3.7.2
+Build-Depends: debhelper (>= 7), pkg-config, cmake, libarchive-dev
+Files:
+  58f2bac971d05de313cd5d9ca3e60c9b 9259 lthor_1.0.tar.gz
diff --git a/packaging/lthor.spec b/packaging/lthor.spec
new file mode 100644 (file)
index 0000000..3873610
--- /dev/null
@@ -0,0 +1,44 @@
+#
+# spec file for cats-core
+#
+Name:          lthor
+Summary:       Flashing tool for Tizen lunchbox
+Version:       1.0
+Release:       1
+Group:         Development/Tools/Other
+License:       Samsung reserved
+URL:           https://download.tizendev.org/tools/lthor/
+Source0:       %{name}_%{version}.tar.gz
+
+BuildRequires:  libarchive-devel
+BuildRequires:  cmake
+BuildRequires:  pkg-config
+
+%description
+Tool for downloading binaries from a Linux host PC to a target phone.
+It uses a USB cable as a physical communication medium.
+It is prerequisite that the boot-loader should support download protocol
+which is compatible with 'lthor'.
+
+%prep 
+%setup -q
+
+%build
+cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr .
+make %{?_smp_mflags}
+
+%install
+rm -rf $RPM_BUILD_ROOT
+make install DESTDIR=$RPM_BUILD_ROOT
+
+%clean
+rm -rf %{buildroot}
+
+%post
+
+%files
+%defattr(-,root,root)
+%{_bindir}/%{name}
+
+%changelog
+
diff --git a/thor-proto.h b/thor-proto.h
new file mode 100644 (file)
index 0000000..0b8ee39
--- /dev/null
@@ -0,0 +1,78 @@
+#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__ */