serial_port_export.c

来自「This is a resource based on j2me embedde」· C语言 代码 · 共 503 行

C
503
字号
/* *    * * Copyright  1990-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER *  * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation. *  * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is * included at /legal/license.txt). *  * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA *  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. *//*========================================================================= * SYSTEM:    KVM * SUBSYSTEM: networking * FILE:      commProtocol_md.c * OVERVIEW:  Operations to support serial communication ports *            on Unix (native Unix support for the 'comm:' protocol) * AUTHOR:     *=======================================================================*//*======================================================================= * Include files *=======================================================================*/#include <sys/types.h>#include <sys/stat.h>/* * Note: To use this file on UNIX System V platforms like Solaris *       remove the ioctl.h include */#include <sys/ioctl.h>#include <fcntl.h>#include <unistd.h>#include <errno.h>#include <termios.h>#include <string.h>#include <stdio.h>#include <midpServices.h>#include <serial_port_export.h>#include <midp_logging.h>#define DEVICE_PORT_PREFIX "/dev/ttyS"#define PORT_NUM_START_POS ((int)sizeof(DEVICE_PORT_PREFIX) - 1)/** * Converts the given logical port name into the platform-dependent name * of the device to open. * Note that only port with numbers from 1 to 9 are supported. * * @param pLogicalPortName logical name of the port, for example, COM1 * * @return pointer to a static buffer containing the platform-specific name *         of the port to open */static char*logical_port_name2device_port_name(const char* pLogicalPortName) {    static char pDevicePortName[] = DEVICE_PORT_PREFIX "xx";    int pos = PORT_NUM_START_POS;    while (*pLogicalPortName && pos < (int)(sizeof(pDevicePortName) - 1)) {        char ch = *pLogicalPortName++;        if (ch >= '1' && ch <= '9') {            pDevicePortName[pos++] = ch - 1;            break;        }    }    if (pos == PORT_NUM_START_POS) {        pDevicePortName[pos++] = '0';    }    pDevicePortName[pos] = 0;    return pDevicePortName;}#undef PORT_NUM_START_POS/** * Open a serial port by logical device name. * * @param pszDeviceName logical name of the port (for example, COM1) * @param baudRate baud rate to set the port at * @param options options for the serial port * bit 0: 0 - 1 stop bit, 1 - 2 stop bits  * bit 2-1: 00 - no parity, 01 - odd parity, 10 - even parity  * bit 4: 0 - no auto RTS, 1 - set auto RTS  * bit 5: 0 - no auto CTS, 1 - set auto CTS  * bit 7-6: 01 - 7 bits per symbol, 11 - 8 bits per symbol  * @param pHandle returns the connection handle; it is *        set only when this function returns PCSL_NET_SUCCESS * @param pContext filled by ptr to data for reinvocations * * @return PCSL_NET_SUCCESS for successful read operation;\n  *       PCSL_NET_WOULDBLOCK if the operation would block,\n  *       PCSL_NET_INTERRUPTED for an Interrupted IO Exception,\n *       PCSL_NET_IOERROR for all other errors */int openPortByNameStart(char* pszDeviceName, int baudRate,                    int options, int *pHandle, void **pContext) {    int hPort, openFlags;    /* Linux implementation never returns PCSL_NET_WOULDBLOCK */    (void)pContext;    /* do not become the controlling tty */    openFlags = O_RDWR | O_NOCTTY;    hPort = open(logical_port_name2device_port_name(pszDeviceName), openFlags);    if (hPort < 0) {        *pHandle = (int)INVALID_HANDLE;        return PCSL_NET_IOERROR;    }    /* Set exclusive use flag to block other open calls with EBUSY. */    ioctl(hPort, TIOCEXCL, 0);    if (configurePort(hPort, baudRate, options) != PCSL_NET_SUCCESS) {        close(hPort);        *pHandle = (int)INVALID_HANDLE;        return PCSL_NET_IOERROR;    }    *pHandle = hPort;    return PCSL_NET_SUCCESS;}/** * Open a serial port by system dependent device name. * * @param pszDeviceName device name of the port * @param baudRate baud rate to set the port at * @param options options for the serial port * bit 0: 0 - 1 stop bit, 1 - 2 stop bits  * bit 2-1: 00 - no parity, 01 - odd parity, 10 - even parity  * bit 4: 0 - no auto RTS, 1 - set auto RTS  * bit 5: 0 - no auto CTS, 1 - set auto CTS  * bit 7-6: 01 - 7 bits per symbol, 11 - 8 bits per symbol  * @param pHandle returns the connection handle; it is *        set only when this function returns PCSL_NET_SUCCESS * @param context ptr to data saved before sleeping * * @return PCSL_NET_SUCCESS for successful read operation;\n  *       PCSL_NET_WOULDBLOCK if the operation would block,\n  *       PCSL_NET_INTERRUPTED for an Interrupted IO Exception,\n *       PCSL_NET_IOERROR for all other errors */int openPortByNameFinish(char* pszDeviceName, int baudRate,    int options, int *pHandle, void *context) {    /*Do nothing*/    (void)pszDeviceName;    (void)baudRate;    (void)options;    (void)pHandle;    (void)context;    return PCSL_NET_IOERROR;}/** * Configure a serial port optional parameters. * * @param hPort port number * @param baudRate baudRate rate to set the port at * @param options options for the serial port: * bit 0: 0 - 1 stop bit, 1 - 2 stop bits  * bit 2-1: 00 - no parity, 01 - odd parity, 10 - even parity  * bit 4: 0 - no auto RTS, 1 - set auto RTS  * bit 5: 0 - no auto CTS, 1 - set auto CTS  * bit 7-6: 01 - 7 bits per symbol, 11 - 8 bits per symbol  * * @return PCSL_NET_SUCCESS for successful configure operation;\n  *       PCSL_NET_IOERROR for any error */int configurePort(int hPort, int baudRate, unsigned int options) {    struct termios attributes;    speed_t speed;    int linesToSet;    int flgs;    /* memset(&attributes, 0, sizeof (attributes)); */    tcgetattr(hPort, &attributes);    /* Raw input */    attributes.c_lflag &= ~(ICANON | ECHO | ISIG);    /* Raw output */    attributes.c_cflag |= CREAD | CLOCAL | HUPCL;    /* Don't make any CR/LF changes on input/output streams */    attributes.c_iflag &= ~INLCR;    attributes.c_iflag &= ~IGNCR;    attributes.c_iflag &= ~ICRNL;    attributes.c_iflag &= ~IXON;    attributes.c_oflag &= ~(ONLCR | OCRNL | ONOCR | ONLRET);    switch(baudRate) {    case 50:        speed = B50;        break;    case 75:        speed = B75;        break;    case 110:        speed = B110;        break;    case 134:        speed = B134;        break;    case 150:        speed = B150;        break;    case 200:        speed = B200;        break;    case 300:        speed = B300;        break;    case 600:        speed = B600;        break;    case 1200:        speed = B1200;        break;    case 1800:        speed = B1800;        break;    case 2400:        speed = B2400;        break;    case 4800:        speed = B4800;        break;    case 9600:        speed = B9600;        break;    case 19200:        speed = B19200;        break;    case 38400:        speed = B38400;        break;    case 57600:        speed = B57600;        break;    case 115200:        speed = B115200;        break;    default:        return PCSL_NET_IOERROR;    }    cfsetispeed(&attributes, speed);    cfsetospeed(&attributes, speed);    /* default no parity */    if (options & ODD_PARITY) {        attributes.c_cflag |= PARENB | PARODD;    } else if (options & EVEN_PARITY) {        attributes.c_cflag |= PARENB;    }    /* CTS output flow control */    if (options & AUTO_CTS) {        attributes.c_cflag |= CRTSCTS;    }    /* RTS flow control */    /*     * This option is no support on Linux but if this file is used     * on UNIX System V platform like Solaris then uncomment RTS option code.      *     * if (options & AUTO_RTS) {     *     attributes.c_cflag |= CRTSXOFF;     * }     */    /* BITS_PER_CHAR_8 is 2 bits and includes BITS_PER_CHAR_7 */    if ((options & BITS_PER_CHAR_8) == BITS_PER_CHAR_8) {        attributes.c_cflag |= CS8;    } else {        attributes.c_cflag |= CS7;    }    /* default 1 stop bit */    if (options & STOP_BITS_2) {        attributes.c_cflag |= CSTOPB;    }    /* set non blocking since we are not using async methods */    flgs = fcntl(hPort, F_GETFL, 0);    fcntl(hPort, F_SETFL, flgs | O_NONBLOCK);    /* no minimum amount of bytes, no secs */    attributes.c_cc[VMIN] = 0;    attributes.c_cc[VTIME] = 0;    if (tcsetattr(hPort, TCSANOW, &attributes) == -1) {        return PCSL_NET_IOERROR;    }    /* Make sure the Data Terminal Ready line is on */    linesToSet = TIOCM_DTR;    ioctl(hPort, TIOCMBIS, &linesToSet);    return PCSL_NET_SUCCESS;}/** * Close a serial port. * * @param hPort handle to a native serial port */void closePort(int hPort) {    close(hPort);}/** * Write to a serial port without blocking. * * @param hPort handle to a native serial port * @param pBuffer I/O buffer * @param nNumberOfBytesToWrite length of data * @param pBytesWritten returns the number of bytes written after *        successful write operation; only set if this function returns *        PCSL_NET_SUCCESS * @param pContext filled by ptr to data for reinvocations * * @return PCSL_NET_SUCCESS for successful write operation;\n  *       PCSL_NET_WOULDBLOCK if the operation would block,\n  *       PCSL_NET_INTERRUPTED for an Interrupted IO Exception\n  *       PCSL_NET_IOERROR for all other errors */int writeToPortStart(int hPort, char* pBuffer,        int nNumberOfBytesToWrite, int* pBytesWritten, void **pContext) {    int status = PCSL_NET_IOERROR;    /* Linux implementation never returns PCSL_NET_WOULDBLOCK */    (void)pContext;    if (nNumberOfBytesToWrite == 0) {        *pBytesWritten = 0;        status = PCSL_NET_SUCCESS;    } else {        int bytesWritten = write((int)hPort, pBuffer, nNumberOfBytesToWrite);        if (bytesWritten == -1) { /* error writing */            switch (errno) {                case EAGAIN: /* Write would block */                    /** IMPL_NOTE.                       * Function should return PCSL_NET_WOULDBLOCK                     * at this case. Will be implemented.                     */                    /* status = PCSL_NET_WOULDBLOCK; */                    *pBytesWritten = 0;                    status = PCSL_NET_SUCCESS;                    break;                case EINTR: /* Writing has been interrupted */                    status = PCSL_NET_INTERRUPTED;                    break;                default:                    status = PCSL_NET_IOERROR;            }        } else { /* Writing is correct */            *pBytesWritten = bytesWritten;            status = PCSL_NET_SUCCESS;        }    }    return status;}/** * Write to a serial port without blocking. * * @param hPort handle to a native serial port * @param pBuffer I/O buffer * @param nNumberOfBytesToWrite length of data * @param pBytesWritten returns the number of bytes written after *        successful write operation; only set if this function returns *        PCSL_NET_SUCCESS * @param context ptr to data saved before sleeping * * @return PCSL_NET_SUCCESS for successful write operation;\n  *       PCSL_NET_WOULDBLOCK if the operation would block,\n  *       PCSL_NET_INTERRUPTED for an Interrupted IO Exception\n  *       PCSL_NET_IOERROR for all other errors */int writeToPortFinish(int hPort, char* pBuffer,        int nNumberOfBytesToWrite, int* pBytesWritten, void *context) {    (void)context;    return writeToPortStart(hPort, pBuffer, nNumberOfBytesToWrite,        pBytesWritten, NULL);}/** * Read from a serial port. * * @param hPort handle to a native serial port * @param pBuffer I/O buffer * @param nNumberOfBytesToRead length of data * @param pBytesRead returns the number of bytes actually read; it is *        set only when this function returns PCSL_NET_SUCCESS * @param pContext filled by ptr to data for reinvocations * * @return PCSL_NET_SUCCESS for successful read operation;\n  *       PCSL_NET_WOULDBLOCK if the operation would block,\n  *       PCSL_NET_INTERRUPTED for an Interrupted IO Exception,\n *       PCSL_NET_IOERROR for all other errors */int readFromPortStart(int hPort, char* pBuffer,                 int nNumberOfBytesToRead, int* pBytesRead, void **pContext) {    int status = PCSL_NET_IOERROR;    /* Linux implementation never returns PCSL_NET_WOULDBLOCK */    (void)pContext;    if (nNumberOfBytesToRead == 0) {        *pBytesRead = 0;        status = PCSL_NET_SUCCESS;    } else {        int bytesRead = read((int)hPort, pBuffer, nNumberOfBytesToRead);        if (bytesRead == -1) { /* error reading */            switch (errno) {                case EAGAIN: /* No data available */                    /** IMPL_NOTE.                       * Function should return PCSL_NET_WOULDBLOCK                     * at this case. Will be implemented.                     */                    /* status = PCSL_NET_WOULDBLOCK; */                    *pBytesRead = 0;                    status = PCSL_NET_SUCCESS;                    break;                case EINTR: /* Reading has been interrupted */                    status = PCSL_NET_INTERRUPTED;                    break;                default:                    status = PCSL_NET_IOERROR;            }        } else { /* Reading is correct */            *pBytesRead = bytesRead;            status = PCSL_NET_SUCCESS;        }    }    return status;}/** * Read from a serial port. * * @param hPort handle to a native serial port * @param pBuffer I/O buffer * @param nNumberOfBytesToRead length of data * @param pBytesRead returns the number of bytes actually read; it is *        set only when this function returns PCSL_NET_SUCCESS * @param context ptr to data saved before sleeping * * @return PCSL_NET_SUCCESS for successful read operation;\n  *       PCSL_NET_WOULDBLOCK if the operation would block,\n  *       PCSL_NET_INTERRUPTED for an Interrupted IO Exception,\n *       PCSL_NET_IOERROR for all other errors */int readFromPortFinish(int hPort, char* pBuffer,     int nNumberOfBytesToRead, int* pBytesRead, void *context) {    (void)context;    return readFromPortStart(hPort, pBuffer, nNumberOfBytesToRead,        pBytesRead, NULL);}

⌨️ 快捷键说明

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