MakeCall with Device Specific data

May 22, 2013 at 12:27 AM
Hi

Can Atapi send Device Specific data on the MakeCall method of TapiLine?

I went through the source code and it seems that MakeCallParams.ProcessCallParams doesn't support it, but I'm not sure if I missed something.


Many thanks
João
Coordinator
May 22, 2013 at 4:47 PM
No, I don't think I ever ran into a TSP which had support for it so I don't think I ever added it into ATAPI. If you've got a candidate, it would be a great addition!

mark

May 23, 2013 at 12:26 AM
I'm trying to use a TSP for which I need to specify the Trunk (Private or Public) using the following devSpecific struct:
typedef struct _MakeCallSpecStruct
{
    DWORD dwStructSize; // Structure size
    DWORD dwDialCmd; // MAKECALL_DIALCMD_... command
    DWORD dwLineNum; // Target line number (MAKECALL_DIALCMD_LINE)
    DWORD dwNumSDN; // SDN number (MAKECALL_DIALCMD_SDN)
    DWORD dwSystemNum; // Target system number
    DWORD dwTrunkType; // MAKECALL_TRUNKTYPE_...
    char szNumbers[28]; // Reserved
} MakeCallSpecStruct, *PMakeCallSpecStruct;
I've already changed the struct to something I could use from the C# side:
[StructLayout(LayoutKind.Sequential)]
public class _MakeCallSpecStruct
{
    public uint dwStructSize; // Structure size
    public uint dwDialCmd; // MAKECALL_DIALCMD_... command
    public uint dwLineNum; // Target line number (MAKECALL_DIALCMD_LINE)
    public uint dwNumSDN; // SDN number (MAKECALL_DIALCMD_SDN)
    public uint dwSystemNum; // Target system number
    public uint dwTrunkType; // MAKECALL_TRUNKTYPE_...
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 28)]
    public char[] szNumbers; // Reserved
}
I've also added a "byte[] DeviceSpecific" property to MakeCallParams class and changed the ProcessCallParams. I looks like this:
public void TestMakeCallDevSpec(int addressId, int callFlags)
{
    var devSpec = new _MakeCallSpecStruct();
    devSpec.dwTrunkType = 2;
    devSpec.dwStructSize = (uint)Marshal.SizeOf(devSpec);

    MakeCallParams param = new MakeCallParams();
    param.DeviceSpecific = GetBytes(devSpec); // Added property to MakeCallParams

    ProcessCallParams(addressId, param, callFlags);
}

static internal IntPtr ProcessCallParams(int addressId, MakeCallParams param, int callFlags)
{
    IntPtr lpCp = IntPtr.Zero;

    if (param != null)
    {
        var lcp = new LINECALLPARAMS
          {
              dwBearerMode = (int) param.BearerMode,
              dwMinRate = param.MinRate,
              dwMaxRate = param.MaxRate,
              dwMediaMode = (int) param.MediaMode,
              dwCallParamFlags = callFlags
          };

        if (param.BlockCallerId)
            lcp.dwCallParamFlags |= NativeMethods.LINECALLPARAMFLAGS_BLOCKID;
        if (param.TakeDestinationOffhook)
            lcp.dwCallParamFlags |= NativeMethods.LINECALLPARAMFLAGS_DESTOFFHOOK;
        if (param.TakeOriginationOffhook)
            lcp.dwCallParamFlags |= NativeMethods.LINECALLPARAMFLAGS_ORIGOFFHOOK;
        if (param.OriginateOnIdleCall)
            lcp.dwCallParamFlags |= NativeMethods.LINECALLPARAMFLAGS_IDLE;
        if (param.WantSecureCall)
            lcp.dwCallParamFlags |= NativeMethods.LINECALLPARAMFLAGS_SECURE;
        if (param.WantPredictiveDialing)
            lcp.dwCallParamFlags |= NativeMethods.LINECALLPARAMFLAGS_PREDICTIVEDIAL;

        lcp.dwUserUserInfoSize = (param.UserUserInfo == null) ? 0 : param.UserUserInfo.Length;
        lcp.dwNoAnswerTimeout = param.NoAnswerTimeout;
        lcp.dwOrigAddressSize = String.IsNullOrEmpty(param.OriginationAddress) ? 0 : param.OriginationAddress.Length;
        lcp.dwTargetAddressSize = String.IsNullOrEmpty(param.TargetAddress) ? 0 : param.TargetAddress.Length;
        lcp.dwAddressMode = NativeMethods.LINEADDRESSMODE_ADDRESSID;
        lcp.dwAddressID = addressId;
        lcp.DialParams.dwDialPause = param.DialPause;
        lcp.DialParams.dwDialSpeed = param.DialSpeed;
        lcp.DialParams.dwDigitDuration = param.DigitDuration;
        lcp.DialParams.dwWaitForDialtone = param.WaitForDialtoneDuration;

        lcp.dwTotalSize = Marshal.SizeOf(lcp);
        if (lcp.dwUserUserInfoSize > 0)
        {
            lcp.dwUserUserInfoOffset = lcp.dwTotalSize;
            lcp.dwTotalSize += lcp.dwUserUserInfoSize;
        }
        if (lcp.dwOrigAddressSize > 0)
        {
            lcp.dwOrigAddressOffset = lcp.dwTotalSize;
            lcp.dwTotalSize += lcp.dwOrigAddressSize;
        }
        if (lcp.dwTargetAddressSize > 0)
        {
            lcp.dwTargetAddressOffset = lcp.dwTotalSize;
            lcp.dwTotalSize += lcp.dwTargetAddressSize;
        }

        // Added -----------------------------------------------------------------
        lcp.dwDevSpecificSize = (param.DeviceSpecific == null) ? 0 : param.DeviceSpecific.Length;
        if (lcp.dwDevSpecificSize > 0) 
        {
            lcp.dwDevSpecificOffset = lcp.dwTotalSize;
            lcp.dwTotalSize += lcp.dwDevSpecificSize;
        }
        // --------------------------------------------------------------------------
        
        lpCp = Marshal.AllocHGlobal(lcp.dwTotalSize);
        Marshal.StructureToPtr(lcp, lpCp, true);
        if (lcp.dwUserUserInfoSize > 0)
            NativeMethods.WriteByteArray(param.UserUserInfo, lpCp, lcp.dwUserUserInfoOffset);
        if (lcp.dwOrigAddressSize > 0 && param.OriginationAddress != null)
            NativeMethods.WriteByteArray(Encoding.Default.GetBytes(param.OriginationAddress), lpCp, lcp.dwOrigAddressOffset);
        if (lcp.dwTargetAddressSize > 0 && param.TargetAddress != null)
            NativeMethods.WriteByteArray(Encoding.Default.GetBytes(param.TargetAddress), lpCp, lcp.dwTargetAddressOffset);

        // Added -----------------------------------------------------------------
        if (lcp.dwDevSpecificSize > 0)
            NativeMethods.WriteByteArray(param.DeviceSpecific, lpCp, lcp.dwDevSpecificOffset);
        // --------------------------------------------------------------------------
    }

    return lpCp;
}
Tomorrow I will test it, do you think that it will work?
Coordinator
May 23, 2013 at 11:48 PM
Seems like it should. How did it work out?

Mark Smith

[email removed] | @marksm | 214-774-4749 | www.julmar.com/blog/mark



May 24, 2013 at 12:09 AM
I'm getting a [0x80000019] Invalid LINECALLPARAMS structure, still trying to figure it out why.