etisserant@448: /* etisserant@448: This file is part of CanFestival, a library implementing CanOpen Stack. etisserant@448: etisserant@448: Copyright (C): Edouard TISSERANT and Francis DUPIN etisserant@448: etisserant@448: Ruthlessly butchered by James Steward to produce a serial (tty) port etisserant@448: driver. etisserant@448: etisserant@448: See COPYING file for copyrights details. etisserant@448: etisserant@448: This library is free software; you can redistribute it and/or etisserant@448: modify it under the terms of the GNU Lesser General Public etisserant@448: License as published by the Free Software Foundation; either etisserant@448: version 2.1 of the License, or (at your option) any later version. etisserant@448: etisserant@448: This library is distributed in the hope that it will be useful, etisserant@448: but WITHOUT ANY WARRANTY; without even the implied warranty of etisserant@448: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU etisserant@448: Lesser General Public License for more details. etisserant@448: etisserant@448: You should have received a copy of the GNU Lesser General Public etisserant@448: License along with this library; if not, write to the Free Software etisserant@448: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA etisserant@448: */ etisserant@448: etisserant@448: /* etisserant@448: Single serial port CAN driver. etisserant@448: */ etisserant@448: etisserant@448: #include etisserant@448: #include etisserant@448: #include etisserant@448: #include etisserant@448: #include etisserant@448: #include etisserant@448: #include etisserant@448: etisserant@448: #define NEED_PRINT_MESSAGE etisserant@448: #include "can_driver.h" etisserant@448: #include "def.h" etisserant@448: etisserant@448: typedef struct { etisserant@448: int fd; etisserant@448: struct termios old_termio, new_termio; etisserant@448: } CANPort; etisserant@448: etisserant@448: /*********functions which permit to communicate with the board****************/ etisserant@448: UNS8 canReceive_driver(CAN_HANDLE fd0, Message * m) etisserant@448: { etisserant@448: int rv, N, n = 0; etisserant@448: fd_set rfds; etisserant@448: struct timeval tv; etisserant@448: etisserant@448: N = 4; //initially try to read 4 bytes, including the length byte etisserant@448: etisserant@448: retry: etisserant@448: rv = read(((CANPort *) fd0)->fd, &((char *)m)[n], N - n); etisserant@448: etisserant@448: if (rv == -1) { etisserant@448: fprintf(stderr, "read: %s\n", strerror(errno)); etisserant@448: return 1; etisserant@448: } etisserant@448: etisserant@448: n += rv; etisserant@448: etisserant@448: if (n == 4) { etisserant@448: N = (4 + m->len); etisserant@448: etisserant@448: if (m->len > 8) { etisserant@448: fprintf(stderr, "Warning: invalid message length %d\n", etisserant@448: m->len); etisserant@448: etisserant@448: //try to resync etisserant@448: n = 0; etisserant@448: N = 4; etisserant@448: } etisserant@448: etisserant@448: } etisserant@448: etisserant@448: if (n < N) { etisserant@448: etisserant@448: FD_ZERO(&rfds); etisserant@448: FD_SET(((CANPort *) fd0)->fd, &rfds); etisserant@448: etisserant@448: tv.tv_sec = 0; etisserant@448: tv.tv_usec=100000; etisserant@448: etisserant@448: rv = select(((CANPort *) fd0)->fd + 1, &rfds, NULL, NULL, &tv); etisserant@448: if (rv == -1) { etisserant@448: fprintf(stderr, "select: %s\n", strerror(errno)); etisserant@448: return 1; etisserant@448: } else if (rv == 0) { etisserant@448: n = 0; etisserant@448: } etisserant@448: etisserant@448: goto retry; etisserant@448: } etisserant@448: etisserant@448: print_message(m); etisserant@448: etisserant@448: return 0; etisserant@448: } etisserant@448: etisserant@448: /***************************************************************************/ edouard@631: UNS8 canSend_driver(CAN_HANDLE fd0, Message const * m) etisserant@448: { etisserant@448: int rv; etisserant@448: etisserant@448: print_message(m); etisserant@448: etisserant@448: // Send to serial port etisserant@448: rv = write(((CANPort *) fd0)->fd, m, 4 + m->len); etisserant@448: etisserant@448: if (rv != 4 + m->len) { etisserant@448: return 1; etisserant@448: } etisserant@448: etisserant@448: return 0; etisserant@448: } etisserant@448: etisserant@448: /***************************************************************************/ etisserant@448: int TranslateBaudRate(char *optarg) etisserant@448: { etisserant@448: if (!strcmp(optarg, "1M")) etisserant@448: return (int) 1000; etisserant@448: if (!strcmp(optarg, "500K")) etisserant@448: return (int) 500; etisserant@448: if (!strcmp(optarg, "250K")) etisserant@448: return (int) 250; etisserant@448: if (!strcmp(optarg, "125K")) etisserant@448: return (int) 125; etisserant@448: if (!strcmp(optarg, "100K")) etisserant@448: return (int) 100; etisserant@448: if (!strcmp(optarg, "50K")) etisserant@448: return (int) 50; etisserant@448: if (!strcmp(optarg, "20K")) etisserant@448: return (int) 20; etisserant@448: if (!strcmp(optarg, "10K")) etisserant@448: return (int) 10; etisserant@448: if (!strcmp(optarg, "5K")) etisserant@448: return (int) 5; etisserant@448: if (!strcmp(optarg, "none")) etisserant@448: return 0; etisserant@448: return 0x0000; etisserant@448: } etisserant@448: etisserant@448: UNS8 canChangeBaudRate_driver(CAN_HANDLE fd0, char *baud) etisserant@448: { etisserant@448: printf("Faked changing to baud rate %s[%d]\n", etisserant@448: baud, TranslateBaudRate(baud)); etisserant@448: return 0; etisserant@448: } etisserant@448: etisserant@448: /***************************************************************************/ etisserant@448: CAN_HANDLE canOpen_driver(s_BOARD * board) etisserant@448: { etisserant@448: int rv; etisserant@448: etisserant@448: CANPort *p; etisserant@448: etisserant@448: p = (CANPort *)calloc(1, sizeof(CANPort)); etisserant@448: etisserant@448: if (p == NULL) { etisserant@448: fprintf(stderr, "calloc: %s\n", strerror(errno)); etisserant@448: return (CAN_HANDLE) NULL; etisserant@448: } etisserant@448: etisserant@448: p->fd = open(board->busname, O_RDWR); etisserant@448: etisserant@448: if (p->fd < 0) { etisserant@448: fprintf(stderr, "open: %s, %s\n", etisserant@448: board->busname, strerror(errno)); etisserant@448: free(p); etisserant@448: return (CAN_HANDLE) NULL; etisserant@448: } etisserant@448: etisserant@448: if (tcgetattr(p->fd, &p->old_termio) != 0) { etisserant@448: fprintf(stderr, "tcgetattr: %s, %s\n", etisserant@448: board->busname, strerror(errno)); etisserant@448: close(p->fd); etisserant@448: free(p); etisserant@448: return (CAN_HANDLE) NULL; etisserant@448: } etisserant@448: etisserant@448: memcpy(&p->new_termio, &p->old_termio, etisserant@448: sizeof(p->old_termio)); etisserant@448: cfmakeraw(&p->new_termio); etisserant@448: cfsetispeed(&p->new_termio, B115200); etisserant@448: cfsetospeed(&p->new_termio, B115200); etisserant@448: tcsetattr(p->fd, TCSANOW, &p->new_termio); etisserant@448: etisserant@448: return (CAN_HANDLE) p; etisserant@448: } etisserant@448: etisserant@448: /***************************************************************************/ etisserant@448: int canClose_driver(CAN_HANDLE fd0) etisserant@448: { etisserant@448: if ((CANPort *) fd0 && ((CANPort *) fd0)->fd >= 0) { etisserant@448: tcsetattr(((CANPort *) fd0)->fd, TCSANOW, etisserant@448: &((CANPort *) fd0)->old_termio); etisserant@448: close(((CANPort *) fd0)->fd); etisserant@448: free((CANPort *) fd0); etisserant@448: } etisserant@448: etisserant@448: return 0; etisserant@448: } etisserant@448: etisserant@448: int canfd_driver(CAN_HANDLE fd0) etisserant@448: { etisserant@448: if ((CANPort *) fd0) { etisserant@448: return ((CANPort *) fd0)->fd; etisserant@448: } etisserant@448: etisserant@448: return -1; etisserant@448: } etisserant@448: