1 /*---------------------------------------------------------------------------*
2   Project:  HIO2 demos - multi
3   File:     multi.cpp
4 
5   (C)2005 HUDSON SOFT
6 
7   $Header: /home/cvsroot/SDK/build/demos/hio2demo/vc++/multi/multi.cpp,v 1.3 2006/03/15 06:31:26 mitu Exp $
8 
9   $NoKeywords: $
10  *---------------------------------------------------------------------------*/
11 
12 // multi.cpp : Defines the class behaviors for the application.
13 //
14 
15 #include "stdafx.h"
16 #include "multi.h"
17 #include "MainFrm.h"
18 
19 #include "ChildFrm.h"
20 #include "multiDoc.h"
21 #include "multiView.h"
22 #include ".\multi.h"
23 
24 #ifdef _DEBUG
25 #define new DEBUG_NEW
26 #endif
27 
28 ///////// for multiApp /////////
29 
30 // the comparison function specified in m_cInfoList.IndexOf()
MultiCompID(CMultiApp::LPAPPINFO pItem,LPVOID pData)31 BOOL	MultiCompID(CMultiApp::LPAPPINFO pItem, LPVOID pData)
32 {
33 	return (pItem->m_nHioIfID == (HIO2IF_ID)pData) ? TRUE : FALSE;
34 }
35 
36 ///////////////////////////////////////////////////////////////////////////////
37 //
38 // local function and thread function definition
39 //
40 
41 // Get active view
42 static
GetActiveView(HIO2IF_ID nID)43 CMultiView*	GetActiveView(HIO2IF_ID nID)
44 {
45 	POSITION pos;
46 	CDocTemplate* pDocTemplate;
47 	CMultiDoc* pDoc;
48 
49 	// Document Template
50 	pos = GetApp()->GetFirstDocTemplatePosition();
51 	if ( pos == NULL ) return NULL;
52 	pDocTemplate = GetApp()->GetNextDocTemplate(pos);
53 
54 	// Document
55 	pos = pDocTemplate->GetFirstDocPosition();
56 	if ( pos == NULL ) return NULL;
57 	while ( pos != NULL )
58 	{
59 		pDoc = static_cast<CMultiDoc *>(pDocTemplate->GetNextDoc(pos));
60 		if ( pDoc->m_nHioIfID == nID )
61 		{
62 			POSITION viewpos = pDoc->GetFirstViewPosition();
63 			if ( viewpos != NULL )
64 				return static_cast<CMultiView *>(pDoc->GetNextView(viewpos));
65 		}
66 	}
67 	return NULL;
68 }
69 
70 // CHioIf::HIO2IF_EVENT_CALLBACK
71 static
HioIfEventCallback(HIO2IF_ID id,HIO2IF_EVENT event)72 void	HioIfEventCallback(HIO2IF_ID id, HIO2IF_EVENT event)
73 {
74 	CMultiView* pView;
75 	CMultiApp* pApp = GetApp();
76 	int nIndex =
77         GetApp()->m_cInfoList.IndexOf((LPVOID)id, MultiCompID);
78 	CMultiApp::LPAPPINFO pInfo = pApp->m_cInfoList.GetItem(nIndex);
79 
80 	switch ( event )
81 	{
82 	case HIO2IF_EVENT_CONNECT:		// connection established
83 		{
84 			BYTE clearBuf[MULTI_BUFFER_SIZE * 2];
85 
86 			// message to View
87 			if ( (pView=GetActiveView(id)) != NULL )
88 				pView->PostMessage(WM_USER, CMultiView::EVENT_CONNECT, 0);
89 
90 			// clear the region
91 			ZeroMemory(clearBuf, sizeof(clearBuf));
92 			pApp->m_pHioIf->WriteFree(id, MULTI_PC2NNGC_ADDR, clearBuf, sizeof(clearBuf), FALSE);
93 			break;
94 		}
95 	case HIO2IF_EVENT_DISCONNECT:	// connection released
96 		pApp->m_pHioIf->Close(id);
97 
98 		// message to View
99 		if ( (pView=GetActiveView(id)) != NULL )
100 			pView->PostMessage(WM_USER, CMultiView::EVENT_DISCONNECT, 0);
101 		break;
102 	case HIO2IF_EVENT_RECEIVED:		// Data reception
103 		{
104 			HIO2IF_RESULT result = pApp->m_pHioIf->Read(
105 									id,
106 									MULTI_NNGC2PC_ADDR,
107 									(LPVOID)&(pInfo->m_stPacket),
108 									MULTI_BUFFER_SIZE,
109 									pInfo->m_bSync);
110 
111 			if ( HIO2IF_SUCCESS(result) && !pInfo->m_bSync )
112 			{
113 				if ( (pView=GetActiveView(id)) != NULL )
114 					pView->PostMessage(WM_USER, CMultiView::EVENCT_RECEIVED, 0);
115 			}
116 			break;
117 		}
118 
119 	case HIO2IF_EVENT_READ_ASYNC_DONE:
120 		if ( (pView=GetActiveView(id)) != NULL )
121 			pView->PostMessage(WM_USER, CMultiView::EVENCT_RECEIVED, 0);
122 		break;
123 
124 	case HIO2IF_EVENT_WRITE_ASYNC_DONE:
125 		if ( (pView=GetActiveView(id)) != NULL )
126 			pView->PostMessage(WM_USER, CMultiView::EVENT_WRITE_DONE, 0);
127 		break;
128 
129 	case HIO2IF_EVENT_SEND_POSSIBLE:	// send possible
130 	default:
131 		break;
132 	}
133 }
134 
135 // ReadFree thread
136 static
PollingThread(LPVOID pHandle)137 DWORD WINAPI	PollingThread( LPVOID pHandle )
138 {
139 	CMultiApp* pApp = static_cast<CMultiApp *>(pHandle);
140 
141 	pApp->m_bThreadBreak = FALSE;
142 	while ( !pApp->m_bThreadBreak )
143 	{
144 		for (int i=0; i<pApp->m_cInfoList.GetCount(); i++ )
145 		{
146 			CMultiView* pView;
147 			DWORD dwStatus = 0;
148 
149 			CMultiApp::LPAPPINFO pInfo = pApp->m_cInfoList.GetItem(i);
150 
151 			// get communication status
152 			pApp->m_pHioIf->ReadStatus(pInfo->m_nHioIfID, dwStatus);
153 
154 			// update displayed PC time, communication status
155 			if ( (pView=GetActiveView(pInfo->m_nHioIfID)) != NULL )
156 				pView->PostMessage(WM_USER, CMultiView::EVENT_UPDATE_PC_TIME, dwStatus);
157 
158 #ifndef	PROTOCOL_USED
159 			// don't process when connection is broken
160 			if ( !pApp->m_pHioIf->IsConnected(pInfo->m_nHioIfID) ) continue;
161 
162 			HIO2IF_RESULT result = pApp->m_pHioIf->ReadFree(
163 										pInfo->m_nHioIfID,
164 										MULTI_NNGC2PC_ADDR,
165 										(LPVOID)&(pInfo->m_stPacket),
166 										MULTI_BUFFER_SIZE,
167 										pInfo->m_bSync);
168 
169 			pView = GetActiveView(pInfo->m_nHioIfID);
170 			if ( HIO2IF_SUCCESS(result) && (pView != NULL) )
171 				pView->PostMessage(WM_USER, CMultiView::EVENCT_RECEIVED, 0);
172 #endif
173 		}
174 
175 		// Read for roughly each 1V
176 		Sleep(1000 / 60);
177 	}
178 
179 	return 0;
180 }
181 
182 
183 ///////////////////////////////////////////////////////////////////////////////
184 //
185 // CMultiApp - Host I/O API interface
186 //
187 
188 //-----------------------------------------------------------------------------
HioIfInit()189 BOOL	CMultiApp::HioIfInit()
190 {
191 	// initialization
192 	if ( HIO2IF_FAILED(m_pHioIf->Init()) ) return FALSE;
193 
194 	// open the detected number of EXI channels
195 	for (int i=0; i<m_pHioIf->GetDeviceCount(); i++)
196 	{
197 		HIO2IF_ID id;
198 		HIO2DevicePath pPath = m_pHioIf->GetDevicePath(i);
199 		if ( HIO2IF_FAILED(m_pHioIf->Open(pPath, HioIfEventCallback, id)) )
200 			return FALSE;
201 
202 		LPAPPINFO pInfo = new APPINFO;
203 #ifndef	HW0
204 		pInfo->m_pDevice = new TCHAR [lstrlen(pPath) + 1];
205 		lstrcpy((LPSTR)pInfo->m_pDevice, pPath);
206 #else	// HW0
207 		pInfo->m_pDevice = pPath;
208 #endif	// HW0
209 		pInfo->m_nHioIfID = id;
210 		m_cInfoList.AddTail(pInfo);
211 	}
212 
213 	// update displayed PC time, create thread to run ReadFree() from CHioIf
214 	DWORD dwTmp;
215 
216 	m_bThreadBreak = TRUE;
217 	m_hThread = ::CreateThread(NULL, 0, PollingThread, (LPVOID)this, 0, &dwTmp);
218 
219 	// wait until thread launches
220 	// set m_bThreadBreak to FALSE within the PollingThread function)
221 	while ( m_bThreadBreak ) ;
222 
223 	// when protocol communication is taking place, call HIO2IF_EVENT_CALLBACK to go from HioIf
224 	// to Read
225 
226 	return TRUE;
227 }
228 
229 //-----------------------------------------------------------------------------
CreateInfo()230 void	CMultiApp::CreateInfo()
231 {
232 	POSITION pos = GetFirstDocTemplatePosition();
233 	ASSERT(pos != NULL);
234 	CMultiDocTemplate* pDocTemplate =
235 		static_cast<CMultiDocTemplate *>(GetNextDocTemplate(pos));
236 
237 	for (int i=0; i<m_cInfoList.GetCount(); i++)
238 	{
239 		LPAPPINFO pInfo = m_cInfoList.GetItem(i);
240 		CMultiDoc* pDoc =
241 			static_cast<CMultiDoc *>(pDocTemplate->OpenDocumentFile(NULL, TRUE));
242 		pDoc->m_nHioIfID = pInfo->m_nHioIfID;
243 		pDoc->UpdateTitle();
244 	}
245 }
246 
247 //-----------------------------------------------------------------------------
HioIfExit()248 BOOL	CMultiApp::HioIfExit()
249 {
250 	// terminate three if PollingThread is valid
251 	StopPollingThread();
252 
253 	m_pHioIf->EnterCriticalSection();
254 	m_pHioIf->Exit();	// HIO termination
255 	m_pHioIf->LeaveCriticalSection();
256 
257 	m_cInfoList.Clear();
258 
259 	return TRUE;
260 }
261 
262 //-----------------------------------------------------------------------------
StopPollingThread()263 void	CMultiApp::StopPollingThread()
264 {
265 	// terminate three if PollingThread is valid
266 	if ( m_hThread != INVALID_HANDLE_VALUE )
267 	{
268         // halt the EXI thread
269 		m_bThreadBreak = TRUE;
270 		WaitForSingleObject(m_hThread,1000*30);
271 		CloseHandle(m_hThread);
272 		m_hThread = INVALID_HANDLE_VALUE;
273 	}
274 }
275 
Connect(HIO2IF_ID id)276 void	CMultiApp::Connect(HIO2IF_ID id)
277 {
278 	m_pHioIf->EnterCriticalSection();
279 
280 	int nIndex = m_cInfoList.IndexOf((LPVOID)id, MultiCompID);
281 	LPAPPINFO pInfo = m_cInfoList.GetItem(nIndex);
282 
283 	if ( HIO2IF_FAILED(m_pHioIf->Open(pInfo->m_pDevice,	HioIfEventCallback, id)) )
284 	{
285 		MessageBox(NULL, "reopen failed", "ERROR", MB_OK);
286 	}
287 
288 	m_pHioIf->LeaveCriticalSection();
289 }
290 
Disconnect(HIO2IF_ID id)291 void	CMultiApp::Disconnect(HIO2IF_ID id)
292 {
293 	m_pHioIf->EnterCriticalSection();
294 	m_pHioIf->Close(id);
295 	m_pHioIf->LeaveCriticalSection();
296 
297 	CMultiView* pView = GetActiveView(id);
298 	if ( pView != NULL )
299 		pView->PostMessage(WM_USER, CMultiView::EVENT_DISCONNECT, 0);
300 }
301 
CreatePcTime(MULTI_PACKET * pPacket)302 void	CMultiApp::CreatePcTime(MULTI_PACKET* pPacket)
303 {
304 	struct tm *pLocalTime;
305 	__time64_t lTime;
306 
307 	_time64(&lTime);
308 	pLocalTime = _localtime64(&lTime);
309 
310 	pPacket->mon	= pLocalTime->tm_mon;
311 	pPacket->mday	= pLocalTime->tm_mday;
312 	pPacket->hour	= pLocalTime->tm_hour;
313 	pPacket->min	= pLocalTime->tm_min;
314 	pPacket->sec	= pLocalTime->tm_sec;
315 	pPacket->msec	= 0;
316 	strcpy(pPacket->string, "PC TIME");
317 }
318 
319 ///////////////////////////////////////////////////////////////////////////////
320 //
321 // CMultiApp
322 //
323 
BEGIN_MESSAGE_MAP(CMultiApp,CWinApp)324 BEGIN_MESSAGE_MAP(CMultiApp, CWinApp)
325 	ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
326 	// Standard file based document commands
327 	ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)
328 	ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen)
329 END_MESSAGE_MAP()
330 
331 
332 // CMultiApp construction
333 
334 CMultiApp::CMultiApp()
335 {
336 	// TODO : add construction code here,
337 	// Place all significant initialization in InitInstance
338 }
339 
340 
341 // The one and only CMultiApp object
342 
343 CMultiApp theApp;
344 
345 // CMultiApp initialization
346 
InitInstance()347 BOOL CMultiApp::InitInstance()
348 {
349 	// InitCommonControls() is required on Windows XP if an application
350 	// manifest specifies use of ComCtl32.dll version 6 or later to enable
351 	// visual styles.  Otherwise, any window creation will fail.
352 	InitCommonControls();
353 
354 	CWinApp::InitInstance();
355 
356 	// Initialize OLE libraries
357 	if (!AfxOleInit())
358 	{
359 		AfxMessageBox(IDP_OLE_INIT_FAILED);
360 		return FALSE;
361 	}
362 	AfxEnableControlContainer();
363 	// Standard initialization
364 	// If you are not using these features and wish to reduce the size
365 	// of your final executable, you should remove from the following
366 	// the specific initialization routines you do not need
367 	// Change the registry key under which our settings are stored
368 	// TODO : You should modify this string to be something appropriate
369 	// such as the name of your company or organization
370 	SetRegistryKey(_T("Local AppWizard-Generated Applications"));
371 	LoadStdProfileSettings(4);  // Load standard INI file options (including MRU)
372 
373 	////////// for multiApp //////////
374 	m_pHioIf = Hio2CreateInterface();
375 	if ( !HioIfInit() )
376 	{
377 		MessageBox(NULL, m_pHioIf->GetMessage(), "ERROR", (MB_OK | MB_ICONWARNING));
378 		m_cInfoList.Clear();
379 		return FALSE;
380 	}
381 
382 	// Register the application's document templates.  Document templates
383 	//  serve as the connection between documents, frame windows and views
384 	CMultiDocTemplate* pDocTemplate;
385 	pDocTemplate = new CMultiDocTemplate(IDR_multiTYPE,
386 		RUNTIME_CLASS(CMultiDoc),
387 		RUNTIME_CLASS(CChildFrame), // custom MDI child frame
388 		RUNTIME_CLASS(CMultiView));
389 	if (!pDocTemplate)
390 		return FALSE;
391 	AddDocTemplate(pDocTemplate);
392 	// create main MDI Frame window
393 	CMainFrame* pMainFrame = new CMainFrame;
394 	if (!pMainFrame || !pMainFrame->LoadFrame(IDR_MAINFRAME))
395 		return FALSE;
396 	m_pMainWnd = pMainFrame;
397 	// call DragAcceptFiles only if there's a suffix
398 	//  In an MDI app, this should occur immediately after setting m_pMainWnd
399 	// Parse command line for standard shell commands, DDE, file open
400 	CCommandLineInfo cmdInfo;
401 	ParseCommandLine(cmdInfo);
402 	// Dispatch commands specified on the command line.  Will return FALSE if
403 	// app was launched with /RegServer, /Register, /Unregserver or /Unregister.
404 #if 0
405 	if (!ProcessShellCommand(cmdInfo))
406 		return FALSE;
407 #endif
408 	// The main window has been initialized, so show and update it
409 	pMainFrame->ShowWindow(m_nCmdShow);
410 	pMainFrame->UpdateWindow();
411 
412 	////////// for multiApp //////////
413 	// create a window for each EXI channel
414 	CreateInfo();
415 
416 	return TRUE;
417 }
418 
419 // CMultiApp message handlers
420 
421 
ExitInstance()422 int CMultiApp::ExitInstance()
423 {
424 	////////// for multiApp //////////
425 	HioIfExit();
426 	Hio2ReleaseInterface(m_pHioIf);
427 
428 	return CWinApp::ExitInstance();
429 }
430 
431 // CAboutDlg dialog used for App About
432 
433 class CAboutDlg : public CDialog
434 {
435 public:
436 	CAboutDlg();
437 
438 // Dialog Data
439 	enum { IDD = IDD_ABOUTBOX };
440 
441 protected:
442 	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
443 
444 // Implementation
445 protected:
446 	DECLARE_MESSAGE_MAP()
447 };
448 
CAboutDlg()449 CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
450 {
451 }
452 
DoDataExchange(CDataExchange * pDX)453 void CAboutDlg::DoDataExchange(CDataExchange* pDX)
454 {
455 	CDialog::DoDataExchange(pDX);
456 }
457 
BEGIN_MESSAGE_MAP(CAboutDlg,CDialog)458 BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
459 END_MESSAGE_MAP()
460 
461 // App command to run the dialog
462 void CMultiApp::OnAppAbout()
463 {
464 	CAboutDlg aboutDlg;
465 	aboutDlg.DoModal();
466 }
467 
468 
469