📄 unix_devs.c
字号:
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 + -