drivers/can_copcican_win32/can_copcican_win32.cpp
changeset 629 b9274b595650
equal deleted inserted replaced
628:9e496a2aadca 629:b9274b595650
       
     1 // can_copcican_win32.cpp : Defines the exported functions for the DLL application.
       
     2 //
       
     3 
       
     4 
       
     5 #include "stdafx.h"
       
     6 
       
     7 /*
       
     8 This file is part of CanFestival, a library implementing CanOpen Stack.
       
     9 
       
    10 Copyright (C): Cosateq GmbH & Co.KG
       
    11                http://www.cosateq.com/
       
    12                http://www.scale-rt.com/
       
    13 
       
    14 See COPYING file for copyrights details.
       
    15 
       
    16 This library is free software; you can redistribute it and/or
       
    17 modify it under the terms of the GNU Lesser General Public
       
    18 License as published by the Free Software Foundation; either
       
    19 version 2.1 of the License, or (at your option) any later version.
       
    20 
       
    21 This library is distributed in the hope that it will be useful,
       
    22 but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    24 Lesser General Public License for more details.
       
    25 
       
    26 You should have received a copy of the GNU Lesser General Public
       
    27 License along with this library; if not, write to the Free Software
       
    28 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
       
    29 */
       
    30 
       
    31 /*
       
    32 	CAN driver interface for CO-PCICAN card.
       
    33 */
       
    34 
       
    35 #include <stdio.h>
       
    36 //#include <unistd.h>
       
    37 #include <fcntl.h>
       
    38 
       
    39 //#define NEED_PRINT_MESSAGE
       
    40 static int initdone = 0;
       
    41 
       
    42 inline void * maskDevID(int devId){	return ((void*)( (devId & 0x0000000F) | 0xC05A0000)); }
       
    43 inline int unmaskDevID(void * Ptr){	return ((int)((int)Ptr & 0x0000000F)); }
       
    44 
       
    45 /* at the moment not threadsafe :-( */
       
    46 static unsigned char selectedChannelRx = 1, selectedChannelTx = 1;
       
    47 
       
    48 static cosateq::devices::can::co_baudrate_t TranslateBaudRate( char* optarg )
       
    49 {
       
    50   /* values see documentation of CO-PCICAN */
       
    51 	if( !strcmp( optarg, "1M"    ) ) return cosateq::devices::can::CO_BAUD_1M;
       
    52 	if( !strcmp( optarg, "800K"  ) ) return cosateq::devices::can::CO_BAUD_800k;
       
    53 	if( !strcmp( optarg, "500K"  ) ) return cosateq::devices::can::CO_BAUD_500k;
       
    54   if( !strcmp( optarg, "250K"  ) ) return cosateq::devices::can::CO_BAUD_250k;
       
    55   if( !strcmp( optarg, "125K"  ) ) return cosateq::devices::can::CO_BAUD_125k;
       
    56   if( !strcmp( optarg, "100K"  ) ) return cosateq::devices::can::CO_BAUD_100k;
       
    57   if( !strcmp( optarg, "83.3K" ) ) return cosateq::devices::can::CO_BAUD_83k;
       
    58   if( !strcmp( optarg, "10K"   ) ) return cosateq::devices::can::CO_BAUD_10k;
       
    59 
       
    60   return (cosateq::devices::can::co_baudrate_t)-1;
       
    61 }
       
    62 
       
    63 int co_pcican_select_channel( const unsigned char channel, const unsigned int direction )
       
    64 {
       
    65   if( channel >= CHANNELS )
       
    66   {
       
    67     MSG("can_copcican_linux: co_pcican_select_channel(): invalid channel\n");
       
    68     return -1;
       
    69   }
       
    70 
       
    71   /* at the moment not threadsafe :-( */
       
    72   switch( direction )
       
    73   {
       
    74     case cosateq::devices::can::CO_CAN_RX: selectedChannelRx = channel;
       
    75              break;
       
    76     case cosateq::devices::can::CO_CAN_TX: selectedChannelTx = channel;
       
    77              break;
       
    78     default: return -1;
       
    79   }
       
    80 
       
    81   return 0;
       
    82 }
       
    83 
       
    84 int co_pcican_configure_selected_channel( const int fd, s_BOARD *board, const unsigned int direction )
       
    85 {
       
    86   unsigned int selectedChannel;
       
    87   int ret = 0;
       
    88 
       
    89   if( fd < 0 )
       
    90   {
       
    91     MSG("can_copcican_linux: co_pcican_configure_selected_channel(): invalid file descriptor\n");
       
    92     return -1;
       
    93   }
       
    94 
       
    95   if( board == NULL )
       
    96   {
       
    97     MSG("can_copcican_linux: co_pcican_configure_selected_channel(): board is NULL\n");
       
    98     return -1;
       
    99   }
       
   100 
       
   101   if( board->baudrate == NULL )
       
   102   {
       
   103     MSG("can_copcican_linux: co_pcican_configure_selected_channel(): baudrate is NULL\n");
       
   104     return -1;
       
   105   }
       
   106 
       
   107   switch( direction )
       
   108   {
       
   109     case cosateq::devices::can::CO_CAN_RX: selectedChannel = selectedChannelRx;
       
   110              break;
       
   111     case cosateq::devices::can::CO_CAN_TX: selectedChannel = selectedChannelTx;
       
   112              break;
       
   113     default: selectedChannel = 0xff;
       
   114   }
       
   115 
       
   116   if( selectedChannel >= CHANNELS )
       
   117   {
       
   118     MSG("can_copcican_linux: co_pcican_configure_selected_channel(): invalid channel selected\n");
       
   119     return -1;
       
   120   }
       
   121 
       
   122   ret = can_setChannelConfig( TranslateBaudRate( board->baudrate ),0x0,unmaskDevID((void*)fd),selectedChannel);
       
   123   if ( ret != 0 ) {
       
   124 	  can_enterRunMode(unmaskDevID((void*)fd),selectedChannel/2);
       
   125 	  return -ret;
       
   126   }else{
       
   127 	  ret = can_setIrqMode(unmaskDevID((void*)fd),selectedChannel);
       
   128 	  can_enterRunMode(unmaskDevID((void*)fd),selectedChannel/2);
       
   129   }
       
   130   return ret;
       
   131 }
       
   132 
       
   133 /*********functions which permit to communicate with the board****************/
       
   134 
       
   135 UNS8 __stdcall canReceive_driver( CAN_HANDLE fd0, Message *m )
       
   136 {
       
   137   cosateq::devices::can::co_can_packet_t p;
       
   138   int ret = 0;
       
   139 
       
   140   if ( !m )
       
   141 	  return 0;
       
   142 
       
   143   memset(&p,0,sizeof(cosateq::devices::can::co_can_packet_t));
       
   144   ret = can_receive(&p,unmaskDevID(fd0),selectedChannelRx);
       
   145   //printf("rec: %d\n",ret);
       
   146   if ( ret != 0 )
       
   147 	  return 1;
       
   148 
       
   149   //printf("rec2: %d\n",ret);
       
   150   if ( p.size > 8 )
       
   151 	  p.size = 8;
       
   152 
       
   153   if ( !(p.type & MSG_RTR ) )
       
   154     memcpy(m->data,p.data,p.size);
       
   155 
       
   156   m->cob_id = p.id;
       
   157   m->len = p.size;
       
   158   m->rtr = p.type & MSG_RTR;
       
   159   
       
   160   return 0;
       
   161 }
       
   162 
       
   163 /***************************************************************************/
       
   164 
       
   165 UNS8 __stdcall canSend_driver( CAN_HANDLE fd0, Message *m )
       
   166 {
       
   167   cosateq::devices::can::co_can_packet_t p;
       
   168   
       
   169   if ( !m )
       
   170 	  return 0;
       
   171   memset(&p,0,sizeof(cosateq::devices::can::co_can_packet_t));
       
   172   p.id = m->cob_id;
       
   173   p.size = (m->len > 8) ? 8 : m->len;
       
   174   p.type = ( m->rtr ) ? 0x2:0x0;
       
   175   if ( p.id > 0x800 )
       
   176 	  p.type |= MSG_EXT;
       
   177   memcpy(p.data,m->data,p.size);
       
   178 
       
   179   return can_send(&p,unmaskDevID(fd0),selectedChannelTx);
       
   180 }
       
   181 
       
   182 
       
   183 
       
   184 /***************************************************************************/
       
   185 
       
   186 UNS8 __stdcall canChangeBaudRate_driver( CAN_HANDLE fd0, char* baud )
       
   187 {
       
   188   UNS8 ret = 0;
       
   189 
       
   190   ret = can_enterCfgMode(unmaskDevID(fd0),0);
       
   191   if ( ret != 0)
       
   192     MSG("Enter config mode for Channelpair 0 failed in Function %s! Error: %d\n",__FUNCTION__,ret);
       
   193   ret = can_enterCfgMode(unmaskDevID(fd0),1);
       
   194   if ( ret != 0)
       
   195     MSG("Enter config mode for Channelpair 1 failed in Function %s! Error: %d\n",__FUNCTION__,ret);
       
   196 
       
   197   for ( int i = 0; i < 4; i++ ) {
       
   198       ret = can_setChannelConfig(TranslateBaudRate(baud),0x0,unmaskDevID(fd0),i);
       
   199       if ( ret != 0)
       
   200         MSG("Set config for channel %d failed in Function %s! Error: %d\n",i,__FUNCTION__,ret);
       
   201 	  can_setIrqMode(unmaskDevID(fd0),i);
       
   202   }
       
   203   ret = can_enterRunMode(unmaskDevID(fd0),0);
       
   204   if ( ret != 0)
       
   205     MSG("Enter run mode for Channelpair 1 failed in Function %s! Error: %d\n",__FUNCTION__,ret);
       
   206 
       
   207   ret = can_enterRunMode(unmaskDevID(fd0),1);
       
   208   if ( ret != 0)
       
   209     MSG("Enter run mode for Channelpair 1 failed in Function %s! Error: %d\n",__FUNCTION__,ret);
       
   210 
       
   211   return ret;
       
   212 }
       
   213 
       
   214 CAN_HANDLE __stdcall canOpen_driver( s_BOARD *board )
       
   215 {
       
   216 	int ret = 0;
       
   217 	int devId = 0;
       
   218 	if ( !board )
       
   219 		return NULL;
       
   220 	if ( !board->busname )
       
   221 		return NULL;
       
   222 	//TODO find out how boardname resolves
       
   223 
       
   224 	//printf("BOARD: 0x%x %s\n",board,board->busname);
       
   225 	//sscanf_s(board->busname,"%d",&devId);
       
   226 
       
   227 	if ( devId < 0 || devId > 15 )
       
   228 		return NULL;
       
   229 
       
   230 	//return (can_HANDLE)NULL;
       
   231 	if ( !initdone ) {
       
   232 		can_init();
       
   233 		initdone = 1;
       
   234 	}
       
   235 
       
   236 	ret = can_open(devId);
       
   237 	if ( ret < 0 )
       
   238 		return (CAN_HANDLE)NULL;
       
   239 	
       
   240 	canChangeBaudRate_driver( maskDevID(devId),board->baudrate );
       
   241 	
       
   242 	return maskDevID(devId);
       
   243 }
       
   244 
       
   245 int __stdcall canClose_driver(CAN_HANDLE fd0 )
       
   246 {
       
   247 	return can_close(unmaskDevID(fd0));
       
   248 }
       
   249