trainlog/tui/tools/mtp_roundtrip_probe.c

273 lines
5.3 KiB
C

#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "trainlog/mtp.h"
#include "trainlog/status.h"
#include "trainlog/usb.h"
#define DEVICE_CAPACITY 16U
#define STORAGE_CAPACITY 16U
#define ENTRY_CAPACITY 128U
static const char EXPECTED_CONTENT[] =
"Trainlog MTP write probe\n"
"If you can read this file on Android, USB/MTP write works.\n";
static int verify_file(
const char *path
)
{
FILE *stream;
char buffer[256];
size_t read_size;
stream =
fopen(
path,
"rb"
);
if (stream == NULL) {
return -1;
}
read_size =
fread(
buffer,
1U,
sizeof(buffer),
stream
);
if (ferror(stream) != 0) {
(void)fclose(stream);
return -1;
}
if (fclose(stream) != 0) {
return -1;
}
if (read_size !=
sizeof(EXPECTED_CONTENT) - 1U) {
return -1;
}
if (memcmp(
buffer,
EXPECTED_CONTENT,
read_size
) != 0) {
return -1;
}
return 0;
}
int main(void)
{
TrainlogUsbDevice
devices[DEVICE_CAPACITY];
TrainlogMtpStorage
storages[STORAGE_CAPACITY];
TrainlogMtpEntry
entries[ENTRY_CAPACITY];
size_t device_count = 0U;
size_t storage_count = 0U;
size_t entry_count = 0U;
size_t index;
uint32_t folder_id = 0U;
uint32_t probe_item_id = 0U;
bool created = false;
char local_path[] =
"/tmp/trainlog-mtp-readback-XXXXXX";
int fd;
TrainlogStatus status;
status =
trainlog_usb_list_mtp_devices(
devices,
DEVICE_CAPACITY,
&device_count
);
if (status != TRAINLOG_STATUS_OK ||
device_count == 0U) {
(void)fprintf(
stderr,
"No physical MTP device available.\n"
);
return 1;
}
status =
trainlog_mtp_list_storages(
devices[0].bus_number,
devices[0].device_number,
storages,
STORAGE_CAPACITY,
&storage_count
);
if (status != TRAINLOG_STATUS_OK ||
storage_count == 0U) {
(void)fprintf(
stderr,
"No MTP storage available.\n"
);
return 1;
}
status =
trainlog_mtp_ensure_root_folder(
devices[0].bus_number,
devices[0].device_number,
storages[0].storage_id,
"Trainlog",
&folder_id,
&created
);
if (status != TRAINLOG_STATUS_OK) {
(void)fprintf(
stderr,
"Unable to locate Trainlog folder: %d\n",
(int)status
);
return 1;
}
(void)printf(
"Trainlog folder id=0x%08x (%s)\n",
folder_id,
created
? "created"
: "already present"
);
status =
trainlog_mtp_list_folder(
devices[0].bus_number,
devices[0].device_number,
storages[0].storage_id,
folder_id,
entries,
ENTRY_CAPACITY,
&entry_count
);
if (status != TRAINLOG_STATUS_OK) {
(void)fprintf(
stderr,
"Unable to list Trainlog folder: %d\n",
(int)status
);
return 1;
}
(void)printf(
"Trainlog entries: %zu\n",
entry_count
);
for (index = 0U;
index < entry_count;
++index) {
(void)printf(
" %s id=0x%08x %s size=%llu\n",
entries[index].folder
? "[DIR] "
: "[FILE]",
entries[index].item_id,
entries[index].name,
(unsigned long long)
entries[index].size_bytes
);
if (!entries[index].folder &&
strcmp(
entries[index].name,
"trainlog-probe.txt"
) == 0) {
probe_item_id =
entries[index].item_id;
}
}
if (probe_item_id == 0U) {
(void)fprintf(
stderr,
"trainlog-probe.txt not found.\n"
);
return 1;
}
fd =
mkstemp(
local_path
);
if (fd < 0) {
(void)fprintf(
stderr,
"Unable to create local readback file.\n"
);
return 1;
}
if (close(fd) != 0) {
(void)unlink(local_path);
return 1;
}
status =
trainlog_mtp_receive_file(
devices[0].bus_number,
devices[0].device_number,
probe_item_id,
local_path
);
if (status != TRAINLOG_STATUS_OK) {
(void)unlink(local_path);
(void)fprintf(
stderr,
"Unable to download probe file: %d\n",
(int)status
);
return 1;
}
if (verify_file(
local_path
) != 0) {
(void)unlink(local_path);
(void)fprintf(
stderr,
"Readback content mismatch.\n"
);
return 1;
}
(void)unlink(
local_path
);
(void)printf(
"ROUNDTRIP=PASS "
"Trainlog/trainlog-probe.txt\n"
);
return 0;
}