diff -r 9e496a2aadca -r b9274b595650 drivers/can_copcican_win32/can_copcican_win32.cpp --- /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 +//#include +#include + +//#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)); +} +