| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287 |
- // SPDX-License-Identifier: LGPL-2.1-or-later
- /*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2017 Intel Corporation. All rights reserved.
- *
- *
- */
- #ifdef HAVE_CONFIG_H
- #include <config.h>
- #endif
- #include <stdio.h>
- #include <errno.h>
- #include <unistd.h>
- #include <stdlib.h>
- #include <stdbool.h>
- #include <inttypes.h>
- #include <stdbool.h>
- #include <sys/uio.h>
- #include <wordexp.h>
- #include <readline/readline.h>
- #include <readline/history.h>
- #include <glib.h>
- #include "src/shared/shell.h"
- #include "src/shared/util.h"
- #include "tools/mesh-gatt/mesh-net.h"
- #include "tools/mesh-gatt/keys.h"
- #include "tools/mesh-gatt/net.h"
- #include "tools/mesh-gatt/node.h"
- #include "tools/mesh-gatt/prov-db.h"
- #include "tools/mesh-gatt/util.h"
- #include "tools/mesh-gatt/onoff-model.h"
- static uint8_t trans_id;
- static uint16_t onoff_app_idx = APP_IDX_INVALID;
- static int client_bind(uint16_t app_idx, int action)
- {
- if (action == ACTION_ADD) {
- if (onoff_app_idx != APP_IDX_INVALID) {
- return MESH_STATUS_INSUFF_RESOURCES;
- } else {
- onoff_app_idx = app_idx;
- bt_shell_printf("On/Off client model: new binding"
- " %4.4x\n", app_idx);
- }
- } else {
- if (onoff_app_idx == app_idx)
- onoff_app_idx = APP_IDX_INVALID;
- }
- return MESH_STATUS_SUCCESS;
- }
- static void print_remaining_time(uint8_t remaining_time)
- {
- uint8_t step = (remaining_time & 0xc0) >> 6;
- uint8_t count = remaining_time & 0x3f;
- int secs = 0, msecs = 0, minutes = 0, hours = 0;
- switch (step) {
- case 0:
- msecs = 100 * count;
- secs = msecs / 1000;
- msecs -= (secs * 1000);
- break;
- case 1:
- secs = 1 * count;
- minutes = secs / 60;
- secs -= (minutes * 60);
- break;
- case 2:
- secs = 10 * count;
- minutes = secs / 60;
- secs -= (minutes * 60);
- break;
- case 3:
- minutes = 10 * count;
- hours = minutes / 60;
- minutes -= (hours * 60);
- break;
- default:
- break;
- }
- bt_shell_printf("\n\t\tRemaining time: %d hrs %d mins %d secs %d"
- " msecs\n", hours, minutes, secs, msecs);
- }
- static bool client_msg_recvd(uint16_t src, uint8_t *data,
- uint16_t len, void *user_data)
- {
- uint32_t opcode;
- int n;
- if (mesh_opcode_get(data, len, &opcode, &n)) {
- len -= n;
- data += n;
- } else
- return false;
- bt_shell_printf("On Off Model Message received (%d) opcode %x\n",
- len, opcode);
- print_byte_array("\t",data, len);
- switch (opcode) {
- default:
- return false;
- case OP_GENERIC_ONOFF_STATUS:
- if (len != 1 && len != 3)
- break;
- bt_shell_printf("Node %4.4x: Off Status present = %s",
- src, data[0] ? "ON" : "OFF");
- if (len == 3) {
- bt_shell_printf(", target = %s",
- data[1] ? "ON" : "OFF");
- print_remaining_time(data[2]);
- } else
- bt_shell_printf("\n");
- break;
- }
- return true;
- }
- static uint32_t target;
- static uint32_t parms[8];
- static uint32_t read_input_parameters(int argc, char *argv[])
- {
- uint32_t i;
- if (!argc)
- return 0;
- --argc;
- ++argv;
- if (!argc || argv[0][0] == '\0')
- return 0;
- memset(parms, 0xff, sizeof(parms));
- for (i = 0; i < sizeof(parms)/sizeof(parms[0]) && i < (unsigned) argc;
- i++) {
- sscanf(argv[i], "%x", &parms[i]);
- if (parms[i] == 0xffffffff)
- break;
- }
- return i;
- }
- static void cmd_set_node(int argc, char *argv[])
- {
- uint32_t dst;
- char *end;
- dst = strtol(argv[1], &end, 16);
- if (end != (argv[1] + 4)) {
- bt_shell_printf("Bad unicast address %s: "
- "expected format 4 digit hex\n", argv[1]);
- target = UNASSIGNED_ADDRESS;
- return bt_shell_noninteractive_quit(EXIT_FAILURE);
- } else {
- bt_shell_printf("Controlling ON/OFF for node %4.4x\n", dst);
- target = dst;
- set_menu_prompt("on/off", argv[1]);
- return bt_shell_noninteractive_quit(EXIT_SUCCESS);
- }
- }
- static bool send_cmd(uint8_t *buf, uint16_t len)
- {
- struct mesh_node *node = node_get_local_node();
- uint8_t ttl;
- if(!node)
- return false;
- ttl = node_get_default_ttl(node);
- return net_access_layer_send(ttl, node_get_primary(node),
- target, onoff_app_idx, buf, len);
- }
- static void cmd_get_status(int argc, char *argv[])
- {
- uint16_t n;
- uint8_t msg[32];
- struct mesh_node *node;
- if (IS_UNASSIGNED(target)) {
- bt_shell_printf("Destination not set\n");
- return bt_shell_noninteractive_quit(EXIT_FAILURE);
- }
- node = node_find_by_addr(target);
- if (!node)
- return;
- n = mesh_opcode_set(OP_GENERIC_ONOFF_GET, msg);
- if (!send_cmd(msg, n)) {
- bt_shell_printf("Failed to send \"GENERIC ON/OFF GET\"\n");
- return bt_shell_noninteractive_quit(EXIT_FAILURE);
- }
- return bt_shell_noninteractive_quit(EXIT_SUCCESS);
- }
- static void cmd_set(int argc, char *argv[])
- {
- uint16_t n;
- uint8_t msg[32];
- struct mesh_node *node;
- if (IS_UNASSIGNED(target)) {
- bt_shell_printf("Destination not set\n");
- return bt_shell_noninteractive_quit(EXIT_FAILURE);
- }
- node = node_find_by_addr(target);
- if (!node)
- return;
- if ((read_input_parameters(argc, argv) != 1) &&
- parms[0] != 0 && parms[0] != 1) {
- bt_shell_printf("Bad arguments: Expecting \"0\" or \"1\"\n");
- return bt_shell_noninteractive_quit(EXIT_FAILURE);
- }
- n = mesh_opcode_set(OP_GENERIC_ONOFF_SET, msg);
- msg[n++] = parms[0];
- msg[n++] = trans_id++;
- if (!send_cmd(msg, n)) {
- bt_shell_printf("Failed to send \"GENERIC ON/OFF SET\"\n");
- return bt_shell_noninteractive_quit(EXIT_FAILURE);
- }
- return bt_shell_noninteractive_quit(EXIT_SUCCESS);
- }
- static const struct bt_shell_menu onoff_menu = {
- .name = "onoff",
- .desc = "On/Off Model Submenu",
- .entries = {
- {"target", "<unicast>", cmd_set_node,
- "Set node to configure"},
- {"get", NULL, cmd_get_status,
- "Get ON/OFF status"},
- {"onoff", "<0/1>", cmd_set,
- "Send \"SET ON/OFF\" command"},
- {} },
- };
- static struct mesh_model_ops client_cbs = {
- client_msg_recvd,
- client_bind,
- NULL,
- NULL
- };
- bool onoff_client_init(uint8_t ele)
- {
- if (!node_local_model_register(ele, GENERIC_ONOFF_CLIENT_MODEL_ID,
- &client_cbs, NULL))
- return false;
- bt_shell_add_submenu(&onoff_menu);
- return true;
- }
|