/* * This file is part of GAPK (GSM Audio Pocket Knife). * * (C) 2018 by Vadim Yanitskiy * * GAPK is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GAPK is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GAPK. If not, see . */ #include #include #include #include #include #include #include #include #include /* A good FR frame */ static const char *sample_frame_hex = \ "d9ec9be212901f802335598c501f805bad3d4ba01f809b69df5a501f809cd1b4da"; static void talloc_ctx_walk_cb(const void *chunk, int depth, int max_depth, int is_ref, void *data) { const char *chunk_name = talloc_get_name(chunk); int spaces_cnt; /* Hierarchical spacing */ for (spaces_cnt = 0; spaces_cnt < depth; spaces_cnt++) printf(" "); /* Chunk info */ printf("chunk %s: depth=%d\n", chunk_name, depth); } void pq_execute(struct osmo_gapk_pq *pq, uint8_t *frame, size_t len) { struct osmo_gapk_pq_item *pq_item; unsigned int len_prev = len; uint8_t *buf_prev = frame; int rv; /* Iterate over all items in the chain */ llist_for_each_entry(pq_item, &pq->items, list) { printf("Block '%s/%s/%s' in (len=%d): %s\n", pq->name, pq_item->cat_name, pq_item->sub_name, len_prev, osmo_hexdump(buf_prev, len_prev)); /* Call item's processing handler */ rv = pq_item->proc(pq_item->state, pq_item->buf, buf_prev, len_prev); assert(rv > 0); printf("Block '%s/%s/%s' out (len=%d): %s\n", pq->name, pq_item->cat_name, pq_item->sub_name, rv, osmo_hexdump(pq_item->buf, rv)); buf_prev = pq_item->buf; len_prev = rv; } } void test_fr_concealment(struct osmo_gapk_pq *pq) { uint8_t fb[GSM_FR_BYTES]; int i; /* Init frame buffer with BFI */ memset(fb, 0x00, sizeof(fb)); fb[0] = 0xd0; /* Process a BFI frame */ printf("[i] Process a BFI frame: %s\n", osmo_hexdump(fb, sizeof(fb))); pq_execute(pq, fb, sizeof(fb)); printf("\n"); /* Parse frame from string to hex */ osmo_hexparse(sample_frame_hex, fb, GSM_FR_BYTES); /* Process a good frame (reset ECU) */ printf("[i] Process a good frame: %s\n", osmo_hexdump(fb, sizeof(fb))); pq_execute(pq, fb, sizeof(fb)); printf("\n"); /* Now pretend that we do not receive any good frames anymore */ memset(fb, 0x00, sizeof(fb)); fb[0] = 0xd0; printf("[i] Pretend that we do not receive any good frames anymore\n"); for (i = 0; i < 20; i++) pq_execute(pq, fb, sizeof(fb)); printf("\n"); } int main(int argc, char **argv) { const struct osmo_gapk_codec_desc *codec; struct osmo_gapk_pq *pq; int rc; /* Enable tracking the use of NULL memory contexts */ talloc_enable_null_tracking(); /* Allocate a single processing chain */ pq = osmo_gapk_pq_create("pq_ecu_test"); assert(pq != NULL); /* Obtain FR codec description */ codec = osmo_gapk_codec_get_from_type(CODEC_FR); assert(codec->ecu_proc); /* Put a FR ECU */ rc = osmo_gapk_pq_queue_ecu(pq, codec); assert(rc == 0); /* Put a FR decoder */ rc = osmo_gapk_pq_queue_codec(pq, codec, 0); assert(rc == 0); /* Prepare the chain */ rc = osmo_gapk_pq_prepare(pq); assert(rc == 0); test_fr_concealment(pq); /* Release memory */ osmo_gapk_pq_destroy(pq); /* Make sure we have no memleaks */ talloc_report_depth_cb(NULL, 0, 10, &talloc_ctx_walk_cb, NULL); /* Make both Valgrind and LeakSanitizer happy */ talloc_disable_null_tracking(); return 0; }