view src/g23m-fad/udp/udp_kerf.c @ 263:b5e8dfd114a7

Switch_ON(): go into charging boot mode on either CHGSTS or CHGPRES If someone were to plug and then unplug a charger into a switched-off phone in an extremely brief "glitch" manner, we should do an automatic power-off on boot in this condition. When we were checking only CHGPRES in Switch_ON(), we would go into Misc boot state instead, which is undesirable. Now if we have a CHGSTS but not CHGPRES condition, we will go into charging boot mode, and FCBM will then do the automatic power-off upon detecting absence of the charger in its periodic polling.
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 14 May 2021 05:50:36 +0000
parents fa8dc04885d8
children
line wrap: on
line source

/*
+----------------------------------------------------------------------------
|  Project :
|  Modul   :
+----------------------------------------------------------------------------
|  Copyright 2002 Texas Instruments Berlin, AG
|                 All rights reserved.
|
|                 This file is confidential and a trade secret of Texas
|                 Instruments Berlin, AG
|                 The receipt of or possession of this file does not convey
|                 any rights to reproduce or disclose its contents or to
|                 manufacture, use, or sell anything it may describe, in
|                 whole, or in part, without the specific written consent of
|                 Texas Instruments Berlin, AG.
+----------------------------------------------------------------------------
|  Purpose :  This Modul defines the functions for processing
|             of incomming primitives for the component
|             Internet Protocol of the mobile station
+----------------------------------------------------------------------------
*/

#define ENTITY_UDP

#include <string.h>
#include "typedefs.h"
#include "pcm.h"
#include "pconst.cdg"
#include "mconst.cdg"
#include "message.h"
#include "ccdapi.h"
#include "vsi.h"
#include "macdef.h" /* to get PFREE_DESC2 */
#include "custom.h"
#include "gsm.h"
#include "prim.h"
#include "cus_udp.h"
#include "cnf_udp.h"
#include "mon_udp.h"
#include "pei.h"
#include "tok.h"
#include "dti.h" /* to get dti lib */
#include "udp.h"
#include "ip_udp.h"

/*
+--------------------------------------------------------------------+
| PROJECT : WAP                                 MODULE  : udp_kerf.c |
| STATE   : code                                ROUTINE : init_udp   |
+--------------------------------------------------------------------+

  PURPOSE : Init the global variables of UDP
*/

void init_udp (void)
{
  T_HILA * p_ul;
  T_LOLA * p_dl;
  T_KER * p_ker = & udp_data->ker;

  /* Set global variables for every entity */

  INIT_STATE (HILA, DOWN);
  INIT_STATE (LOLA, DOWN);

  p_ul = & udp_data->hila;
  *p_ul->entity_name = 0;
  p_ul->dti_state    = DTI_CLOSED;
  p_ul->dti_data_req = NULL;

  p_dl = & udp_data->lola;
  *p_dl->entity_name = 0;
  p_dl->dti_state    = DTI_CLOSED;
  p_dl->dti_data_ind = NULL;
  p_dl->drop_packet  = FALSE;
  p_dl->state_err    = STATE_DL_NO_ERROR;
  p_dl->src_addr     = NO_ADDR;
  p_dl->dst_addr     = NO_ADDR;
  p_dl->dst_port     = NO_PORT;
  p_dl->src_port     = NO_PORT;

  /* Downlink and uplink for one entity */

  p_ker->send_icmp         = FALSE;
  p_ker->port_state        = PORT_DOWN;
  p_ker->dti_data_req_icmp = NULL;

  p_ker->dst_addr = NO_ADDR;
  p_ker->src_addr = NO_ADDR;
  p_ker->src_port = NO_PORT;
  p_ker->dst_port = NO_PORT;
}

/*
+--------------------------------------------------------------------+
| PROJECT : WAP                           MODULE  : udp_kerf.c       |
| STATE   : code                          ROUTINE : udp_build_packet |
+--------------------------------------------------------------------+

  PURPOSE : Build UDP and ICMP packets to send
*/

void udp_build_packet (BOOL hila, UBYTE to_do)
{
  T_KER * p_ker = & udp_data->ker;

  if (hila) /* Build the packets for higher layer */
  {
    switch (to_do)
    {
    case B_NORMAL_PACKET:
      {
        T_desc_list2 * desc_list = & udp_data->hila.dti_data_req->desc_list2;
        T_desc2 * desc = (T_desc2 *) desc_list->first;
        USHORT udp_payload_len = desc_list->list_len;

        if (desc == NULL)
        {
          TRACE_ERROR ("Hila's desc == NULL in udp_build_packet().");
          return;
        }
        else
        {
          /* Make a new desc for the IP and UDP packet header */

          USHORT headroom = LEN_IP_HEADER_B + LEN_UDP_HEADER_B;
          UBYTE * ip_header;
          T_desc2 * desc_new = M_ALLOC (offsetof (T_desc2, buffer) + headroom);

          if (desc_new == NULL)
          {
            TRACE_ERROR ("Not enough memory in udp_build_packet().");
            return;
          }
          desc_new->next = (ULONG) desc;
          desc_new->offset = 0;
          desc_new->len = headroom;
          desc_new->size = headroom;
          ip_header = desc_new->buffer;
          {
            register unsigned i;
            for (i=0; i < headroom; i++)
              ip_header[i] = '\0';/*lint !e661 !e662 (Warning -- access/creation of out-of-bounds pointer) */
          }

          /* Put the desc at the first place of the descs and
           * build the UDP header */

          desc_list->first = (ULONG) desc_new;
          desc_list->list_len = (USHORT) (desc_new->len + desc_list->list_len);

          /* Fill in IP header information */

          SET_IP_VERSION (ip_header, IP_VERSION);
          SET_IP_HEADER_LEN (ip_header, MIN_HEADER_LEN);
          /*lint -e{661, 662} (Warning -- access/creation of out-of-bounds pointer) */
         {
          SET_IP_TOTAL_LEN (ip_header, desc_list->list_len);
          SET_IP_PROT (ip_header, UDP_PROT);
          SET_IP_SOURCE_ADDR (ip_header, p_ker->src_addr);
          SET_IP_DEST_ADDR (ip_header, p_ker->dst_addr);

          SET_UDP_SRC_PORT (ip_header, p_ker->src_port);
          SET_UDP_DST_PORT (ip_header, p_ker->dst_port);
          SET_UDP_LEN (ip_header, udp_payload_len + LEN_UDP_HEADER_B);
          }
          {
            UBYTE pseudo_header [LEN_PSEUDO_HEADER_B];
            ULONG overlay;
            USHORT chksum;

            /* Build the pseudoheader for to calculate the chksum */

            SET_UDP_PSEUDO_H_SRC_ADDR (pseudo_header, p_ker->src_addr);
            SET_UDP_PSEUDO_H_DEST_ADDR (pseudo_header, p_ker->dst_addr);
            SET_UDP_PSEUDO_H_ZERO (pseudo_header, 0);
            SET_UDP_PSEUDO_H_PROT (pseudo_header, UDP_PROT);
            SET_UDP_PSEUDO_H_LEN (pseudo_header, udp_payload_len + LEN_UDP_HEADER_B);

            /* Calculate the checksum for the pseudoheader */
            overlay = partial_checksum (pseudo_header, LEN_PSEUDO_HEADER_B);

            /* Calculate for the UDP header and the data */
            RESET_UDP_CHKSUM (ip_header, LEN_IP_HEADER_B);/*lint !e661 !e662 (Warning -- access/creation of out-of-bounds pointer) */
            chksum = desc_checksum (desc_list, LEN_IP_HEADER_B, overlay);
            SET_UDP_CHKSUM (ip_header, LEN_IP_HEADER_B, chksum);/*lint !e661 !e662 (Warning -- access/creation of out-of-bounds pointer) */
          }
        }
      }
      break;

    default:
      break;
    }
  }
  else /* Build the packets for lower layer */
  {
    T_LOLA * p_dl = & udp_data->lola;
    T_desc_list2 * desc_list = & p_dl->dti_data_ind->desc_list2;
    T_desc2 * desc = (T_desc2 *) desc_list->first;

    if (desc == NULL)
    {
      TRACE_ERROR ("Lola's desc == NULL in udp_build_packet().");
      return;
    }
    if (desc->len < LEN_IP_HEADER_B)
    {
      TRACE_ERROR (
        "Lola's desc->len < LEN_IP_HEADER_B "
        "in udp_build_packet()."
      );
      return;
    }
    if (GET_IP_HEADER_LEN_B (desc->buffer + desc->offset) < LEN_IP_HEADER_B)
    {
      TRACE_ERROR (
        "Lola's GET_IP_HEADER_LEN_B() < LEN_IP_HEADER_B "
        "in udp_build_packet()."
      );
      return;
    }

    switch (to_do)
    {
    case B_NORMAL_PACKET:
      {
        /* Build a new desc for IP addresses and port numbers */

        T_desc2 * addr = M_ALLOC (
          offsetof (T_desc2, buffer) + sizeof (T_SRC_DES)
        );
        if (addr == NULL) {
          TRACE_ERROR ("Not enough memory in udp_build_packet().");
          return;
        }

        addr->next = (ULONG) desc;
        addr->offset = 0;
        addr->len = sizeof (T_SRC_DES);
        addr->size = sizeof (T_SRC_DES);

        memcpy (((T_SRC_DES *) addr->buffer)->src_ip, & p_dl->src_addr, 4);
        memcpy (((T_SRC_DES *) addr->buffer)->des_ip, & p_dl->dst_addr, 4);
        memcpy (((T_SRC_DES *) addr->buffer)->src_port, & p_dl->src_port, 2);
        memcpy (((T_SRC_DES *) addr->buffer)->des_port, & p_dl->dst_port, 2);

        desc_list->first = (ULONG) addr;
        desc_list->list_len = (USHORT) (addr->len + desc_list->list_len);

        /* Filter out the given IP and UDP header */
        {
          register unsigned headroom =
            GET_IP_HEADER_LEN_B (desc->buffer + desc->offset) + LEN_UDP_HEADER_B;
          if (desc->len < headroom)
          {
            TRACE_ERROR ("Lola's IP packet is short in udp_build_packet().");
            return;
          }
          memmove (
            desc->buffer + desc->offset,
            desc->buffer + desc->offset + headroom,
            desc->len - headroom
          );
          desc->len = (USHORT) (desc->len - headroom);
          desc_list->list_len = (USHORT) (desc_list->list_len - headroom);
        }
      }
      break;

    case B_NO_DEST_PORT:
      {
        /* We build the whole ICMP packet */

        PPASS (p_dl->dti_data_ind, data_req, DTI2_DATA_REQ);

        desc_list = & data_req->desc_list2;
        desc = (T_desc2 *) desc_list->first;

        build_icmp_with_payload (
          data_req,
          IDENTITY_0,
          STANDARD_TTL,
          GET_IP_DEST_ADDR (desc->buffer + desc->offset),
          ICMP_TYP_DEST_URECHBL,
          ICMP_CODE_NO_PORT
        );

        p_ker->dti_data_req_icmp = data_req;
      }
      break;

    default:
      break;
    }
  }
}

/*-------------------------------------------------------------------------*/