summaryrefslogtreecommitdiffstats
path: root/sw-linux/rom-loader/main.cpp
blob: 3c845baab3e9901360b7085a0cc298c626173891 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#include <iostream>
#include <string>
#include <vector>

#include <cstdio>
#include <cstdlib>

#include "serial.hpp"

struct args_t
{
    std::string file_name;
    bool file_name_set;
    std::string port_name;
    bool port_name_set;
    long baudrate;
    bool baudrate_set;
};

void usage(void)
{
    std::cout << "rom-loader -p [PORT] -f [FILE]" << std::endl
              << std::endl
              << "Nao Pross <naopross@thearcway.org>" << std::endl;
}

bool parse_arguments(const int argc, const char * const argv[], args_t& args)
{
    if (argc < 2) {
        usage();
        return false;
    }

    args.file_name_set = false;
    args.port_name_set = false;
    args.baudrate_set = false;

    for (int i = 1; i < argc; i++) {
        const std::string arg(argv[i]);

        bool next = false;
        std::string next_arg = "";

        // check that is an option
        if (arg.front() != '-') {
            usage();
            return false;
        }

        // help option
        if (arg[1] == 'h') {
            usage();
            return false;
        }

        // check that threre is an argument
        if (i+1 < argc) {
            next_arg = std::string(argv[i+1]);
            i++;
        } else {
            std::cerr << "Missing option argument" << std::endl;
            return false;
        }

        switch (arg[1]) {
        case 'p':
            args.port_name = next_arg;
            args.port_name_set = true;
            break;

        case 'f':
            args.file_name = next_arg;
            args.file_name_set = true;
            break;

        case 'b':
            args.baudrate = std::stol(next_arg);
            args.baudrate_set = true;
            break;

        default:
            std::cerr << "Invalid option " << arg << std::endl;
            return false;
        }
    }

    if (!args.file_name_set || !args.port_name_set) {
        std::cerr << "Missing required options: ";
        
        if (!args.file_name_set)
            std::cerr << "-f [FILE] ";

        if (!args.port_name_set)
            std::cerr << "-p [PORT] ";

        std::cerr << std::endl;

        return false;
    }

    return true;
}

int main(int argc, char *argv[])
{
    args_t args;

    if (!parse_arguments(argc, argv, args)) {
        return -1;
    }

    FILE *fileptr = std::fopen(args.file_name.c_str(), "rb");

    if (!fileptr) {
        std::cerr << "Failed to open file " << args.file_name << std::endl;
        return -2;
    }

    serial s_dev(args.port_name, B9600);

    int chr;
    while ((chr = std::fgetc(fileptr)) != EOF) {
        const char byte = static_cast<char>(chr);

        // std::cout << std::hex << byte << std::endl;
        s_dev.write(&byte, 1);
    }

    if (std::ferror(fileptr))
        std::cerr << "I/O error when reading file " 
                  << args.file_name << std::endl;

    if (!std::feof(fileptr))
        std::cerr << "The reading ended before reaching EOF" << std::endl;

    std::fclose(fileptr);

    return 0;
}