drivers/win32/drivers_win32.cpp
changeset 267 96c688ebcde7
parent 266 8678a3cf7fe7
child 268 8a21eb5bdedc
equal deleted inserted replaced
266:8678a3cf7fe7 267:96c688ebcde7
     1 /*
       
     2 This file is part of CanFestival, a library implementing CanOpen Stack.
       
     3 
       
     4 Copyright (C): Edouard TISSERANT and Francis DUPIN
       
     5 Copyright (C) Win32 Port Leonid Tochinski
       
     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  CAN driver interface.
       
    26 */
       
    27 
       
    28 #include <windows.h>
       
    29 
       
    30 extern "C"
       
    31    {
       
    32 #define DLL_CALL(funcname) (*_##funcname)
       
    33 #define FCT_PTR_INIT =NULL
       
    34 #include "canfestival.h"
       
    35 #include "timer.h"
       
    36 
       
    37 #include "timers_driver.h"
       
    38    };
       
    39 
       
    40 typedef UNS8 (*CANRECEIVE_DRIVER_PROC)(void* inst, Message *m);
       
    41 typedef UNS8 (*CANSEND_DRIVER_PROC)(void* inst, const Message *m);
       
    42 typedef void* (*CANOPEN_DRIVER_PROC)(s_BOARD *board);
       
    43 typedef int (*CANCLOSE_DRIVER_PROC)(void* inst);
       
    44 
       
    45 
       
    46 class driver_procs
       
    47    {
       
    48    public:
       
    49       driver_procs();
       
    50       ~driver_procs();
       
    51 
       
    52       HMODULE load_canfestival_driver(LPCTSTR driver_name);
       
    53       bool can_driver_valid() const;
       
    54 
       
    55    public:
       
    56       // can driver
       
    57       CANRECEIVE_DRIVER_PROC m_canReceive;
       
    58       CANSEND_DRIVER_PROC m_canSend;
       
    59       CANOPEN_DRIVER_PROC m_canOpen;
       
    60       CANCLOSE_DRIVER_PROC m_canClose;
       
    61 
       
    62       // driver module habndle
       
    63       HMODULE m_driver_handle;
       
    64    };
       
    65 
       
    66 driver_procs::driver_procs() : m_canReceive(0),
       
    67       m_canSend(0),
       
    68       m_canOpen(0),
       
    69       m_canClose(0),
       
    70       m_driver_handle(0)
       
    71    {}
       
    72 
       
    73 driver_procs::~driver_procs()
       
    74    {
       
    75    if (m_driver_handle)
       
    76       ::FreeLibrary(m_driver_handle);
       
    77    }
       
    78 
       
    79 bool driver_procs::can_driver_valid() const
       
    80    {
       
    81    return ((m_canReceive != NULL) &&
       
    82            (m_canSend != NULL) &&
       
    83            (m_canOpen != NULL) &&
       
    84            (m_canClose != NULL));
       
    85    }
       
    86 
       
    87 // GetProcAddress doesn't have an UNICODE version for NT
       
    88 #ifdef UNDER_CE
       
    89   #define myTEXT(str) TEXT(str)
       
    90 #else
       
    91   #define myTEXT(str) str
       
    92 #endif
       
    93 
       
    94 HMODULE driver_procs::load_canfestival_driver(LPCTSTR driver_name)
       
    95    {
       
    96    if (can_driver_valid())
       
    97       return m_driver_handle;
       
    98    m_driver_handle = ::LoadLibrary(driver_name);
       
    99    if (m_driver_handle == NULL)
       
   100       return NULL;
       
   101 
       
   102    m_canReceive = (CANRECEIVE_DRIVER_PROC)::GetProcAddress(m_driver_handle, myTEXT("canReceive_driver"));
       
   103    m_canSend = (CANSEND_DRIVER_PROC)::GetProcAddress(m_driver_handle, myTEXT("canSend_driver"));
       
   104    m_canOpen = (CANOPEN_DRIVER_PROC)::GetProcAddress(m_driver_handle, myTEXT("canOpen_driver"));
       
   105    m_canClose = (CANCLOSE_DRIVER_PROC)::GetProcAddress(m_driver_handle, myTEXT("canClose_driver"));
       
   106    return can_driver_valid()?m_driver_handle:NULL;
       
   107    }
       
   108 
       
   109 struct driver_data
       
   110    {
       
   111    CO_Data * d;
       
   112    HANDLE receive_thread;
       
   113    void* inst;
       
   114    volatile bool continue_receive_thread;
       
   115    };
       
   116 
       
   117 driver_procs s_driver_procs;
       
   118 
       
   119 LIB_HANDLE LoadCanDriver(char* driver_name)
       
   120    {
       
   121 		return s_driver_procs.load_canfestival_driver((LPCTSTR)driver_name);
       
   122    }
       
   123 
       
   124 UNS8 canReceive(CAN_PORT fd0, Message *m)
       
   125    {
       
   126    if (fd0 != NULL && s_driver_procs.m_canReceive != NULL)
       
   127 	   {
       
   128 		  driver_data* data = (driver_data*)fd0;
       
   129 		  return (*s_driver_procs.m_canReceive)(data->inst, m);
       
   130 	   }
       
   131    return 1;
       
   132    }
       
   133 
       
   134 void* canReceiveLoop(CAN_PORT fd0)
       
   135    {
       
   136    driver_data* data = (driver_data*)fd0;
       
   137    Message m;
       
   138    while (data->continue_receive_thread)
       
   139       {
       
   140       if (!canReceive(fd0, &m))
       
   141          {
       
   142          EnterMutex();
       
   143          canDispatch(data->d, &m);
       
   144          LeaveMutex();
       
   145          }
       
   146       else
       
   147          {
       
   148 		 break;
       
   149          ::Sleep(1);
       
   150          }
       
   151       }
       
   152    return 0;
       
   153    }
       
   154 
       
   155 /***************************************************************************/
       
   156 UNS8 canSend(CAN_PORT fd0, Message *m)
       
   157    {
       
   158    if (fd0 != NULL && s_driver_procs.m_canSend != NULL)
       
   159       {
       
   160       UNS8 res;
       
   161       driver_data* data = (driver_data*)fd0;
       
   162       res = (*s_driver_procs.m_canSend)(data->inst, m);      
       
   163       if (res)
       
   164          return 0;
       
   165       }
       
   166    return 1;
       
   167    }
       
   168 
       
   169 /***************************************************************************/
       
   170 CAN_HANDLE canOpen(s_BOARD *board, CO_Data * d)
       
   171    {
       
   172    if (board != NULL && s_driver_procs.m_canOpen != NULL)
       
   173       {
       
   174       void* inst = (*s_driver_procs.m_canOpen)(board);
       
   175       if (inst != NULL)
       
   176          {
       
   177          driver_data* data = new driver_data;
       
   178          data->d = d;
       
   179          data->inst = inst;
       
   180          data->continue_receive_thread = true;
       
   181          CreateReceiveTask(data, &data->receive_thread, &canReceiveLoop);
       
   182 	 EnterMutex();
       
   183          d->canHandle = data;
       
   184          LeaveMutex();
       
   185          return data;
       
   186          }
       
   187       }
       
   188    return NULL;
       
   189    }
       
   190 
       
   191 /***************************************************************************/
       
   192 int canClose(CO_Data * d)
       
   193    {
       
   194    if (s_driver_procs.m_canClose != NULL)
       
   195       {
       
   196 		  driver_data* data;
       
   197 		  EnterMutex();
       
   198 		  if(d->canHandle != NULL){
       
   199 			data = (driver_data*)d->canHandle;
       
   200 			d->canHandle = NULL;
       
   201 			data->continue_receive_thread = false;}
       
   202 		  LeaveMutex();
       
   203 		  WaitReceiveTaskEnd(&data->receive_thread);
       
   204 		  (*s_driver_procs.m_canClose)(data->inst);
       
   205 		  delete data;
       
   206 		  return 0;
       
   207       }
       
   208    return 0;
       
   209    }
       
   210 
       
   211