Files
EF3-Interface/PcDmis/Base/Interfac/Msi/Hsi/Keyence/Keyence_Proto.cpp
T
2013-05-09 20:29:54 +08:00

660 lines
23 KiB
C++

#include "stdafx.h"
#include "Keyence_Proto.h"
#include "math.h"
#define MY_CONFIG 1
#define MAX_DEVPATH_LENGTH 256
#define ENDPOINT_TIMEOUT 500
//***** Static Data *****
struct_Keyence_ep_buff CKeyence_Proto::ep_buff[lEPSIZE];
//================================================================
int CKeyence_Proto::g_hEP81_Thread_State=THREAD_PAUSED;
HANDLE CKeyence_Proto::g_hEP81_Thread_Id=NULL;
//================================================================
int CKeyence_Proto::g_hEP82_Thread_State=THREAD_PAUSED;
HANDLE CKeyence_Proto::g_hEP82_Thread_Id=NULL;
//================================================================
int CKeyence_Proto::g_hEP01_Thread_State=THREAD_PAUSED;
HANDLE CKeyence_Proto::g_hEP01_Thread_Id=NULL;
HANDLE CKeyence_Proto::g_hEP01_Serial_Mutex;
//================================================================
int CKeyence_Proto::g_hEP02_Thread_State=THREAD_PAUSED;
HANDLE CKeyence_Proto::g_hEP02_Thread_Id=NULL;
HANDLE CKeyence_Proto::g_hEP02_Serial_Mutex;
//================================================================
struct_Keyence_machine CKeyence_Proto::g_machine;
usb_dev_handle *CKeyence_Proto::g_dev=NULL;
CLogger *CKeyence_Proto::g_pLogger;
HANDLE CKeyence_Proto::g_hHomedEvent = NULL;
//===========================================================================
// Worker Thread to serialize EP_KEYENCE_01 commands.
//===========================================================================
unsigned __stdcall CKeyence_Proto::g_EP01_Thread(LPVOID pThis)
{
CKeyence_Proto* _This = (CKeyence_Proto*)pThis;
for (;;)
{
TRACE0("g_hSerialUsbThread in loop set.\n");
if (g_hEP01_Thread_State == THREAD_EXIT)
ExitThread(0);
WaitForSingleObject(ep_buff[EP_01_CMD_IDX]._event,INFINITE);
TRACE0("g_hSerialUsbThread obtained event.\n");
switch (g_hEP01_Thread_State)
{
case THREAD_EXIT:
{
ExitThread(0);
}
case THREAD_PAUSED:
break;
case THREAD_RUNNING:
{
TRACE0("g_hSerialUsbThread processing _send_usb_data();\n");
_This->_send_usb_data(EP_01_CMD_IDX);
TRACE0("g_hSerialUsbThread return from _send_usb_data();\n");
break;
}
default:
ExitThread(0);
}
};
g_hEP01_Thread_State = THREAD_EXIT;
ExitThread(0);
};
//===========================================================================
// Worker Thread to serialize EP_KEYENCE_02 commands.
//===========================================================================
unsigned __stdcall CKeyence_Proto::g_EP02_Thread(LPVOID pThis)
{
CKeyence_Proto* _This = (CKeyence_Proto*)pThis;
for (;;)
{
TRACE0("g_hEP02_Thread in loop set.\n");
if (g_hEP02_Thread_State == THREAD_EXIT)
ExitThread(0);
WaitForSingleObject(ep_buff[EP_02_CMD_IDX]._event,INFINITE);
TRACE0("g_hEP02_Thread obtained event.\n");
switch (g_hEP02_Thread_State)
{
case THREAD_EXIT:
{
ExitThread(0);
}
case THREAD_PAUSED:
break;
case THREAD_RUNNING:
{
TRACE0("g_hEP02_Thread calling _send_usb_data. EP_KEYENCE_02; %x\n");
_This->_send_usb_data(EP_02_CMD_IDX);
TRACE0("g_hEP02_Thread return _send_usb_data. EP_KEYENCE_02; %x\n");
break;
}
default:
ExitThread(0);
}
};
g_hEP02_Thread_State = THREAD_EXIT;
ExitThread(0);
};
//******************************************************************************
// This is the worker thread to process USBD_TRANSFER_DIRECTION_IN
//******************************************************************************
unsigned __stdcall CKeyence_Proto::g_EP81_Thread(LPVOID pThis)
{
CKeyence_Proto* _This = (CKeyence_Proto*)pThis;
for (;;)
{
WaitForSingleObject(ep_buff[EP_81_DATA_IDX]._event, INFINITE);
switch (g_hEP81_Thread_State)
{
case THREAD_EXIT:
{
ExitThread(0);
}
case THREAD_PAUSED:
break;
case THREAD_RUNNING:
{
_This->_reap_async_8x(EP_81_DATA_IDX);
break;
}
default:
ExitThread(0);
}
}
}
//******************************************************************************
// This is the worker thread to process USBD_TRANSFER_DIRECTION_IN
//******************************************************************************
unsigned __stdcall CKeyence_Proto::g_EP82_Thread(LPVOID pThis)
{
CKeyence_Proto* _This = (CKeyence_Proto*)pThis;
for (;;)
{
WaitForSingleObject(ep_buff[EP_82_DATA_IDX]._event, INFINITE);
switch (g_hEP82_Thread_State)
{
case THREAD_EXIT:
{
ExitThread(0);
}
case THREAD_PAUSED:
break;
case THREAD_RUNNING:
{
_This->_reap_async_8x(EP_82_DATA_IDX);
break;
}
default:
ExitThread(0);
}
}
}
//===========================================================================
void CKeyence_Proto::Trace_EP_Buff(long lIndex)
{
UCHAR tmp[256];
CString csTmp;
memcpy(tmp, ep_buff[lIndex]._buffer, ep_buff[lIndex]._size);
csTmp = _T("Trace_EP_Buff _59 ");
for (int ii= 0 ; ii < ep_buff[lIndex]._size ; ++ii)
{
CString csTmpHex;
csTmpHex.Format(_T("%2X"), tmp[ii] );
csTmp += csTmpHex;
}
TRACE1("_process_KEYENCE_CMD_GET_INDEX_4E() Trace_EP_Buff %s \n", csTmp);
}
//******************************************************************************
// Parse the data received based on the index (which EP are we processing).
// The CCmdObj should only have one CMD_STATUS_PROCESSING.
// Update CCmdObj _ep_01_status and _ep_81_status.
// Update _status to CMD_STATUS_COMPLETE when both _ep_01_status and _ep_81_status
// are CMD_STATUS_COMPLETE.
//
//******************************************************************************
void CKeyence_Proto::_process_rcv_transfer_data(int iEP)
{
static long lRcvCnt = 0;
static long lRcvCnt2 = 0;
switch (iEP)
{
case EP_01_CMD_IDX :
TRACE0("_process_rcv_transfer_data() : Update EP_01_CMD_IDX.\r\n");
++lRcvCnt;
break;
case EP_81_DATA_IDX : //
++lRcvCnt;
TRACE0("_process_rcv_transfer_data() : Update EP_81_DATA_IDX status.\r\n");
break;
case EP_02_CMD_IDX :
TRACE0("_process_rcv_transfer_data() : Update EP_02_CMD_IDX.\r\n");
++lRcvCnt2;
break;
case EP_82_DATA_IDX :
// parse result and put into its proper place.
_process_KEYENCE_CMD_GET_LASER_DATA();
++lRcvCnt2;
break;
default:
break;
};
lRcvCnt = (lRcvCnt == 2) ? 0:lRcvCnt;
lRcvCnt2 = (lRcvCnt2 == 2) ? 0:lRcvCnt2;
};
//******************************************************************************
CKeyence_Proto::CKeyence_Proto()
{
ep_buff[EP_01_CMD_IDX]._ep = EP_KEYENCE_01;
ep_buff[EP_81_DATA_IDX]._ep = EP_KEYENCE_81;
ep_buff[EP_02_CMD_IDX]._ep = EP_KEYENCE_02;
ep_buff[EP_82_DATA_IDX]._ep = EP_KEYENCE_82;
for (int i=0;i<lEPSIZE;i++)
{
ep_buff[i]._size = 0;
ep_buff[i]._save_send_cmd = 99;
ep_buff[i]._async_context = NULL;
ep_buff[i]._buffer = (char *)malloc(MAX_BUFF_SIZE);
ep_buff[i]._hProtoPending = false;
ep_buff[i]._event = NULL;
};
g_pLogger = new CLogger(_T("UtilityDebug.Log"));
};
//******************************************************************************
CKeyence_Proto::~CKeyence_Proto()
{
for (int i=0;i<lEPSIZE;i++)
{
free(ep_buff[i]._buffer);
};
delete g_pLogger;
g_pLogger = NULL;
}
#pragma warning(disable:4996)
//******************************************************************************
//******************************************************************************
usb_dev_handle* CKeyence_Proto::_open_usb_dev(void)
{
struct usb_bus *bus = NULL;
struct usb_device *dev = NULL;
for (bus = usb_get_busses(); bus; bus = bus->next)
{
for (dev = bus->devices; dev; dev = dev->next)
{
if (dev->descriptor.idVendor == KEYENCE_VID && dev->descriptor.idProduct == KEYENCE_PID)
{
return usb_open(dev);
}
}
}
return NULL;
}
//******************************************************************************
SSI_STATUS_MOTION CKeyence_Proto::_usb_reset(void)
{
if (g_dev)
{
usb_reset(g_dev);
g_dev = NULL;
}
else
{
ASSERT(0);
return SSI_STATUS_MOTION_TIMEOUT;
}
return SSI_STATUS_MOTION_TIMEOUT;
}
//******************************************************************************
// Send is direct and async.
// The receive thread will receive data and interpret it.
//******************************************************************************
SSI_STATUS_MOTION CKeyence_Proto::Init_MvUsb()
{
// Set initial state of the machine
g_machine.s_status._machine_running = false;
SSI_STATUS_MOTION Status=SSI_STATUS_MOTION_NORMAL;
UNREFERENCED_PARAMETER(Status);
/*if (g_pLogger->m_lLogMask & LOGACTIONS)
g_pLogger->SendAndFlushPerMode(_T("Enter Initialize Mv Usb\n"));
*/
int usb_status = NULL;
usb_init(); // initialize the library
usb_status = usb_find_busses(); // find all busses
usb_status = usb_find_devices(); // find all connected devices
g_dev = _open_usb_dev();
if (!g_dev)
{
MessageBox(NULL, _T("Unable to open device"), _T("Message"), MB_OK);
g_pLogger->SendAndFlushPerMode(_T("Unable to open device %s"), usb_strerror());
return SSI_STATUS_MOTION_DATALINK_ERROR;
}
if (usb_set_configuration(g_dev, MY_CONFIG) < 0)
{
MessageBox(NULL, _T("Unable to SET CONFIGURATION"), _T("Message"), MB_OK);
return SSI_STATUS_MOTION_DATALINK_ERROR;
}
if (usb_claim_interface(g_dev, 0) < 0)
{
usb_close(g_dev);
MessageBox(NULL, _T("Unable to CLAIM DEVICE"), _T("Message"), MB_OK);
return SSI_STATUS_MOTION_DATALINK_ERROR;
}
// ********************************************************************
// This event is used to kick the Serial Usb Command process. This threading model
// is important because the underlying library is not thread-safe.
//
ep_buff[EP_01_CMD_IDX]._event = CreateEvent(NULL, // default security attributes
FALSE, // manual reset event object
NULL, // signaled
NULL); // unamed object
g_hEP01_Thread_Id = CreateThread( (LPSECURITY_ATTRIBUTES) NULL,
0,
(LPTHREAD_START_ROUTINE) g_EP01_Thread,
(LPVOID) this,
0,
NULL);
g_hEP01_Thread_State = THREAD_RUNNING;
// ********************************************************************
// This event is used to kick the Serial Usb Command process. This threading model
// is important because the underlying library is not thread-safe.
//
ep_buff[EP_02_CMD_IDX]._event = CreateEvent(NULL, // default security attributes
FALSE, // manual reset event object
NULL, // signaled
NULL); // unamed object
g_hEP02_Thread_Id = CreateThread( (LPSECURITY_ATTRIBUTES) NULL,
0,
(LPTHREAD_START_ROUTINE) g_EP02_Thread,
(LPVOID) this,
0,
NULL);
g_hEP02_Thread_State = THREAD_RUNNING;
// ********************************************************************
// Prepare and start EP_KEYENCE_81 Thread - Use async commit.
//
ep_buff[EP_81_DATA_IDX]._event = CreateEvent(NULL, // default security attributes
FALSE, // manual reset event object
NULL, // signaled
NULL); // unamed object
g_hEP81_Thread_State = THREAD_PAUSED;
g_hEP81_Thread_Id = CreateThread( (LPSECURITY_ATTRIBUTES) NULL,
0,
(LPTHREAD_START_ROUTINE) g_EP81_Thread,
(LPVOID) this,
0,
NULL);
g_hEP01_Serial_Mutex = CreateMutex(NULL, // default security attributes
FALSE, // initial owner
NULL); // name
// ********************************************************************
// Prepare and start EP_KEYENCE_82 Thread - Use async commit.
//
ep_buff[EP_82_DATA_IDX]._event = CreateEvent(NULL, // default security attributes
FALSE, // manual reset event object
NULL, // signaled
NULL); // unamed object
g_hEP82_Thread_State = THREAD_PAUSED;
g_hEP82_Thread_Id = CreateThread( (LPSECURITY_ATTRIBUTES) NULL,
0,
(LPTHREAD_START_ROUTINE) g_EP82_Thread,
(LPVOID) this,
0,
NULL);
g_hEP02_Serial_Mutex = CreateMutex(NULL, // default security attributes
FALSE, // initial owner
NULL); // name
// *********************************************************************
g_hHomedEvent = CreateEvent(NULL, // default security attributes
TRUE, // manual reset event object
FALSE, // initial state is signaled
NULL); // unamed object
//if (g_pLogger->m_lLogMask & LOGACTIONS)
// g_pLogger->SendAndFlushPerMode(_T("Exit Initialize Usb\n"));
return SSI_STATUS_MOTION_NORMAL;
}
//******************************************************************************
SSI_STATUS_MOTION CKeyence_Proto::Exit_MvUsb()
{
SSI_STATUS_MOTION Status=SSI_STATUS_MOTION_NORMAL;
//if (g_pLogger->m_lLogMask & LOGACTIONS)
// g_pLogger->SendAndFlushPerMode(_T("Enter Exit_MvUsb\n"));
g_hEP81_Thread_State = THREAD_EXIT;
g_hEP82_Thread_State = THREAD_EXIT;
g_hEP01_Thread_State = THREAD_EXIT;
g_hEP02_Thread_State = THREAD_EXIT;
SetEvent(ep_buff[EP_81_DATA_IDX]._event);
if (g_hEP81_Thread_Id)
{
DWORD dwCode = STILL_ACTIVE;
while (dwCode == STILL_ACTIVE)
{
GetExitCodeThread(g_hEP81_Thread_Id,&dwCode);
Sleep(1);
}
}
SetEvent(ep_buff[EP_82_DATA_IDX]._event);
if (g_hEP82_Thread_Id)
{
DWORD dwCode = STILL_ACTIVE;
while (dwCode == STILL_ACTIVE)
{
GetExitCodeThread(g_hEP82_Thread_Id,&dwCode);
Sleep(1);
}
}
SetEvent(ep_buff[EP_01_CMD_IDX]._event);
if (g_hEP01_Thread_Id)
{
DWORD dwCode = STILL_ACTIVE;
while (dwCode == STILL_ACTIVE)
{
GetExitCodeThread(g_hEP01_Thread_Id,&dwCode);
Sleep(1);
}
}
SetEvent(ep_buff[EP_02_CMD_IDX]._event);
if (g_hEP02_Thread_Id)
{
DWORD dwCode = STILL_ACTIVE;
while (dwCode == STILL_ACTIVE)
{
GetExitCodeThread(g_hEP02_Thread_Id,&dwCode);
Sleep(1);
}
}
if (g_dev)
{
usb_release_interface(g_dev,0);
usb_close(g_dev);
g_dev = NULL;
}
SetEvent(ep_buff[EP_81_DATA_IDX]._event);
CloseHandle(ep_buff[EP_81_DATA_IDX]._event);
SetEvent(ep_buff[EP_82_DATA_IDX]._event);
CloseHandle(ep_buff[EP_82_DATA_IDX]._event);
g_hEP01_Thread_State = THREAD_EXIT;
SetEvent(ep_buff[EP_01_CMD_IDX]._event);
CloseHandle(ep_buff[EP_01_CMD_IDX]._event);
g_hEP02_Thread_State = THREAD_EXIT;
SetEvent(ep_buff[EP_02_CMD_IDX]._event);
CloseHandle(ep_buff[EP_02_CMD_IDX]._event);
ReleaseMutex(g_hEP01_Serial_Mutex);
CloseHandle(g_hEP01_Serial_Mutex);
ReleaseMutex(g_hEP02_Serial_Mutex);
CloseHandle(g_hEP02_Serial_Mutex);
//if (g_pLogger->m_lLogMask & LOGACTIONS)
// g_pLogger->SendAndFlushPerMode(_T("Exit Exit_MvUsb\n"));
return Status;
}
//******************************************************************************
// Kick the g_hEP01_Thread_Event to get the g_EP01_Thread going.
// iEP = EP_KEYENCE_01 or EP_KEYENCE_02 = 0x01 or 0x02
//******************************************************************************
SSI_STATUS_MOTION CKeyence_Proto::_do_single_threaded_usb_comm(int iEP_Base)
{
TRACE1("=====_do_single_threaded_usb_comm(iEP) g_hEP01_Thread_Event. %x\n", iEP_Base);
while ((ep_buff[iEP_Base]._hProtoPending == TRUE) || (ep_buff[iEP_Base+1]._hProtoPending == TRUE))
{
ASSERT(0);
Sleep(3);
}
ep_buff[iEP_Base]._hProtoPending = ep_buff[iEP_Base+1]._hProtoPending = TRUE;
TRACE1("=====_do_single_threaded_usb_comm(iEP_Base) SetEvent(g_hEP01_Thread_Event): %X \r\n", ep_buff[iEP_Base]._save_send_cmd);
SetEvent(ep_buff[iEP_Base]._event);
while ((ep_buff[iEP_Base]._hProtoPending == TRUE) || (ep_buff[iEP_Base+1]._hProtoPending == TRUE))
{
Sleep(3);
}
TRACE1("=====_do_single_threaded_usb_comm(iEP) g_hProtoDoneEvents. %x\n", iEP_Base);
return SSI_STATUS_MOTION_NORMAL;
}
//******************************************************************************
// This startup just kicks off the EP_KEYENCE_81 worker thread.
//******************************************************************************
SSI_STATUS_MOTION CKeyence_Proto::_start_machine()
{
g_hEP81_Thread_State = THREAD_RUNNING;
g_hEP82_Thread_State = THREAD_RUNNING;
g_machine.s_status._machine_running = true;
return SSI_STATUS_MOTION_NORMAL;
};
//===============================================================================
SSI_STATUS_MOTION CKeyence_Proto::_shutdown_machine()
{
g_machine.s_status._machine_running = false;
return SSI_STATUS_MOTION_NORMAL;
};
//===============================================================================
// iEP = EP_KEYENCE_01 or EP_KEYENCE_02
//===============================================================================
SSI_STATUS_MOTION CKeyence_Proto::_submit_async_8x(int iEP_Base)
{
int _ret;
_ret = usb_bulk_setup_async(g_dev, &(ep_buff[iEP_Base]._async_context), (unsigned char)ep_buff[iEP_Base]._ep);
if (_ret < 0)
{
return SSI_STATUS_MOTION_SETUP_ASYNC_CONTEXT_ERROR;
}
_ret = usb_submit_async(ep_buff[iEP_Base]._async_context, ep_buff[iEP_Base]._buffer, ep_buff[iEP_Base]._size);
if (_ret < 0)
{
printf("error usb_submit_async_ep_xx:\n%s\n", usb_strerror());
return SSI_STATUS_MOTION_SETUP_ASYNC_CONTEXT_ERROR;
}
return SSI_STATUS_MOTION_NORMAL;
}
//===============================================================================
// iEP_Base : EP_81_DATA_IDX/EP_82_DATA_IDX
//
//===============================================================================
SSI_STATUS_MOTION CKeyence_Proto::_reap_async_8x(int iEP_Base)
{
int _ret;
_ret = usb_reap_async(ep_buff[iEP_Base]._async_context, 1000);
if (_ret > 0)
{
_process_rcv_transfer_data(iEP_Base);
usb_free_async(&(ep_buff[iEP_Base]._async_context));
ep_buff[iEP_Base]._hProtoPending = false;
}
else
{
usb_free_async(&(ep_buff[iEP_Base]._async_context));
ASSERT(0);
return SSI_STATUS_MOTION_TIMEOUT;
}
return SSI_STATUS_MOTION_NORMAL;
}
//===============================================================================
// _send_usb_data(iEP) sends data to the corresponding iEP channel.
// iEP = EP_KEYENCE_01 / EP_KEYENCE_02 EP_KEYENCE_01 = 0x01; EP_KEYENCE_02 = 0x02;
//===============================================================================
SSI_STATUS_MOTION CKeyence_Proto::_send_usb_data(int iEP_Base)
{
int _ret;
ep_buff[iEP_Base]._save_send_cmd = ep_buff[iEP_Base]._buffer[0];
ep_buff[iEP_Base]._save_send_cmd0 = ep_buff[iEP_Base]._buffer[1];
ep_buff[iEP_Base]._save_send_cmd1 = ep_buff[iEP_Base]._buffer[2];
TRACE3("_send_usb_data() iEP : %X - ep_buff[iEP]._save_send_cmd : %X ._buffer[0] : %X\r\n", iEP_Base, ep_buff[EP_01_CMD_IDX]._save_send_cmd, ep_buff[EP_81_DATA_IDX]._buffer[0]);
_ret = usb_bulk_setup_async(g_dev, &(ep_buff[iEP_Base]._async_context), (unsigned char)ep_buff[iEP_Base]._ep);
if (_ret < 0)
{
return SSI_STATUS_MOTION_SETUP_ASYNC_CONTEXT_ERROR;
}
_ret = usb_submit_async(ep_buff[iEP_Base]._async_context, ep_buff[iEP_Base]._buffer, ep_buff[iEP_Base]._size);//send data
if (_ret < 0)
{
printf("error usb_submit_async_ep_xx:\n%s\n", usb_strerror());
return SSI_STATUS_MOTION_SETUP_ASYNC_CONTEXT_ERROR;
}
TRACE1("_submit_async_8x(EP:%X)\r\n", iEP_Base);
//
ep_buff[iEP_Base+1]._save_send_cmd = ep_buff[iEP_Base+1]._buffer[0];
ep_buff[iEP_Base+1]._save_send_cmd0 = ep_buff[iEP_Base+1]._buffer[1];
ep_buff[iEP_Base+1]._save_send_cmd1 = ep_buff[iEP_Base+1]._buffer[2];
//
_submit_async_8x(iEP_Base+1); // Send EP_KEYENCE_81/EP_KEYENCE_82
// Get ready to receive on EP_KEYENCE_81 or EP_KEYENCE_82
SetEvent(ep_buff[iEP_Base+1]._event);
// Get ready to receive on EP_KEYENCE_01 or EP_KEYENCE_02
_ret = usb_reap_async(ep_buff[iEP_Base]._async_context, 10000);
if (_ret > 0)
{
_process_rcv_transfer_data(iEP_Base);
usb_free_async(&(ep_buff[iEP_Base]._async_context));
ep_buff[iEP_Base]._hProtoPending = false;
}
else
{
usb_free_async(&(ep_buff[iEP_Base]._async_context));
ASSERT(0);
return SSI_STATUS_MOTION_TIMEOUT;
}
return SSI_STATUS_MOTION_NORMAL;
}
//==============================================================
SSI_STATUS_MOTION CKeyence_Proto::_send_cmd_KEYENCE_CMD_GET_LASER_DATA()
{
WaitForSingleObject(g_hEP01_Serial_Mutex, INFINITE);
memset(ep_buff[EP_01_CMD_IDX]._buffer, 0x00, MAX_BUFF_SIZE);
ep_buff[EP_01_CMD_IDX]._buffer[0] = 0x00;
ep_buff[EP_01_CMD_IDX]._buffer[1] = 0x01;
ep_buff[EP_01_CMD_IDX]._buffer[2] = 0x01;
ep_buff[EP_01_CMD_IDX]._buffer[3] = 0x01;
ep_buff[EP_01_CMD_IDX]._buffer[4] = 0x01;
ep_buff[EP_01_CMD_IDX]._buffer[5] = 0x01;
ep_buff[EP_01_CMD_IDX]._size = 0x0C;
ep_buff[EP_82_DATA_IDX]._size = 0x45;
_do_single_threaded_usb_comm(EP_01_CMD_IDX);
ReleaseMutex(g_hEP01_Serial_Mutex);
return SSI_STATUS_MOTION_NORMAL;
};
//==============================================================
SSI_STATUS_MOTION CKeyence_Proto::_process_KEYENCE_CMD_GET_LASER_DATA()
{
return SSI_STATUS_MOTION_NORMAL;
};