⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 comm.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * COPYRIGHT:       See COPYING in the top level directory
 * PROJECT:         ReactOS system libraries
 * FILE:            lib/kernel32/misc/comm.c
 * PURPOSE:         Comm functions
 * PROGRAMMER:      Ariadne ( ariadne@xs4all.nl)
 *                  modified from WINE [ Onno Hovers, (onno@stack.urc.tue.nl) ]
 *					Robert Dickenson (robd@mok.lvcom.com)
 *					Saveliy Tretiakov (saveliyt@mail.ru)
 *					Dmitry Philippov (shedon@mail.ru)
 * UPDATE HISTORY:
 *                  Created 01/11/98
 *                  RDD (30/09/2002) implemented many function bodies to call serial driver.
 *                  KJK (11/02/2003) implemented BuildCommDCB & BuildCommDCBAndTimeouts
 *                  ST  (21/03/2005) implemented GetCommProperties
 *                  ST  (24/03/2005) implemented ClearCommError. Corrected many functions.
 *                  ST  (05/04/2005) implemented CommConfigDialog
 *                  DP  (11/06/2005) implemented GetCommConfig
 *                  DP  (12/06/2005) implemented SetCommConfig
 *
 */

#include <k32.h>

#define NDEBUG
#include "../include/debug.h"

/* BUILDCOMMDCB & BUILDCOMMDCBANDTIMEOUTS */

/* TYPES */

/* Pointer to a callback that handles a particular parameter */
typedef BOOL (*COMMDCB_PARAM_CALLBACK)(DCB *, COMMTIMEOUTS *, BOOL *, LPWSTR *);

/* Symbolic flag of any length */
typedef struct _COMMDCB_PARAM_STRFLAG
{
    UNICODE_STRING String;
    ULONG_PTR Value;
} COMMDCB_PARAM_STRFLAG, *PCOMMDCB_PARAM_STRFLAG;

/* One char long symbolic flag */
typedef struct _COMMDCB_PARAM_CHARFLAG
{
    WCHAR Char;
    ULONG_PTR Value;
} COMMDCB_PARAM_CHARFLAG, *PCOMMDCB_PARAM_CHARFLAG;

/* MACROS */

/* Declare a parameter handler */
#define COMMDCB_PARAM_HANDLER(__P__) \
 BOOL COMMDCB_ ## __P__ ## Param \
 ( \
     DCB * Dcb, \
     COMMTIMEOUTS * Timeouts, \
     BOOL *StopBitsSet, \
     LPWSTR *StrTail \
 )

/* UTILITIES */
/*
 Lookup a string flag and return its numerical value. The flags array must be
 sorted - a dichotomycal search is performed
*/
static BOOL
COMMDCB_LookupStrFlag(PUNICODE_STRING Flag,
                      PCOMMDCB_PARAM_STRFLAG Flags,
                      int FlagCount,
                      PULONG_PTR Value)
{
    /* Lower and upper bound for dichotomycal search */
    int nLowerBound = 0;
    int nUpperBound = FlagCount - 1;

    do
    {
        LONG nComparison;
        /* pick the element in the middle of the area of interest as the pivot */
        int nCurFlag = nLowerBound + (nUpperBound - nLowerBound) / 2;

        /* compare the string with the pivot */
        nComparison = RtlCompareUnicodeString(Flag,
                                              &Flags[nCurFlag].String,
                                              TRUE);

        /* string is equal */
        if(nComparison == 0)
        {
            /* return the flag's value */
            *Value = Flags[nCurFlag].Value;

            /* success */
            return TRUE;
        }
        else if(nComparison < 0)
        {
            /*
             * restrict the search to the first half of the current slice, minus the pivot
             */
            nUpperBound = nCurFlag - 1;
        }
        else
        {
            /*
             * restrict the search to the second half of the current slice, minus the pivot
             */
            nLowerBound = nCurFlag + 1;
        }
    } while(nLowerBound <= nUpperBound);

    /* string not found: failure */
    return FALSE;
}

/* PARSERS */
/*
 Find the next character flag and return its numerical value. The flags array
 must be sorted - a dichotomycal search is performed
*/
static BOOL
COMMDCB_ParseCharFlag(LPWSTR *StrTail,
                      PCOMMDCB_PARAM_CHARFLAG Flags,
                      int FlagCount,
                      PULONG_PTR Value)
{
    /* Lower and upper bound for dichotomycal search */
    int nLowerBound = 0;
    int nUpperBound = FlagCount - 1;
    /* get the first character as the flag */
    WCHAR wcFlag = (*StrTail)[0];

    /* premature end of string, or the character is whitespace */
    if(!wcFlag || iswspace(wcFlag))
        return FALSE;

    /* uppercase the character for case-insensitive search */
    wcFlag = towupper(wcFlag);

    /* skip the character flag */
    (*StrTail)++;

    /* see COMMDCB_LookupStrFlag for a description of the algorithm */
    do
    {
        LONG nComparison;
        int nCurFlag = nLowerBound + (nUpperBound - nLowerBound) / 2;

        nComparison = wcFlag - towupper(Flags[nCurFlag].Char);

        if(nComparison == 0)
        {
            *Value = Flags[nCurFlag].Value;

            return TRUE;
        }
        else if(nComparison < 0)
        {
            nUpperBound = nCurFlag - 1;
        }
        else
        {
            nLowerBound = nCurFlag + 1;
        }
    } while(nUpperBound >= nLowerBound);

    /* flag not found: failure */
    return FALSE;
}

/*
 Find the next string flag and return its numerical value. The flags array must
 be sorted - a dichotomycal search is performed
*/
static BOOL
COMMDCB_ParseStrFlag(LPWSTR *StrTail,
                     PCOMMDCB_PARAM_STRFLAG Flags,
                     int FlagCount,
                     PULONG_PTR Value)
{
    LPWSTR pwcNewTail;
    UNICODE_STRING wstrFlag;

    /* scan the string until the first space character or the terminating null */
    for(pwcNewTail = *StrTail;
        pwcNewTail[0] && !iswspace(pwcNewTail[0]);
        pwcNewTail++);

    /* string flag empty */
    if(pwcNewTail == *StrTail)
        return FALSE;

    /* build the UNICODE_STRING description of the string flag */
    wstrFlag.Buffer = *StrTail;
    wstrFlag.Length = (pwcNewTail - *StrTail) * sizeof(WCHAR);
    wstrFlag.MaximumLength = wstrFlag.Length;

    /* skip the string flag */
    *StrTail = pwcNewTail;

    /* lookup the string flag's value and return it */
    return COMMDCB_LookupStrFlag(&wstrFlag, Flags, FlagCount, Value);
}

/*
 Parse a boolean value in the symbolic form on/off
*/
static BOOL
COMMDCB_ParseBool(LPWSTR *StrTail,
                  PBOOL Value)
{
    BOOL bRetVal;
    ULONG_PTR nValue;
    static COMMDCB_PARAM_STRFLAG a_BoolFlags[] = {
       { RTL_CONSTANT_STRING(L"off"), FALSE },
       { RTL_CONSTANT_STRING(L"on"),  TRUE }
    };

    /* try to recognize the next flag as a boolean */
    bRetVal = COMMDCB_ParseStrFlag(StrTail,
                                   a_BoolFlags,
                                   sizeof(a_BoolFlags) / sizeof(a_BoolFlags[0]),
                                   &nValue);


    if(!bRetVal)
        return FALSE;

    /* success */
    *Value = (nValue ? TRUE : FALSE);
    return TRUE;
}

/*
 Parse a decimal integer
*/
static BOOL
COMMDCB_ParseInt(LPWSTR *StrTail,
                 DWORD *Value)
{
    LPWSTR pwcPrevTail = *StrTail;
    DWORD nValue = wcstoul(*StrTail, StrTail, 10);

    /* no character was consumed: failure */
    if(pwcPrevTail == *StrTail)
        return FALSE;

    /* success */
    *Value = nValue;
    return TRUE;
}

/* PARAMETER HANDLERS */
/* baud= */
COMMDCB_PARAM_HANDLER(baud)
{
    DWORD nValue;

    (void)Timeouts;

    /* parse the baudrate */
    if(!COMMDCB_ParseInt(StrTail, &nValue))
        return FALSE;

    switch(nValue)
    {
        /* documented abbreviations */
        case 11:
            Dcb->BaudRate = 110;
            break;
        case 15:
            Dcb->BaudRate = 150;
            break;
        case 30:
            Dcb->BaudRate = 300;
            break;
        case 60:
            Dcb->BaudRate = 600;
            break;
        case 12:
            Dcb->BaudRate = 1200;
            break;
        case 24:
            Dcb->BaudRate = 2400;
            break;
        case 48:
            Dcb->BaudRate = 4800;
            break;
        case 96:
            Dcb->BaudRate = 9600;
            break;
        case 19:
            Dcb->BaudRate = 19200;
            break;

        /* literal value */
        default:
            Dcb->BaudRate = nValue;
            break;
    }

    /* if the stop bits haven't been specified explicitely */
    if(!(*StopBitsSet))
    {
        /* default the stop bits to 2 for 110 baud */
        if(Dcb->BaudRate == 110)
            Dcb->StopBits = TWOSTOPBITS;
        /* else, default the stop bits to 1 */
        else
            Dcb->StopBits = ONESTOPBIT;
    }

    /* success */
    return TRUE;
}

/* data= */
COMMDCB_PARAM_HANDLER(data)
{
    DWORD nValue;

    (void)Timeouts;
    (void)StopBitsSet;

    /* parse the data bits */
    if(!COMMDCB_ParseInt(StrTail, &nValue))
        return FALSE;

    /* value out of range: failure */
    if(nValue < 5 || nValue > 8)
        return FALSE;

    /* success */
    Dcb->ByteSize = nValue;
    return TRUE;
}

/* dtr= */
COMMDCB_PARAM_HANDLER(dtr)
{
    BOOL bRetVal;
    ULONG_PTR nValue;
    static COMMDCB_PARAM_STRFLAG a_DTRFlags[] = {
        { RTL_CONSTANT_STRING(L"hs"),  DTR_CONTROL_HANDSHAKE },
        { RTL_CONSTANT_STRING(L"off"), DTR_CONTROL_DISABLE },
        { RTL_CONSTANT_STRING(L"on"),  DTR_CONTROL_ENABLE }
    };

    (void)Timeouts;
    (void)StopBitsSet;

    /* parse the flag */
    bRetVal = COMMDCB_ParseStrFlag(StrTail,
                                   a_DTRFlags,
                                   sizeof(a_DTRFlags) / sizeof(a_DTRFlags[0]),
                                   &nValue);

    /* failure */
    if(!bRetVal)
        return FALSE;

    /* success */
    Dcb->fDtrControl = nValue;
    return TRUE;
}

/* idsr= */
COMMDCB_PARAM_HANDLER(idsr)
{
    BOOL bValue;

    (void)Timeouts;
    (void)StopBitsSet;

    /* parse the flag */
    if(!COMMDCB_ParseBool(StrTail, &bValue))
       return FALSE;

    /* success */
    Dcb->fDsrSensitivity = bValue;
    return TRUE;
}

/* octs= */
COMMDCB_PARAM_HANDLER(octs)
{
    BOOL bValue;

    (void)Timeouts;
    (void)StopBitsSet;

    /* parse the flag */
    if(!COMMDCB_ParseBool(StrTail, &bValue))
        return FALSE;

    /* success */
    Dcb->fOutxCtsFlow = bValue;
    return TRUE;
}

/* odsr= */
COMMDCB_PARAM_HANDLER(odsr)
{
    BOOL bValue;

    (void)Timeouts;
    (void)StopBitsSet;

    /* parse the flag */
    if(!COMMDCB_ParseBool(StrTail, &bValue))
        return FALSE;

    /* success */
    Dcb->fOutxDsrFlow = bValue;
    return TRUE;
}

/* parity= */
COMMDCB_PARAM_HANDLER(parity)
{
    BOOL bRetVal;
    ULONG_PTR nValue;
    static COMMDCB_PARAM_CHARFLAG a_ParityFlags[] = {
        { L'e', EVENPARITY },
        { L'm', MARKPARITY },
        { L'n', NOPARITY },
        { L'o', ODDPARITY },
        { L's', SPACEPARITY }
    };

    (void)Timeouts;
    (void)StopBitsSet;

    /* parse the flag */
    bRetVal = COMMDCB_ParseCharFlag(StrTail,
                                    a_ParityFlags,
                                    sizeof(a_ParityFlags) / sizeof(a_ParityFlags[0]),
                                    &nValue);

    /* failure */
    if(!bRetVal)
        return FALSE;

    /* success */
    Dcb->Parity = nValue;
    return TRUE;
}

/* rts= */
COMMDCB_PARAM_HANDLER(rts)
{
    DWORD nRetVal;
    ULONG_PTR nValue;
    static COMMDCB_PARAM_STRFLAG a_RTSFlags[] = {
        { RTL_CONSTANT_STRING(L"hs"),  RTS_CONTROL_HANDSHAKE },
        { RTL_CONSTANT_STRING(L"off"), RTS_CONTROL_DISABLE },
        { RTL_CONSTANT_STRING(L"on"),  RTS_CONTROL_ENABLE },
        { RTL_CONSTANT_STRING(L"tg"),  RTS_CONTROL_TOGGLE }
    };

    (void)Timeouts;
    (void)StopBitsSet;

    /* parse the flag */
    nRetVal = COMMDCB_ParseStrFlag(StrTail,
                                   a_RTSFlags,
                                   sizeof(a_RTSFlags) / sizeof(a_RTSFlags[0]),
                                   &nValue);

    /* failure */
    if(!nRetVal)
        return FALSE;

    /* success */
    Dcb->fRtsControl = nValue;
    return TRUE;
}

/* stop= */
COMMDCB_PARAM_HANDLER(stop)
{
    BOOL bRetVal;
    ULONG_PTR nValue;
    static COMMDCB_PARAM_STRFLAG a_StopFlags[] = {
        { RTL_CONSTANT_STRING(L"1"),   ONESTOPBIT },
        { RTL_CONSTANT_STRING(L"1.5"), ONE5STOPBITS },
        { RTL_CONSTANT_STRING(L"2"),   TWOSTOPBITS }
    };

    (void)Timeouts;

    /* parse the flag */
    bRetVal = COMMDCB_ParseStrFlag(StrTail,
                                   a_StopFlags,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -