/*
 *      radio.c from Access Point SNMP Utils for Linux
 *
 * Copyright (c) 2002 Roman Festchook <roma at polesye dot net>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License Version 2 from
 * June 1991 as published by the Free Software Foundation.
 *
 * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 *
 */
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include "ap-utils.h"

#define RADIO_HELP _("[key] - power level; UIOP or LR - antenna; W - write config; Q - quit to menu")

#define ANTENNA _("Antenna:")
#define ANTENNA_LEFT _("[L] Left:")
#define ANTENNA_RIGHT _("[R] Right:")

extern WINDOW *main_sub;
extern short ap_type;

void power()
{
    char TestModeRadioConfiguration[] =
	{ 0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x01, 0x08, 0x08,
	0x00
    };

    char operAntennaSettings[] =
	{ 0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x01, 0x0C,
	0x00
    };

#if defined(WORDS_BIGENDIAN)
    struct twobytes_antenna_struct {
	int reserv2:6;
	int trans_right:1;
	int trans_left:1;
	int reserv1:6;
	int recv_right:1;
	int recv_left:1;
    };

    struct onebyte_antenna_struct {
	int reserv:6;
	int right:1;
	int left:1;
    };
#else	/* !WORDS_BIGENDIAN */
    struct twobytes_antenna_struct {
	int recv_left:1;
	int recv_right:1;
	int reserv1:6;
	int trans_left:1;
	int trans_right:1;
	int reserv2:6;
    };

    struct onebyte_antenna_struct {
	int left:1;
	int right:1;
	int reserv:6;
    };
#endif	/* !WORDS_BIGENDIAN */

    union antenna_union {
	struct twobytes_antenna_struct antennas_tb;
	unsigned short antennai;
	struct onebyte_antenna_struct antennas_ob;
	char antennac;
    } antenna;


    char message[1024];
    unsigned char power[14], m_power = 0, a[] = { 0, 0 }, m_antenna = 0;
    varbind varbinds[2];
    int i, c = 0, antenna_vlen;

    if (ap_type == ATMEL12350) {
	TestModeRadioConfiguration[5] = 0xE0;
	TestModeRadioConfiguration[6] = 0x3E;
	operAntennaSettings[5] = 0xE0;
	operAntennaSettings[6] = 0x3E;
    }

    varbinds[0].oid = TestModeRadioConfiguration;
    varbinds[0].len_oid = sizeof(TestModeRadioConfiguration);
    varbinds[0].value = TestModeRadioConfiguration;
    varbinds[0].len_val = 0;
    varbinds[0].type = NULL_VALUE;
    varbinds[1].oid = operAntennaSettings;
    varbinds[1].value = TestModeRadioConfiguration;
    varbinds[1].len_oid = sizeof(operAntennaSettings);
    varbinds[1].len_val = 0;
    varbinds[1].type = NULL_VALUE;

    print_help(WAIT_RET);
    if (snmp(varbinds, 2, GET) < 2) {
	print_helperr(ERR_RET);
	goto exit;
    }
    print_help(RADIO_HELP);

    memcpy(power, varbinds[0].value, 14);
    antenna_vlen = varbinds[1].len_val;

    print_top(NULL, _("Radio Configuration"));
    mvwaddstr(main_sub, 0, 1, _("Output RF signal power level (CR31 register values)"));
    mvwaddstr(main_sub, 1, 1, "---------------------------------------------------");
    mvwaddstr(main_sub, 2, 1, _("Key Channel Level"));

    for (i = 0; i < 14; i++) {
	sprintf(message, "[%X]     %02u   %3u", i + 1, i + 1, power[i]);
	mvwaddstr(main_sub, i + 3, 1, message);
    }

    if (antenna_vlen == 2) {
	memcpy(&antenna.antennai, varbinds[1].value, 2);
	antenna.antennai = ntohs(antenna.antennai);
	sprintf(message, "%s %s %3s, %s %3s",
	    ANTENNA_RX,
	    ANTENNA_RX_LEFT, (antenna.antennas_tb.recv_left) ? ON : OFF,
	    ANTENNA_RX_RIGHT, (antenna.antennas_tb.recv_right) ? ON : OFF);
	mvwaddstr(main_sub, 18, 1, message);
	sprintf(message, "%s %s %3s, %s %3s",
	    ANTENNA_TX,
	    ANTENNA_TX_LEFT, (antenna.antennas_tb.trans_left) ? ON : OFF,
	    ANTENNA_TX_RIGHT, (antenna.antennas_tb.trans_right) ? ON : OFF);
	mvwaddstr(main_sub, 19, 1, message);
    } else { /* antenna_vlen == 1 */
	antenna.antennac = *varbinds[1].value;
	sprintf(message, "%s %s %3s, %s %3s",
	    ANTENNA,
	    ANTENNA_LEFT, (antenna.antennas_ob.left) ? ON : OFF,
	    ANTENNA_RIGHT, (antenna.antennas_ob.right) ? ON : OFF);
	mvwaddstr(main_sub, 18, 1, message);
    }

    wrefresh(main_sub);
    noecho();
    while (1) {
	c = getch();
	switch (c) {
	case '1':
	case '2':
	case '3':
	case '4':
	case '5':
	case '6':
	case '7':
	case '8':
	case '9':
	case 'a':
	case 'b':
	case 'c':
	case 'd':
	case 'e':
	case 'A':
	case 'B':
	case 'C':
	case 'D':
	case 'E':
	    a[0] = c;
	    i = strtol(a, NULL, 16);
	    get_value(message, i + 2, 14, 4, INT_STRING, 0, 255, RADIO_HELP);
	    c = atoi(message) & 0xFF;
	    power[i - 1] = c;
	    m_power = 1;
	    continue;
	case 'i':
	case 'I':
	    if (antenna_vlen == 1)
		continue;
	    i = strlen(ANTENNA_RX) + 1 +
		strlen(ANTENNA_RX_LEFT) + 6 +
		strlen(ANTENNA_RX_RIGHT) + 2;
	    m_antenna = on_off(18, i);
	    antenna.antennas_tb.recv_right = (m_antenna == 2) ? 0 : 1;
	    sprintf(message, "%3s", (antenna.antennas_tb.recv_right) ? ON : OFF);
	    print_menusel(18, i, NULL, message);
	    continue;
	case 'u':
	case 'U':
	    if (antenna_vlen == 1)
		continue;
	    i = strlen(ANTENNA_RX) + 1 +
		strlen(ANTENNA_RX_LEFT) + 2;
	    m_antenna = on_off(18, i);
	    antenna.antennas_tb.recv_left = (m_antenna == 2) ? 0 : 1;
	    sprintf(message, "%3s", (antenna.antennas_tb.recv_left) ? ON : OFF);
	    print_menusel(18, i, NULL, message);
	    continue;
	case 'p':
	case 'P':
	    if (antenna_vlen == 1)
		continue;
	    i = strlen(ANTENNA_TX) + 1 +
		strlen(ANTENNA_TX_LEFT) + 6 +
		strlen(ANTENNA_TX_RIGHT) + 2;
	    m_antenna = on_off(19, i);
	    antenna.antennas_tb.trans_right = (m_antenna == 2) ? 0 : 1;
	    sprintf(message, "%3s", (antenna.antennas_tb.trans_right) ? ON : OFF);
	    print_menusel(19, i, NULL, message);
	    continue;
	case 'o':
	case 'O':
	    if (antenna_vlen == 1)
		continue;
	    i = strlen(ANTENNA_TX) + 1 +
		strlen(ANTENNA_TX_LEFT) + 2;
	    m_antenna = on_off(19, i);
	    antenna.antennas_tb.trans_left = (m_antenna == 2) ? 0 : 1;
	    sprintf(message, "%3s", (antenna.antennas_tb.trans_left) ? ON : OFF);
	    print_menusel(19, i, NULL, message);
	    continue;
	case 'r':
	case 'R':
	    if (antenna_vlen == 2)
		continue;
	    i = strlen(ANTENNA) + 1 +
		strlen(ANTENNA_LEFT) + 6 +
		strlen(ANTENNA_RIGHT) + 2;
	    m_antenna = on_off(18, i);
	    antenna.antennas_ob.right = (m_antenna == 2) ? 0 : 1;
	    sprintf(message, "%3s", (antenna.antennas_ob.right) ? ON : OFF);
	    print_menusel(18, i, NULL, message);
	    continue;
	case 'l':
	case 'L':
	    if (antenna_vlen == 2)
		continue;
	    i = strlen(ANTENNA) + 1 +
		strlen(ANTENNA_LEFT) + 2;
	    m_antenna = on_off(18, i);
	    antenna.antennas_ob.left = (m_antenna == 2) ? 0 : 1;
	    sprintf(message, "%3s", (antenna.antennas_ob.left) ? ON : OFF);
	    print_menusel(18, i, NULL, message);
	    continue;
	case 'q':
	case 'Q':
	    goto quit;
	case 'w':
	case 'W':
	    i = 0;
	    if (m_power) {
		varbinds[i].oid = TestModeRadioConfiguration;
		varbinds[i].len_oid = sizeof(TestModeRadioConfiguration);
		varbinds[i].value = power;
		varbinds[i].len_val = 14;
		varbinds[i].type = STRING_VALUE;
		i++;
	    }

	    if (m_antenna) {
		if ( (antenna_vlen == 1 &&
			(antenna.antennas_ob.left == 0 &&
			 antenna.antennas_ob.right == 0))
		    ||
		     (antenna_vlen == 2 &&
			( (antenna.antennas_tb.trans_left == 0 &&
			   antenna.antennas_tb.trans_right == 0) ||
			  (antenna.antennas_tb.recv_left == 0 &&
			   antenna.antennas_tb.recv_right == 0))) ) {
		    print_helperr
			(_
			 ("You can't disable both antennas; unable to save antenna-config. Press any key."));
		    getch();
		} else {

		    varbinds[i].oid = operAntennaSettings;
		    varbinds[i].len_oid = sizeof(operAntennaSettings);
		    if (antenna_vlen == 2) {
			unsigned short antenna_hw = htons(antenna.antennai);

			varbinds[i].value = (char *) &antenna_hw;
		    } else /* antenna_vlen == 1 */
			varbinds[i].value = &antenna.antennac;
		    varbinds[i].type = INT_VALUE;
		    varbinds[i].len_val = antenna_vlen;
		    i++;
		}
	    }

	    print_help(WAIT_SET);
	    if (snmp(varbinds, i, SET) <= 0) {
		print_helperr(ERR_SET);
		goto exit;
	    }
	    wbkgd(main_sub, A_NORMAL);
	    wrefresh(main_sub);
	    break;
	default:
	    continue;
	}
	break;
    }

    print_help(ANY_KEY);
  exit:
    getch();
  quit:
    print_top(NULL, NULL);
    clear_main(0);
}

