blob: b37cbf3b074d8d3facb323cb6ae4887f733d3e26 [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <fuchsia/hardware/serial/llcpp/fidl.h>
#include <lib/fdio/unsafe.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <threads.h>
#include <unistd.h>
#include <zircon/syscalls.h>
#define DEV_SERIAL "/dev/class/serial"
namespace fuchsia = ::llcpp::fuchsia;
static void serial_print(int fd, const char* str) { write(fd, str, strlen(str)); }
int main(int argc, char** argv) {
struct dirent* de;
DIR* dir = opendir(DEV_SERIAL);
if (!dir) {
printf("Error opening %s\n", DEV_SERIAL);
return -1;
}
int fd = -1;
char path[100];
while ((de = readdir(dir)) != NULL) {
if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
continue;
}
snprintf(path, sizeof(path), "%s/%s", DEV_SERIAL, de->d_name);
fd = open(path, O_RDWR);
if (fd < 0) {
continue;
}
fdio_t* fdio = fdio_unsafe_fd_to_io(fd);
auto result = fuchsia::hardware::serial::Device::Call::GetClass(
zx::unowned_channel(fdio_unsafe_borrow_channel(fdio)));
fuchsia::hardware::serial::Class device_class = result->device_class;
fdio_unsafe_release(fdio);
if (!result.ok() || device_class != fuchsia::hardware::serial::Class::GENERIC) {
close(fd);
continue;
} else {
break;
}
}
if (fd < 0) {
fprintf(stderr, "could not find generic serial port in %s\n", DEV_SERIAL);
return -1;
}
while (1) {
char buffer[100];
ssize_t count = read(fd, buffer, sizeof(buffer));
if (count < 0) {
fprintf(stderr, "serial read failed: %s\n", strerror(errno));
break;
}
// echo text locally
for (ssize_t i = 0; i < count; i++) {
printf("%c", buffer[i]);
}
fflush(stdout);
if (buffer[0] == 'x' || buffer[0] == 'X') {
serial_print(fd, "Closing and reopening the serial port. Wish me luck!\n");
// wait for data to be written before closing handle
// TODO(voydanoff) eliminate this sleep after we implement socket_flush()
sleep(1);
close(fd);
// wait a bit for serial port to shut down before reopening
sleep(1);
fd = open(path, O_RDWR);
if (fd < 0) {
fprintf(stderr, "failed to reopen serial port: %s\n", strerror(errno));
return fd;
}
serial_print(fd, "...and we're back!\n");
} else {
serial_print(fd, "Read: \"");
write(fd, buffer, count);
serial_print(fd, "\"\n");
}
}
close(fd);
return 0;
}