drivers/can_kvaser/can_kvaser.c
changeset 400 7d845f5d730c
child 631 08b6b903f84a
equal deleted inserted replaced
399:8d22c323fe0f 400:7d845f5d730c
       
     1 
       
     2 /*
       
     3 Copyright (C): Giuseppe Massimo BERTANI
       
     4 gmbertani@users.sourceforge.net
       
     5 
       
     6 
       
     7 See COPYING file for copyrights details.
       
     8 
       
     9 This library is free software; you can redistribute it and/or
       
    10 modify it under the terms of the GNU Lesser General Public
       
    11 License as published by the Free Software Foundation; either
       
    12 version 2.1 of the License, or (at your option) any later version.
       
    13 
       
    14 This library is distributed in the hope that it will be useful,
       
    15 but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    17 Lesser General Public License for more details.
       
    18 
       
    19 You should have received a copy of the GNU Lesser General Public
       
    20 License along with this library; if not, write to the Free Software
       
    21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
       
    22 */
       
    23 
       
    24 /**
       
    25  * @file can_kvaser.c
       
    26  * @author GMB
       
    27  * @date 17/1/08
       
    28  *
       
    29  * This file is needed to interface Kvaser's CAN Leaf (USB-CAN adapter) 
       
    30  * and probably others Kvaser's products compatible with Kvaser's CANLIB,
       
    31  * to CANfestival open source CANopen stack.
       
    32  *
       
    33  * It was tested under Linux 2.6 with "Leaf Professional" and CANLIB 4.72 Beta (Oct 1,2007)
       
    34 */
       
    35 
       
    36 #include <stdio.h>
       
    37 #include <string.h>
       
    38 #include <errno.h>
       
    39 #include <fcntl.h>
       
    40 #include <signal.h>
       
    41 #include <unistd.h>
       
    42 
       
    43 /* includes Kvaser's CANLIB header */
       
    44 #include <canlib.h>
       
    45 
       
    46 #include "can_driver.h"
       
    47  
       
    48     
       
    49 /**
       
    50  * CAN_HANDLES must have value >=1 while CANLIB wants handles >= 0
       
    51  * so fd0 needs to be decremented before use.
       
    52  *
       
    53  */ 
       
    54 UNS8 canReceive_driver(CAN_HANDLE fd0, Message *m)
       
    55 {
       
    56 canStatus retval = canOK;
       
    57 unsigned flags = 0;
       
    58 unsigned long timeStamp;
       
    59 
       
    60     fd0--;
       
    61 
       
    62     /* checking for input message (blocking) */
       
    63     retval = canReadWait((int)fd0, (long*)&m->cob_id, &m->data, (unsigned*)&m->len, &flags, &timeStamp, -1);
       
    64     if (retval != canOK)
       
    65     {
       
    66   	    fprintf(stderr, "canReceive_driver (Kvaser) : canReadWait() error, cob_id=%08X, len=%u, flags=%08X, returned value = %d\n", 
       
    67                 m->cob_id, m->len, flags, retval);
       
    68         canClose((int)fd0);
       
    69         return retval;
       
    70     }
       
    71 
       
    72     m->rtr = 0;
       
    73     if (flags & canMSG_RTR)
       
    74     {
       
    75         m->rtr = 1;
       
    76     }
       
    77 
       
    78     if (flags & canMSG_EXT)
       
    79     {
       
    80         /* TODO: is it correct to set this info in cob_id? */
       
    81         m->cob_id |= 0x20000000;
       
    82     }
       
    83     
       
    84     //fprintf(stderr, "canReceive_driver (Kvaser) : canReadWait() received packet, cob_id=%08X, len=%u, flags=%08X, timestamp=%d  returned value = %d\n", 
       
    85     //       m->cob_id, m->len, flags, timeStamp, retval);
       
    86 
       
    87     return retval;
       
    88 }
       
    89 
       
    90 /**
       
    91  *
       
    92  * CAN_HANDLES must have value >=1 while CANLIB wants handles >= 0
       
    93  * so fd0 needs to be decremented before use.
       
    94  *
       
    95  */ 
       
    96 UNS8 canSend_driver(CAN_HANDLE fd0, Message *m)
       
    97 {
       
    98 canStatus retval = canOK;
       
    99 unsigned flags = 0;
       
   100 
       
   101     fd0--;
       
   102 
       
   103     flags |= canMSG_STD;
       
   104     
       
   105     if (m->cob_id & 0x20000000)
       
   106     {
       
   107         /* TODO: is it correct to desume this info from cob_id? */
       
   108         flags |= canMSG_EXT;
       
   109     }
       
   110 
       
   111     if (m->cob_id & 0x40000000)
       
   112     {
       
   113         flags |= canMSG_RTR;
       
   114     }
       
   115 
       
   116     /*
       
   117      * TODO: when should I set canMSG_ERROR_FRAME?
       
   118      */ 
       
   119     
       
   120     retval = canWriteWait((int)fd0, m->cob_id, m->data, m->len, 10000, flags);
       
   121     if (retval != canOK)
       
   122     {
       
   123   	    fprintf(stderr, "canSend_driver (Kvaser) :  canWriteWait() error, cob_id=%08X, len=%u, flags=%08X, returned value = %d\n", 
       
   124                 m->cob_id, m->len, flags, retval);
       
   125         canClose((int)fd0);
       
   126         return retval;
       
   127     }
       
   128    
       
   129     //fprintf(stderr, "canSend_driver (Kvaser) :  canWriteWait() send packet, cob_id=%08X, len=%u, flags=%08X, returned value = %d\n", 
       
   130     //            m->cob_id, m->len, flags, retval);
       
   131     return retval; 
       
   132 
       
   133 }
       
   134 
       
   135 
       
   136 /**
       
   137  * 
       
   138  */ 
       
   139 int TranslateBaudRate(char* optarg)
       
   140 {
       
   141 	if(!strcmp( optarg, "1M")) 
       
   142         return BAUD_1M;
       
   143 	if(!strcmp( optarg, "500K")) 
       
   144         return BAUD_500K;
       
   145 	if(!strcmp( optarg, "250K")) 
       
   146         return BAUD_250K;
       
   147 	if(!strcmp( optarg, "125K")) 
       
   148         return BAUD_125K;
       
   149 	if(!strcmp( optarg, "100K")) 
       
   150         return BAUD_100K;
       
   151 	if(!strcmp( optarg, "62K")) 
       
   152         return BAUD_62K;
       
   153 	if(!strcmp( optarg, "50K")) 
       
   154         return BAUD_50K;
       
   155 
       
   156 	return 0;
       
   157 }
       
   158 
       
   159 /**
       
   160  * Channels and their descriptors are numbered starting from zero.
       
   161  * So I need to increment by 1 the handle returned by CANLIB because
       
   162  * CANfestival CAN_HANDLEs with value zero are considered NOT VALID. 
       
   163  * 
       
   164  * The baud rate could be given directly as bit/s
       
   165  * or using one of the BAUD_* constants defined
       
   166  * in canlib.h
       
   167  */ 
       
   168 CAN_HANDLE canOpen_driver(s_BOARD *board)
       
   169 {
       
   170 int fd0 = -1;
       
   171 int channel, baud;
       
   172 canStatus retval = canOK;
       
   173 
       
   174     fd0--;
       
   175 
       
   176     sscanf(board->busname, "%d", &channel);  
       
   177 
       
   178     baud = TranslateBaudRate(board->baudrate);
       
   179 
       
   180     if (baud == 0)
       
   181     {
       
   182         sscanf(board->baudrate, "%d", &baud);
       
   183     }
       
   184 
       
   185     fd0 = canOpenChannel(channel, canWANT_EXCLUSIVE|canWANT_EXTENDED);
       
   186     if (fd0 < 0)
       
   187     {
       
   188   	    fprintf(stderr, "canOpen_driver (Kvaser) : error opening channel %d\n", channel);
       
   189         return (CAN_HANDLE)(fd0+1);
       
   190     }
       
   191     canBusOff(fd0);
       
   192 
       
   193     /* values for tseg1, tseg2, sjw, noSamp and  syncmode
       
   194      * come from canlib example "simplewrite.c". The doc
       
   195      * says that default values will be taken if baud is one of
       
   196      * the BAUD_* values
       
   197      */ 
       
   198     retval = canSetBusParams(fd0, baud, 4, 3, 1, 1, 0);
       
   199     if (retval != canOK)
       
   200     {
       
   201   	    fprintf(stderr, "canOpen_driver (Kvaser) :  canSetBusParams() error, returned value = %d, baud=%d, \n", retval, baud);
       
   202         canClose((int)fd0);
       
   203         return (CAN_HANDLE)retval;
       
   204     }
       
   205     
       
   206     canSetBusOutputControl(fd0, canDRIVER_NORMAL);
       
   207     if (retval != canOK)
       
   208     {
       
   209   	    fprintf(stderr, "canOpen_driver (Kvaser) :  canSetBusOutputControl() error, returned value = %d\n", retval);
       
   210         canClose((int)fd0);
       
   211         return (CAN_HANDLE)retval;
       
   212     }
       
   213 
       
   214 
       
   215 
       
   216     
       
   217     retval = canBusOn(fd0);
       
   218     if (retval != canOK)
       
   219     {
       
   220   	    fprintf(stderr, "canOpen_driver (Kvaser) :  canBusOn() error, returned value = %d\n", retval);
       
   221         canClose((int)fd0);
       
   222         return (CAN_HANDLE)retval;
       
   223     }
       
   224     
       
   225     return (CAN_HANDLE)(fd0+1);
       
   226 
       
   227 }
       
   228 
       
   229 UNS8 canChangeBaudRate_driver( CAN_HANDLE fd0, char* baud)
       
   230 {
       
   231 int baudrate;
       
   232 canStatus retval = canOK;
       
   233 
       
   234 
       
   235     baudrate = TranslateBaudRate(baud);
       
   236     if (baudrate == 0)
       
   237     {
       
   238         sscanf(baud, "%d", &baudrate);
       
   239     }
       
   240 
       
   241 
       
   242     fprintf(stderr, "%x-> changing to baud rate %s[%d]\n", (int)fd0, baud, baudrate); 
       
   243     
       
   244     canBusOff((int)fd0);
       
   245 
       
   246     /* values for tseg1, tseg2, sjw, noSamp and  syncmode
       
   247      * come from canlib example "simplewrite.c". The doc
       
   248      * says that default values will be taken if baud is one of
       
   249      * the BAUD_* values
       
   250      */ 
       
   251     retval = canSetBusParams((int)fd0, baudrate, 4, 3, 1, 1, 0);
       
   252     if (retval != canOK)
       
   253     {
       
   254   	    fprintf(stderr, "canChangeBaudRate_driver (Kvaser) :  canSetBusParams() error, returned value = %d, baud=%d, \n", retval, baud);
       
   255         canClose((int)fd0);
       
   256         return (UNS8)retval;
       
   257     }
       
   258     
       
   259     canSetBusOutputControl((int)fd0, canDRIVER_NORMAL);
       
   260     if (retval != canOK)
       
   261     {
       
   262   	    fprintf(stderr, "canChangeBaudRate_driver (Kvaser) :  canSetBusOutputControl() error, returned value = %d\n", retval);
       
   263         canClose((int)fd0);
       
   264         return (UNS8)retval;
       
   265     }
       
   266     
       
   267     retval = canBusOn((int)fd0);
       
   268     if (retval != canOK)
       
   269     {
       
   270   	    fprintf(stderr, "canChangeBaudRate_driver (Kvaser) :  canBusOn() error, returned value = %d\n", retval);
       
   271         canClose((int)fd0);
       
   272         return (UNS8)retval;
       
   273     }
       
   274 
       
   275     return 0;
       
   276 }
       
   277 
       
   278 
       
   279 /**
       
   280  *
       
   281  * CAN_HANDLES must have value >=1 while CANLIB wants handles >= 0
       
   282  * so fd0 needs to be decremented before use.
       
   283  */ 
       
   284 int canClose_driver(CAN_HANDLE fd0)
       
   285 {
       
   286 canStatus retval = canOK;
       
   287 
       
   288     fd0--;
       
   289     
       
   290     retval = canBusOff((int)fd0);
       
   291     if (retval != canOK)
       
   292     {
       
   293   	    fprintf(stderr, "canClose_driver (Kvaser) :  canBusOff() error, returned value = %d\n", retval);
       
   294         canClose((int)fd0);
       
   295         return retval;
       
   296     }
       
   297     
       
   298     retval = canClose((int)fd0);
       
   299     if (retval != canOK)
       
   300     {
       
   301   	    fprintf(stderr, "canClose_driver (Kvaser) :  canClose() error, returned value = %d\n", retval);
       
   302         return retval;
       
   303     }
       
   304     
       
   305     return retval;
       
   306 }
       
   307