commprotocol_md.c

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

C
561
字号
/* * @(#)commProtocol_md.c	1.13 06/10/10 *  * Copyright  1990-2008 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/Linux (native Unix support for the 'comm:' protocol) * AUTHOR:     *=======================================================================*//*======================================================================= * Include files *=======================================================================*/#define LINUX#include <sys/types.h>#include <sys/stat.h>#ifdef LINUX#include <sys/ioctl.h>#endif /* LINUX */#include <fcntl.h>#include <unistd.h>#include <errno.h>#include <termios.h>#include <string.h>#include <stdio.h>#include <commProtocol.h>#include "jni.h"#include "jni_util.h"/*======================================================================= * Definitions and declarations *=======================================================================*/static char* getLastErrorMsg(char* pHeader);/* non system errors */static char* COMM_BAD_PORTNUMBER = "Invalid port number";static char* COMM_BAD_BAUDRATE   = "Invalid baud rate";/*========================================================================= * Protocol implementation functions *=======================================================================*//*========================================================================= * FUNCTION:        freePortError * OVERVIEW:         * INTERFACE: *   parameters:    *pszError: Error message *   returns:       <nothing> *=======================================================================*/void freePortError(char* pszError) {}/*========================================================================= * FUNCTION:        openPortByNumber * OVERVIEW:        Opens a serial port from the specified port number. * INTERFACE: *   parameters:    **ppszError: Error message *                  port:        Port number *                  baudRate:    The speed of the connection. *                  options:     Options to be used for the port. *   returns:       The open port  *=======================================================================*/long openPortByNumber(char** ppszError, long port, long baudRate,                      long options) {    char* pFileName = NULL;    switch (port) {    case 0:        pFileName = "/dev/term/a";#ifdef LINUX        pFileName = "/dev/ttyS0";#endif        break;    case 1:        pFileName = "/dev/term/b";#ifdef LINUX        pFileName = "/dev/ttyS1";#endif        break;    default:      *ppszError = strdup(COMM_BAD_PORTNUMBER);      return -1;    }       return((long)openPortByName(ppszError, pFileName, baudRate, options));}/*========================================================================= * FUNCTION:        openPortByName * OVERVIEW:        Opens a serial port from a specified name ie "/dev/term/a". * INTERFACE: *   parameters:    **ppszError:    Error message *                  *pszDeviceName: Port number *                  baudRate:       The speed of the connection. *                  options:        Options to be used for the port. *   returns:       The open port *=======================================================================*/long openPortByName(char** ppszError, char* pszDeviceName, long baudRate,                    long  options) {    int hPort = 0;    int openFlags = 0;    /* Need to prepend /dev/ before the devicename, if it is not */    const char * prefix = "/dev/";    /* do not become the controlling tty */    openFlags = O_RDWR | O_NOCTTY;    if (strncmp(pszDeviceName, prefix, strlen(prefix)) != 0) {        char dest[strlen(pszDeviceName) + strlen(prefix) + 1];        strcpy(dest, prefix);        strcat(dest, pszDeviceName);        hPort = open(dest, openFlags);    } else {        hPort = open(pszDeviceName, openFlags);    }    if (hPort < 0) {      *ppszError = getLastErrorMsg("open failed");      printf("open failed: %s\n", *ppszError);      return -1;    }    /* Set exclusive use flag to block other open calls with EBUSY. */    //ioctl(hPort, TIOCEXCL, 0);    configurePort(ppszError, hPort, baudRate, options);    if (*ppszError != NULL) {        close(hPort);        return -1;    }    return (int)hPort;}/*========================================================================= * FUNCTION:        configurePort * OVERVIEW:        Configures the open serial port. * INTERFACE: *   parameters:    **ppszError:   Error message *                  hPort:         The port to be configured. *                  baudRate:      The speed of the connection. *                  options:       Options to be used for the port. *   returns:       <nothing> *=======================================================================*/void configurePort(char** ppszError, int hPort, long baudRate,                          unsigned long options) {    struct termios attributes;    speed_t speed;    int linesToSet;    int flgs;    memset(&attributes, 0, sizeof (attributes));    attributes.c_cflag = CREAD | HUPCL | CLOCAL;    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:        *ppszError = COMM_BAD_BAUDRATE;        return;    }    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;    }/*  The following is not supported by Linux */#ifndef LINUX    /* RTS flow control */    if (options & AUTO_RTS) {        /***attributes.c_cflag |= CRTSXOFF;***/    }#endif    /* 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 blocking since we are not using async methods */    flgs = fcntl(hPort, F_GETFL, 0);    //    fcntl(hPort, F_SETFL, flgs | O_NONBLOCK);    /* block for at least 1 character, but wait .1 secs */    attributes.c_cc[VMIN] = 1;    attributes.c_cc[VTIME] = 0;        if (tcsetattr(hPort, TCSANOW, &attributes) == -1) {      *ppszError = getLastErrorMsg("set attr failed");      return;    }    /* Make sure the Data Terminal Ready line is on */    linesToSet = TIOCM_DTR;    ioctl(hPort, TIOCMBIS, &linesToSet);    /* 6227981: set it to NULL only if the error string was previously allocated */    if (ppszError != NULL)        *ppszError = NULL;}/*========================================================================= * FUNCTION:        closePort * OVERVIEW:        Closes the open serial port. * INTERFACE: *   parameters:    hPort:  The open port. *   returns:       <nothing> *=======================================================================*/void closePort(long hPort) {    close((int)hPort);}/*========================================================================= * FUNCTION:        writeToPort * OVERVIEW:        Writes to the open port, without blocking * INTERFACE: *   parameters:    **ppszError:            Error message *                  hPort:                  The name of the port to write to. *                  *pBuffer:               The data to be written to the port. *                  nNumberOfBytesToWrite:  The number of bytes to write. *   returns:       The number of bytes written. *=======================================================================*/long writeToPort(char** ppszError, long hPort, char* pBuffer,                 long nNumberOfBytesToWrite) {    int nNumberOfBytesWritten = 0;    nNumberOfBytesWritten = write((int)hPort, pBuffer, nNumberOfBytesToWrite);    if (nNumberOfBytesWritten < 0) {        if (errno == EAGAIN) {            return 0;        }        *ppszError = getLastErrorMsg("write failed");        return -1;    }    *ppszError = NULL;    return nNumberOfBytesWritten;}/*========================================================================= * FUNCTION:        readFromPort * OVERVIEW:        reads from a serial port, with blocking * INTERFACE: *   parameters:    **ppszError:          Error message *                  hPort:                The name of the port to read from. *                  pBuffer:              The buffer to store the bytes read. *                  nNumberOfBytesToRead: The number of bytes to read. *   returns:       The number of bytes read. *=======================================================================*/long readFromPort(char** ppszError, long hPort, char* pBuffer,                 long nNumberOfBytesToRead) {    int nNumberOfBytesRead = 0;    nNumberOfBytesRead = read((int)hPort, pBuffer, nNumberOfBytesToRead);    if (nNumberOfBytesRead < 0) {      if (errno == EAGAIN) {	return 0;      }      *ppszError = getLastErrorMsg("read failed");      return -1;    }    *ppszError = NULL;    return nNumberOfBytesRead;}/*========================================================================= * FUNCTION:        getLastErrorMsg * OVERVIEW:        Returns the last error message. * INTERFACE: *   parameters:    *pHeader:  The message header. *   returns:       The error message. *=======================================================================*/static char* getLastErrorMsg(char* pHeader) {    int lastError;    char* pszError;    lastError = errno;    pszError = strerror(lastError);#if INCLUDEDEBUGCODE    printf("%s(%08.8X): ", pHeader, lastError);    puts(pszError);    #endif /* INCLUDEDEBUGCODE */    return pszError;}/************************ New JNI Functions ************************/JNIEXPORT void JNICALL Java_com_sun_cdc_io_j2me_comm_Protocol_native_1openByNumber(JNIEnv *env,							    jobject this,							    jint port,							    jint baud,							    jint flags){  char *errorMsg = NULL;  long portNum;  portNum = openPortByNumber(&errorMsg, (long)port, (long)baud,			(long)flags);}JNIEXPORT jint JNICALL Java_com_sun_cdc_io_j2me_comm_Protocol_native_1openByName(JNIEnv *env,							  jobject this,							  jstring name,							  jint baud,							  jint flags){  char *errorMsg = "okay";  long portNum;  char *portname;  char* pFileName = NULL;  pFileName = "/dev/ttyS0";         if (IS_NULL(name)) {    JNU_ThrowNullPointerException(env, "name is null");    return -1;    }  portname = (char *)JNU_GetStringPlatformChars(env, name, NULL);  portNum = openPortByName(&errorMsg, (char *)portname, (long)baud,                    (long)flags);  return(portNum);}JNIEXPORT void JNICALL  Java_com_sun_cdc_io_j2me_comm_Protocol_native_1configurePort(JNIEnv *env,							     jobject this,							     jint port,							     jint baud,							     jint flags){  char *errorMsg = NULL;  configurePort(&errorMsg, (long)port, (long)baud, (long)flags);}JNIEXPORT void JNICALL  Java_com_sun_cdc_io_j2me_comm_Protocol_native_1close(JNIEnv *env,						     jobject this,						     jint hPort){  closePort((long)hPort);}JNIEXPORT void JNICALL  Java_com_sun_cdc_io_j2me_comm_Protocol_registerCleanup(JNIEnv *env,						       jobject this){}static const jint BUFSIZE = 1024;JNIEXPORT jint JNICALL  Java_com_sun_cdc_io_j2me_comm_Protocol_native_1readBytes(JNIEnv *env,							 jobject this,							 jint hPort,							 jbyteArray bArray,							 jint off,							 jint len){    char *errorMsg = NULL;    jbyte b[BUFSIZE];    jint chunk = BUFSIZE;    jint bytesRead = BUFSIZE;    jint result = 0;    jint end = off + len;    for (; off < end && bytesRead == chunk; off += chunk) {        if (off + chunk > end) {            chunk = end - off;        }        bytesRead = readFromPort(&errorMsg, (long)hPort, (char *)b,                (long)chunk);                if (bytesRead > 0) {            result += bytesRead;            (*env)->SetByteArrayRegion(env, bArray, off, bytesRead, (jbyte *)b);        }    }    return(result);}JNIEXPORT jint JNICALL Java_com_sun_cdc_io_j2me_comm_Protocol_native_1writeBytes(JNIEnv *env,							  jobject this,							  jint hPort,							  jbyteArray bArray,							  jint off,							  jint len){    char *errorMsg = NULL;    jbyte b[BUFSIZE];    jint chunk = BUFSIZE;    jint bytesWritten = BUFSIZE;    jint result = 0;    jint end = off + len;    for (; off < end && bytesWritten == chunk; off += chunk) {        if (off + chunk > end) {            chunk = end - off;        }        (*env)->GetByteArrayRegion(env, bArray, off, chunk, b);        bytesWritten = writeToPort(&errorMsg, (long)hPort, (char *)b,                        (long)chunk);        if (bytesWritten > 0) {            result += bytesWritten;        }    }    return(result);}

⌨️ 快捷键说明

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