16caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent/* 26caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent * Copyright (C) 2015 The Android Open Source Project 36caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent * 46caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent * Licensed under the Apache License, Version 2.0 (the "License"); 56caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent * you may not use this file except in compliance with the License. 66caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent * You may obtain a copy of the License at 76caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent * 86caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent * http://www.apache.org/licenses/LICENSE-2.0 96caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent * 106caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent * Unless required by applicable law or agreed to in writing, software 116caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent * distributed under the License is distributed on an "AS IS" BASIS, 126caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent * See the License for the specific language governing permissions and 146caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent * limitations under the License. 156caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent */ 166caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent 176caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent#define LOG_TAG "radio_metadata" 186caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent/*#define LOG_NDEBUG 0*/ 196caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent 206caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent#include <errno.h> 218198c3b752e2fb00acb15345496e2a03eefb5ffbMark Salyzyn#include <limits.h> 226caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent#include <stdlib.h> 236caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent#include <string.h> 248198c3b752e2fb00acb15345496e2a03eefb5ffbMark Salyzyn 254df5a2bb302fb5cb61ab48dff7fa2b1984b6ced8Mark Salyzyn#include <log/log.h> 264df5a2bb302fb5cb61ab48dff7fa2b1984b6ced8Mark Salyzyn 276caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent#include <system/radio.h> 286caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent#include <system/radio_metadata.h> 29a2b50fb31ac5b6192dfe29859a56cee771c9dffeDan Willemsen#include "radio_metadata_hidden.h" 30a2b50fb31ac5b6192dfe29859a56cee771c9dffeDan Willemsen 316caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurentconst radio_metadata_type_t metadata_key_type_table[] = 326caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent{ 33acf670dcadd90f8499cef867dfe27770a0188491Tomasz Wasilczyk RADIO_METADATA_TYPE_INT, 346caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent RADIO_METADATA_TYPE_TEXT, 356caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent RADIO_METADATA_TYPE_INT, 366caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent RADIO_METADATA_TYPE_INT, 376caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent RADIO_METADATA_TYPE_TEXT, 386caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent RADIO_METADATA_TYPE_TEXT, 396caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent RADIO_METADATA_TYPE_TEXT, 406caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent RADIO_METADATA_TYPE_TEXT, 416caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent RADIO_METADATA_TYPE_TEXT, 426caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent RADIO_METADATA_TYPE_RAW, 436caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent RADIO_METADATA_TYPE_RAW, 443c4b35deff3f53ce8eb757bd6b33ad94e4c74d4fSanket Agarwal RADIO_METADATA_TYPE_CLOCK, 456caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent}; 466caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent 476caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent/** 486caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent * private functions 496caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent */ 506caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent 516caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurentbool is_valid_metadata_key(const radio_metadata_key_t key) 526caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent{ 536caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent if (key < RADIO_METADATA_KEY_MIN || key > RADIO_METADATA_KEY_MAX) { 546caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent return false; 556caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent } 566caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent return true; 576caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent} 586caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent 59ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurentint check_size(radio_metadata_buffer_t **metadata_ptr, const uint32_t size_int) 606caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent{ 616caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent radio_metadata_buffer_t *metadata = *metadata_ptr; 62ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent uint32_t index_offset = metadata->size_int - metadata->count - 1; 63ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent uint32_t data_offset = *((uint32_t *)metadata + index_offset); 64ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent uint32_t req_size_int; 65ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent uint32_t new_size_int; 666caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent 67ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent LOG_ALWAYS_FATAL_IF(metadata->size_int < (metadata->count + 1), 68ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent "%s: invalid size %u", __func__, metadata->size_int); 696caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent if (size_int == 0) { 706caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent return 0; 716caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent } 726caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent 736caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent req_size_int = data_offset + metadata->count + 1 + 1 + size_int; 746caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent /* do not grow buffer if it can accommodate the new entry plus an additional index entry */ 756caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent 766caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent if (req_size_int <= metadata->size_int) { 776caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent return 0; 786caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent } 796caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent 806caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent if (req_size_int > RADIO_METADATA_MAX_SIZE || metadata->size_int >= RADIO_METADATA_MAX_SIZE) { 816caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent return -ENOMEM; 826caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent } 836caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent /* grow meta data buffer by a factor of 2 until new data fits */ 846caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent new_size_int = metadata->size_int; 856caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent while (new_size_int < req_size_int) 866caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent new_size_int *= 2; 876caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent 886caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent ALOGV("%s growing from %u to %u", __func__, metadata->size_int, new_size_int); 89ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent metadata = realloc(metadata, new_size_int * sizeof(uint32_t)); 906caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent /* move index table */ 91ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent memmove((uint32_t *)metadata + new_size_int - (metadata->count + 1), 92ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent (uint32_t *)metadata + metadata->size_int - (metadata->count + 1), 93ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent (metadata->count + 1) * sizeof(uint32_t)); 946caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent metadata->size_int = new_size_int; 956caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent 966caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent *metadata_ptr = metadata; 976caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent return 0; 986caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent} 996caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent 1006caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent/* checks on size and key validity are done before calling this function */ 1016caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurentint add_metadata(radio_metadata_buffer_t **metadata_ptr, 1026caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent const radio_metadata_key_t key, 1036caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent const radio_metadata_type_t type, 1046caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent const void *value, 105ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent const size_t size) 1066caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent{ 107ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent uint32_t entry_size_int; 1086caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent int ret; 1096caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent radio_metadata_entry_t *entry; 110ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent uint32_t index_offset; 111ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent uint32_t data_offset; 1126caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent radio_metadata_buffer_t *metadata = *metadata_ptr; 1136caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent 114ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent entry_size_int = (uint32_t)(size + sizeof(radio_metadata_entry_t)); 115ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent entry_size_int = (entry_size_int + sizeof(uint32_t) - 1) / sizeof(uint32_t); 1166caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent 1176caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent ret = check_size(metadata_ptr, entry_size_int); 1186caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent if (ret < 0) { 1196caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent return ret; 1206caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent } 1216caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent metadata = *metadata_ptr; 1226caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent index_offset = metadata->size_int - metadata->count - 1; 123ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent data_offset = *((uint32_t *)metadata + index_offset); 1246caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent 125ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent entry = (radio_metadata_entry_t *)((uint32_t *)metadata + data_offset); 1266caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent entry->key = key; 1276caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent entry->type = type; 128ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent entry->size = (uint32_t)size; 1296caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent memcpy(entry->data, value, size); 1306caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent 1316caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent data_offset += entry_size_int; 132ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent *((uint32_t *)metadata + index_offset -1) = data_offset; 1336caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent metadata->count++; 134ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent 1356caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent return 0; 1366caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent} 1376caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent 1386caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurentradio_metadata_entry_t *get_entry_at_index( 1396caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent const radio_metadata_buffer_t *metadata, 1406caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent const unsigned index, 1416caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent bool check) 1426caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent{ 143ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent uint32_t index_offset = metadata->size_int - index - 1; 144ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent uint32_t data_offset = *((uint32_t *)metadata + index_offset); 1456caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent 146ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent LOG_ALWAYS_FATAL_IF(metadata->size_int < (index + 1), 147ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent "%s: invalid size %u", __func__, metadata->size_int); 1486caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent if (check) { 1496caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent if (index >= metadata->count) { 1506caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent return NULL; 1516caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent } 152ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent uint32_t min_offset; 153ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent uint32_t max_offset; 154ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent uint32_t min_entry_size_int; 155ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent min_offset = (sizeof(radio_metadata_buffer_t) + sizeof(uint32_t) - 1) / 156ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent sizeof(uint32_t); 1576caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent if (data_offset < min_offset) { 1586caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent return NULL; 1596caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent } 1606caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent min_entry_size_int = 1 + sizeof(radio_metadata_entry_t); 161ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent min_entry_size_int = (min_entry_size_int + sizeof(uint32_t) - 1) / sizeof(uint32_t); 162ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent 163ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent LOG_ALWAYS_FATAL_IF(metadata->size_int < (metadata->count + 1), 164ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent "%s: invalid size %u vs count %u", __func__, 165ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent metadata->size_int, metadata->count); 166ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent 1676caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent max_offset = metadata->size_int - metadata->count - 1 - min_entry_size_int; 1686caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent if (data_offset > max_offset) { 1696caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent return NULL; 1706caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent } 1716caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent } 172ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent return (radio_metadata_entry_t *)((uint32_t *)metadata + data_offset); 1736caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent} 1746caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent 1756caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent/** 1766caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent * metadata API functions 1776caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent */ 1786caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent 1796caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurentradio_metadata_type_t radio_metadata_type_of_key(const radio_metadata_key_t key) 1806caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent{ 1816caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent if (!is_valid_metadata_key(key)) { 1826caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent return RADIO_METADATA_TYPE_INVALID; 1836caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent } 1846caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent return metadata_key_type_table[key - RADIO_METADATA_KEY_MIN]; 1856caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent} 1866caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent 1876caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurentint radio_metadata_allocate(radio_metadata_t **metadata, 188ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent const uint32_t channel, 189ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent const uint32_t sub_channel) 1906caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent{ 1916caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent radio_metadata_buffer_t *metadata_buf = 192ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent (radio_metadata_buffer_t *)calloc(RADIO_METADATA_DEFAULT_SIZE, sizeof(uint32_t)); 1936caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent if (metadata_buf == NULL) { 1946caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent return -ENOMEM; 1956caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent } 1966caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent 1976caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent metadata_buf->channel = channel; 1986caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent metadata_buf->sub_channel = sub_channel; 1996caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent metadata_buf->size_int = RADIO_METADATA_DEFAULT_SIZE; 200ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent *((uint32_t *)metadata_buf + RADIO_METADATA_DEFAULT_SIZE - 1) = 201ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent (sizeof(radio_metadata_buffer_t) + sizeof(uint32_t) - 1) / 202ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent sizeof(uint32_t); 2036caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent *metadata = (radio_metadata_t *)metadata_buf; 2046caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent return 0; 2056caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent} 2066caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent 2076caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurentvoid radio_metadata_deallocate(radio_metadata_t *metadata) 2086caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent{ 2096caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent free(metadata); 2106caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent} 2116caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent 2126caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurentint radio_metadata_add_int(radio_metadata_t **metadata, 2136caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent const radio_metadata_key_t key, 214ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent const int32_t value) 2156caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent{ 2166caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent radio_metadata_type_t type = radio_metadata_type_of_key(key); 2176caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent if (metadata == NULL || *metadata == NULL || type != RADIO_METADATA_TYPE_INT) { 2186caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent return -EINVAL; 2196caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent } 2206caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent return add_metadata((radio_metadata_buffer_t **)metadata, 221ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent key, type, &value, sizeof(int32_t)); 2226caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent} 2236caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent 2246caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurentint radio_metadata_add_text(radio_metadata_t **metadata, 2256caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent const radio_metadata_key_t key, 2266caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent const char *value) 2276caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent{ 2286caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent radio_metadata_type_t type = radio_metadata_type_of_key(key); 2296caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent if (metadata == NULL || *metadata == NULL || type != RADIO_METADATA_TYPE_TEXT || 2306caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent value == NULL || strlen(value) >= RADIO_METADATA_TEXT_LEN_MAX) { 2316caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent return -EINVAL; 2326caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent } 2336caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent return add_metadata((radio_metadata_buffer_t **)metadata, key, type, value, strlen(value) + 1); 2346caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent} 2356caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent 2366caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurentint radio_metadata_add_raw(radio_metadata_t **metadata, 2376caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent const radio_metadata_key_t key, 2386caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent const unsigned char *value, 239ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent const size_t size) 2406caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent{ 2416caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent radio_metadata_type_t type = radio_metadata_type_of_key(key); 2426caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent if (metadata == NULL || *metadata == NULL || type != RADIO_METADATA_TYPE_RAW || value == NULL) { 2436caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent return -EINVAL; 2446caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent } 2456caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent return add_metadata((radio_metadata_buffer_t **)metadata, key, type, value, size); 2466caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent} 2476caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent 2483c4b35deff3f53ce8eb757bd6b33ad94e4c74d4fSanket Agarwalint radio_metadata_add_clock(radio_metadata_t **metadata, 2493c4b35deff3f53ce8eb757bd6b33ad94e4c74d4fSanket Agarwal const radio_metadata_key_t key, 2503c4b35deff3f53ce8eb757bd6b33ad94e4c74d4fSanket Agarwal const radio_metadata_clock_t *clock) { 2513c4b35deff3f53ce8eb757bd6b33ad94e4c74d4fSanket Agarwal radio_metadata_type_t type = radio_metadata_type_of_key(key); 2523c4b35deff3f53ce8eb757bd6b33ad94e4c74d4fSanket Agarwal if (metadata == NULL || *metadata == NULL || type != RADIO_METADATA_TYPE_CLOCK || 2533c4b35deff3f53ce8eb757bd6b33ad94e4c74d4fSanket Agarwal clock == NULL || clock->timezone_offset_in_minutes < (-12 * 60) || 2543c4b35deff3f53ce8eb757bd6b33ad94e4c74d4fSanket Agarwal clock->timezone_offset_in_minutes > (14 * 60)) { 2553c4b35deff3f53ce8eb757bd6b33ad94e4c74d4fSanket Agarwal return -EINVAL; 2563c4b35deff3f53ce8eb757bd6b33ad94e4c74d4fSanket Agarwal } 2573c4b35deff3f53ce8eb757bd6b33ad94e4c74d4fSanket Agarwal return add_metadata( 2583c4b35deff3f53ce8eb757bd6b33ad94e4c74d4fSanket Agarwal (radio_metadata_buffer_t **)metadata, key, type, clock, sizeof(radio_metadata_clock_t)); 2593c4b35deff3f53ce8eb757bd6b33ad94e4c74d4fSanket Agarwal} 2603c4b35deff3f53ce8eb757bd6b33ad94e4c74d4fSanket Agarwal 2616caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurentint radio_metadata_add_metadata(radio_metadata_t **dst_metadata, 2626caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent radio_metadata_t *src_metadata) 2636caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent{ 2646caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent radio_metadata_buffer_t *src_metadata_buf = (radio_metadata_buffer_t *)src_metadata; 2656caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent radio_metadata_buffer_t *dst_metadata_buf; 2666caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent int status; 267ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent uint32_t index; 2686caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent 2696caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent if (dst_metadata == NULL || src_metadata == NULL) { 2706caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent return -EINVAL; 2716caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent } 2726caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent if (*dst_metadata == NULL) { 2736caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent status = radio_metadata_allocate(dst_metadata, src_metadata_buf->channel, 2746caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent src_metadata_buf->sub_channel); 2756caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent if (status != 0) { 2766caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent return status; 2776caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent } 2786caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent } 2796caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent 2806caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent dst_metadata_buf = (radio_metadata_buffer_t *)*dst_metadata; 2816caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent dst_metadata_buf->channel = src_metadata_buf->channel; 2826caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent dst_metadata_buf->sub_channel = src_metadata_buf->sub_channel; 2836caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent 2846caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent for (index = 0; index < src_metadata_buf->count; index++) { 2856caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent radio_metadata_key_t key; 2866caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent radio_metadata_type_t type; 2876caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent void *value; 288ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent size_t size; 2896caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent status = radio_metadata_get_at_index(src_metadata, index, &key, &type, &value, &size); 2906caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent if (status != 0) 2916caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent continue; 2926caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent status = add_metadata((radio_metadata_buffer_t **)dst_metadata, key, type, value, size); 2936caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent if (status != 0) 2946caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent break; 2956caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent } 2966caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent return status; 2976caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent} 2986caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent 2996caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurentint radio_metadata_check(const radio_metadata_t *metadata) 3006caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent{ 3016caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent radio_metadata_buffer_t *metadata_buf = 3026caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent (radio_metadata_buffer_t *)metadata; 303ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent uint32_t count; 304ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent uint32_t min_entry_size_int; 3056caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent 3066caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent if (metadata_buf == NULL) { 3076caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent return -EINVAL; 3086caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent } 3096caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent 3106caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent if (metadata_buf->size_int > RADIO_METADATA_MAX_SIZE) { 3116caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent return -EINVAL; 3126caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent } 3136caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent 3146caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent /* sanity check on entry count versus buffer size */ 3156caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent min_entry_size_int = 1 + sizeof(radio_metadata_entry_t); 316ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent min_entry_size_int = (min_entry_size_int + sizeof(uint32_t) - 1) / 317ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent sizeof(uint32_t); 3186caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent if ((metadata_buf->count * min_entry_size_int + metadata_buf->count + 1 + 319ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent (sizeof(radio_metadata_buffer_t) + sizeof(uint32_t) - 1) / sizeof(uint32_t)) > 3206caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent metadata_buf->size_int) { 3216caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent return -EINVAL; 3226caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent } 3236caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent 3246caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent /* sanity check on each entry */ 3256caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent for (count = 0; count < metadata_buf->count; count++) { 3266caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent radio_metadata_entry_t *entry = get_entry_at_index(metadata_buf, count, true); 3276caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent radio_metadata_entry_t *next_entry; 3286caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent if (entry == NULL) { 3296caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent return -EINVAL; 3306caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent } 3316caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent if (!is_valid_metadata_key(entry->key)) { 3326caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent return -EINVAL; 3336caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent } 3346caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent if (entry->type != radio_metadata_type_of_key(entry->key)) { 3356caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent return -EINVAL; 3366caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent } 3376caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent 3386caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent /* do not request check because next entry can be the free slot */ 3396caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent next_entry = get_entry_at_index(metadata_buf, count + 1, false); 3406caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent if ((char *)entry->data + entry->size > (char *)next_entry) { 3416caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent return -EINVAL; 3426caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent } 3436caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent } 3446caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent 3456caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent return 0; 3466caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent} 3476caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent 3486caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurentsize_t radio_metadata_get_size(const radio_metadata_t *metadata) 3496caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent{ 3506caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent radio_metadata_buffer_t *metadata_buf = 3516caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent (radio_metadata_buffer_t *)metadata; 3526caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent 3536caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent if (metadata_buf == NULL) { 3546caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent return 0; 3556caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent } 356ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent return metadata_buf->size_int * sizeof(uint32_t); 3576caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent} 3586caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent 3596caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurentint radio_metadata_get_count(const radio_metadata_t *metadata) 3606caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent{ 3616caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent radio_metadata_buffer_t *metadata_buf = 3626caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent (radio_metadata_buffer_t *)metadata; 3636caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent 3646caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent if (metadata_buf == NULL) { 3656caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent return -EINVAL; 3666caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent } 3676caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent return (int)metadata_buf->count; 3686caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent} 3696caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent 3706caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurentint radio_metadata_get_at_index(const radio_metadata_t *metadata, 371ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent const uint32_t index, 3726caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent radio_metadata_key_t *key, 3736caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent radio_metadata_type_t *type, 3746caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent void **value, 375ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent size_t *size) 3766caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent{ 3776caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent radio_metadata_entry_t *entry; 3786caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent radio_metadata_buffer_t *metadata_buf = 3796caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent (radio_metadata_buffer_t *)metadata; 3806caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent 3816caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent if (metadata_buf == NULL || key == NULL || type == NULL || 3826caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent value == NULL || size == NULL) { 3836caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent return -EINVAL; 3846caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent } 3856caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent if (index >= metadata_buf->count) { 3866caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent return -EINVAL; 3876caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent } 3886caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent 3896caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent entry = get_entry_at_index(metadata_buf, index, false); 3906caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent *key = entry->key; 3916caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent *type = entry->type; 3926caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent *value = (void *)entry->data; 393ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent *size = (size_t)entry->size; 3946caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent 3956caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent return 0; 3966caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent} 3976caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent 3986caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurentint radio_metadata_get_from_key(const radio_metadata_t *metadata, 3996caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent const radio_metadata_key_t key, 4006caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent radio_metadata_type_t *type, 4016caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent void **value, 402ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent size_t *size) 4036caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent{ 404ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent uint32_t count; 4056caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent radio_metadata_entry_t *entry = NULL; 4066caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent radio_metadata_buffer_t *metadata_buf = 4076caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent (radio_metadata_buffer_t *)metadata; 4086caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent 4096caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent if (metadata_buf == NULL || type == NULL || value == NULL || size == NULL) { 4106caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent return -EINVAL; 4116caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent } 4126caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent if (!is_valid_metadata_key(key)) { 4136caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent return -EINVAL; 4146caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent } 4156caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent 4166caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent for (count = 0; count < metadata_buf->count; entry = NULL, count++) { 4176caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent entry = get_entry_at_index(metadata_buf, count, false); 4186caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent if (entry->key == key) { 4196caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent break; 4206caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent } 4216caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent } 4226caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent if (entry == NULL) { 4236caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent return -ENOENT; 4246caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent } 4256caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent *type = entry->type; 4266caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent *value = (void *)entry->data; 427ff407960d77cad24b90c07a97e7aa431385f3607Eric Laurent *size = (size_t)entry->size; 4286caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent return 0; 4296caceaed8856e7e3cf05fa3232bc4fd8a22d2295Eric Laurent} 43071dd3519837738303185b888ed3741763b1ae3eeEric Laurent 43171dd3519837738303185b888ed3741763b1ae3eeEric Laurentint radio_metadata_get_channel(radio_metadata_t *metadata, 43271dd3519837738303185b888ed3741763b1ae3eeEric Laurent uint32_t *channel, 43371dd3519837738303185b888ed3741763b1ae3eeEric Laurent uint32_t *sub_channel) 43471dd3519837738303185b888ed3741763b1ae3eeEric Laurent{ 43571dd3519837738303185b888ed3741763b1ae3eeEric Laurent radio_metadata_buffer_t *metadata_buf = 43671dd3519837738303185b888ed3741763b1ae3eeEric Laurent (radio_metadata_buffer_t *)metadata; 43771dd3519837738303185b888ed3741763b1ae3eeEric Laurent 43871dd3519837738303185b888ed3741763b1ae3eeEric Laurent if (metadata_buf == NULL || channel == NULL || sub_channel == NULL) { 43971dd3519837738303185b888ed3741763b1ae3eeEric Laurent return -EINVAL; 44071dd3519837738303185b888ed3741763b1ae3eeEric Laurent } 44171dd3519837738303185b888ed3741763b1ae3eeEric Laurent *channel = metadata_buf->channel; 44271dd3519837738303185b888ed3741763b1ae3eeEric Laurent *sub_channel = metadata_buf->sub_channel; 44371dd3519837738303185b888ed3741763b1ae3eeEric Laurent return 0; 44471dd3519837738303185b888ed3741763b1ae3eeEric Laurent} 445