package brn.analysis.dump;

import jist.swans.misc.Pickle;

//struct ath_desc {
//  /*
//   * The following definitions are passed directly
//   * the hardware and managed by the HAL.  Drivers
//   * should not touch those elements marked opaque.
//   */
//  u_int32_t ds_link;  /* phys address of next descriptor */
//  u_int32_t ds_data;  /* phys address of data buffer */
//  u_int32_t ds_ctl0;  /* opaque DMA control 0 */
//  u_int32_t ds_ctl1;  /* opaque DMA control 1 */
//  u_int32_t ds_hw[4]; /* opaque h/w region */
//  /*
//   * The remaining definitions are managed by software;
//   * these are valid only after the rx/tx process descriptor
//   * methods return a non-EINPROGRESS  code.
//   */
//  union {
//    struct ath_tx_status tx;/* xmit status */
//    struct ath_rx_status rx;/* recv status */
//  } ds_us;
//  void    *ds_vdata;  /* virtual addr of data buffer */
//} __packed;

//struct ath_rx_status {
//  u_int16_t rs_datalen; /* rx frame length */
//  u_int16_t rs_tstamp;  /* h/w assigned timestamp */
//  u_int8_t  rs_status;  /* rx status, 0 => recv ok */
//  u_int8_t  rs_phyerr;  /* phy error code */
//  int8_t    rs_rssi;  /* rx frame RSSI */
//  u_int8_t  rs_keyix; /* key cache index */
//  u_int8_t  rs_rate;  /* h/w receive rate index */
//  u_int8_t  rs_antenna; /* antenna information */
//  u_int8_t  rs_more;  /* more descriptors follow */
//};
//
//struct ath_tx_status {
//  u_int16_t ts_seqnum;  /* h/w assigned sequence number */
//  u_int16_t ts_tstamp;  /* h/w assigned timestamp */
//  u_int8_t  ts_status;  /* frame status, 0 => xmit ok */
//  u_int8_t  ts_rate;  /* h/w transmit rate index */
//#define HAL_TXSTAT_ALTRATE  0x80  /* alternate xmit rate used */
//  int8_t    ts_rssi;  /* tx ack RSSI */
//  u_int8_t  ts_shortretry;  /* # short retries */
//  u_int8_t  ts_longretry; /* # long retries */
//  u_int8_t  ts_virtcol; /* virtual collision count */
//  u_int8_t  ts_antenna; /* antenna information */
//};
//
//#define HAL_TXERR_XRETRY  0x01  /* excessive retries */
//#define HAL_TXERR_FILT    0x02  /* blocked by tx filtering */
//#define HAL_TXERR_FIFO    0x04  /* fifo underrun */


/*
 * 
 */
public class AthdescHeader {

  public static final int HEADER_BASE_SIZE = 8 * 4;
  
  public static final int HEADER_EXTRA_SIZE = 11;

  public static final int HEADER_SIZE = HEADER_EXTRA_SIZE + HEADER_BASE_SIZE;

  public static byte getRxRate(byte[] msg, int offset) {
    short rssi = Pickle.arrayToShort(msg, offset + 17);
    return (byte)((rssi >> 7) & 0xFF);
  }

  public static byte getRxRateMbps(byte[] msg, int offset) {
    switch (getRxRate(msg, offset)) {
    case 0x08: return 48;
    case 0x09: return 24;
    case 0x0A: return 12;
    case 0x0B: return 6;
    case 0x0C: return 54;
    case 0x0D: return 36;
    case 0x0E: return 18;
    case 0x0F: return 9;
    case 0x18: return 11;
    case 0x19: return 5;
    case 0x1A: return 2;
    case 0x1B: return 1;
    default: return 0;
    }
  }

  public static byte getRateIdx(byte[] msg, int offset) {
    switch (getRxRateMbps(msg,offset)) {
    case 48: return 10;
    case 24: return 8;
    case 12: return 6;
    case 6: return 4;
    case 54: return 11;
    case 36: return 9;
    case 18: return 7;
    case 9: return 5;
    case 11: return 3;
    case 5: return 2;
    case 2: return 1;
    case 1: return 0;
    default: return 12;
    }
  }

  public static short getFrameLen(byte[] msg, int offset) {
    return (short)(Pickle.arrayToUShort(msg, offset + 8) & 0x0FFF);
  }

  public static boolean getTxFeedback(byte[] msg, int offset) {
    return (getFrameLen(msg, offset) != 0);
  }
  
  public static boolean getTxFail(byte[] msg, int offset) {
    return (msg[8 + 16] & 0x02) != 0;
  }

  public static byte getExtTxLongRetry(byte[] msg, int offset) {
    if (msg.length <= offset + HEADER_BASE_SIZE + 8)
      return 0;
    return (msg[offset + HEADER_BASE_SIZE + 8]);
  }


  public static byte getExtTxRate(byte[] msg, int offset) {
    if (msg.length <= offset + HEADER_BASE_SIZE + 5)
      return 0;
    return (msg[offset + HEADER_BASE_SIZE + 5]);
  }

  public static byte getExtTxRateMbps(byte[] msg, int offset) {
    switch (getExtTxRate(msg, offset)) {
    case 0x08: return 48;
    case 0x09: return 24;
    case 0x0A: return 12;
    case 0x0B: return 6;
    case 0x0C: return 54;
    case 0x0D: return 36;
    case 0x0E: return 18;
    case 0x0F: return 9;
    case 0x18: return 11;
    case 0x19: return 5;
    case 0x1A: return 2;
    case 0x1B: return 1;
    default: return 0;
    }
  }

  public static byte getExtTxRateIdx(byte[] msg, int offset) {
    switch (getExtTxRateMbps(msg,offset)) {
    case 48: return 10;
    case 24: return 8;
    case 12: return 6;
    case 6: return 4;
    case 54: return 11;
    case 36: return 9;
    case 18: return 7;
    case 9: return 5;
    case 11: return 3;
    case 5: return 2;
    case 2: return 1;
    case 1: return 0;
    default: return 12;
    }
  }

  public static byte getRxRssi(byte[] msg, int offset) {
    short rssi = Pickle.arrayToShort(msg, offset + 18);
    return (byte)((rssi >> 4) & 0xFF);
  }
  
  public static byte getExtRxStatus(byte[] msg, int offset) {
    if (msg.length <= offset + HEADER_BASE_SIZE + 4)
      return -1;
    return msg[offset + HEADER_BASE_SIZE + 4];
  }

  public static byte getExtRxPhyerr(byte[] msg, int offset) {
    return msg[offset + HEADER_BASE_SIZE + 5];
  }

  public static byte getExtRxRssi(byte[] msg, int offset) {
    return msg[offset + HEADER_BASE_SIZE + 6];
  }

  public static byte getExtRxRate(byte[] msg, int offset) {
    if (msg.length > offset + HEADER_BASE_SIZE + 8)
      return msg[offset + HEADER_BASE_SIZE + 8];
    else
      return 0;
  }

  public static byte getExtRxRateMbps(byte[] msg, int offset) {
    if (msg.length <= offset + HEADER_BASE_SIZE + 8)
      return 0;
    switch (msg[offset + HEADER_BASE_SIZE + 8]) {
    case 0x08: return 48;
    case 0x09: return 24;
    case 0x0A: return 12;
    case 0x0B: return 6;
    case 0x0C: return 54;
    case 0x0D: return 36;
    case 0x0E: return 18;
    case 0x0F: return 9;
    case 0x18: return 11;
    case 0x19: return 5;
    case 0x1A: return 2;
    case 0x1B: return 1;
    default: return 0;
    }
  }

  public static byte getExtRxRateIdx(byte[] msg, int offset) {
    switch (getExtRxRateMbps(msg,offset)) {
    case 48: return 10;
    case 24: return 8;
    case 12: return 6;
    case 6: return 4;
    case 54: return 11;
    case 36: return 9;
    case 18: return 7;
    case 9: return 5;
    case 11: return 3;
    case 5: return 2;
    case 2: return 1;
    case 1: return 0;
    default: return 12;
    }
  }
}
