| // Copyright 2022 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 <ctype.h> |
| #include <dirent.h> |
| #include <fcntl.h> |
| #include <fidl/examples.acpi.multiply/cpp/wire.h> |
| #include <getopt.h> |
| #include <lib/fdio/directory.h> |
| #include <libgen.h> |
| #include <stdbool.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <sys/types.h> |
| |
| constexpr char kDevicePath[] = "/dev/acpi-multiply-controller/acpi-multiply"; |
| |
| int usage(const char* cmd) { |
| fprintf(stderr, |
| "\nInteract with the ACPI multiplier device:\n" |
| " %s multiply Perform a multiply operation\n" |
| " %s help Print this message\n", |
| cmd, cmd); |
| return -1; |
| } |
| |
| // Returns "true" if the argument matches the prefix. |
| // In this case, moves the argument past the prefix. |
| bool prefix_match(const char** arg, const char* prefix) { |
| if (!strncmp(*arg, prefix, strlen(prefix))) { |
| *arg += strlen(prefix); |
| return true; |
| } |
| return false; |
| } |
| |
| // Open a FIDL client connection to the examples.acpi.multiply/Device |
| fidl::WireSyncClient<examples_acpi_multiply::Device> OpenDevice() { |
| int device = open(kDevicePath, O_RDWR); |
| if (device < 0) { |
| fprintf(stderr, "Failed to open temperature device: %s\n", strerror(errno)); |
| return {}; |
| } |
| fidl::ClientEnd<examples_acpi_multiply::Device> client_end; |
| zx_status_t st = fdio_get_service_handle(device, client_end.channel().reset_and_get_address()); |
| if (st != ZX_OK) { |
| fprintf(stderr, "Failed to get service handle: %s\n", zx_status_get_string(st)); |
| return {}; |
| } |
| return fidl::WireSyncClient(std::move(client_end)); |
| } |
| |
| // Send a command to perform a multiply operation and print the result. |
| // Returns 0 on success. |
| int do_multiply(uint32_t a, uint32_t b) { |
| auto client = OpenDevice(); |
| if (!client.is_valid()) { |
| return -1; |
| } |
| |
| auto multiply_result = client->Multiply(a, b); |
| if (!multiply_result.ok()) { |
| fprintf(stderr, "Error: failed to read multply result: %s\n", |
| zx_status_get_string(multiply_result.status())); |
| return -1; |
| } |
| |
| auto overflowed = multiply_result->value()->overflowed; |
| if (overflowed) { |
| printf("Multiply(%u, %u): Invalid result: Overflow\n", a, b); |
| } else { |
| printf("Multiply(%u, %u) = %d\n", a, b, multiply_result->value()->result); |
| } |
| return 0; |
| } |
| |
| int main(int argc, char* argv[]) { |
| const char* cmd = basename(argv[0]); |
| |
| // If no arguments passed, bail out after dumping |
| // usage information. |
| if (argc < 2) { |
| return usage(cmd); |
| } |
| |
| const char* arg = argv[1]; |
| if (prefix_match(&arg, "multiply")) { |
| do_multiply(UINT32_MAX, 9); |
| do_multiply(2, 9); |
| return 0; |
| } |
| return usage(cmd); |
| } |