2 * Copyright (c) 2017 Petr Manek
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 #include <str_error.h>
41 #include <usbdiag_iface.h>
46 #define MAX_PATH_LENGTH 1024
48 /** Common command handler for all test commands.
49 * @param[in] argc Number of arguments.
50 * @param[in] argv Argument values. Must point to exactly `argc` strings.
54 int tmon_test_main(int argc
, char *argv
[], const tmon_test_ops_t
*ops
)
56 // Resolve device function.
57 devman_handle_t fun
= -1;
59 if (argc
>= 2 && *argv
[1] != '-') {
60 // Assume that the first argument is device path.
61 if (tmon_resolve_named(argv
[1], &fun
))
64 // The first argument is either an option or not present.
65 if (tmon_resolve_default(&fun
))
71 char path
[MAX_PATH_LENGTH
];
72 if ((rc
= devman_fun_get_path(fun
, path
, sizeof(path
)))) {
73 printf(NAME
": Error resolving path of device with handle "
74 "%" PRIun
". %s\n", fun
, str_error(rc
));
78 printf("Device: %s\n", path
);
80 // Read test parameters from options.
82 if ((rc
= ops
->read_params(argc
, argv
, ¶ms
))) {
83 printf(NAME
": Reading test parameters failed. %s\n", str_error(rc
));
87 if ((rc
= ops
->pre_run(params
))) {
88 printf(NAME
": Pre-run hook failed. %s\n", str_error(rc
));
93 async_sess_t
*sess
= usbdiag_connect(fun
);
95 printf(NAME
": Could not connect to the device.\n");
99 async_exch_t
*exch
= async_exchange_begin(sess
);
101 printf(NAME
": Could not start exchange with the device.\n");
106 ec
= ops
->run(exch
, params
);
107 async_exchange_end(exch
);
110 usbdiag_disconnect(sess
);
115 /** Unit of quantity used for pretty formatting. */
116 typedef struct tmon_unit
{
117 /** Prefix letter, which is printed before the actual unit. */
119 /** Factor of the unit. */
123 /** Format a value for human reading.
124 * @param[in] val The value to format.
125 * @param[in] fmt Format string. Must include one double and char.
127 * @return Heap-allocated string if successful (caller becomes its owner), NULL otherwise.
129 static char *format_unit(double val
, const char *fmt
, const tmon_unit_t
*units
, size_t len
)
131 // Figure out the "tightest" unit.
133 for (i
= 0; i
< len
; ++i
) {
134 if (units
[i
].factor
<= val
)
140 const char *unit
= units
[i
].unit
;
141 double factor
= units
[i
].factor
;
144 const double div_size
= val
/ factor
;
147 asprintf(&out
, fmt
, div_size
, unit
);
152 /** Static array of size units with decreasing factors. */
153 static const tmon_unit_t size_units
[] = {
154 { .unit
= "EB", .factor
= 1ULL << 60 },
155 { .unit
= "PB", .factor
= 1ULL << 50 },
156 { .unit
= "TB", .factor
= 1ULL << 40 },
157 { .unit
= "GB", .factor
= 1ULL << 30 },
158 { .unit
= "MB", .factor
= 1ULL << 20 },
159 { .unit
= "kB", .factor
= 1ULL << 10 },
160 { .unit
= "B", .factor
= 1ULL },
163 char *tmon_format_size(double val
, const char *fmt
)
165 return format_unit(val
, fmt
, size_units
, ARRAY_SIZE(size_units
));
168 /** Static array of duration units with decreasing factors. */
169 static const tmon_unit_t dur_units
[] = {
170 { .unit
= "d", .factor
= 60 * 60 * 24 },
171 { .unit
= "h", .factor
= 60 * 60 },
172 { .unit
= "min", .factor
= 60 },
173 { .unit
= "s", .factor
= 1 },
174 { .unit
= "ms", .factor
= 1e-3 },
175 { .unit
= "us", .factor
= 1e-6 },
176 { .unit
= "ns", .factor
= 1e-9 },
177 { .unit
= "ps", .factor
= 1e-12 },
180 char *tmon_format_duration(usbdiag_dur_t val
, const char *fmt
)
182 return format_unit(val
/ 1000.0, fmt
, dur_units
, ARRAY_SIZE(dur_units
));