summaryrefslogtreecommitdiff
path: root/libthor/thor.c
diff options
context:
space:
mode:
authorDongwoo Lee <dwoo08.lee@samsung.com>2017-09-26 10:50:41 +0900
committerSeung-Woo Kim <sw0312.kim@samsung.com>2018-05-31 15:35:48 +0900
commitc34bb09c195829235f6921812b4d85c30cc44f2b (patch)
tree93f364791187eec32af0665f913da4fe2297efb3 /libthor/thor.c
parent644503bbf4cd6d429b84955feb06fb1aebc7396f (diff)
downloadlthor-c34bb09c195829235f6921812b4d85c30cc44f2b.tar.gz
lthor-c34bb09c195829235f6921812b4d85c30cc44f2b.tar.bz2
lthor-c34bb09c195829235f6921812b4d85c30cc44f2b.zip
Re-structure lthor to extend its transfer methods
Currently, thor has very specific code structure for considering only usb transfer, thus it is too hard to add other transfer methods. This patch makes lthor to be extendable by just implementing few operations: open, close, send, recv, and send_data. Change-Id: If455a9d7a5c7fd86cf6e8808f29c643456e80166 Signed-off-by: Dongwoo Lee <dwoo08.lee@samsung.com> Signed-off-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Diffstat (limited to 'libthor/thor.c')
-rw-r--r--libthor/thor.c465
1 files changed, 109 insertions, 356 deletions
diff --git a/libthor/thor.c b/libthor/thor.c
index 6dc37e4..37c4b24 100644
--- a/libthor/thor.c
+++ b/libthor/thor.c
@@ -14,69 +14,58 @@
* limitations under the License.
*/
+#include <assert.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include "thor.h"
#include "thor_internal.h"
+#include "thor_transport.h"
-int thor_init()
+thor_device_handle *thor_init(enum thor_transport_type type)
{
- return libusb_init(NULL);
-}
+ thor_device_handle *th;
+ int ret;
-void thor_cleanup()
-{
- libusb_exit(NULL);
-}
+ th = calloc(1, sizeof(*th));
+ if (!th)
+ return NULL;
-int thor_check_proto(struct thor_device_id *dev_id)
-{
- struct thor_device_handle *th;
- int ret;
+ th->type = type;
- ret = thor_open(dev_id, 0, &th);
- if (!ret)
- thor_close(th);
+ ret = t_thor_init(th);
+ if (ret < 0) {
+ free(th);
+ th = NULL;
+ }
- return ret;
+ return th;
}
-static struct thor_device_id * thor_choose_id(
- struct thor_device_id *user_dev_id)
+void thor_cleanup(thor_device_handle *th)
{
- static struct thor_device_id default_id = {
- .busid = NULL,
- .vid = 0x04e8,
- .pid = 0x685d,
- .serial = NULL,
- };
-
- if (user_dev_id->busid == NULL
- && user_dev_id->vid < 0
- && user_dev_id->pid < 0
- && user_dev_id->serial == NULL)
- user_dev_id = &default_id;
-
- return user_dev_id;
+ if (!th)
+ return;
+ t_thor_cleanup(th);
+ free(th);
}
-static int t_thor_do_handshake(struct thor_device_handle *th)
+static int thor_do_handshake(thor_device_handle *th)
{
char challenge[] = "THOR";
char response[] = "ROHT";
char buffer[sizeof(response)];
int ret;
- ret = t_usb_send(th, (unsigned char *)challenge, sizeof(challenge) - 1,
- DEFAULT_TIMEOUT);
+ ret = t_thor_send(th, (unsigned char *)challenge, sizeof(challenge) - 1,
+ DEFAULT_TIMEOUT);
if (ret < 0)
return ret;
- ret = t_usb_recv(th, (unsigned char *)buffer, sizeof(buffer) - 1,
- DEFAULT_TIMEOUT);
+ ret = t_thor_recv(th, (unsigned char *)buffer, sizeof(buffer) - 1,
+ DEFAULT_TIMEOUT);
if (ret < 0)
return ret;
@@ -88,49 +77,77 @@ static int t_thor_do_handshake(struct thor_device_handle *th)
return 0;
}
-int thor_open(struct thor_device_id *user_dev_id, int wait,
- thor_device_handle **handle)
+int thor_open(thor_device_handle *th, struct thor_device_id *dev_id, int wait)
{
- struct thor_device_id *dev_id = thor_choose_id(user_dev_id);
- struct thor_device_handle *th;
- int found, ret;
+ int ret;
- th = calloc(sizeof(*th), 1);
if (!th)
- return -ENOMEM;
+ return -ENOENT;
- found = t_usb_find_device(dev_id, wait, th);
- if (found <= 0) {
- ret = -ENODEV;
- goto close_dev;
- }
-
- ret = t_acm_prepare_device(th);
+ ret = t_thor_open(th, dev_id, wait);
if (ret)
- goto close_dev;
+ return ret;
- ret = t_thor_do_handshake(th);
+ ret = thor_do_handshake(th);
if (ret) {
- ret = -EINVAL;
- goto close_dev;
+ thor_close(th);
+ return ret;
}
- *handle = th;
return 0;
-close_dev:
- thor_close(th);
- return ret;
}
void thor_close(thor_device_handle *th)
{
- t_usb_close_device(th);
- free(th);
+ if (!th)
+ return;
+
+ t_thor_close(th);
}
-static int t_thor_exec_cmd_full(thor_device_handle *th, request_type req_id,
- int req_sub_id, int *idata, int icnt,
- char **sdata, int scnt, struct res_pkt *res)
+static int thor_send_req(thor_device_handle *th, request_type req_id,
+ int req_sub_id, int *idata, int icnt,
+ char **sdata, int scnt)
+{
+ struct rqt_pkt req;
+ int i;
+ int ret;
+
+ assert(icnt <= ARRAY_SIZE(req.int_data));
+ assert(icnt >= 0);
+ assert(scnt <= ARRAY_SIZE(req.str_data));
+ 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++)
+ strncpy(req.str_data[i], sdata[i], 32);
+ }
+
+ ret = t_thor_send(th, (unsigned char *)&req, RQT_PKT_SIZE,
+ DEFAULT_TIMEOUT);
+
+ return ret;
+}
+
+static inline int thor_recv_req(thor_device_handle *th, struct res_pkt *resp)
+{
+ return t_thor_recv(th, (unsigned char *)resp, sizeof(*resp),
+ DEFAULT_TIMEOUT);
+}
+
+static int thor_exec_cmd_full(thor_device_handle *th, request_type req_id,
+ int req_sub_id, int *idata, int icnt,
+ char **sdata, int scnt, struct res_pkt *res)
{
int ret;
struct res_pkt resp;
@@ -138,23 +155,23 @@ static int t_thor_exec_cmd_full(thor_device_handle *th, request_type req_id,
if (!res)
res = &resp;
- ret = t_usb_send_req(th, req_id, req_sub_id, idata, icnt,
- sdata, scnt);
+ ret = thor_send_req(th, req_id, req_sub_id, idata, icnt,
+ sdata, scnt);
if (ret < 0)
return ret;
- ret = t_usb_recv_req(th, res);
+ ret = thor_recv_req(th, res);
if (ret < 0)
return ret;
return res->ack;
}
-static int t_thor_exec_cmd(thor_device_handle *th, request_type req_id,
- int req_sub_id, int *idata, int icnt)
+static inline int thor_exec_cmd(thor_device_handle *th, request_type req_id,
+ int req_sub_id, int *idata, int icnt)
{
- return t_thor_exec_cmd_full(th, req_id, req_sub_id, idata, icnt,
- NULL, 0, NULL);
+ return thor_exec_cmd_full(th, req_id, req_sub_id, idata, icnt,
+ NULL, 0, NULL);
}
int thor_get_proto_ver(thor_device_handle *th)
@@ -162,8 +179,11 @@ int thor_get_proto_ver(thor_device_handle *th)
int ret;
struct res_pkt resp;
- ret = t_thor_exec_cmd_full(th, RQT_INFO, RQT_INFO_VER_PROTOCOL,
- NULL, 0, NULL, 0, &resp);
+ if (!th)
+ return -ENOENT;
+
+ ret = thor_exec_cmd_full(th, RQT_INFO, RQT_INFO_VER_PROTOCOL,
+ NULL, 0, NULL, 0, &resp);
if (!ret)
ret = (resp.int_data[0] << 8) | resp.int_data[1];
@@ -178,8 +198,8 @@ int thor_start_session(thor_device_handle *th, off_t total)
int_data[0] = (uint32_t)(total & 0xffffffff);
int_data[1] = (uint32_t)((total >> 32) & 0xffffffff);
- ret = t_thor_exec_cmd(th, RQT_DL, RQT_DL_INIT, int_data,
- ARRAY_SIZE(int_data));
+ ret = thor_exec_cmd(th, RQT_DL, RQT_DL_INIT, int_data,
+ ARRAY_SIZE(int_data));
return ret;
}
@@ -188,273 +208,10 @@ int thor_end_session(thor_device_handle *th)
{
int ret;
- ret = t_thor_exec_cmd(th, RQT_DL, RQT_DL_EXIT, NULL, 0);
-
- return ret;
-}
-
-static int t_thor_submit_chunk(struct t_thor_data_chunk *chunk)
-{
- int ret;
-
- chunk->data_finished = chunk->resp_finished = 0;
-
- ret = t_usb_submit_transfer(&chunk->data_transfer);
- if (ret)
- goto out;
-
- memset(&chunk->resp, 0, DATA_RES_PKT_SIZE);
- ret = t_usb_submit_transfer(&chunk->resp_transfer);
- if (ret)
- goto cancel_data_transfer;
-
- return 0;
-cancel_data_transfer:
- t_usb_cancel_transfer(&chunk->data_transfer);
-out:
- return ret;
-}
-
-static int t_thor_prep_next_chunk(struct t_thor_data_chunk *chunk,
- struct t_thor_data_transfer *transfer_data)
-{
- off_t to_read;
- int ret;
-
- to_read = transfer_data->data_left - transfer_data->data_in_progress;
- if (to_read <= 0) {
- printf("to big data in progress\n");
- fflush(stdout);
- return -EINVAL;
- }
-
- chunk->useful_size = to_read > chunk->trans_unit_size ?
- chunk->trans_unit_size : to_read;
-
- ret = transfer_data->data->get_block(transfer_data->data,
- chunk->buf, chunk->useful_size);
- if (ret < 0 || ret != chunk->useful_size)
- return ret;
-
- memset(chunk->buf + chunk->useful_size, 0,
- chunk->trans_unit_size - chunk->useful_size);
- chunk->chunk_number = transfer_data->chunk_number++;
-
- ret = t_thor_submit_chunk(chunk);
- if (!ret)
- transfer_data->data_in_progress += chunk->useful_size;
-
- return ret;
-}
-
-static void check_next_chunk(struct t_thor_data_chunk *chunk,
- struct t_thor_data_transfer *transfer_data)
-{
- /* If there is some more data to be queued */
- if (transfer_data->data_left - transfer_data->data_in_progress) {
- int ret;
-
- ret = t_thor_prep_next_chunk(chunk, transfer_data);
- if (ret) {
- transfer_data->ret = ret;
- transfer_data->completed = 1;
- }
- } else {
- /* Last one turns the light off */
- if (transfer_data->data_in_progress == 0)
- transfer_data->completed = 1;
- }
-}
-
-static void data_transfer_finished(struct t_usb_transfer *_data_transfer)
-{
- struct t_thor_data_chunk *chunk = container_of(_data_transfer,
- struct t_thor_data_chunk,
- data_transfer);
- struct t_thor_data_transfer *transfer_data = chunk->user_data;
-
- chunk->data_finished = 1;
-
- if (_data_transfer->cancelled || transfer_data->ret)
- return;
-
- if (_data_transfer->ret) {
- transfer_data->ret = _data_transfer->ret;
- transfer_data->completed = 1;
- }
-
- if (chunk->resp_finished)
- check_next_chunk(chunk, transfer_data);
-}
-
-static void resp_transfer_finished(struct t_usb_transfer *_resp_transfer)
-{
- struct t_thor_data_chunk *chunk = container_of(_resp_transfer,
- struct t_thor_data_chunk,
- resp_transfer);
- struct t_thor_data_transfer *transfer_data = chunk->user_data;
-
- chunk->resp_finished = 1;
- transfer_data->data_in_progress -= chunk->useful_size;
-
- if (_resp_transfer->cancelled || transfer_data->ret) {
- if (transfer_data->data_in_progress == 0)
- transfer_data->completed = 1;
- return;
- }
-
- if (_resp_transfer->ret) {
- transfer_data->ret = _resp_transfer->ret;
- goto complete_all;
- }
-
- if (chunk->resp.cnt != chunk->chunk_number) {
- printf ("chunk number mismatch: %d != %d\n",
- chunk->resp.cnt, chunk->chunk_number);
- fflush(stdout);
- transfer_data->ret = -EINVAL;
- goto complete_all;
- }
-
- transfer_data->data_sent += chunk->useful_size;
- transfer_data->data_left -= chunk->useful_size;
- if (transfer_data->report_progress)
- transfer_data->report_progress(transfer_data->th,
- transfer_data->data,
- transfer_data->data_sent,
- transfer_data->data_left,
- chunk->chunk_number,
- transfer_data->user_data);
-
- if (chunk->data_finished)
- check_next_chunk(chunk, transfer_data);
-
- return;
-complete_all:
- transfer_data->completed = 1;
- return;
-}
-
-static int t_thor_init_chunk(struct t_thor_data_chunk *chunk,
- thor_device_handle *th,
- off_t trans_unit_size,
- void *user_data)
-{
- int ret;
-
- chunk->user_data = user_data;
- chunk->useful_size = 0;
- chunk->trans_unit_size = trans_unit_size;
-
- chunk->buf = malloc(trans_unit_size);
- if (!chunk->buf)
- return -ENOMEM;
-
- ret = t_usb_init_out_transfer(&chunk->data_transfer, th, chunk->buf,
- trans_unit_size, data_transfer_finished,
- DEFAULT_TIMEOUT);
- if (ret)
- goto free_buf;
-
- ret = t_usb_init_in_transfer(&chunk->resp_transfer, th,
- (unsigned char *)&chunk->resp,
- DATA_RES_PKT_SIZE,
- resp_transfer_finished,
- 2*DEFAULT_TIMEOUT);
- if (ret)
- goto cleanup_data_transfer;
-
- return 0;
-cleanup_data_transfer:
- t_usb_cleanup_transfer(&chunk->data_transfer);
-free_buf:
- free(chunk->buf);
-
- return ret;
-}
-
-static void t_thor_cleanup_chunk(struct t_thor_data_chunk *chunk)
-{
- t_usb_cleanup_transfer(&chunk->data_transfer);
- t_usb_cleanup_transfer(&chunk->resp_transfer);
- free(chunk->buf);
-}
-
-static inline int
-t_thor_handle_events(struct t_thor_data_transfer *transfer_data)
-{
- return t_usb_handle_events_completed(&transfer_data->completed);
-}
-
-static inline void t_thor_cancel_chunk(struct t_thor_data_chunk *chunk)
-{
- t_usb_cancel_transfer(&chunk->data_transfer);
- t_usb_cancel_transfer(&chunk->resp_transfer);
-}
-
-static int t_thor_send_raw_data(thor_device_handle *th,
- struct thor_data_src *data,
- off_t trans_unit_size,
- thor_progress_cb report_progress,
- void *user_data)
-{
- struct t_thor_data_chunk chunk[3];
- struct t_thor_data_transfer transfer_data;
- int i, j;
- int ret;
-
- for (i = 0; i < ARRAY_SIZE(chunk); ++i) {
- ret = t_thor_init_chunk(chunk + i, th, trans_unit_size,
- &transfer_data);
- if (ret)
- goto cleanup_chunks;
- }
-
- transfer_data.data = data;
- transfer_data.report_progress = report_progress;
- transfer_data.user_data = user_data;
- transfer_data.data_left = data->get_file_length(data);
- transfer_data.data_sent = 0;
- transfer_data.chunk_number = 1;
- transfer_data.completed = 0;
- transfer_data.data_in_progress = 0;
- transfer_data.ret = 0;
-
- for (i = 0;
- i < ARRAY_SIZE(chunk)
- && (transfer_data.data_left - transfer_data.data_in_progress > 0);
- ++i) {
- ret = t_thor_prep_next_chunk(chunk + i, &transfer_data);
- if (ret)
- goto cancel_chunks;
- }
-
- t_thor_handle_events(&transfer_data);
-
- if (transfer_data.data_in_progress) {
- ret = transfer_data.ret;
- goto cancel_chunks;
- }
-
- for (i = 0; i < ARRAY_SIZE(chunk); ++i)
- t_thor_cleanup_chunk(chunk + i);
-
- return transfer_data.ret;
-
-cancel_chunks:
- for (j = 0; j < i; ++j)
- t_thor_cancel_chunk(chunk + j);
- if (i) {
- transfer_data.completed = 0;
- t_thor_handle_events(&transfer_data);
- }
-
- i = ARRAY_SIZE(chunk);
-cleanup_chunks:
- for (j = 0; j < i; ++j)
- t_thor_cleanup_chunk(chunk + j);
+ if (!th)
+ return -ENOENT;
- return ret;
+ return thor_exec_cmd(th, RQT_DL, RQT_DL_EXIT, NULL, 0);
}
int thor_send_data(thor_device_handle *th, struct thor_data_src *data,
@@ -508,20 +265,18 @@ int thor_send_data(thor_device_handle *th, struct thor_data_src *data,
if (!th)
continue;
- ret = t_thor_exec_cmd_full(th, RQT_DL, RQT_DL_FILE_INFO,
- int_data, ARRAY_SIZE(int_data),
- (char **)str_data, scnt, &resp);
+ ret = thor_exec_cmd_full(th, RQT_DL, RQT_DL_FILE_INFO,
+ int_data, ARRAY_SIZE(int_data),
+ (char **)str_data, scnt, &resp);
if (ret < 0)
return ret;
trans_unit_size = resp.int_data[0];
- if (th) {
- ret = t_thor_exec_cmd(th, RQT_DL, RQT_DL_FILE_START,
- NULL, 0);
- if (ret < 0)
- return ret;
- }
+ ret = thor_exec_cmd(th, RQT_DL, RQT_DL_FILE_START,
+ NULL, 0);
+ if (ret < 0)
+ return ret;
ret = t_thor_send_raw_data(th, data, trans_unit_size,
report_progress, user_data);
@@ -529,8 +284,8 @@ int thor_send_data(thor_device_handle *th, struct thor_data_src *data,
return ret;
if (th) {
- ret = t_thor_exec_cmd(th, RQT_DL, RQT_DL_FILE_END,
- NULL, 0);
+ ret = thor_exec_cmd(th, RQT_DL, RQT_DL_FILE_END,
+ NULL, 0);
if (ret < 0)
return ret;
}
@@ -541,11 +296,10 @@ int thor_send_data(thor_device_handle *th, struct thor_data_src *data,
int thor_reboot(thor_device_handle *th)
{
- int ret;
-
- ret = t_thor_exec_cmd(th, RQT_CMD, RQT_CMD_REBOOT, NULL, 0);
+ if (!th)
+ return -ENOENT;
- return ret;
+ return thor_exec_cmd(th, RQT_CMD, RQT_CMD_REBOOT, NULL, 0);
}
int thor_get_data_src(const char *path, enum thor_data_src_format format,
@@ -572,4 +326,3 @@ void thor_release_data_src(struct thor_data_src *data)
if (data->release)
data->release(data);
}
-