blob: 27acc80e28f10a97c79a75c124a7f1251daf60c7 [file] [log] [blame]
// Copyright 2019 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 <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fbl/auto_call.h>
#include <fuchsia/hardware/light/c/fidl.h>
#include <lib/fdio/fd.h>
#include <lib/fdio/fdio.h>
#include <lib/fdio/directory.h>
#include <zircon/status.h>
#include <zircon/syscalls.h>
#include <zircon/types.h>
static int name_command(zx_handle_t svc, int argc, const char* argv[]) {
if (argc != 1) {
fprintf(stderr, "expected one argument\n");
return -1;
}
uint32_t index;
if (sscanf(argv[0], "%u", &index) != 1) {
fprintf(stderr, "could not parse index %s\n", argv[0]);
return -1;
}
char buffer[fuchsia_hardware_light_LIGHT_NAME_LEN];
size_t actual;
zx_status_t status2;
auto status = fuchsia_hardware_light_LightGetName(svc, index, &status2, buffer, sizeof(buffer),
&actual);
if (status == ZX_OK) {
status = status2;
}
if (status == ZX_OK) {
printf("%s\n", buffer);
return 0;
} else {
fprintf(stderr, "fuchsia_hardware_light_DeviceGetName failed: %s\n",
zx_status_get_string(status));
return -1;
}
}
static int count_command(zx_handle_t svc, int argc, const char* argv[]) {
uint32_t count;
auto status = fuchsia_hardware_light_LightGetCount(svc, &count);
if (status == ZX_OK) {
printf("%u\n", count);
return 0;
} else {
fprintf(stderr, "fuchsia_hardware_light_DeviceGetCount failed: %s\n",
zx_status_get_string(status));
return -1;
}
}
static int has_capability_command(zx_handle_t svc, int argc, const char* argv[]) {
if (argc != 2) {
fprintf(stderr, "expected two arguments\n");
return -1;
}
uint32_t index;
if (sscanf(argv[0], "%u", &index) != 1) {
fprintf(stderr, "could not parse index %s\n", argv[0]);
return -1;
}
fuchsia_hardware_light_Capability capability;
if (!strcmp(argv[1], "brightness")) {
capability = fuchsia_hardware_light_Capability_BRIGHTNESS;
} else if (!strcmp(argv[1], "rgb")) {
capability = fuchsia_hardware_light_Capability_RGB;
} else {
fprintf(stderr, "unknown capability \"%s\"\n", argv[1]);
return -1;
}
zx_status_t status2;
bool has;
auto status = fuchsia_hardware_light_LightHasCapability(svc, index, capability, &status2, &has);
if (status == ZX_OK) {
status = status2;
}
if (status == ZX_OK) {
printf("%s\n", (has ? "true" : "false"));
return 0;
} else {
fprintf(stderr, "fuchsia_hardware_light_LightHasCapability failed: %s\n",
zx_status_get_string(status));
return -1;
}
}
static int get_value_command(zx_handle_t svc, int argc, const char* argv[]) {
if (argc != 1) {
fprintf(stderr, "expected one argument\n");
return -1;
}
uint32_t index;
if (sscanf(argv[0], "%u", &index) != 1) {
fprintf(stderr, "could not parse index %s\n", argv[0]);
return -1;
}
zx_status_t status2;
uint8_t value;
auto status = fuchsia_hardware_light_LightGetSimpleValue(svc, index, &status2, &value);
if (status == ZX_OK) {
status = status2;
}
if (status == ZX_OK) {
printf("%u\n", value);
return 0;
} else {
fprintf(stderr, "fuchsia_hardware_light_LightGetSimpleValue failed: %s\n",
zx_status_get_string(status));
return -1;
}
}
static int set_value_command(zx_handle_t svc, int argc, const char* argv[]) {
if (argc != 2) {
fprintf(stderr, "expected two arguments\n");
return -1;
}
uint32_t index;
if (sscanf(argv[0], "%u", &index) != 1) {
fprintf(stderr, "could not parse index %s\n", argv[0]);
return -1;
}
uint32_t value;
if (sscanf(argv[1], "%u", &value) != 1) {
fprintf(stderr, "could not parse value %s\n", argv[1]);
return -1;
}
if (value >= UINT8_MAX) {
fprintf(stderr, "value %u out of range\n", value);
return -1;
}
zx_status_t status2;
auto status = fuchsia_hardware_light_LightSetSimpleValue(svc, index,
static_cast<uint8_t>(value), &status2);
if (status == ZX_OK) {
status = status2;
}
if (status == ZX_OK) {
return 0;
} else {
fprintf(stderr, "fuchsia_hardware_light_LightSetSimpleValue failed: %s\n",
zx_status_get_string(status));
return -1;
}
}
struct Command {
const char* name;
int (*command)(zx_handle_t svc, int argc, const char* argv[]);
const char* description;
};
static Command commands[] = {
{
"name",
name_command,
"name <index> - returns the name of the light"
},
{
"count",
count_command,
"count - returns the number of physical lights"
},
{
"capability",
has_capability_command,
"capability <index> [brightness|rgb] - returns true if the light has the capability"
},
{
"get-value",
get_value_command,
"get-value <index> - returns the current value of the light"
},
{
"set-value",
set_value_command,
"set-value <index> <value> - sets the current value of the light"
},
{},
};
static void usage(void) {
fprintf(stderr, "usage: \"light [-d <dev-file>] <command>\", where command is one of:\n");
Command* command = commands;
while (command->name) {
fprintf(stderr, " %s\n", command->description);
command++;
}
}
int main(int argc, const char** argv) {
if (argc < 2) {
usage();
return -1;
}
argv++;
argc--;
const char* dev_file_name = "000";
if (!strcmp(argv[0], "-d")) {
if (argc < 3) {
usage();
return -1;
}
dev_file_name = argv[1];
if (strlen(dev_file_name) != 3) {
usage();
return -1;
}
argv += 2;
argc -= 2;
}
char path[PATH_MAX];
snprintf(path, sizeof(path), "/dev/class/light/%s", dev_file_name);
int fd = open(path, O_RDWR);
if (fd < 0) {
printf("Error opening %s\n", path);
return -1;
}
zx_handle_t svc;
zx_status_t status = fdio_get_service_handle(fd, &svc);
if (status != ZX_OK) {
close(fd);
printf("Error opening FIDL connection for %s\n", path);
return -1;
}
auto cleanup = fbl::MakeAutoCall([fd, svc]() {zx_handle_close(svc); close(fd); });
const char* command_name = argv[0];
argv++;
argc--;
Command* command = commands;
while (command->name) {
if (!strcmp(command_name, command->name)) {
return command->command(svc, argc, argv);
}
command++;
}
// if we fall through, print usage
usage();
return -1;
}