// Copyright 2016 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 <errno.h>
#include <fcntl.h>
#include <fuchsia/i2c/c/fidl.h>
#include <zircon/syscalls.h>
#include <zircon/types.h>
#include <lib/fdio/unsafe.h>
#include <lib/fdio/util.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

const char* prog_name;

void print_usage(void) {
    printf("Usage:\n");
    printf("\n");
    printf("%s DEVICE COMMAND [command arguments]\n", prog_name);
    printf("DEVICE is either the i2c bus or i2c slave COMMAND applies to.\n");
    printf("COMMAND is one of the following commands, optionally followed \n");
    printf("arguments which are specific to each command.\n");
    printf("\n");
    printf("read LENGTH: Read data from the target slave device.\n");
    printf("LENGTH is the number of bytes to read in decimal.\n");
    printf("\n");
    printf("write [data]: Write data to the target slave device.\n");
    printf("data is a sequence of hex values which each represent one byte\n");
    printf("of data to write to the target device.\n");
    printf("\n");
    printf("transfer [segments]: Perform a transfer to/from the i2c slave.\n");
    printf("segments is a series of segment descriptions which are a\n");
    printf("direction, a length, and then (for writes) a series of bytes\n");
    printf("in hexadecimal.\n");
    printf("\n");
    printf("The direction is specified as either \"w\" for writes, or\n");
    printf("\"r\" for reads.\n");
    printf("\n");
    printf("For example, to perform a write of one byte and then a read\n");
    printf("of one byte without giving up the bus:\n");
    printf("%s [dev] transfer w 1 00 r 1\n", prog_name);
}

int cmd_read(int fd, int argc, const char** argv) {
    if (argc < 1) {
        print_usage();
        return 1;
    }

    errno = 0;
    long int length = strtol(argv[0], NULL, 10);
    if (errno) {
        print_usage();
        return errno;
    }

    uint8_t* buf = malloc(length);
    if (!buf) {
        printf("Failed to allocate buffer.\n");
        return 1;
    }

    int ret = read(fd, buf, length);
    if (ret < 0) {
        printf("Error reading from slave. (%d)\n", ret);
        goto cmd_read_finish;
    }

    for (int i = 0; i < length; i++) {
        printf(" %02x", buf[i]);
        if (i % 32 == 31) printf("\n");
    }
    printf("\n");

cmd_read_finish:
    free(buf);
    return ret;
}

int cmd_write(int fd, int argc, const char** argv) {
    if (argc < 1) {
        print_usage();
        return 1;
    }

    uint8_t* buf = malloc(argc);
    if (!buf) {
        printf("Failed to allocate buffer.\n");
        return 1;
    }

    int ret = 0;

    errno = 0;
    for (int i = 0; i < argc; i++) {
        buf[i] = strtol(argv[i], NULL, 16);
        if (errno) {
            ret = errno;
            print_usage();
            goto cmd_write_finish;
        }
    }

    ret = write(fd, buf, argc);
    if (ret < 0)
        printf("Error writing to slave. (%d)\n", ret);

cmd_write_finish:
    free(buf);
    return ret;
}

int cmd_transfer(int fd, int argc, const char** argv) {
    const size_t base_size = sizeof(fuchsia_i2c_Segment);
    int ret = ZX_OK;

    // Figure out how big our buffers need to be.
    // Start the counters with enough space for the fuchsia_i2c_SegmentType_END
    // segment.
    size_t in_len = base_size;
    size_t out_len = 0;
    int segments = 1;
    int count = argc;
    const char** arg = argv;
    errno = 0;
    while (count) {
        if (count < 2) {
            print_usage();
            goto cmd_transfer_finish_2;
        }

        in_len += base_size;

        int read;
        if (!strcmp(arg[0], "r")) {
            read = 1;
        } else if (!strcmp(arg[0], "w")) {
            read = 0;
        } else {
            print_usage();
            goto cmd_transfer_finish_2;
        }
        segments++;

        long int length = strtol(arg[1], NULL, 10);
        if (errno) {
            print_usage();
            return errno;
        }
        arg += 2;
        count -= 2;
        if (read) {
            out_len += length;
        } else {
            in_len += length;
            if (length > count) {
                print_usage();
                goto cmd_transfer_finish_2;
            }
            arg += length;
            count -= length;
        }
    }

    // Allocate the input and output buffers.
    void* in_buf = malloc(in_len);
    void* out_buf = malloc(out_len);
    if (!in_buf || !out_buf) {
        ret = 1;
        goto cmd_transfer_finish_1;
    }
    uint8_t* data_addr = (uint8_t*)in_buf + segments * base_size;
    uint8_t* data_buf = data_addr;

    // Fill the "input" buffer which is sent via FIDL.
    uintptr_t in_addr = (uintptr_t)in_buf;
    int i = 0;
    fuchsia_i2c_Segment* segment = (fuchsia_i2c_Segment*)in_addr;
    while (i < argc) {
        if (!strcmp(argv[i++], "r")) {
            segment->type = fuchsia_i2c_SegmentType_READ;
            segment->len = strtol(argv[i++], NULL, 10);
            if (errno) {
                print_usage();
                return errno;
            }
        } else {
            segment->type = fuchsia_i2c_SegmentType_WRITE;
            segment->len = strtol(argv[i++], NULL, 10);
            if (errno) {
                print_usage();
                return errno;
            }

            for (uint32_t seg = 0; seg < segment->len; seg++) {
                *data_buf++ = strtol(argv[i++], NULL, 16);
                if (errno) {
                    print_usage();
                    return errno;
                }
            }
        }
        segment++;
    }
    segment->type = fuchsia_i2c_SegmentType_END;
    segment->len = 0;
    segment++;
    // We should be at the start of the data section now.
    if ((uint8_t*)segment != data_addr) {
        ret = 1;
        goto cmd_transfer_finish_1;
    }

    fdio_t* io = fdio_unsafe_fd_to_io(fd); // Get a fdio channel from the fd.
    if (io == NULL) return ZX_ERR_INVALID_ARGS;
    zx_status_t status;
    size_t out_actual;
    zx_status_t res =
        fuchsia_i2c_DeviceSlaveTransfer(fdio_unsafe_borrow_channel(io), in_buf, in_len,
                                       &status, out_buf, out_len, &out_actual);
    fdio_unsafe_release(io); // Release the channel manually.
    if (out_actual < out_len) {
        status = ZX_ERR_BUFFER_TOO_SMALL;
    }
    if (res == ZX_OK) {
        res = status;
    }
    if (res != ZX_OK) {
        printf("Error in transfer to/from slave. (%d)\n", res);
        goto cmd_transfer_finish_1;
    }

    for (size_t i = 0; i < out_len; i++) {
        printf(" %02x", ((uint8_t*)out_buf)[i]);
        if (i % 32 == 31) printf("\n");
    }
    printf("\n");

    ret = 0;

cmd_transfer_finish_1:
    free(in_buf);
    free(out_buf);
cmd_transfer_finish_2:
    return ret;
}

int main(int argc, const char** argv) {
    if (argc < 1)
        return 1;

    prog_name = argv[0];

    if (argc < 3) {
        print_usage();
        return 1;
    }

    const char* dev = argv[1];
    const char* cmd = argv[2];

    argc -= 3;
    argv += 3;

    int fd = open(dev, O_RDWR);
    if (fd < 0) {
        printf("Error opening I2C device.\n");
        return 1;
    }

    if (!strcmp("read", cmd)) {
        return cmd_read(fd, argc, argv);
    } else if (!strcmp("write", cmd)) {
        return cmd_write(fd, argc, argv);
    } else if (!strcmp("transfer", cmd)) {
        return cmd_transfer(fd, argc, argv);
    } else {
        printf("Unrecognized command %s.\n", cmd);
        print_usage();
        return 1;
    }

    printf("We should never get here!.\n");
    return 1;
}
