/**
 * @file i4bcmgr_capiutil.c
 *
 * I4BCMgr-CapiUtil - Utility functions to handle CAPI messages.
 *
 * Copyright: 2000-2003 Thomas Wintergerst. All rights reserved.
 *
 * $FreeBSD$
 * $Id: i4bcmgr_capiutil.c,v 1.1.2.1 2006/02/28 21:35:28 thomas Exp $
 * Project  CAPI for BSD
 * Target   i4bcapimgr - The I4B driver for CAPI manager driven controllers
 * @date    01.01.2000
 * @author  "Thomas Wintergerst" <twinterg@gmx.de>
 * <p>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * </p>
 */

#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");

/* system includes */
#include <sys/param.h>
#include <sys/types.h>
#include <sys/systm.h>
#include <sys/mbuf.h>
#include <capi20.h>
#include <i4b_ioctl.h>

/* import includes */

#define __I4BCMGR_CAPIUTIL__

/* local includes */
#include <i4b/i4bcapimgr/i4bcmgr_capiutil.h>





/* === public definitions ================================================ */





/* === private definitions =============================================== */





/* === prototypes for private functions ================================== */





/* === definition of public functions ==================================== */





/*
        store the called party number into a character array
        ----------------------------------------------------
*/

const unsigned char *CapiUt_ExtractCalledPartyNumber
   (const unsigned char *pOrgPos,
    char                *pszCalledPartyNumber,
    size_t               nLenCalledPartyNumber)
{
   size_t      nLen = *pOrgPos;
   const char *pSrc = pOrgPos + 1;
   char       *pDst = pszCalledPartyNumber;
   
   /* if called party number is empty: ready */
   if (nLen == 0)
   {
      if (nLenCalledPartyNumber > 0)
      {
         pszCalledPartyNumber [0] = '\0';
      }
      return (pOrgPos + 1);
   }
   
   /* the first byte is the type of number and numbering plan */
   nLen--;
   pSrc++;
   
   /* copy the number bytes to the buffer specified */
   while (nLen > 0 && nLenCalledPartyNumber > 1)
   {
      *(pDst++) = *(pSrc++);
      nLen--;
      nLenCalledPartyNumber--;
   }
   if (nLenCalledPartyNumber > 0)
   {
      *pDst = '\0';
   }
   
   /* return the position behind the last byte of the number */
   return (pSrc + nLen);
} /* CapiUt_ExtractCalledPartyNumber */
    




/*
        store the calling party number into a character array
        -----------------------------------------------------
*/

const unsigned char *CapiUt_ExtractCallingPartyNumber
   (const unsigned char *pOrgPos,
    char                *pszCallingPartyNumber,
    size_t               nLenCallingPartyNumber,
    int                 *piScreeningInd,
    int                 *piPresentationInd)
{
   size_t      nLen = *pOrgPos;
   const char *pSrc = pOrgPos + 1;
   char       *pDst = pszCallingPartyNumber;
   
   /* initialize the last two return values */
   if (piScreeningInd)
   {
      *piScreeningInd = SCR_NONE;
   }
   if (piPresentationInd)
   {
      *piPresentationInd = PRS_NONE;
   }

   /* if called party number is empty: ready */
   if (nLen == 0)
   {
      if (nLenCallingPartyNumber > 0)
      {
         pszCallingPartyNumber [0] = '\0';
      }
      return (pOrgPos + 1);
   }
   
   /* the first byte is the type of number and numbering plan, the second is
    * the presentation and screening indicator
    */
   nLen--;
   if (nLen > 0 && (*pSrc & 0x80) == 0)
   {
      if (piScreeningInd)
      {
         *piScreeningInd = (*pSrc & 0x03) + SCR_USR_NOSC;
      }
      if (piPresentationInd)
      {
         *piPresentationInd = ((*pSrc >> 5) & 0x03) + PRS_ALLOWED;
      }
      nLen--;
      pSrc += 2;
   }
   else
   {
      pSrc++;
   }
   
   /* copy the number bytes to the buffer specified */
   while (nLen > 0 && nLenCallingPartyNumber > 1)
   {
      *(pDst++) = *(pSrc++);
      nLen--;
      nLenCallingPartyNumber--;
   }
   if (nLenCallingPartyNumber > 0)
   {
      *pDst = '\0';
   }
   
   /* return the position behind the last byte of the number */
   return (pSrc + nLen);
} /* CapiUt_ExtractCallingPartyNumber */

    
    
    

/*
        enter an empty CAPI structure at specified position
        ---------------------------------------------------
*/

unsigned char *CapiUt_EnterEmptyStruct
   (unsigned char *pOrgPos)
{
   *(pOrgPos++) = 0;
   return (pOrgPos);
} /* CapiUt_EnterEmptyStruct */
   




/*
        enter a string into a CAPI structure at specified position
        ----------------------------------------------------------
*/

unsigned char *CapiUt_EnterString
   (unsigned char *pOrgPos,
    const char    *pszString)
{
   char   *pDst = (char *) pOrgPos + 1;
   size_t  nLen = 0;
   
   if (! pszString)
   {
      return (CapiUt_EnterEmptyStruct (pOrgPos));
   }
   
   while (*pszString)
   {
      *(pDst++) = *(pszString++);
      nLen++;
   }
   
   *pOrgPos = (unsigned char) nLen;
   
   return (pDst);
} /* CapiUt_EnterString */
    




/*
        enter the called party number at specified position
        ---------------------------------------------------
*/

unsigned char *CapiUt_EnterCalledPartyNumber
   (unsigned char *pOrgPos,
    const char    *pszNumber)
{
   char   *pDst = (char *) pOrgPos + 1;
   size_t  nLen = 0;
   
   /* check if a number is really specified */
   if (! pszNumber || ! pszNumber [0])
   {
      return (CapiUt_EnterEmptyStruct (pOrgPos));
   }
   
   /* the first byte is the type of number and numbering plan */
   *(pDst++) = 0x80;
   nLen++;
   
   /* copy the number string */
   while (*pszNumber)
   {
      *(pDst++) = *(pszNumber++);
      nLen++;
   }
   
   /* set the total length of the CAPI structure */
   *pOrgPos = (unsigned char) nLen;
   
   return (pDst);
} /* CapiUt_EnterCalledPartyNumber */
    




/*
        enter the calling party number at specified position
        ----------------------------------------------------
*/

unsigned char *CapiUt_EnterCallingPartyNumber
   (unsigned char *pOrgPos,
    const char    *pszNumber)
{
   char   *pDst = (char *) pOrgPos + 1;
   size_t  nLen = 0;
   
   /* check if a number is really specified */
   if (! pszNumber || ! pszNumber [0])
   {
      return (CapiUt_EnterEmptyStruct (pOrgPos));
   }
   
   /* the first byte is the type of number and numbering plan, the second is
    * the presentation and screening indicator
    */
   *(pDst++) = 0x0;
   *(pDst++) = 0x80;
   nLen += 2;
   
   /* copy the number string */
   while (*pszNumber)
   {
      *(pDst++) = *(pszNumber++);
      nLen++;
   }
   
   /* set the total length of the CAPI structure */
   *pOrgPos = (unsigned char) nLen;
   
   return (pDst);
} /* CapiUt_EnterCallingPartyNumber */





/* === definition of private functions =================================== */





