--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/can_copcican_win32/can_copcican_win32.cpp Fri Nov 12 22:24:06 2010 +0100
@@ -0,0 +1,249 @@
+// can_copcican_win32.cpp : Defines the exported functions for the DLL application.
+//
+
+
+#include "stdafx.h"
+
+/*
+This file is part of CanFestival, a library implementing CanOpen Stack.
+
+Copyright (C): Cosateq GmbH & Co.KG
+ http://www.cosateq.com/
+ http://www.scale-rt.com/
+
+See COPYING file for copyrights details.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+/*
+ CAN driver interface for CO-PCICAN card.
+*/
+
+#include <stdio.h>
+//#include <unistd.h>
+#include <fcntl.h>
+
+//#define NEED_PRINT_MESSAGE
+static int initdone = 0;
+
+inline void * maskDevID(int devId){ return ((void*)( (devId & 0x0000000F) | 0xC05A0000)); }
+inline int unmaskDevID(void * Ptr){ return ((int)((int)Ptr & 0x0000000F)); }
+
+/* at the moment not threadsafe :-( */
+static unsigned char selectedChannelRx = 1, selectedChannelTx = 1;
+
+static cosateq::devices::can::co_baudrate_t TranslateBaudRate( char* optarg )
+{
+ /* values see documentation of CO-PCICAN */
+ if( !strcmp( optarg, "1M" ) ) return cosateq::devices::can::CO_BAUD_1M;
+ if( !strcmp( optarg, "800K" ) ) return cosateq::devices::can::CO_BAUD_800k;
+ if( !strcmp( optarg, "500K" ) ) return cosateq::devices::can::CO_BAUD_500k;
+ if( !strcmp( optarg, "250K" ) ) return cosateq::devices::can::CO_BAUD_250k;
+ if( !strcmp( optarg, "125K" ) ) return cosateq::devices::can::CO_BAUD_125k;
+ if( !strcmp( optarg, "100K" ) ) return cosateq::devices::can::CO_BAUD_100k;
+ if( !strcmp( optarg, "83.3K" ) ) return cosateq::devices::can::CO_BAUD_83k;
+ if( !strcmp( optarg, "10K" ) ) return cosateq::devices::can::CO_BAUD_10k;
+
+ return (cosateq::devices::can::co_baudrate_t)-1;
+}
+
+int co_pcican_select_channel( const unsigned char channel, const unsigned int direction )
+{
+ if( channel >= CHANNELS )
+ {
+ MSG("can_copcican_linux: co_pcican_select_channel(): invalid channel\n");
+ return -1;
+ }
+
+ /* at the moment not threadsafe :-( */
+ switch( direction )
+ {
+ case cosateq::devices::can::CO_CAN_RX: selectedChannelRx = channel;
+ break;
+ case cosateq::devices::can::CO_CAN_TX: selectedChannelTx = channel;
+ break;
+ default: return -1;
+ }
+
+ return 0;
+}
+
+int co_pcican_configure_selected_channel( const int fd, s_BOARD *board, const unsigned int direction )
+{
+ unsigned int selectedChannel;
+ int ret = 0;
+
+ if( fd < 0 )
+ {
+ MSG("can_copcican_linux: co_pcican_configure_selected_channel(): invalid file descriptor\n");
+ return -1;
+ }
+
+ if( board == NULL )
+ {
+ MSG("can_copcican_linux: co_pcican_configure_selected_channel(): board is NULL\n");
+ return -1;
+ }
+
+ if( board->baudrate == NULL )
+ {
+ MSG("can_copcican_linux: co_pcican_configure_selected_channel(): baudrate is NULL\n");
+ return -1;
+ }
+
+ switch( direction )
+ {
+ case cosateq::devices::can::CO_CAN_RX: selectedChannel = selectedChannelRx;
+ break;
+ case cosateq::devices::can::CO_CAN_TX: selectedChannel = selectedChannelTx;
+ break;
+ default: selectedChannel = 0xff;
+ }
+
+ if( selectedChannel >= CHANNELS )
+ {
+ MSG("can_copcican_linux: co_pcican_configure_selected_channel(): invalid channel selected\n");
+ return -1;
+ }
+
+ ret = can_setChannelConfig( TranslateBaudRate( board->baudrate ),0x0,unmaskDevID((void*)fd),selectedChannel);
+ if ( ret != 0 ) {
+ can_enterRunMode(unmaskDevID((void*)fd),selectedChannel/2);
+ return -ret;
+ }else{
+ ret = can_setIrqMode(unmaskDevID((void*)fd),selectedChannel);
+ can_enterRunMode(unmaskDevID((void*)fd),selectedChannel/2);
+ }
+ return ret;
+}
+
+/*********functions which permit to communicate with the board****************/
+
+UNS8 __stdcall canReceive_driver( CAN_HANDLE fd0, Message *m )
+{
+ cosateq::devices::can::co_can_packet_t p;
+ int ret = 0;
+
+ if ( !m )
+ return 0;
+
+ memset(&p,0,sizeof(cosateq::devices::can::co_can_packet_t));
+ ret = can_receive(&p,unmaskDevID(fd0),selectedChannelRx);
+ //printf("rec: %d\n",ret);
+ if ( ret != 0 )
+ return 1;
+
+ //printf("rec2: %d\n",ret);
+ if ( p.size > 8 )
+ p.size = 8;
+
+ if ( !(p.type & MSG_RTR ) )
+ memcpy(m->data,p.data,p.size);
+
+ m->cob_id = p.id;
+ m->len = p.size;
+ m->rtr = p.type & MSG_RTR;
+
+ return 0;
+}
+
+/***************************************************************************/
+
+UNS8 __stdcall canSend_driver( CAN_HANDLE fd0, Message *m )
+{
+ cosateq::devices::can::co_can_packet_t p;
+
+ if ( !m )
+ return 0;
+ memset(&p,0,sizeof(cosateq::devices::can::co_can_packet_t));
+ p.id = m->cob_id;
+ p.size = (m->len > 8) ? 8 : m->len;
+ p.type = ( m->rtr ) ? 0x2:0x0;
+ if ( p.id > 0x800 )
+ p.type |= MSG_EXT;
+ memcpy(p.data,m->data,p.size);
+
+ return can_send(&p,unmaskDevID(fd0),selectedChannelTx);
+}
+
+
+
+/***************************************************************************/
+
+UNS8 __stdcall canChangeBaudRate_driver( CAN_HANDLE fd0, char* baud )
+{
+ UNS8 ret = 0;
+
+ ret = can_enterCfgMode(unmaskDevID(fd0),0);
+ if ( ret != 0)
+ MSG("Enter config mode for Channelpair 0 failed in Function %s! Error: %d\n",__FUNCTION__,ret);
+ ret = can_enterCfgMode(unmaskDevID(fd0),1);
+ if ( ret != 0)
+ MSG("Enter config mode for Channelpair 1 failed in Function %s! Error: %d\n",__FUNCTION__,ret);
+
+ for ( int i = 0; i < 4; i++ ) {
+ ret = can_setChannelConfig(TranslateBaudRate(baud),0x0,unmaskDevID(fd0),i);
+ if ( ret != 0)
+ MSG("Set config for channel %d failed in Function %s! Error: %d\n",i,__FUNCTION__,ret);
+ can_setIrqMode(unmaskDevID(fd0),i);
+ }
+ ret = can_enterRunMode(unmaskDevID(fd0),0);
+ if ( ret != 0)
+ MSG("Enter run mode for Channelpair 1 failed in Function %s! Error: %d\n",__FUNCTION__,ret);
+
+ ret = can_enterRunMode(unmaskDevID(fd0),1);
+ if ( ret != 0)
+ MSG("Enter run mode for Channelpair 1 failed in Function %s! Error: %d\n",__FUNCTION__,ret);
+
+ return ret;
+}
+
+CAN_HANDLE __stdcall canOpen_driver( s_BOARD *board )
+{
+ int ret = 0;
+ int devId = 0;
+ if ( !board )
+ return NULL;
+ if ( !board->busname )
+ return NULL;
+ //TODO find out how boardname resolves
+
+ //printf("BOARD: 0x%x %s\n",board,board->busname);
+ //sscanf_s(board->busname,"%d",&devId);
+
+ if ( devId < 0 || devId > 15 )
+ return NULL;
+
+ //return (can_HANDLE)NULL;
+ if ( !initdone ) {
+ can_init();
+ initdone = 1;
+ }
+
+ ret = can_open(devId);
+ if ( ret < 0 )
+ return (CAN_HANDLE)NULL;
+
+ canChangeBaudRate_driver( maskDevID(devId),board->baudrate );
+
+ return maskDevID(devId);
+}
+
+int __stdcall canClose_driver(CAN_HANDLE fd0 )
+{
+ return can_close(unmaskDevID(fd0));
+}
+