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