/* * fastext.c: Routines to handle FASTEXT extensions * * $Id: fastext.c,v 1.1 1997/07/31 23:28:44 mb Exp mb $ * * Copyright (c) 1996 Martin Buck * Read COPYING for more information * */ #include #include #include #include #include "safe_malloc.h" #include "misc.h" #include "vtxtools.h" #include "vtxdecode.h" #include "fastext.h" typedef struct fastext_info_s { int subpage; fastext_buttons_t buttons; fastext_links_t links; byte_t packet24[40], packet27[4 * 40]; struct fastext_info_s *next; } fastext_info_t; int fastext_ok; static fastext_info_t *fastext_info[800]; static fastext_info_t * find_pageentry(int pgnum, int subpage, int fallback) { fastext_info_t *curr; curr = fastext_info[pgnum]; while (curr) { if (curr->subpage == subpage) { return curr; } curr = curr->next; } if (!fallback) { return NULL; } curr = fastext_info[pgnum]; if (curr && !curr->subpage) { return curr; } return NULL; } int fastext_cmp_packets(const byte_t *packet24_1, const byte_t *packet27_1, const byte_t *packet24_2, const byte_t *packet27_2) { int subpkt; if (memcmp(packet24_1, packet24_2, 40 * sizeof(*packet24_1))) { return FALSE; } for (subpkt = 0; subpkt <= 3; subpkt++) { if (memcmp(packet27_1 + subpkt * 40, packet27_2 + subpkt * 40, 37 * sizeof(*packet27_1))) { return FALSE; } } return TRUE; } int fastext_newpage(const byte_t *packet24, const byte_t *packet27, const vtx_pageinfo_t *pginf) { int pos, subpkt, link_max = -1, pgofs; int ofs, link, link_num, link_data[6], page, hour, minute; fastext_links_t tmp_links; fastext_buttons_t tmp_btns; fastext_info_t *info_ent; if (!vtx_chkpgnum(pginf->pagenum, FALSE)) return FALSE; pgofs = vtx_hex2dec(pginf->pagenum) - 100; /* Return if same FASTEXT-data is already in cache */ if ((info_ent = find_pageentry(pgofs, pginf->minute, TRUE)) && fastext_cmp_packets(packet24, packet27, info_ent->packet24, info_ent->packet27)) { return FALSE; } /* Decode packets 24 & 27 */ for (subpkt = 0; subpkt <= 3; subpkt++) { if (packet27[subpkt * 40] == subpkt) { #ifdef DEBUG_FASTEXT if (!subpkt) { fprintf(stderr, "fastext_newpage: %X.%X\n", pginf->pagenum, pginf->minute); } fprintf(stderr, "fastext_newpage: 27/%d: ", subpkt); #endif for (link = 0; link <= 5; link++) { ofs = subpkt * 40 + link * 6 + 1; for (pos = 0; pos <= 5; pos++) { if ((link_data[pos] = vtx_chkhamming(packet27[ofs++])) < 0) { break; } } if (pos == 6) { link_max = subpkt * 6 + link; page = ((link_data[1] << 4) | link_data[0] | (pginf->pagenum & 0x700)) ^ (((link_data[5] & 0xc) << 7) | ((link_data[3] & 8) << 5)); if (page < 0x100) { page += 0x800; } hour = ((link_data[5] & 3) << 4) | link_data[4]; minute = ((link_data[3] & 7) << 4) | link_data[2]; #ifdef DEBUG_FASTEXT fprintf(stderr, "%d:%X,%X,%X ", link, page, hour, minute); #endif } else { page = hour = minute = 0; #ifdef DEBUG_FASTEXT fprintf(stderr, "%d:hamming err. ", link); #endif } link_num = subpkt * 6 + link; tmp_links.link[link_num].page = page; tmp_links.link[link_num].hour = hour; tmp_links.link[link_num].minute = minute; } #ifdef DEBUG_FASTEXT fprintf(stderr, "\n"); #endif } } if (link_max >= 0) { int button, is_btn = FALSE, btnpos = 0; byte_t chr; for (button = 0; button < NELEM(tmp_btns.button); button++) { tmp_btns.button[button] = -1; } button = 0; for (pos = 0; pos <= 39; pos++) { chr = packet24[pos]; if (!is_btn) { if ((chr & 0x7f) > ' ' || (!vtx_chkparity(&chr) && (chr & 0x7f) >= ' ')) { if (button >= NELEM(tmp_btns.button)) { button = 0; break; } tmp_btns.button[button++] = btnpos; is_btn = TRUE; } } if (is_btn) { if (!vtx_chkparity(&chr) && (chr & 0x7f) >= ' ') { chr = '?'; } if ((chr & 0x7f) >= ' ') { chr = vtx2iso_table[cct2vtx_table[pginf->charset][chr - 32]]; tmp_btns.btnbuf[btnpos++] = chr; } else { tmp_btns.btnbuf[btnpos--] = '\0'; while (btnpos && tmp_btns.btnbuf[btnpos] == ' ') { tmp_btns.btnbuf[btnpos--] = '\0'; } btnpos += 2; is_btn = FALSE; } } } if (button) { tmp_btns.btnbuf[btnpos--] = '\0'; while (btnpos && tmp_btns.btnbuf[btnpos] == ' ') { tmp_btns.btnbuf[btnpos--] = '\0'; } #ifdef DEBUG_FASTEXT fprintf(stderr, "fastext_newpage: buttons: "); for (button = 0; button <= 3; button++) { fprintf(stderr, "<%s> ", tmp_btns.btnbuf + tmp_btns.button[button]); } fprintf(stderr, "\n"); } else { fprintf(stderr, "fastext_newpage: no buttons\n"); #endif } tmp_btns.num_buttons = button; } /* If valid FASTEXT-data was found, add it to cache. Overwrite current entry for given * subpage if it already exists. Otherwise create new one, possibly with subpage-number * 0 if that entry doesn't already exist. Entries with subpage-number 0 are valid for all * subpages without an individual entry. Entries with subpage number != 0 will be created * only, if an entry for 0 already exists and if the new entry is different from the current * entry for subpage 0. */ if (link_max >= 0) { fastext_ok = TRUE; if (!(info_ent = find_pageentry(pgofs, pginf->minute, FALSE))) { fastext_info_t **curr; int newsubpg; newsubpg = find_pageentry(pgofs, 0, FALSE) ? pginf->minute : 0; curr = &fastext_info[pgofs]; while (*curr) { curr = &(*curr)->next; } info_ent = *curr = smalloc(sizeof(fastext_info_t)); info_ent->next = NULL; info_ent->subpage = newsubpg; } memcpy(info_ent->packet24, packet24, 40 * sizeof(*packet24)); memcpy(info_ent->packet27, packet27, 4 * 40 * sizeof(*packet27)); info_ent->links = tmp_links; info_ent->buttons = tmp_btns; return TRUE; } else { return FALSE; } } int fastext_get_pginfo(int page, int subpage, const fastext_buttons_t **buttons, const fastext_links_t **links, const byte_t **packet24, const byte_t **packet27) { int pgofs; fastext_info_t *info_ent; if (!vtx_chkpgnum(page, FALSE)) return FALSE; pgofs = vtx_hex2dec(page) - 100; if ((info_ent = find_pageentry(pgofs, subpage, TRUE))) { if (buttons) *buttons = &info_ent->buttons; if (links) *links = &info_ent->links; if (packet24) *packet24 = info_ent->packet24; if (packet27) *packet27 = info_ent->packet27; return TRUE; } else { return FALSE; } } void fastext_reset(void) { int pgnum; fastext_info_t *curr, *next; for (pgnum = 0; pgnum < NELEM(fastext_info); pgnum++) { curr = fastext_info[pgnum]; while (curr) { next = curr->next; free(curr); curr = next; } fastext_info[pgnum] = NULL; } fastext_ok = FALSE; }