| | |
| | | * |
| | | * Filename: cp_comport.c |
| | | * Description: It's the comport operate library. |
| | | * |
| | | * |
| | | * Version: 2.0.0(10/17/2018~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "10/17/2018 03:33:25 PM" |
| | | * |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #include "comport.h" |
| | |
| | | |
| | | |
| | | |
| | | /* |
| | | /* |
| | | * description: Open the serial port |
| | | * |
| | | * input args: $comport: corresponding comport point |
| | | * input args: $comport: corresponding comport point |
| | | * $dev_name: The comport device name path, such as '/dev/ttyS3' |
| | | * $baudrate: The baudrate, such as 115200 |
| | | * $settings: The databit,parity,stopbit,flowctrl settings, such as '8N1N' |
| | |
| | | goto CleanUp; |
| | | } |
| | | } |
| | | else |
| | | else |
| | | { |
| | | rv = -5; |
| | | goto CleanUp; |
| | |
| | | |
| | | if (0 != tcgetattr(comport->fd, &old_cfg)) |
| | | { |
| | | rv = -6; // Failed to get Com settings |
| | | rv = -6; // Failed to get Com settings |
| | | goto CleanUp; |
| | | } |
| | | |
| | |
| | | /* Set the parity */ |
| | | switch (comport->parity) |
| | | { |
| | | case 0x01: // Odd |
| | | case 0x01: // Odd |
| | | new_cfg.c_cflag |= (PARENB | PARODD); |
| | | new_cfg.c_cflag |= (INPCK | ISTRIP); |
| | | break; |
| | | case 0x02: // Even |
| | | case 0x02: // Even |
| | | new_cfg.c_cflag |= PARENB; |
| | | new_cfg.c_cflag &= ~PARODD;; |
| | | new_cfg.c_cflag |= (INPCK | ISTRIP); |
| | |
| | | /* Set flow control */ |
| | | switch (comport->flowctrl) |
| | | { |
| | | case 1: // Software control |
| | | case 1: // Software control |
| | | case 3: |
| | | new_cfg.c_cflag &= ~(CRTSCTS); |
| | | new_cfg.c_iflag |= (IXON | IXOFF); |
| | |
| | | tcflush(comport->fd, TCIFLUSH); |
| | | if (0 != tcsetattr(comport->fd, TCSANOW, &new_cfg)) |
| | | { |
| | | rv = -7; // Failed to set device com port settings |
| | | rv = -7; // Failed to set device com port settings |
| | | goto CleanUp; |
| | | } |
| | | |
| | |
| | | |
| | | |
| | | /* |
| | | * description: close comport |
| | | * input args: $comport: corresponding comport point |
| | | * description: close comport |
| | | * input args: $comport: corresponding comport point |
| | | */ |
| | | |
| | | void comport_close(comport_t *comport) |
| | |
| | | int comport_send(comport_t *comport, char *buf, int send_bytes) |
| | | { |
| | | int rv = 0; |
| | | char *ptr, *end; |
| | | char *ptr, left_bytes; |
| | | int send = 0; |
| | | |
| | | if ( !comport || !buf || send_bytes<=0 ) |
| | |
| | | |
| | | //printf("Send %s with %d bytes.\n", buf, send_bytes); |
| | | |
| | | // Large data, then slice them and send |
| | | if (comport->frag_size < send_bytes) |
| | | { |
| | | ptr = buf; |
| | | end = buf + send_bytes; |
| | | |
| | | do |
| | | { |
| | | // Large than frag_size |
| | | if (comport->frag_size < (end - ptr)) |
| | | { |
| | | send = write(comport->fd, ptr, comport->frag_size); |
| | | if (0 >= send || comport->frag_size != send) |
| | | { |
| | | rv = -4; |
| | | goto CleanUp; |
| | | } |
| | | ptr += comport->frag_size; |
| | | } |
| | | else // Less than frag_size, maybe last fragmention. |
| | | { |
| | | send = write(comport->fd, ptr, (end - ptr)); |
| | | if (0 >= send || (end - ptr) != send) |
| | | { |
| | | rv = -4; |
| | | goto CleanUp; |
| | | } |
| | | ptr += (end - ptr); |
| | | } |
| | | } |
| | | while (ptr < end); |
| | | } |
| | | else // The send data is not large than a fragmention. |
| | | left_bytes = send_bytes; |
| | | ptr = buf; |
| | | |
| | | while( left_bytes > 0 ) |
| | | { |
| | | send = write(comport->fd, buf, send_bytes); |
| | | if (0 >= send || send_bytes != send) |
| | | { |
| | | rv = -5; |
| | | goto CleanUp; |
| | | } |
| | | /* Large data, then slice them to frag and send */ |
| | | send = left_bytes>comport->frag_size ? comport->frag_size : left_bytes; |
| | | |
| | | rv = write(comport->fd, ptr, send); |
| | | if( rv<0 ) |
| | | { |
| | | rv = -4; |
| | | goto CleanUp; |
| | | } |
| | | |
| | | left_bytes -= rv; |
| | | ptr += rv; |
| | | } |
| | | |
| | | rv = 0; |
| | | |
| | | CleanUp: |
| | | return rv; |
| | |
| | | iRet = select(comport->fd + 1, &rdfds, 0, &exfds, &stTime); |
| | | if (0 == iRet) |
| | | { |
| | | rv = 0; |
| | | rv = 0; |
| | | goto CleanUp; |
| | | } |
| | | else if (0 < iRet) |
| | | { |
| | | if (0 != FD_ISSET(comport->fd, &exfds)) |
| | | { |
| | | rv = -6; |
| | | rv = -6; |
| | | COM_PRINT("Error checking recv status.\n"); |
| | | goto CleanUp; |
| | | } |
| | | |
| | | if (0 == FD_ISSET(comport->fd, &rdfds)) |
| | | { |
| | | rv = 0; |
| | | rv = 0; |
| | | COM_PRINT("No incoming data.\n"); |
| | | goto CleanUp; |
| | | } |
| | |
| | | if (EINTR == errno) |
| | | { |
| | | COM_PRINT("catch interrupt signal.\n"); |
| | | rv = 0; |
| | | rv = 0; |
| | | } |
| | | else |
| | | { |
| | | COM_PRINT("Check recv status failure.\n"); |
| | | rv = -7; |
| | | rv = -7; |
| | | } |
| | | |
| | | goto CleanUp; |
| | |
| | | /************************************************************************************** |
| | | * Description: Set the comport databit,parity,stopbit,flowctrl into the comport structure |
| | | * Input Args: comport: the comport_t pointer |
| | | * settings: The databit/parity/stopbit/flowctrl settings as like "8N1N" |
| | | * settings: The databit/parity/stopbit/flowctrl settings as like "8N1N" |
| | | * Output Args: NONE |
| | | * Return Value: NONE |
| | | *************************************************************************************/ |