/*
|
* Licensed to the Apache Software Foundation (ASF) under one
|
* or more contributor license agreements. See the NOTICE file
|
* distributed with this work for additional information
|
* regarding copyright ownership. The ASF licenses this file
|
* to you under the Apache License, Version 2.0 (the
|
* "License"); you may not use this file except in compliance
|
* with the License. You may obtain a copy of the License at
|
*
|
* http://www.apache.org/licenses/LICENSE-2.0
|
*
|
* Unless required by applicable law or agreed to in writing,
|
* software distributed under the License is distributed on an
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
* KIND, either express or implied. See the License for the
|
* specific language governing permissions and limitations
|
* under the License.
|
*/
|
|
#include <string.h>
|
|
#include "tinycbor/cbor.h"
|
#include "mgmt/endian.h"
|
#include "mgmt/mgmt.h"
|
|
#pragma diag_suppress 68
|
|
static mgmt_on_evt_cb *evt_cb;
|
static struct mgmt_group *mgmt_group_list;
|
static struct mgmt_group *mgmt_group_list_end;
|
|
void *
|
mgmt_streamer_alloc_rsp(struct mgmt_streamer *streamer, const void *req)
|
{
|
return streamer->cfg->alloc_rsp(req, streamer->cb_arg);
|
}
|
|
void
|
mgmt_streamer_trim_front(struct mgmt_streamer *streamer, void *buf, size_t len)
|
{
|
streamer->cfg->trim_front(buf, len, streamer->cb_arg);
|
}
|
|
void
|
mgmt_streamer_reset_buf(struct mgmt_streamer *streamer, void *buf)
|
{
|
streamer->cfg->reset_buf(buf, streamer->cb_arg);
|
}
|
|
int
|
mgmt_streamer_write_at(struct mgmt_streamer *streamer, size_t offset,
|
const void *data, int len)
|
{
|
return streamer->cfg->write_at(streamer->writer, offset, data, len,
|
streamer->cb_arg);
|
}
|
|
int
|
mgmt_streamer_init_reader(struct mgmt_streamer *streamer, void *buf)
|
{
|
return streamer->cfg->init_reader(streamer->reader, buf, streamer->cb_arg);
|
}
|
|
int
|
mgmt_streamer_init_writer(struct mgmt_streamer *streamer, void *buf)
|
{
|
return streamer->cfg->init_writer(streamer->writer, buf, streamer->cb_arg);
|
}
|
|
void
|
mgmt_streamer_free_buf(struct mgmt_streamer *streamer, void *buf)
|
{
|
streamer->cfg->free_buf(buf, streamer->cb_arg);
|
}
|
|
void
|
mgmt_unregister_group(struct mgmt_group *group)
|
{
|
struct mgmt_group *curr = mgmt_group_list, *prev = NULL;
|
|
if (!group) {
|
return;
|
}
|
|
if (curr == group) {
|
mgmt_group_list = curr->mg_next;
|
return;
|
}
|
|
while (curr && curr != group) {
|
prev = curr;
|
curr = curr->mg_next;
|
}
|
|
if (!prev || !curr) {
|
return;
|
}
|
|
prev->mg_next = curr->mg_next;
|
if (curr->mg_next == NULL) {
|
mgmt_group_list_end = curr;
|
}
|
}
|
|
static struct mgmt_group *
|
mgmt_find_group(uint16_t group_id, uint16_t command_id)
|
{
|
struct mgmt_group *group;
|
|
/*
|
* Find the group with the specified group id, if one exists
|
* check the handler for the command id and make sure
|
* that is not NULL. If that is not set, look for the group
|
* with a command id that is set
|
*/
|
for (group = mgmt_group_list; group != NULL; group = group->mg_next) {
|
if (group->mg_group_id == group_id) {
|
if (command_id >= group->mg_handlers_count) {
|
return NULL;
|
}
|
|
if (!group->mg_handlers[command_id].mh_read &&
|
!group->mg_handlers[command_id].mh_write) {
|
continue;
|
}
|
|
break;
|
}
|
}
|
|
return group;
|
}
|
|
void
|
mgmt_register_group(struct mgmt_group *group)
|
{
|
if (mgmt_group_list_end == NULL) {
|
mgmt_group_list = group;
|
} else {
|
mgmt_group_list_end->mg_next = group;
|
}
|
mgmt_group_list_end = group;
|
}
|
|
const struct mgmt_handler *
|
mgmt_find_handler(uint16_t group_id, uint16_t command_id)
|
{
|
const struct mgmt_group *group;
|
|
group = mgmt_find_group(group_id, command_id);
|
if (!group) {
|
return NULL;
|
}
|
|
return &group->mg_handlers[command_id];
|
}
|
|
int
|
mgmt_write_rsp_status(struct mgmt_ctxt *ctxt, int errcode)
|
{
|
int rc;
|
|
rc = cbor_encode_text_stringz(&ctxt->encoder, "rc");
|
if (rc != 0) {
|
return rc;
|
}
|
|
rc = cbor_encode_int(&ctxt->encoder, errcode);
|
if (rc != 0) {
|
return rc;
|
}
|
|
return 0;
|
}
|
|
int
|
mgmt_err_from_cbor(int cbor_status)
|
{
|
switch (cbor_status) {
|
case CborNoError: return MGMT_ERR_EOK;
|
case CborErrorOutOfMemory: return MGMT_ERR_ENOMEM;
|
default: return MGMT_ERR_EUNKNOWN;
|
}
|
}
|
|
int
|
mgmt_ctxt_init(struct mgmt_ctxt *ctxt, struct mgmt_streamer *streamer)
|
{
|
int rc;
|
|
rc = cbor_parser_init(streamer->reader, 0, &ctxt->parser, &ctxt->it);
|
if (rc != CborNoError) {
|
return mgmt_err_from_cbor(rc);
|
}
|
|
cbor_encoder_init(&ctxt->encoder, streamer->writer, 0);
|
|
return 0;
|
}
|
|
void
|
mgmt_ntoh_hdr(struct mgmt_hdr *hdr)
|
{
|
hdr->nh_len = ntohs(hdr->nh_len);
|
hdr->nh_group = ntohs(hdr->nh_group);
|
}
|
|
void
|
mgmt_hton_hdr(struct mgmt_hdr *hdr)
|
{
|
hdr->nh_len = htons(hdr->nh_len);
|
hdr->nh_group = htons(hdr->nh_group);
|
}
|
|
void
|
mgmt_register_evt_cb(mgmt_on_evt_cb *cb)
|
{
|
evt_cb = cb;
|
}
|
|
void
|
mgmt_evt(uint8_t opcode, uint16_t group, uint8_t id, void *arg)
|
{
|
if (evt_cb) {
|
evt_cb(opcode, group, id, arg);
|
}
|
}
|