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

📄 unix_devs.c

📁 含有完整TCP/IP PPP协议的嵌入式操作系统
💻 C
📖 第 1 页 / 共 3 页
字号:
                break;            default:                return NULL;        }    } else        return NULL;    // check for sockets    // try to split "device name" into ip:port    if (strncmp("stdio", nativeName, 5)==0) {        ip = nativeName;        port = NULL;    } else {         ip = strtok( nativeName, ":");        port = strtok ( NULL, ":");    }    // printf("UnixDevOpen: Nut name = %s, unix name = %s\n",  dev->dev_name, nativeName);    // determine mode -- not implemented yet     // set default mode    mode = O_RDWR | O_NOCTTY;    // fopen unix device    if (strcmp("stdio", nativeName) == 0) {        nativeFile = STDOUT_FILENO;        // make raw        if (tcgetattr(nativeFile, &t) == 0) {            /* set input mode (non-canonical, no echo,...) but allow INTR signal */            // bzero(&t, sizeof(t));            t.c_lflag = ISIG;            t.c_cc[VTIME] = 0;  /* inter-character timer unused */            t.c_cc[VMIN] = 0;   /* non-blocking read */            // apply file descriptor options            if (tcsetattr(nativeFile, TCSANOW, &t) < 0) {                printf("UnixDevOpen: tcsetattr failed\n\r");            }            ((UNIXDCB*)dev->dev_dcb)->dcb_socket = 0;        }    } else if (port) {        // tcp/ip socket        remote_ip = resolve ( ip );        remote_port = atoi( port );                if ( (int) ip != -1) {                    NutEnterCritical();            // create socket            nativeFile = socket(AF_INET, SOCK_STREAM, 0);                        // set inbound address            sinaddr.sin_family = AF_INET;            sinaddr.sin_addr.s_addr = INADDR_ANY;            sinaddr.sin_port = htons(0);            // bind to socket            bind(nativeFile, (struct sockaddr *)&sinaddr, sizeof(sinaddr));                        // set remote address            remote.sin_family = AF_INET;            remote.sin_port = htons(remote_port);            remote.sin_addr.s_addr = remote_ip;                        // try to connect            if ( connect ( nativeFile, (struct sockaddr *)&remote, sizeof(remote) ) == 0) {                // connected                ((UNIXDCB*)dev->dev_dcb)->dcb_socket = 1;                            } else {                NutExitCritical();                printf( "UnixDevOpen: Connect to %s port %d failed (errno = %d)\n\r", ip, remote_port, errno);                return NULL;            }                    } else {            NutExitCritical();            printf("UnixDevOpen: Could not resolve IP address of '%s'!\n", ip);            return NULL;        }              } else {        nativeFile = open(nativeName, mode);                if (nativeFile < 0) {            printf("UnixDevOpen: open('%s',%d) failed!\n", nativeName, mode);            return NULL;        }                /* flush pending data*/        if (tcflush( nativeFile, TCIOFLUSH)) {            printf("UnixDevOpen: tcflush('%s',%d) failed!\n", nativeName, TCIOFLUSH);            return NULL;        }         if (tcgetattr(nativeFile, &t) == 0) {            baud = convertToBaudSpeed(USART_INITSPEED);            bzero(&t, sizeof(t));            t.c_cflag = CS8 | CLOCAL | CREAD;            t.c_iflag = IGNPAR;            t.c_oflag = 0;            cfsetospeed(&t, baud);            cfsetispeed(&t, baud);            /* set input mode (non-canonical, no echo,...) */            t.c_lflag = 0;            t.c_cc[VTIME] = 0;  /* inter-character timer unused */            t.c_cc[VMIN] = 0;   /* non-blocking read */            tcflush(nativeFile, TCIFLUSH);            // apply file descriptor options            if (tcsetattr(nativeFile, TCSANOW, &t) < 0) {                printf("UnixDevOpen: tcsetattr failed\n\r");            }        }        ((UNIXDCB*)dev->dev_dcb)->dcb_socket = 0;    }    if (nativeFile == 0)        return NULL;    // set non-blocking    if (fcntl(nativeFile, F_SETFL, O_NONBLOCK) < 0) {        printf("UnixDevOpen: fcntl O_NONBLOCK failed\n\r");    }    // store unix fd in dev    ((UNIXDCB*)dev->dev_dcb)->dcb_fd = nativeFile;    // printf("UnixDevOpen: %s, fd * %d\n\r", nativeName, nativeFile);    // printf("UnixDevOpen: stdout %d, stdin %d, stderr %d \n\r", fileno(stdin), fileno(stdout), fileno(stderr));    /* initialized rx IRQ handler -- not currently used (see UnixDevReadThread for more info on variants     if (dev->dev_name[4] == '0') {        NutRegisterIrqHandler(IRQ_UART0_RX, UnixDevRxIntr, dev);    } else    {        NutRegisterIrqHandler(IRQ_UART1_RX, UnixDevRxIntr, dev);    }    */            /* Initialize mutex and condition variable objects */    pthread_mutex_init(&unix_devs_mutex, NULL);    pthread_mutex_init(&((UNIXDCB*)dev->dev_dcb)->dcb_rx_mutex, NULL);    pthread_attr_init(&unix_devs_attr);    pthread_attr_setdetachstate(&unix_devs_attr, PTHREAD_CREATE_JOINABLE);    // unix_devs_cv init    pthread_cond_init(&unix_devs_cv, NULL);    pthread_cond_init( &((UNIXDCB*)dev->dev_dcb)->dcb_rx_trigger, NULL);    // get thread struct    thread = malloc(sizeof(pthread_t));    // lock mutex and start thread    pthread_mutex_lock(&unix_devs_mutex);    pthread_create(thread, &unix_devs_attr, UnixDevReadThread, dev);    // printf("UnixDevOpen: %s, waiting for UnixDevRead ack\n\r", nativeName);    // wait for ack    pthread_cond_wait(&unix_devs_cv, &unix_devs_mutex);    pthread_mutex_unlock(&unix_devs_mutex);    // printf("UnixDevOpen: %s, ack from UnixDevRead received\n\r", nativeName);    // create new NUTFILE using malloc    nf = malloc(sizeof(NUTFILE));    // enter data    nf->nf_next = 0;    nf->nf_dev = dev;    nf->nf_fcb = 0;    return nf;}/*! * \brief Blocking write bytes to file * * \return Number of characters sent. */static int UnixDevWrite(NUTFILE * nf, CONST void *buffer, int len){    int rc;    int remaining = len;    UNIXDCB * dcb = (UNIXDCB*) nf->nf_dev->dev_dcb;        /* flush ? */    if (len == 0)        return 0;            do {        rc = write(dcb->dcb_fd, buffer, remaining);        if (rc > 0) {            buffer += rc;            remaining -= rc;        }    } while (remaining > 0);    return len;} /*! * \brief Read bytes from file * * \return Number of characters read. */static int UnixDevRead(NUTFILE * nf, void *buffer, int len){    int newBytes;    int fd;    fd_set rfd_set;    int ret;    struct timeval timeout;    int rc = 0;    UNIXDCB * dcb = (UNIXDCB*) nf->nf_dev->dev_dcb;    // fd    fd = dcb->dcb_fd;    if (fd == STDOUT_FILENO)        fd = STDIN_FILENO;        // test for read len. len == 0 => flush fd    if (len == 0){        tcflush(fd, TCIFLUSH);        return 0;    }        // printf("UnixDevRead: called: len = %d\n\r",len);    timeout.tv_usec = 0;    timeout.tv_sec  = 0;    do {        // data available ?        FD_ZERO(&rfd_set);        FD_SET(fd, &rfd_set);        ret = select(fd + 1, &rfd_set, NULL, NULL, &timeout);              if (FD_ISSET(fd, &rfd_set) == 0) {            // no data available. let's block the nut way...            // printf("UnixDevRead(%s): no data ready, signaling read thread\n\r", nf->nf_dev->dev_name);            // prepared signaling            dcb->dcb_rx_rdy = 0;            // lock mutex and signal read thread            pthread_mutex_lock(&dcb->dcb_rx_mutex);            pthread_cond_signal(&dcb->dcb_rx_trigger);            pthread_mutex_unlock(&dcb->dcb_rx_mutex);            // printf("UnixDevRead(%s): no data ready, waiting for answer\n\r", nf->nf_dev->dev_name);            // wait for data to be ready            NutEventWait( &dcb->dcb_rx_rdy, dcb->dcb_rtimeout);            // printf("UnixDevRead(%s): got answer\n\r", nf->nf_dev->dev_name);        }        //  printf("UnixDevRead(%s): before read\n\r", nf->nf_dev->dev_name);        newBytes = read( fd, buffer, len);        // printf("UnixDevRead(%s): read some bytes. res = %d\n\r", nf->nf_dev->dev_name, newBytes);        /* error or timeout ? */        if (newBytes < 0) {            if (errno == EAGAIN) {                // timeout. No data available right now                // printf("UnixDevRead: no bytes available, trying again\n\r");                errno = 0;                continue;            } else {                printf("UnixDevRead: error %d occured, giving up\n\r", errno);                return newBytes;            }        } else            rc += newBytes;#ifdef UART_SETBLOCKREAD        // printf("UnixDevRead: UART_SETBLOCKREAD defined\n\r");        // check for blocking read: all bytes received        if ( (dcb->dcb_modeflags & USART_MF_BLOCKREAD) && (rc < len)) {            // printf("UnixDevRead: block read enabled, but not enough bytes read \n\r");            continue;        }#endif        // did we get one?        if (rc > 0)            break;    } while (1);    return rc;}/*!  * \brief Close ... * * \return Always 0. */static int UnixDevClose(NUTFILE * nf){    UNIXDCB * dcb = (UNIXDCB*) nf->nf_dev->dev_dcb;    if ( dcb->dcb_fd > STDERR_FILENO)        close( dcb->dcb_fd );    return 0;}/*! * \brief Perform USART control functions. * * This function is called by the ioctl() function of the C runtime * library. * * \param dev  Identifies the device that receives the device-control *             function. * \param req  Requested control function. May be set to one of the *             following constants: *             - \ref UART_SETSPEED *             - \ref UART_GETSPEED *             - \ref UART_SETDATABITS *             - \ref UART_GETDATABITS *             - \ref UART_SETSTOPBITS *             - \ref UART_GETSTOPBITS *             - \ref UART_SETPARITY *             - \ref UART_GETPARITY *             - \ref UART_SETFLOWCONTROL *             - \ref UART_GETFLOWCONTROL *               - \ref UART_SETBLOCKREAD *               - \ref UART_GETBLOCKREAD *               - \ref UART_SETSTATUS *               - \ref UART_GETSTATUS * \param conf Points to a buffer that contains any data required for *             the given control function or receives data from that *             function. * \return 0 on success, -1 otherwise. * * \warning Timeout values are given in milliseconds and are limited to  *          the granularity of the system timer. To disable timeout, *          set the parameter to NUT_WAIT_INFINITE. */int UnixDevIOCTL(NUTDEVICE * dev, int req, void *conf){    struct termios t;    u_long *lvp = (u_long *) conf;    u_long lv = *lvp;    UNIXDCB * dcb = (UNIXDCB*) dev->dev_dcb;        // printf("UnixDevIOCTL, native %x, req: %d, lv: %ld\n\r", dcb->dcb_fd , req, lv);    switch (req) {    case UART_SETSPEED:    case UART_SETFLOWCONTROL:    case UART_SETPARITY:    case UART_SETDATABITS:    case UART_SETSTOPBITS:        // ok on stdio        if ( dcb->dcb_fd <= STDERR_FILENO)            return 0;        // ok on sockets        if ( dcb->dcb_socket)            return 0;        if (tcgetattr( dcb->dcb_fd , &t)) {            printf("UnixDevIOCTL, tcgetattr failed\n\r");            return -1;        }        switch (req) {        case UART_SETSPEED:            lv = convertToBaudSpeed(lv);            cfsetospeed(&t, lv);            cfsetispeed(&t, lv);            break;        case UART_SETFLOWCONTROL:            switch (lv) {            case 0:                t.c_cflag &= ~CRTSCTS;                t.c_iflag &= ~(IXON | IXOFF | IXANY);                break;            case UART_HS_SOFT:                t.c_cflag &= ~CRTSCTS;                t.c_iflag |= (IXON | IXOFF | IXANY);                return -1;            case UART_HS_MODEM:                return -1;            case UART_HS_RTSCTS:                t.c_cflag |= CRTSCTS;                t.c_iflag &= ~(IXON | IXOFF | IXANY);

⌨️ 快捷键说明

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