]> rtime.felk.cvut.cz Git - CanFestival-3.git/blob - drivers/win32/drivers_win32.cpp
Some win32 fixes following yesterday's API changes.
[CanFestival-3.git] / drivers / win32 / drivers_win32.cpp
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       LeaveMutex();
163       res = (*s_driver_procs.m_canSend)(data->inst, m);      
164       EnterMutex();
165       if (res)
166          return 0;
167       }
168    return 1;
169    }
170
171 /***************************************************************************/
172 CAN_HANDLE canOpen(s_BOARD *board, CO_Data * d)
173    {
174    if (board != NULL && s_driver_procs.m_canOpen != NULL)
175       {
176       void* inst = (*s_driver_procs.m_canOpen)(board);
177       if (inst != NULL)
178          {
179          driver_data* data = new driver_data;
180          data->d = d;
181          data->inst = inst;
182          data->continue_receive_thread = true;
183          CreateReceiveTask(data, &data->receive_thread, &canReceiveLoop);
184          EnterMutex();
185          d->canHandle = data;
186          LeaveMutex();
187          return data;
188          }
189       }
190    return NULL;
191    }
192
193 /***************************************************************************/
194 int canClose(CO_Data * d)
195    {
196    if (s_driver_procs.m_canClose != NULL)
197       {
198                   driver_data* data;
199                   EnterMutex();
200                   if(d->canHandle != NULL){
201                         data = (driver_data*)d->canHandle;
202                         d->canHandle = NULL;
203                         data->continue_receive_thread = false;}
204                   LeaveMutex();
205                   WaitReceiveTaskEnd(&data->receive_thread);
206                   (*s_driver_procs.m_canClose)(data->inst);
207                   delete data;
208                   return 0;
209       }
210    return 0;
211    }
212
213