ppavel@26: /*
ppavel@26: This file is part of CanFestival, a library implementing CanOpen Stack.
ppavel@26: 
ppavel@26: Copyright (C): Edouard TISSERANT and Francis DUPIN
ppavel@26: 
ppavel@26: See COPYING file for copyrights details.
ppavel@26: 
ppavel@26: This library is free software; you can redistribute it and/or
ppavel@26: modify it under the terms of the GNU Lesser General Public
ppavel@26: License as published by the Free Software Foundation; either
ppavel@26: version 2.1 of the License, or (at your option) any later version.
ppavel@26: 
ppavel@26: This library is distributed in the hope that it will be useful,
ppavel@26: but WITHOUT ANY WARRANTY; without even the implied warranty of
ppavel@26: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
ppavel@26: Lesser General Public License for more details.
ppavel@26: 
ppavel@26: You should have received a copy of the GNU Lesser General Public
ppavel@26: License along with this library; if not, write to the Free Software
ppavel@26: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
ppavel@26: */
ppavel@26: 
ppavel@26: #include <stdio.h>
ppavel@26: #include <string.h>
ppavel@26: #include <errno.h>
ppavel@26: #include <fcntl.h>
ppavel@26: 
ppavel@26: #include "canmsg.h"
ppavel@26: #include "lincan.h"
ppavel@26: 
ppavel@26: #include "can_driver.h"
ppavel@26: 
ppavel@26: /*********functions which permit to communicate with the board****************/
etisserant@145: UNS8 canReceive_driver(CAN_HANDLE fd0, Message *m)
ppavel@26: {
ppavel@26:   int res;
ppavel@26:   struct canmsg_t canmsg;
ppavel@26: 
ppavel@26:   canmsg.flags = 0; /* Ensure standard receive, not required for LinCAN>=0.3.1 */
ppavel@26: 
ppavel@26:   do{
etisserant@145:     res = read(fd0,&canmsg,sizeof(canmsg_t));
ppavel@26:     if((res<0)&&(errno == -EAGAIN)) res = 0;
ppavel@26:   }while(res==0);
ppavel@26: 
ppavel@26:   if(res != sizeof(canmsg_t)) // No new message
ppavel@26:     return 1;
ppavel@26: 
ppavel@26:   if(canmsg.flags&MSG_EXT){
ppavel@26:     /* There is no mark for extended messages in CanFestival */;
ppavel@26:   }
ppavel@26: 
ppavel@26:   m->cob_id.w = canmsg.id;
ppavel@26:   m->len = canmsg.length;
ppavel@26:   if(canmsg.flags&MSG_RTR){
ppavel@26:     m->rtr = 1;
ppavel@26:   }else{
ppavel@26:     m->rtr = 0;
ppavel@26:     memcpy(m->data,canmsg.data,8);
ppavel@26:   }
ppavel@26: 
ppavel@26:   return 0;
ppavel@26: }
ppavel@26: 
ppavel@26: /***************************************************************************/
etisserant@145: UNS8 canSend_driver(CAN_HANDLE fd0, Message *m)
ppavel@26: {
ppavel@26:   int res;
ppavel@26:   struct canmsg_t canmsg;
ppavel@26: 
ppavel@26: 
ppavel@26:   canmsg.flags = 0;
ppavel@26:   canmsg.id = m->cob_id.w;
ppavel@26:   canmsg.length = m->len;
ppavel@26:   if(m->rtr){
ppavel@26:     canmsg.flags |= MSG_RTR;
ppavel@26:   }else{
ppavel@26:     memcpy(canmsg.data,m->data,8);
ppavel@26:   }
ppavel@26: 
ppavel@26:   if(canmsg.id >= 0x800){
ppavel@26:     canmsg.flags |= MSG_EXT;
ppavel@26:   }
ppavel@26: 
etisserant@145:   res = write(fd0,&canmsg,sizeof(canmsg_t));
ppavel@26:   if(res!=sizeof(canmsg_t))
ppavel@26:     return 1;
ppavel@26: 
ppavel@26:   return 0;
ppavel@26: }
ppavel@26: 
ppavel@26: /***************************************************************************/
ppavel@26: static const char lnx_can_dev_prefix[] = "/dev/can";
ppavel@26: 
etisserant@145: CAN_HANDLE canOpen_driver(s_BOARD *board)
ppavel@26: {
ppavel@26:   int name_len = strlen(board->busname);
ppavel@26:   int prefix_len = strlen(lnx_can_dev_prefix);
ppavel@26:   char dev_name[prefix_len+name_len+1];
ppavel@26:   int o_flags = 0;
ppavel@26:   CAN_HANDLE fd0;
ppavel@26: 
ppavel@26:   fd0=malloc(sizeof(*fd0));
ppavel@26:   if(fd0==NULL)
ppavel@26:     return NULL;
ppavel@26: 
ppavel@26:   /*o_flags = O_NONBLOCK;*/
ppavel@26: 
ppavel@26:   memcpy(dev_name,lnx_can_dev_prefix,prefix_len);
ppavel@26:   memcpy(dev_name+prefix_len,board->busname,name_len);
ppavel@26:   dev_name[prefix_len+name_len] = 0;
ppavel@26: 
etisserant@145:   fd0 = open(dev_name, O_RDWR|o_flags);
etisserant@145:   if(fd0 < 0){
ppavel@26:     fprintf(stderr,"!!! Board %s is unknown. See can_lincan.c\n", board->busname);
ppavel@26:     goto error_ret;
ppavel@26:   }
ppavel@26: 
ppavel@26:   return fd0;
ppavel@26: 
ppavel@26:  error_ret:
ppavel@26:   free(fd0);
ppavel@26:   return NULL;
ppavel@26: }
ppavel@26: 
ppavel@26: /***************************************************************************/
etisserant@145: int canClose_driver(CAN_HANDLE fd0)
ppavel@26: {
ppavel@26:   if(!fd0)
ppavel@26:     return 0;
etisserant@145:   close(fd0);
ppavel@26:   return 0;
ppavel@26: }