|
@@ -70,7 +70,6 @@
|
|
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
-
|
|
|
// kernel modul and driver
|
|
|
|
|
|
//#include <linux/version.h>
|
|
@@ -103,19 +102,16 @@
|
|
|
//#include "kernel/EplPdokCal.h"
|
|
|
#include "proc_fs.h"
|
|
|
|
|
|
-
|
|
|
-
|
|
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
|
|
|
// remove ("make invisible") obsolete symbols for kernel versions 2.6
|
|
|
// and higher
|
|
|
- #define MOD_INC_USE_COUNT
|
|
|
- #define MOD_DEC_USE_COUNT
|
|
|
- #define EXPORT_NO_SYMBOLS
|
|
|
+#define MOD_INC_USE_COUNT
|
|
|
+#define MOD_DEC_USE_COUNT
|
|
|
+#define EXPORT_NO_SYMBOLS
|
|
|
#else
|
|
|
- #error "This driver needs a 2.6.x kernel or higher"
|
|
|
+#error "This driver needs a 2.6.x kernel or higher"
|
|
|
#endif
|
|
|
|
|
|
-
|
|
|
/***************************************************************************/
|
|
|
/* */
|
|
|
/* */
|
|
@@ -127,19 +123,15 @@
|
|
|
// Metainformation
|
|
|
MODULE_LICENSE("Dual BSD/GPL");
|
|
|
#ifdef MODULE_AUTHOR
|
|
|
- MODULE_AUTHOR("Daniel.Krueger@SYSTEC-electronic.com");
|
|
|
- MODULE_DESCRIPTION("EPL API driver");
|
|
|
+MODULE_AUTHOR("Daniel.Krueger@SYSTEC-electronic.com");
|
|
|
+MODULE_DESCRIPTION("EPL API driver");
|
|
|
#endif
|
|
|
|
|
|
-
|
|
|
//---------------------------------------------------------------------------
|
|
|
// Configuration
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
-
|
|
|
-#define EPLLIN_DRV_NAME "systec_epl" // used for <register_chrdev>
|
|
|
-
|
|
|
-
|
|
|
+#define EPLLIN_DRV_NAME "systec_epl" // used for <register_chrdev>
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
// Constant definitions
|
|
@@ -147,23 +139,22 @@ MODULE_LICENSE("Dual BSD/GPL");
|
|
|
|
|
|
// TracePoint support for realtime-debugging
|
|
|
#ifdef _DBG_TRACE_POINTS_
|
|
|
- void PUBLIC TgtDbgSignalTracePoint (BYTE bTracePointNumber_p);
|
|
|
- #define TGT_DBG_SIGNAL_TRACE_POINT(p) TgtDbgSignalTracePoint(p)
|
|
|
+void PUBLIC TgtDbgSignalTracePoint(BYTE bTracePointNumber_p);
|
|
|
+#define TGT_DBG_SIGNAL_TRACE_POINT(p) TgtDbgSignalTracePoint(p)
|
|
|
#else
|
|
|
- #define TGT_DBG_SIGNAL_TRACE_POINT(p)
|
|
|
+#define TGT_DBG_SIGNAL_TRACE_POINT(p)
|
|
|
#endif
|
|
|
|
|
|
#define EVENT_STATE_INIT 0
|
|
|
-#define EVENT_STATE_IOCTL 1 // ioctl entered and ready to receive EPL event
|
|
|
-#define EVENT_STATE_READY 2 // EPL event can be forwarded to user application
|
|
|
-#define EVENT_STATE_TERM 3 // terminate processing
|
|
|
+#define EVENT_STATE_IOCTL 1 // ioctl entered and ready to receive EPL event
|
|
|
+#define EVENT_STATE_READY 2 // EPL event can be forwarded to user application
|
|
|
+#define EVENT_STATE_TERM 3 // terminate processing
|
|
|
|
|
|
#define EPL_STATE_NOTOPEN 0
|
|
|
#define EPL_STATE_NOTINIT 1
|
|
|
#define EPL_STATE_RUNNING 2
|
|
|
#define EPL_STATE_SHUTDOWN 3
|
|
|
|
|
|
-
|
|
|
//---------------------------------------------------------------------------
|
|
|
// Global variables
|
|
|
//---------------------------------------------------------------------------
|
|
@@ -171,73 +162,65 @@ MODULE_LICENSE("Dual BSD/GPL");
|
|
|
#ifdef CONFIG_DEVFS_FS
|
|
|
|
|
|
// driver major number
|
|
|
- static int nDrvMajorNumber_g;
|
|
|
+static int nDrvMajorNumber_g;
|
|
|
|
|
|
#else
|
|
|
|
|
|
// device number (major and minor)
|
|
|
- static dev_t nDevNum_g;
|
|
|
- static struct cdev *pEpl_cdev_g;
|
|
|
+static dev_t nDevNum_g;
|
|
|
+static struct cdev *pEpl_cdev_g;
|
|
|
|
|
|
#endif
|
|
|
|
|
|
-
|
|
|
static volatile unsigned int uiEplState_g = EPL_STATE_NOTOPEN;
|
|
|
|
|
|
-static struct semaphore SemaphoreCbEvent_g; // semaphore for EplLinCbEvent
|
|
|
-static wait_queue_head_t WaitQueueCbEvent_g; // wait queue EplLinCbEvent
|
|
|
-static wait_queue_head_t WaitQueueProcess_g; // wait queue for EplApiProcess (user process)
|
|
|
-static wait_queue_head_t WaitQueueRelease_g; // wait queue for EplLinRelease
|
|
|
-static atomic_t AtomicEventState_g = ATOMIC_INIT(EVENT_STATE_INIT);
|
|
|
-static tEplApiEventType EventType_g; // event type (enum)
|
|
|
-static tEplApiEventArg* pEventArg_g; // event argument (union)
|
|
|
-static tEplKernel RetCbEvent_g; // return code from event callback function
|
|
|
-static wait_queue_head_t WaitQueueCbSync_g; // wait queue EplLinCbSync
|
|
|
-static wait_queue_head_t WaitQueuePI_In_g; // wait queue for EplApiProcessImageExchangeIn (user process)
|
|
|
-static atomic_t AtomicSyncState_g = ATOMIC_INIT(EVENT_STATE_INIT);
|
|
|
-
|
|
|
+static struct semaphore SemaphoreCbEvent_g; // semaphore for EplLinCbEvent
|
|
|
+static wait_queue_head_t WaitQueueCbEvent_g; // wait queue EplLinCbEvent
|
|
|
+static wait_queue_head_t WaitQueueProcess_g; // wait queue for EplApiProcess (user process)
|
|
|
+static wait_queue_head_t WaitQueueRelease_g; // wait queue for EplLinRelease
|
|
|
+static atomic_t AtomicEventState_g = ATOMIC_INIT(EVENT_STATE_INIT);
|
|
|
+static tEplApiEventType EventType_g; // event type (enum)
|
|
|
+static tEplApiEventArg *pEventArg_g; // event argument (union)
|
|
|
+static tEplKernel RetCbEvent_g; // return code from event callback function
|
|
|
+static wait_queue_head_t WaitQueueCbSync_g; // wait queue EplLinCbSync
|
|
|
+static wait_queue_head_t WaitQueuePI_In_g; // wait queue for EplApiProcessImageExchangeIn (user process)
|
|
|
+static atomic_t AtomicSyncState_g = ATOMIC_INIT(EVENT_STATE_INIT);
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
// Local types
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
-typedef struct
|
|
|
-{
|
|
|
- void* m_pUserArg;
|
|
|
- void* m_pData;
|
|
|
+typedef struct {
|
|
|
+ void *m_pUserArg;
|
|
|
+ void *m_pData;
|
|
|
|
|
|
} tEplLinSdoBufHeader;
|
|
|
|
|
|
-
|
|
|
//---------------------------------------------------------------------------
|
|
|
// Local variables
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
-
|
|
|
-
|
|
|
//---------------------------------------------------------------------------
|
|
|
// Prototypes of internal functions
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
-tEplKernel PUBLIC EplLinCbEvent(
|
|
|
- tEplApiEventType EventType_p, // IN: event type (enum)
|
|
|
- tEplApiEventArg* pEventArg_p, // IN: event argument (union)
|
|
|
- void GENERIC* pUserArg_p);
|
|
|
+tEplKernel PUBLIC EplLinCbEvent(tEplApiEventType EventType_p, // IN: event type (enum)
|
|
|
+ tEplApiEventArg * pEventArg_p, // IN: event argument (union)
|
|
|
+ void GENERIC * pUserArg_p);
|
|
|
|
|
|
tEplKernel PUBLIC EplLinCbSync(void);
|
|
|
|
|
|
-static int __init EplLinInit (void);
|
|
|
-static void __exit EplLinExit (void);
|
|
|
-
|
|
|
-
|
|
|
-static int EplLinOpen (struct inode* pDeviceFile_p, struct file* pInstance_p);
|
|
|
-static int EplLinRelease (struct inode* pDeviceFile_p, struct file* pInstance_p);
|
|
|
-static ssize_t EplLinRead (struct file* pInstance_p, char* pDstBuff_p, size_t BuffSize_p, loff_t* pFileOffs_p);
|
|
|
-static ssize_t EplLinWrite (struct file* pInstance_p, const char* pSrcBuff_p, size_t BuffSize_p, loff_t* pFileOffs_p);
|
|
|
-static int EplLinIoctl (struct inode* pDeviceFile_p, struct file* pInstance_p, unsigned int uiIoctlCmd_p, unsigned long ulArg_p);
|
|
|
-
|
|
|
-
|
|
|
+static int __init EplLinInit(void);
|
|
|
+static void __exit EplLinExit(void);
|
|
|
|
|
|
+static int EplLinOpen(struct inode *pDeviceFile_p, struct file *pInstance_p);
|
|
|
+static int EplLinRelease(struct inode *pDeviceFile_p, struct file *pInstance_p);
|
|
|
+static ssize_t EplLinRead(struct file *pInstance_p, char *pDstBuff_p,
|
|
|
+ size_t BuffSize_p, loff_t * pFileOffs_p);
|
|
|
+static ssize_t EplLinWrite(struct file *pInstance_p, const char *pSrcBuff_p,
|
|
|
+ size_t BuffSize_p, loff_t * pFileOffs_p);
|
|
|
+static int EplLinIoctl(struct inode *pDeviceFile_p, struct file *pInstance_p,
|
|
|
+ unsigned int uiIoctlCmd_p, unsigned long ulArg_p);
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
// Kernel Module specific Data Structures
|
|
@@ -245,27 +228,19 @@ static int EplLinIoctl (struct inode* pDeviceFile_p, struct file* pInsta
|
|
|
|
|
|
EXPORT_NO_SYMBOLS;
|
|
|
|
|
|
-
|
|
|
-
|
|
|
module_init(EplLinInit);
|
|
|
module_exit(EplLinExit);
|
|
|
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-static struct file_operations EplLinFileOps_g =
|
|
|
-{
|
|
|
- .owner = THIS_MODULE,
|
|
|
- .open = EplLinOpen,
|
|
|
- .release = EplLinRelease,
|
|
|
- .read = EplLinRead,
|
|
|
- .write = EplLinWrite,
|
|
|
- .ioctl = EplLinIoctl,
|
|
|
+static struct file_operations EplLinFileOps_g = {
|
|
|
+ .owner = THIS_MODULE,
|
|
|
+ .open = EplLinOpen,
|
|
|
+ .release = EplLinRelease,
|
|
|
+ .read = EplLinRead,
|
|
|
+ .write = EplLinWrite,
|
|
|
+ .ioctl = EplLinIoctl,
|
|
|
|
|
|
};
|
|
|
|
|
|
-
|
|
|
-
|
|
|
//=========================================================================//
|
|
|
// //
|
|
|
// P U B L I C F U N C T I O N S //
|
|
@@ -278,1040 +253,1008 @@ static struct file_operations EplLinFileOps_g =
|
|
|
// -> insmod driver
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
-static int __init EplLinInit (void)
|
|
|
+static int __init EplLinInit(void)
|
|
|
{
|
|
|
|
|
|
-tEplKernel EplRet;
|
|
|
-int iErr;
|
|
|
-int iRet;
|
|
|
+ tEplKernel EplRet;
|
|
|
+ int iErr;
|
|
|
+ int iRet;
|
|
|
#ifdef CONFIG_DEVFS_FS
|
|
|
-int nMinorNumber;
|
|
|
+ int nMinorNumber;
|
|
|
#endif
|
|
|
|
|
|
- TRACE0("EPL: + EplLinInit...\n");
|
|
|
- TRACE2("EPL: Driver build: %s / %s\n", __DATE__, __TIME__);
|
|
|
-
|
|
|
- iRet = 0;
|
|
|
-
|
|
|
- // initialize global variables
|
|
|
- atomic_set(&AtomicEventState_g, EVENT_STATE_INIT);
|
|
|
- sema_init(&SemaphoreCbEvent_g, 1);
|
|
|
- init_waitqueue_head(&WaitQueueCbEvent_g);
|
|
|
- init_waitqueue_head(&WaitQueueProcess_g);
|
|
|
- init_waitqueue_head(&WaitQueueRelease_g);
|
|
|
+ TRACE0("EPL: + EplLinInit...\n");
|
|
|
+ TRACE2("EPL: Driver build: %s / %s\n", __DATE__, __TIME__);
|
|
|
|
|
|
+ iRet = 0;
|
|
|
|
|
|
+ // initialize global variables
|
|
|
+ atomic_set(&AtomicEventState_g, EVENT_STATE_INIT);
|
|
|
+ sema_init(&SemaphoreCbEvent_g, 1);
|
|
|
+ init_waitqueue_head(&WaitQueueCbEvent_g);
|
|
|
+ init_waitqueue_head(&WaitQueueProcess_g);
|
|
|
+ init_waitqueue_head(&WaitQueueRelease_g);
|
|
|
|
|
|
#ifdef CONFIG_DEVFS_FS
|
|
|
|
|
|
- // register character device handler
|
|
|
- TRACE2("EPL: Installing Driver '%s', Version %s...\n", EPLLIN_DRV_NAME, EPL_PRODUCT_VERSION);
|
|
|
- TRACE0("EPL: (using dynamic major number assignment)\n");
|
|
|
- nDrvMajorNumber_g = register_chrdev (0, EPLLIN_DRV_NAME, &EplLinFileOps_g);
|
|
|
- if (nDrvMajorNumber_g != 0)
|
|
|
- {
|
|
|
- TRACE2("EPL: Driver '%s' installed successful, assigned MajorNumber=%d\n", EPLLIN_DRV_NAME, nDrvMajorNumber_g);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- TRACE1("EPL: ERROR: Driver '%s' is unable to get a free MajorNumber!\n", EPLLIN_DRV_NAME);
|
|
|
- iRet = -EIO;
|
|
|
- goto Exit;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- // create device node in DEVFS
|
|
|
- nMinorNumber = 0;
|
|
|
- TRACE1("EPL: Creating device node '/dev/%s'...\n", EPLLIN_DEV_NAME);
|
|
|
- iErr = devfs_mk_cdev (MKDEV(nDrvMajorNumber_g, nMinorNumber), S_IFCHR | S_IRUGO | S_IWUGO, EPLLIN_DEV_NAME);
|
|
|
- if (iErr == 0)
|
|
|
- {
|
|
|
- TRACE1("EPL: Device node '/dev/%s' created successful.\n", EPLLIN_DEV_NAME);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- TRACE1("EPL: ERROR: unable to create device node '/dev/%s'\n", EPLLIN_DEV_NAME);
|
|
|
- iRet = -EIO;
|
|
|
- goto Exit;
|
|
|
- }
|
|
|
+ // register character device handler
|
|
|
+ TRACE2("EPL: Installing Driver '%s', Version %s...\n",
|
|
|
+ EPLLIN_DRV_NAME, EPL_PRODUCT_VERSION);
|
|
|
+ TRACE0("EPL: (using dynamic major number assignment)\n");
|
|
|
+ nDrvMajorNumber_g =
|
|
|
+ register_chrdev(0, EPLLIN_DRV_NAME, &EplLinFileOps_g);
|
|
|
+ if (nDrvMajorNumber_g != 0) {
|
|
|
+ TRACE2
|
|
|
+ ("EPL: Driver '%s' installed successful, assigned MajorNumber=%d\n",
|
|
|
+ EPLLIN_DRV_NAME, nDrvMajorNumber_g);
|
|
|
+ } else {
|
|
|
+ TRACE1
|
|
|
+ ("EPL: ERROR: Driver '%s' is unable to get a free MajorNumber!\n",
|
|
|
+ EPLLIN_DRV_NAME);
|
|
|
+ iRet = -EIO;
|
|
|
+ goto Exit;
|
|
|
+ }
|
|
|
+
|
|
|
+ // create device node in DEVFS
|
|
|
+ nMinorNumber = 0;
|
|
|
+ TRACE1("EPL: Creating device node '/dev/%s'...\n", EPLLIN_DEV_NAME);
|
|
|
+ iErr =
|
|
|
+ devfs_mk_cdev(MKDEV(nDrvMajorNumber_g, nMinorNumber),
|
|
|
+ S_IFCHR | S_IRUGO | S_IWUGO, EPLLIN_DEV_NAME);
|
|
|
+ if (iErr == 0) {
|
|
|
+ TRACE1("EPL: Device node '/dev/%s' created successful.\n",
|
|
|
+ EPLLIN_DEV_NAME);
|
|
|
+ } else {
|
|
|
+ TRACE1("EPL: ERROR: unable to create device node '/dev/%s'\n",
|
|
|
+ EPLLIN_DEV_NAME);
|
|
|
+ iRet = -EIO;
|
|
|
+ goto Exit;
|
|
|
+ }
|
|
|
|
|
|
#else
|
|
|
|
|
|
- // register character device handler
|
|
|
- // only one Minor required
|
|
|
- TRACE2("EPL: Installing Driver '%s', Version %s...\n", EPLLIN_DRV_NAME, EPL_PRODUCT_VERSION);
|
|
|
- iRet = alloc_chrdev_region (&nDevNum_g, 0, 1, EPLLIN_DRV_NAME);
|
|
|
- if (iRet == 0)
|
|
|
- {
|
|
|
- TRACE2("EPL: Driver '%s' installed successful, assigned MajorNumber=%d\n", EPLLIN_DRV_NAME, MAJOR(nDevNum_g));
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- TRACE1("EPL: ERROR: Driver '%s' is unable to get a free MajorNumber!\n", EPLLIN_DRV_NAME);
|
|
|
- iRet = -EIO;
|
|
|
- goto Exit;
|
|
|
- }
|
|
|
-
|
|
|
- // register cdev structure
|
|
|
- pEpl_cdev_g = cdev_alloc();
|
|
|
- pEpl_cdev_g->ops = &EplLinFileOps_g;
|
|
|
- pEpl_cdev_g->owner = THIS_MODULE;
|
|
|
- iErr = cdev_add (pEpl_cdev_g, nDevNum_g, 1);
|
|
|
- if (iErr)
|
|
|
- {
|
|
|
- TRACE2("EPL: ERROR %d: Driver '%s' could not be added!\n", iErr, EPLLIN_DRV_NAME);
|
|
|
- iRet = -EIO;
|
|
|
- goto Exit;
|
|
|
- }
|
|
|
-
|
|
|
+ // register character device handler
|
|
|
+ // only one Minor required
|
|
|
+ TRACE2("EPL: Installing Driver '%s', Version %s...\n",
|
|
|
+ EPLLIN_DRV_NAME, EPL_PRODUCT_VERSION);
|
|
|
+ iRet = alloc_chrdev_region(&nDevNum_g, 0, 1, EPLLIN_DRV_NAME);
|
|
|
+ if (iRet == 0) {
|
|
|
+ TRACE2
|
|
|
+ ("EPL: Driver '%s' installed successful, assigned MajorNumber=%d\n",
|
|
|
+ EPLLIN_DRV_NAME, MAJOR(nDevNum_g));
|
|
|
+ } else {
|
|
|
+ TRACE1
|
|
|
+ ("EPL: ERROR: Driver '%s' is unable to get a free MajorNumber!\n",
|
|
|
+ EPLLIN_DRV_NAME);
|
|
|
+ iRet = -EIO;
|
|
|
+ goto Exit;
|
|
|
+ }
|
|
|
+
|
|
|
+ // register cdev structure
|
|
|
+ pEpl_cdev_g = cdev_alloc();
|
|
|
+ pEpl_cdev_g->ops = &EplLinFileOps_g;
|
|
|
+ pEpl_cdev_g->owner = THIS_MODULE;
|
|
|
+ iErr = cdev_add(pEpl_cdev_g, nDevNum_g, 1);
|
|
|
+ if (iErr) {
|
|
|
+ TRACE2("EPL: ERROR %d: Driver '%s' could not be added!\n",
|
|
|
+ iErr, EPLLIN_DRV_NAME);
|
|
|
+ iRet = -EIO;
|
|
|
+ goto Exit;
|
|
|
+ }
|
|
|
#endif
|
|
|
|
|
|
- // create device node in PROCFS
|
|
|
- EplRet = EplLinProcInit();
|
|
|
- if (EplRet != kEplSuccessful)
|
|
|
- {
|
|
|
- goto Exit;
|
|
|
- }
|
|
|
+ // create device node in PROCFS
|
|
|
+ EplRet = EplLinProcInit();
|
|
|
+ if (EplRet != kEplSuccessful) {
|
|
|
+ goto Exit;
|
|
|
+ }
|
|
|
|
|
|
+ Exit:
|
|
|
|
|
|
-Exit:
|
|
|
-
|
|
|
- TRACE1("EPL: - EplLinInit (iRet=%d)\n", iRet);
|
|
|
- return (iRet);
|
|
|
+ TRACE1("EPL: - EplLinInit (iRet=%d)\n", iRet);
|
|
|
+ return (iRet);
|
|
|
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-
|
|
|
//---------------------------------------------------------------------------
|
|
|
// Remove Driver
|
|
|
//---------------------------------------------------------------------------
|
|
|
// -> rmmod driver
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
-static void __exit EplLinExit (void)
|
|
|
+static void __exit EplLinExit(void)
|
|
|
{
|
|
|
|
|
|
-tEplKernel EplRet;
|
|
|
+ tEplKernel EplRet;
|
|
|
|
|
|
- // delete instance for all modules
|
|
|
+ // delete instance for all modules
|
|
|
// EplRet = EplApiShutdown();
|
|
|
// printk("EplApiShutdown(): 0x%X\n", EplRet);
|
|
|
|
|
|
- // deinitialize proc fs
|
|
|
- EplRet = EplLinProcFree();
|
|
|
- printk("EplLinProcFree(): 0x%X\n", EplRet);
|
|
|
-
|
|
|
-
|
|
|
- TRACE0("EPL: + EplLinExit...\n");
|
|
|
+ // deinitialize proc fs
|
|
|
+ EplRet = EplLinProcFree();
|
|
|
+ printk("EplLinProcFree(): 0x%X\n", EplRet);
|
|
|
|
|
|
+ TRACE0("EPL: + EplLinExit...\n");
|
|
|
|
|
|
#ifdef CONFIG_DEVFS_FS
|
|
|
|
|
|
- // remove device node from DEVFS
|
|
|
- devfs_remove (EPLLIN_DEV_NAME);
|
|
|
- TRACE1("EPL: Device node '/dev/%s' removed.\n", EPLLIN_DEV_NAME);
|
|
|
+ // remove device node from DEVFS
|
|
|
+ devfs_remove(EPLLIN_DEV_NAME);
|
|
|
+ TRACE1("EPL: Device node '/dev/%s' removed.\n", EPLLIN_DEV_NAME);
|
|
|
|
|
|
- // unregister character device handler
|
|
|
- unregister_chrdev (nDrvMajorNumber_g, EPLLIN_DRV_NAME);
|
|
|
+ // unregister character device handler
|
|
|
+ unregister_chrdev(nDrvMajorNumber_g, EPLLIN_DRV_NAME);
|
|
|
|
|
|
#else
|
|
|
|
|
|
- // remove cdev structure
|
|
|
- cdev_del(pEpl_cdev_g);
|
|
|
+ // remove cdev structure
|
|
|
+ cdev_del(pEpl_cdev_g);
|
|
|
|
|
|
- // unregister character device handler
|
|
|
- unregister_chrdev_region (nDevNum_g, 1);
|
|
|
+ // unregister character device handler
|
|
|
+ unregister_chrdev_region(nDevNum_g, 1);
|
|
|
|
|
|
#endif
|
|
|
|
|
|
- TRACE1("EPL: Driver '%s' removed.\n", EPLLIN_DRV_NAME);
|
|
|
+ TRACE1("EPL: Driver '%s' removed.\n", EPLLIN_DRV_NAME);
|
|
|
|
|
|
-
|
|
|
- TRACE0("EPL: - EplLinExit\n");
|
|
|
+ TRACE0("EPL: - EplLinExit\n");
|
|
|
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-
|
|
|
//---------------------------------------------------------------------------
|
|
|
// Open Driver
|
|
|
//---------------------------------------------------------------------------
|
|
|
// -> open("/dev/driver", O_RDWR)...
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
-static int EplLinOpen (
|
|
|
- struct inode* pDeviceFile_p, // information about the device to open
|
|
|
- struct file* pInstance_p) // information about driver instance
|
|
|
+static int EplLinOpen(struct inode *pDeviceFile_p, // information about the device to open
|
|
|
+ struct file *pInstance_p) // information about driver instance
|
|
|
{
|
|
|
|
|
|
-int iRet;
|
|
|
+ int iRet;
|
|
|
|
|
|
+ TRACE0("EPL: + EplLinOpen...\n");
|
|
|
|
|
|
- TRACE0("EPL: + EplLinOpen...\n");
|
|
|
+ MOD_INC_USE_COUNT;
|
|
|
|
|
|
- MOD_INC_USE_COUNT;
|
|
|
+ if (uiEplState_g != EPL_STATE_NOTOPEN) { // stack already initialized
|
|
|
+ iRet = -EALREADY;
|
|
|
+ } else {
|
|
|
+ atomic_set(&AtomicEventState_g, EVENT_STATE_INIT);
|
|
|
+ sema_init(&SemaphoreCbEvent_g, 1);
|
|
|
+ init_waitqueue_head(&WaitQueueCbEvent_g);
|
|
|
+ init_waitqueue_head(&WaitQueueProcess_g);
|
|
|
+ init_waitqueue_head(&WaitQueueRelease_g);
|
|
|
+ atomic_set(&AtomicSyncState_g, EVENT_STATE_INIT);
|
|
|
+ init_waitqueue_head(&WaitQueueCbSync_g);
|
|
|
+ init_waitqueue_head(&WaitQueuePI_In_g);
|
|
|
|
|
|
- if (uiEplState_g != EPL_STATE_NOTOPEN)
|
|
|
- { // stack already initialized
|
|
|
- iRet = -EALREADY;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- atomic_set(&AtomicEventState_g, EVENT_STATE_INIT);
|
|
|
- sema_init(&SemaphoreCbEvent_g, 1);
|
|
|
- init_waitqueue_head(&WaitQueueCbEvent_g);
|
|
|
- init_waitqueue_head(&WaitQueueProcess_g);
|
|
|
- init_waitqueue_head(&WaitQueueRelease_g);
|
|
|
- atomic_set(&AtomicSyncState_g, EVENT_STATE_INIT);
|
|
|
- init_waitqueue_head(&WaitQueueCbSync_g);
|
|
|
- init_waitqueue_head(&WaitQueuePI_In_g);
|
|
|
+ uiEplState_g = EPL_STATE_NOTINIT;
|
|
|
+ iRet = 0;
|
|
|
+ }
|
|
|
|
|
|
- uiEplState_g = EPL_STATE_NOTINIT;
|
|
|
- iRet = 0;
|
|
|
- }
|
|
|
-
|
|
|
- TRACE1("EPL: - EplLinOpen (iRet=%d)\n", iRet);
|
|
|
- return (iRet);
|
|
|
+ TRACE1("EPL: - EplLinOpen (iRet=%d)\n", iRet);
|
|
|
+ return (iRet);
|
|
|
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-
|
|
|
//---------------------------------------------------------------------------
|
|
|
// Close Driver
|
|
|
//---------------------------------------------------------------------------
|
|
|
// -> close(device)...
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
-static int EplLinRelease (
|
|
|
- struct inode* pDeviceFile_p, // information about the device to open
|
|
|
- struct file* pInstance_p) // information about driver instance
|
|
|
+static int EplLinRelease(struct inode *pDeviceFile_p, // information about the device to open
|
|
|
+ struct file *pInstance_p) // information about driver instance
|
|
|
{
|
|
|
|
|
|
-tEplKernel EplRet = kEplSuccessful;
|
|
|
-int iRet;
|
|
|
-
|
|
|
-
|
|
|
- TRACE0("EPL: + EplLinRelease...\n");
|
|
|
+ tEplKernel EplRet = kEplSuccessful;
|
|
|
+ int iRet;
|
|
|
|
|
|
- if (uiEplState_g != EPL_STATE_NOTINIT)
|
|
|
- {
|
|
|
- // pass control to sync kernel thread, but signal termination
|
|
|
- atomic_set(&AtomicSyncState_g, EVENT_STATE_TERM);
|
|
|
- wake_up_interruptible(&WaitQueueCbSync_g);
|
|
|
- wake_up_interruptible(&WaitQueuePI_In_g);
|
|
|
+ TRACE0("EPL: + EplLinRelease...\n");
|
|
|
|
|
|
- // pass control to event queue kernel thread
|
|
|
- atomic_set(&AtomicEventState_g, EVENT_STATE_TERM);
|
|
|
- wake_up_interruptible(&WaitQueueCbEvent_g);
|
|
|
+ if (uiEplState_g != EPL_STATE_NOTINIT) {
|
|
|
+ // pass control to sync kernel thread, but signal termination
|
|
|
+ atomic_set(&AtomicSyncState_g, EVENT_STATE_TERM);
|
|
|
+ wake_up_interruptible(&WaitQueueCbSync_g);
|
|
|
+ wake_up_interruptible(&WaitQueuePI_In_g);
|
|
|
|
|
|
- if (uiEplState_g == EPL_STATE_RUNNING)
|
|
|
- { // post NmtEventSwitchOff
|
|
|
- EplRet = EplApiExecNmtCommand(kEplNmtEventSwitchOff);
|
|
|
+ // pass control to event queue kernel thread
|
|
|
+ atomic_set(&AtomicEventState_g, EVENT_STATE_TERM);
|
|
|
+ wake_up_interruptible(&WaitQueueCbEvent_g);
|
|
|
|
|
|
- }
|
|
|
+ if (uiEplState_g == EPL_STATE_RUNNING) { // post NmtEventSwitchOff
|
|
|
+ EplRet = EplApiExecNmtCommand(kEplNmtEventSwitchOff);
|
|
|
|
|
|
- if (EplRet == kEplSuccessful)
|
|
|
- {
|
|
|
- TRACE0("EPL: waiting for NMT_GS_OFF\n");
|
|
|
- wait_event_interruptible(WaitQueueRelease_g,
|
|
|
- (uiEplState_g == EPL_STATE_SHUTDOWN));
|
|
|
- }
|
|
|
- else
|
|
|
- { // post NmtEventSwitchOff failed
|
|
|
- TRACE0("EPL: event post failed\n");
|
|
|
- }
|
|
|
+ }
|
|
|
|
|
|
- // $$$ d.k.: What if waiting was interrupted by signal?
|
|
|
+ if (EplRet == kEplSuccessful) {
|
|
|
+ TRACE0("EPL: waiting for NMT_GS_OFF\n");
|
|
|
+ wait_event_interruptible(WaitQueueRelease_g,
|
|
|
+ (uiEplState_g ==
|
|
|
+ EPL_STATE_SHUTDOWN));
|
|
|
+ } else { // post NmtEventSwitchOff failed
|
|
|
+ TRACE0("EPL: event post failed\n");
|
|
|
+ }
|
|
|
|
|
|
- TRACE0("EPL: call EplApiShutdown()\n");
|
|
|
- // EPL stack can be safely shut down
|
|
|
- // delete instance for all EPL modules
|
|
|
- EplRet = EplApiShutdown();
|
|
|
- printk("EplApiShutdown(): 0x%X\n", EplRet);
|
|
|
- }
|
|
|
+ // $$$ d.k.: What if waiting was interrupted by signal?
|
|
|
|
|
|
- uiEplState_g = EPL_STATE_NOTOPEN;
|
|
|
- iRet = 0;
|
|
|
+ TRACE0("EPL: call EplApiShutdown()\n");
|
|
|
+ // EPL stack can be safely shut down
|
|
|
+ // delete instance for all EPL modules
|
|
|
+ EplRet = EplApiShutdown();
|
|
|
+ printk("EplApiShutdown(): 0x%X\n", EplRet);
|
|
|
+ }
|
|
|
|
|
|
+ uiEplState_g = EPL_STATE_NOTOPEN;
|
|
|
+ iRet = 0;
|
|
|
|
|
|
- MOD_DEC_USE_COUNT;
|
|
|
+ MOD_DEC_USE_COUNT;
|
|
|
|
|
|
-
|
|
|
- TRACE1("EPL: - EplLinRelease (iRet=%d)\n", iRet);
|
|
|
- return (iRet);
|
|
|
+ TRACE1("EPL: - EplLinRelease (iRet=%d)\n", iRet);
|
|
|
+ return (iRet);
|
|
|
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-
|
|
|
//---------------------------------------------------------------------------
|
|
|
// Read Data from Driver
|
|
|
//---------------------------------------------------------------------------
|
|
|
// -> read(...)
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
-static ssize_t EplLinRead (
|
|
|
- struct file* pInstance_p, // information about driver instance
|
|
|
- char* pDstBuff_p, // address of buffer to fill with data
|
|
|
- size_t BuffSize_p, // length of the buffer
|
|
|
- loff_t* pFileOffs_p) // offset in the file
|
|
|
+static ssize_t EplLinRead(struct file *pInstance_p, // information about driver instance
|
|
|
+ char *pDstBuff_p, // address of buffer to fill with data
|
|
|
+ size_t BuffSize_p, // length of the buffer
|
|
|
+ loff_t * pFileOffs_p) // offset in the file
|
|
|
{
|
|
|
|
|
|
-int iRet;
|
|
|
-
|
|
|
-
|
|
|
- TRACE0("EPL: + EplLinRead...\n");
|
|
|
+ int iRet;
|
|
|
|
|
|
+ TRACE0("EPL: + EplLinRead...\n");
|
|
|
|
|
|
- TRACE0("EPL: Sorry, this operation isn't supported.\n");
|
|
|
- iRet = -EINVAL;
|
|
|
+ TRACE0("EPL: Sorry, this operation isn't supported.\n");
|
|
|
+ iRet = -EINVAL;
|
|
|
|
|
|
-
|
|
|
- TRACE1("EPL: - EplLinRead (iRet=%d)\n", iRet);
|
|
|
- return (iRet);
|
|
|
+ TRACE1("EPL: - EplLinRead (iRet=%d)\n", iRet);
|
|
|
+ return (iRet);
|
|
|
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-
|
|
|
//---------------------------------------------------------------------------
|
|
|
// Write Data to Driver
|
|
|
//---------------------------------------------------------------------------
|
|
|
// -> write(...)
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
-static ssize_t EplLinWrite (
|
|
|
- struct file* pInstance_p, // information about driver instance
|
|
|
- const char* pSrcBuff_p, // address of buffer to get data from
|
|
|
- size_t BuffSize_p, // length of the buffer
|
|
|
- loff_t* pFileOffs_p) // offset in the file
|
|
|
+static ssize_t EplLinWrite(struct file *pInstance_p, // information about driver instance
|
|
|
+ const char *pSrcBuff_p, // address of buffer to get data from
|
|
|
+ size_t BuffSize_p, // length of the buffer
|
|
|
+ loff_t * pFileOffs_p) // offset in the file
|
|
|
{
|
|
|
|
|
|
-int iRet;
|
|
|
-
|
|
|
-
|
|
|
- TRACE0("EPL: + EplLinWrite...\n");
|
|
|
+ int iRet;
|
|
|
|
|
|
+ TRACE0("EPL: + EplLinWrite...\n");
|
|
|
|
|
|
- TRACE0("EPL: Sorry, this operation isn't supported.\n");
|
|
|
- iRet = -EINVAL;
|
|
|
+ TRACE0("EPL: Sorry, this operation isn't supported.\n");
|
|
|
+ iRet = -EINVAL;
|
|
|
|
|
|
-
|
|
|
- TRACE1("EPL: - EplLinWrite (iRet=%d)\n", iRet);
|
|
|
- return (iRet);
|
|
|
+ TRACE1("EPL: - EplLinWrite (iRet=%d)\n", iRet);
|
|
|
+ return (iRet);
|
|
|
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-
|
|
|
//---------------------------------------------------------------------------
|
|
|
// Generic Access to Driver
|
|
|
//---------------------------------------------------------------------------
|
|
|
// -> ioctl(...)
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
-static int EplLinIoctl (
|
|
|
- struct inode* pDeviceFile_p, // information about the device to open
|
|
|
- struct file* pInstance_p, // information about driver instance
|
|
|
- unsigned int uiIoctlCmd_p, // Ioctl command to execute
|
|
|
- unsigned long ulArg_p) // Ioctl command specific argument/parameter
|
|
|
+static int EplLinIoctl(struct inode *pDeviceFile_p, // information about the device to open
|
|
|
+ struct file *pInstance_p, // information about driver instance
|
|
|
+ unsigned int uiIoctlCmd_p, // Ioctl command to execute
|
|
|
+ unsigned long ulArg_p) // Ioctl command specific argument/parameter
|
|
|
{
|
|
|
|
|
|
-tEplKernel EplRet;
|
|
|
-int iErr;
|
|
|
-int iRet;
|
|
|
-
|
|
|
+ tEplKernel EplRet;
|
|
|
+ int iErr;
|
|
|
+ int iRet;
|
|
|
|
|
|
// TRACE1("EPL: + EplLinIoctl (uiIoctlCmd_p=%d)...\n", uiIoctlCmd_p);
|
|
|
|
|
|
-
|
|
|
- iRet = -EINVAL;
|
|
|
-
|
|
|
- switch (uiIoctlCmd_p)
|
|
|
- {
|
|
|
- // ----------------------------------------------------------
|
|
|
- case EPLLIN_CMD_INITIALIZE:
|
|
|
- {
|
|
|
- tEplApiInitParam EplApiInitParam;
|
|
|
-
|
|
|
- iErr = copy_from_user(&EplApiInitParam, (const void*)ulArg_p, sizeof (EplApiInitParam));
|
|
|
- if (iErr != 0)
|
|
|
- {
|
|
|
- iRet = -EIO;
|
|
|
- goto Exit;
|
|
|
- }
|
|
|
-
|
|
|
- EplApiInitParam.m_pfnCbEvent = EplLinCbEvent;
|
|
|
- EplApiInitParam.m_pfnCbSync = EplLinCbSync;
|
|
|
-
|
|
|
- EplRet = EplApiInitialize(&EplApiInitParam);
|
|
|
-
|
|
|
- uiEplState_g = EPL_STATE_RUNNING;
|
|
|
-
|
|
|
- iRet = (int) EplRet;
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- // ----------------------------------------------------------
|
|
|
- case EPLLIN_CMD_SHUTDOWN:
|
|
|
- { // shutdown the threads
|
|
|
-
|
|
|
- // pass control to sync kernel thread, but signal termination
|
|
|
- atomic_set(&AtomicSyncState_g, EVENT_STATE_TERM);
|
|
|
- wake_up_interruptible(&WaitQueueCbSync_g);
|
|
|
- wake_up_interruptible(&WaitQueuePI_In_g);
|
|
|
-
|
|
|
- // pass control to event queue kernel thread
|
|
|
- atomic_set(&AtomicEventState_g, EVENT_STATE_TERM);
|
|
|
- wake_up_interruptible(&WaitQueueCbEvent_g);
|
|
|
-
|
|
|
- if (uiEplState_g == EPL_STATE_RUNNING)
|
|
|
- { // post NmtEventSwitchOff
|
|
|
- EplRet = EplApiExecNmtCommand(kEplNmtEventSwitchOff);
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- iRet = 0;
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- // ----------------------------------------------------------
|
|
|
- case EPLLIN_CMD_READ_LOCAL_OBJECT:
|
|
|
- {
|
|
|
- tEplLinLocalObject LocalObject;
|
|
|
- void* pData;
|
|
|
-
|
|
|
- iErr = copy_from_user(&LocalObject, (const void*)ulArg_p, sizeof (LocalObject));
|
|
|
- if (iErr != 0)
|
|
|
- {
|
|
|
- iRet = -EIO;
|
|
|
- goto Exit;
|
|
|
- }
|
|
|
-
|
|
|
- if ((LocalObject.m_pData == NULL) || (LocalObject.m_uiSize == 0))
|
|
|
- {
|
|
|
- iRet = (int) kEplApiInvalidParam;
|
|
|
- goto Exit;
|
|
|
- }
|
|
|
-
|
|
|
- pData = vmalloc(LocalObject.m_uiSize);
|
|
|
- if (pData == NULL)
|
|
|
- { // no memory available
|
|
|
- iRet = -ENOMEM;
|
|
|
- goto Exit;
|
|
|
- }
|
|
|
-
|
|
|
- EplRet = EplApiReadLocalObject(LocalObject.m_uiIndex, LocalObject.m_uiSubindex, pData, &LocalObject.m_uiSize);
|
|
|
-
|
|
|
- if (EplRet == kEplSuccessful)
|
|
|
- {
|
|
|
- iErr = copy_to_user(LocalObject.m_pData, pData, LocalObject.m_uiSize);
|
|
|
-
|
|
|
- vfree(pData);
|
|
|
-
|
|
|
- if (iErr != 0)
|
|
|
- {
|
|
|
- iRet = -EIO;
|
|
|
- goto Exit;
|
|
|
- }
|
|
|
-
|
|
|
- // return actual size (LocalObject.m_uiSize)
|
|
|
- iErr = put_user(LocalObject.m_uiSize,
|
|
|
- (unsigned int*)(ulArg_p + (unsigned long)&LocalObject.m_uiSize - (unsigned long)&LocalObject));
|
|
|
- if (iErr != 0)
|
|
|
- {
|
|
|
- iRet = -EIO;
|
|
|
- goto Exit;
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- vfree(pData);
|
|
|
- }
|
|
|
-
|
|
|
- iRet = (int) EplRet;
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- // ----------------------------------------------------------
|
|
|
- case EPLLIN_CMD_WRITE_LOCAL_OBJECT:
|
|
|
- {
|
|
|
- tEplLinLocalObject LocalObject;
|
|
|
- void* pData;
|
|
|
-
|
|
|
- iErr = copy_from_user(&LocalObject, (const void*)ulArg_p, sizeof (LocalObject));
|
|
|
- if (iErr != 0)
|
|
|
- {
|
|
|
- iRet = -EIO;
|
|
|
- goto Exit;
|
|
|
- }
|
|
|
-
|
|
|
- if ((LocalObject.m_pData == NULL) || (LocalObject.m_uiSize == 0))
|
|
|
- {
|
|
|
- iRet = (int) kEplApiInvalidParam;
|
|
|
- goto Exit;
|
|
|
- }
|
|
|
-
|
|
|
- pData = vmalloc(LocalObject.m_uiSize);
|
|
|
- if (pData == NULL)
|
|
|
- { // no memory available
|
|
|
- iRet = -ENOMEM;
|
|
|
- goto Exit;
|
|
|
- }
|
|
|
- iErr = copy_from_user(pData, LocalObject.m_pData, LocalObject.m_uiSize);
|
|
|
- if (iErr != 0)
|
|
|
- {
|
|
|
- iRet = -EIO;
|
|
|
- goto Exit;
|
|
|
- }
|
|
|
-
|
|
|
- EplRet = EplApiWriteLocalObject(LocalObject.m_uiIndex, LocalObject.m_uiSubindex, pData, LocalObject.m_uiSize);
|
|
|
-
|
|
|
- vfree(pData);
|
|
|
-
|
|
|
- iRet = (int) EplRet;
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- case EPLLIN_CMD_READ_OBJECT:
|
|
|
- {
|
|
|
- tEplLinSdoObject SdoObject;
|
|
|
- void* pData;
|
|
|
- tEplLinSdoBufHeader* pBufHeader;
|
|
|
- tEplSdoComConHdl* pSdoComConHdl;
|
|
|
-
|
|
|
- iErr = copy_from_user(&SdoObject, (const void*)ulArg_p, sizeof (SdoObject));
|
|
|
- if (iErr != 0)
|
|
|
- {
|
|
|
- iRet = -EIO;
|
|
|
- goto Exit;
|
|
|
- }
|
|
|
-
|
|
|
- if ((SdoObject.m_le_pData == NULL) || (SdoObject.m_uiSize == 0))
|
|
|
- {
|
|
|
- iRet = (int) kEplApiInvalidParam;
|
|
|
- goto Exit;
|
|
|
- }
|
|
|
-
|
|
|
- pBufHeader = (tEplLinSdoBufHeader*) vmalloc(sizeof (tEplLinSdoBufHeader) + SdoObject.m_uiSize);
|
|
|
- if (pBufHeader == NULL)
|
|
|
- { // no memory available
|
|
|
- iRet = -ENOMEM;
|
|
|
- goto Exit;
|
|
|
- }
|
|
|
-
|
|
|
- // initiate temporary buffer
|
|
|
- pBufHeader->m_pUserArg = SdoObject.m_pUserArg; // original user argument pointer
|
|
|
- pBufHeader->m_pData = SdoObject.m_le_pData; // original data pointer from app
|
|
|
- pData = pBufHeader + sizeof (tEplLinSdoBufHeader);
|
|
|
-
|
|
|
- if (SdoObject.m_fValidSdoComConHdl != FALSE)
|
|
|
- {
|
|
|
- pSdoComConHdl = &SdoObject.m_SdoComConHdl;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- pSdoComConHdl = NULL;
|
|
|
- }
|
|
|
-
|
|
|
- EplRet = EplApiReadObject(pSdoComConHdl, SdoObject.m_uiNodeId, SdoObject.m_uiIndex,
|
|
|
- SdoObject.m_uiSubindex, pData, &SdoObject.m_uiSize,
|
|
|
- SdoObject.m_SdoType, pBufHeader);
|
|
|
-
|
|
|
- // return actual SDO handle (SdoObject.m_SdoComConHdl)
|
|
|
- iErr = put_user(SdoObject.m_SdoComConHdl,
|
|
|
- (unsigned int*)(ulArg_p + (unsigned long)&SdoObject.m_SdoComConHdl - (unsigned long)&SdoObject));
|
|
|
- if (iErr != 0)
|
|
|
- {
|
|
|
- iRet = -EIO;
|
|
|
- goto Exit;
|
|
|
- }
|
|
|
-
|
|
|
- if (EplRet == kEplSuccessful)
|
|
|
- {
|
|
|
- iErr = copy_to_user(SdoObject.m_le_pData, pData, SdoObject.m_uiSize);
|
|
|
-
|
|
|
- vfree(pBufHeader);
|
|
|
-
|
|
|
- if (iErr != 0)
|
|
|
- {
|
|
|
- iRet = -EIO;
|
|
|
- goto Exit;
|
|
|
- }
|
|
|
-
|
|
|
- // return actual size (SdoObject.m_uiSize)
|
|
|
- iErr = put_user(SdoObject.m_uiSize,
|
|
|
- (unsigned int*)(ulArg_p + (unsigned long)&SdoObject.m_uiSize - (unsigned long)&SdoObject));
|
|
|
- if (iErr != 0)
|
|
|
- {
|
|
|
- iRet = -EIO;
|
|
|
- goto Exit;
|
|
|
- }
|
|
|
- }
|
|
|
- else if (EplRet != kEplApiTaskDeferred)
|
|
|
- { // error ocurred
|
|
|
- vfree(pBufHeader);
|
|
|
- if (iErr != 0)
|
|
|
- {
|
|
|
- iRet = -EIO;
|
|
|
- goto Exit;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- iRet = (int) EplRet;
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- case EPLLIN_CMD_WRITE_OBJECT:
|
|
|
- {
|
|
|
- tEplLinSdoObject SdoObject;
|
|
|
- void* pData;
|
|
|
- tEplLinSdoBufHeader* pBufHeader;
|
|
|
- tEplSdoComConHdl* pSdoComConHdl;
|
|
|
-
|
|
|
- iErr = copy_from_user(&SdoObject, (const void*)ulArg_p, sizeof (SdoObject));
|
|
|
- if (iErr != 0)
|
|
|
- {
|
|
|
- iRet = -EIO;
|
|
|
- goto Exit;
|
|
|
- }
|
|
|
-
|
|
|
- if ((SdoObject.m_le_pData == NULL) || (SdoObject.m_uiSize == 0))
|
|
|
- {
|
|
|
- iRet = (int) kEplApiInvalidParam;
|
|
|
- goto Exit;
|
|
|
- }
|
|
|
-
|
|
|
- pBufHeader = (tEplLinSdoBufHeader*) vmalloc(sizeof (tEplLinSdoBufHeader) + SdoObject.m_uiSize);
|
|
|
- if (pBufHeader == NULL)
|
|
|
- { // no memory available
|
|
|
- iRet = -ENOMEM;
|
|
|
- goto Exit;
|
|
|
- }
|
|
|
-
|
|
|
- // initiate temporary buffer
|
|
|
- pBufHeader->m_pUserArg = SdoObject.m_pUserArg; // original user argument pointer
|
|
|
- pBufHeader->m_pData = SdoObject.m_le_pData; // original data pointer from app
|
|
|
- pData = pBufHeader + sizeof (tEplLinSdoBufHeader);
|
|
|
-
|
|
|
- iErr = copy_from_user(pData, SdoObject.m_le_pData, SdoObject.m_uiSize);
|
|
|
-
|
|
|
- if (iErr != 0)
|
|
|
- {
|
|
|
- iRet = -EIO;
|
|
|
- goto Exit;
|
|
|
- }
|
|
|
-
|
|
|
- if (SdoObject.m_fValidSdoComConHdl != FALSE)
|
|
|
- {
|
|
|
- pSdoComConHdl = &SdoObject.m_SdoComConHdl;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- pSdoComConHdl = NULL;
|
|
|
- }
|
|
|
-
|
|
|
- EplRet = EplApiWriteObject(pSdoComConHdl, SdoObject.m_uiNodeId, SdoObject.m_uiIndex,
|
|
|
- SdoObject.m_uiSubindex, pData, SdoObject.m_uiSize,
|
|
|
- SdoObject.m_SdoType, pBufHeader);
|
|
|
-
|
|
|
- // return actual SDO handle (SdoObject.m_SdoComConHdl)
|
|
|
- iErr = put_user(SdoObject.m_SdoComConHdl,
|
|
|
- (unsigned int*)(ulArg_p + (unsigned long)&SdoObject.m_SdoComConHdl - (unsigned long)&SdoObject));
|
|
|
- if (iErr != 0)
|
|
|
- {
|
|
|
- iRet = -EIO;
|
|
|
- goto Exit;
|
|
|
- }
|
|
|
-
|
|
|
- if (EplRet != kEplApiTaskDeferred)
|
|
|
- { // succeeded or error ocurred, but task not deferred
|
|
|
- vfree(pBufHeader);
|
|
|
- }
|
|
|
-
|
|
|
- iRet = (int) EplRet;
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- // ----------------------------------------------------------
|
|
|
- case EPLLIN_CMD_FREE_SDO_CHANNEL:
|
|
|
- {
|
|
|
- // forward SDO handle to EPL stack
|
|
|
- EplRet = EplApiFreeSdoChannel((tEplSdoComConHdl)ulArg_p);
|
|
|
-
|
|
|
- iRet = (int) EplRet;
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
+ iRet = -EINVAL;
|
|
|
+
|
|
|
+ switch (uiIoctlCmd_p) {
|
|
|
+ // ----------------------------------------------------------
|
|
|
+ case EPLLIN_CMD_INITIALIZE:
|
|
|
+ {
|
|
|
+ tEplApiInitParam EplApiInitParam;
|
|
|
+
|
|
|
+ iErr =
|
|
|
+ copy_from_user(&EplApiInitParam,
|
|
|
+ (const void *)ulArg_p,
|
|
|
+ sizeof(EplApiInitParam));
|
|
|
+ if (iErr != 0) {
|
|
|
+ iRet = -EIO;
|
|
|
+ goto Exit;
|
|
|
+ }
|
|
|
+
|
|
|
+ EplApiInitParam.m_pfnCbEvent = EplLinCbEvent;
|
|
|
+ EplApiInitParam.m_pfnCbSync = EplLinCbSync;
|
|
|
+
|
|
|
+ EplRet = EplApiInitialize(&EplApiInitParam);
|
|
|
+
|
|
|
+ uiEplState_g = EPL_STATE_RUNNING;
|
|
|
+
|
|
|
+ iRet = (int)EplRet;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ // ----------------------------------------------------------
|
|
|
+ case EPLLIN_CMD_SHUTDOWN:
|
|
|
+ { // shutdown the threads
|
|
|
+
|
|
|
+ // pass control to sync kernel thread, but signal termination
|
|
|
+ atomic_set(&AtomicSyncState_g, EVENT_STATE_TERM);
|
|
|
+ wake_up_interruptible(&WaitQueueCbSync_g);
|
|
|
+ wake_up_interruptible(&WaitQueuePI_In_g);
|
|
|
+
|
|
|
+ // pass control to event queue kernel thread
|
|
|
+ atomic_set(&AtomicEventState_g, EVENT_STATE_TERM);
|
|
|
+ wake_up_interruptible(&WaitQueueCbEvent_g);
|
|
|
+
|
|
|
+ if (uiEplState_g == EPL_STATE_RUNNING) { // post NmtEventSwitchOff
|
|
|
+ EplRet =
|
|
|
+ EplApiExecNmtCommand(kEplNmtEventSwitchOff);
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ iRet = 0;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ // ----------------------------------------------------------
|
|
|
+ case EPLLIN_CMD_READ_LOCAL_OBJECT:
|
|
|
+ {
|
|
|
+ tEplLinLocalObject LocalObject;
|
|
|
+ void *pData;
|
|
|
+
|
|
|
+ iErr =
|
|
|
+ copy_from_user(&LocalObject, (const void *)ulArg_p,
|
|
|
+ sizeof(LocalObject));
|
|
|
+ if (iErr != 0) {
|
|
|
+ iRet = -EIO;
|
|
|
+ goto Exit;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((LocalObject.m_pData == NULL)
|
|
|
+ || (LocalObject.m_uiSize == 0)) {
|
|
|
+ iRet = (int)kEplApiInvalidParam;
|
|
|
+ goto Exit;
|
|
|
+ }
|
|
|
+
|
|
|
+ pData = vmalloc(LocalObject.m_uiSize);
|
|
|
+ if (pData == NULL) { // no memory available
|
|
|
+ iRet = -ENOMEM;
|
|
|
+ goto Exit;
|
|
|
+ }
|
|
|
+
|
|
|
+ EplRet =
|
|
|
+ EplApiReadLocalObject(LocalObject.m_uiIndex,
|
|
|
+ LocalObject.m_uiSubindex,
|
|
|
+ pData, &LocalObject.m_uiSize);
|
|
|
+
|
|
|
+ if (EplRet == kEplSuccessful) {
|
|
|
+ iErr =
|
|
|
+ copy_to_user(LocalObject.m_pData, pData,
|
|
|
+ LocalObject.m_uiSize);
|
|
|
+
|
|
|
+ vfree(pData);
|
|
|
+
|
|
|
+ if (iErr != 0) {
|
|
|
+ iRet = -EIO;
|
|
|
+ goto Exit;
|
|
|
+ }
|
|
|
+ // return actual size (LocalObject.m_uiSize)
|
|
|
+ iErr = put_user(LocalObject.m_uiSize,
|
|
|
+ (unsigned int *)(ulArg_p +
|
|
|
+ (unsigned long)
|
|
|
+ &LocalObject.
|
|
|
+ m_uiSize -
|
|
|
+ (unsigned long)
|
|
|
+ &LocalObject));
|
|
|
+ if (iErr != 0) {
|
|
|
+ iRet = -EIO;
|
|
|
+ goto Exit;
|
|
|
+ }
|
|
|
+
|
|
|
+ } else {
|
|
|
+ vfree(pData);
|
|
|
+ }
|
|
|
+
|
|
|
+ iRet = (int)EplRet;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ // ----------------------------------------------------------
|
|
|
+ case EPLLIN_CMD_WRITE_LOCAL_OBJECT:
|
|
|
+ {
|
|
|
+ tEplLinLocalObject LocalObject;
|
|
|
+ void *pData;
|
|
|
+
|
|
|
+ iErr =
|
|
|
+ copy_from_user(&LocalObject, (const void *)ulArg_p,
|
|
|
+ sizeof(LocalObject));
|
|
|
+ if (iErr != 0) {
|
|
|
+ iRet = -EIO;
|
|
|
+ goto Exit;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((LocalObject.m_pData == NULL)
|
|
|
+ || (LocalObject.m_uiSize == 0)) {
|
|
|
+ iRet = (int)kEplApiInvalidParam;
|
|
|
+ goto Exit;
|
|
|
+ }
|
|
|
+
|
|
|
+ pData = vmalloc(LocalObject.m_uiSize);
|
|
|
+ if (pData == NULL) { // no memory available
|
|
|
+ iRet = -ENOMEM;
|
|
|
+ goto Exit;
|
|
|
+ }
|
|
|
+ iErr =
|
|
|
+ copy_from_user(pData, LocalObject.m_pData,
|
|
|
+ LocalObject.m_uiSize);
|
|
|
+ if (iErr != 0) {
|
|
|
+ iRet = -EIO;
|
|
|
+ goto Exit;
|
|
|
+ }
|
|
|
+
|
|
|
+ EplRet =
|
|
|
+ EplApiWriteLocalObject(LocalObject.m_uiIndex,
|
|
|
+ LocalObject.m_uiSubindex,
|
|
|
+ pData, LocalObject.m_uiSize);
|
|
|
+
|
|
|
+ vfree(pData);
|
|
|
+
|
|
|
+ iRet = (int)EplRet;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ case EPLLIN_CMD_READ_OBJECT:
|
|
|
+ {
|
|
|
+ tEplLinSdoObject SdoObject;
|
|
|
+ void *pData;
|
|
|
+ tEplLinSdoBufHeader *pBufHeader;
|
|
|
+ tEplSdoComConHdl *pSdoComConHdl;
|
|
|
+
|
|
|
+ iErr =
|
|
|
+ copy_from_user(&SdoObject, (const void *)ulArg_p,
|
|
|
+ sizeof(SdoObject));
|
|
|
+ if (iErr != 0) {
|
|
|
+ iRet = -EIO;
|
|
|
+ goto Exit;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((SdoObject.m_le_pData == NULL)
|
|
|
+ || (SdoObject.m_uiSize == 0)) {
|
|
|
+ iRet = (int)kEplApiInvalidParam;
|
|
|
+ goto Exit;
|
|
|
+ }
|
|
|
+
|
|
|
+ pBufHeader =
|
|
|
+ (tEplLinSdoBufHeader *)
|
|
|
+ vmalloc(sizeof(tEplLinSdoBufHeader) +
|
|
|
+ SdoObject.m_uiSize);
|
|
|
+ if (pBufHeader == NULL) { // no memory available
|
|
|
+ iRet = -ENOMEM;
|
|
|
+ goto Exit;
|
|
|
+ }
|
|
|
+ // initiate temporary buffer
|
|
|
+ pBufHeader->m_pUserArg = SdoObject.m_pUserArg; // original user argument pointer
|
|
|
+ pBufHeader->m_pData = SdoObject.m_le_pData; // original data pointer from app
|
|
|
+ pData = pBufHeader + sizeof(tEplLinSdoBufHeader);
|
|
|
+
|
|
|
+ if (SdoObject.m_fValidSdoComConHdl != FALSE) {
|
|
|
+ pSdoComConHdl = &SdoObject.m_SdoComConHdl;
|
|
|
+ } else {
|
|
|
+ pSdoComConHdl = NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ EplRet =
|
|
|
+ EplApiReadObject(pSdoComConHdl,
|
|
|
+ SdoObject.m_uiNodeId,
|
|
|
+ SdoObject.m_uiIndex,
|
|
|
+ SdoObject.m_uiSubindex, pData,
|
|
|
+ &SdoObject.m_uiSize,
|
|
|
+ SdoObject.m_SdoType, pBufHeader);
|
|
|
+
|
|
|
+ // return actual SDO handle (SdoObject.m_SdoComConHdl)
|
|
|
+ iErr = put_user(SdoObject.m_SdoComConHdl,
|
|
|
+ (unsigned int *)(ulArg_p +
|
|
|
+ (unsigned long)
|
|
|
+ &SdoObject.
|
|
|
+ m_SdoComConHdl -
|
|
|
+ (unsigned long)
|
|
|
+ &SdoObject));
|
|
|
+ if (iErr != 0) {
|
|
|
+ iRet = -EIO;
|
|
|
+ goto Exit;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (EplRet == kEplSuccessful) {
|
|
|
+ iErr =
|
|
|
+ copy_to_user(SdoObject.m_le_pData, pData,
|
|
|
+ SdoObject.m_uiSize);
|
|
|
+
|
|
|
+ vfree(pBufHeader);
|
|
|
+
|
|
|
+ if (iErr != 0) {
|
|
|
+ iRet = -EIO;
|
|
|
+ goto Exit;
|
|
|
+ }
|
|
|
+ // return actual size (SdoObject.m_uiSize)
|
|
|
+ iErr = put_user(SdoObject.m_uiSize,
|
|
|
+ (unsigned int *)(ulArg_p +
|
|
|
+ (unsigned long)
|
|
|
+ &SdoObject.
|
|
|
+ m_uiSize -
|
|
|
+ (unsigned long)
|
|
|
+ &SdoObject));
|
|
|
+ if (iErr != 0) {
|
|
|
+ iRet = -EIO;
|
|
|
+ goto Exit;
|
|
|
+ }
|
|
|
+ } else if (EplRet != kEplApiTaskDeferred) { // error ocurred
|
|
|
+ vfree(pBufHeader);
|
|
|
+ if (iErr != 0) {
|
|
|
+ iRet = -EIO;
|
|
|
+ goto Exit;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ iRet = (int)EplRet;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ case EPLLIN_CMD_WRITE_OBJECT:
|
|
|
+ {
|
|
|
+ tEplLinSdoObject SdoObject;
|
|
|
+ void *pData;
|
|
|
+ tEplLinSdoBufHeader *pBufHeader;
|
|
|
+ tEplSdoComConHdl *pSdoComConHdl;
|
|
|
+
|
|
|
+ iErr =
|
|
|
+ copy_from_user(&SdoObject, (const void *)ulArg_p,
|
|
|
+ sizeof(SdoObject));
|
|
|
+ if (iErr != 0) {
|
|
|
+ iRet = -EIO;
|
|
|
+ goto Exit;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((SdoObject.m_le_pData == NULL)
|
|
|
+ || (SdoObject.m_uiSize == 0)) {
|
|
|
+ iRet = (int)kEplApiInvalidParam;
|
|
|
+ goto Exit;
|
|
|
+ }
|
|
|
+
|
|
|
+ pBufHeader =
|
|
|
+ (tEplLinSdoBufHeader *)
|
|
|
+ vmalloc(sizeof(tEplLinSdoBufHeader) +
|
|
|
+ SdoObject.m_uiSize);
|
|
|
+ if (pBufHeader == NULL) { // no memory available
|
|
|
+ iRet = -ENOMEM;
|
|
|
+ goto Exit;
|
|
|
+ }
|
|
|
+ // initiate temporary buffer
|
|
|
+ pBufHeader->m_pUserArg = SdoObject.m_pUserArg; // original user argument pointer
|
|
|
+ pBufHeader->m_pData = SdoObject.m_le_pData; // original data pointer from app
|
|
|
+ pData = pBufHeader + sizeof(tEplLinSdoBufHeader);
|
|
|
+
|
|
|
+ iErr =
|
|
|
+ copy_from_user(pData, SdoObject.m_le_pData,
|
|
|
+ SdoObject.m_uiSize);
|
|
|
+
|
|
|
+ if (iErr != 0) {
|
|
|
+ iRet = -EIO;
|
|
|
+ goto Exit;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (SdoObject.m_fValidSdoComConHdl != FALSE) {
|
|
|
+ pSdoComConHdl = &SdoObject.m_SdoComConHdl;
|
|
|
+ } else {
|
|
|
+ pSdoComConHdl = NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ EplRet =
|
|
|
+ EplApiWriteObject(pSdoComConHdl,
|
|
|
+ SdoObject.m_uiNodeId,
|
|
|
+ SdoObject.m_uiIndex,
|
|
|
+ SdoObject.m_uiSubindex, pData,
|
|
|
+ SdoObject.m_uiSize,
|
|
|
+ SdoObject.m_SdoType, pBufHeader);
|
|
|
+
|
|
|
+ // return actual SDO handle (SdoObject.m_SdoComConHdl)
|
|
|
+ iErr = put_user(SdoObject.m_SdoComConHdl,
|
|
|
+ (unsigned int *)(ulArg_p +
|
|
|
+ (unsigned long)
|
|
|
+ &SdoObject.
|
|
|
+ m_SdoComConHdl -
|
|
|
+ (unsigned long)
|
|
|
+ &SdoObject));
|
|
|
+ if (iErr != 0) {
|
|
|
+ iRet = -EIO;
|
|
|
+ goto Exit;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (EplRet != kEplApiTaskDeferred) { // succeeded or error ocurred, but task not deferred
|
|
|
+ vfree(pBufHeader);
|
|
|
+ }
|
|
|
+
|
|
|
+ iRet = (int)EplRet;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ // ----------------------------------------------------------
|
|
|
+ case EPLLIN_CMD_FREE_SDO_CHANNEL:
|
|
|
+ {
|
|
|
+ // forward SDO handle to EPL stack
|
|
|
+ EplRet =
|
|
|
+ EplApiFreeSdoChannel((tEplSdoComConHdl) ulArg_p);
|
|
|
+
|
|
|
+ iRet = (int)EplRet;
|
|
|
+ break;
|
|
|
+ }
|
|
|
|
|
|
#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
|
|
|
- // ----------------------------------------------------------
|
|
|
- case EPLLIN_CMD_MN_TRIGGER_STATE_CHANGE:
|
|
|
- {
|
|
|
- tEplLinNodeCmdObject NodeCmdObject;
|
|
|
-
|
|
|
- iErr = copy_from_user(&NodeCmdObject, (const void*)ulArg_p, sizeof (NodeCmdObject));
|
|
|
- if (iErr != 0)
|
|
|
- {
|
|
|
- iRet = -EIO;
|
|
|
- goto Exit;
|
|
|
- }
|
|
|
-
|
|
|
- EplRet = EplApiMnTriggerStateChange(NodeCmdObject.m_uiNodeId,
|
|
|
- NodeCmdObject.m_NodeCommand);
|
|
|
- iRet = (int) EplRet;
|
|
|
- break;
|
|
|
- }
|
|
|
+ // ----------------------------------------------------------
|
|
|
+ case EPLLIN_CMD_MN_TRIGGER_STATE_CHANGE:
|
|
|
+ {
|
|
|
+ tEplLinNodeCmdObject NodeCmdObject;
|
|
|
+
|
|
|
+ iErr =
|
|
|
+ copy_from_user(&NodeCmdObject,
|
|
|
+ (const void *)ulArg_p,
|
|
|
+ sizeof(NodeCmdObject));
|
|
|
+ if (iErr != 0) {
|
|
|
+ iRet = -EIO;
|
|
|
+ goto Exit;
|
|
|
+ }
|
|
|
+
|
|
|
+ EplRet =
|
|
|
+ EplApiMnTriggerStateChange(NodeCmdObject.m_uiNodeId,
|
|
|
+ NodeCmdObject.
|
|
|
+ m_NodeCommand);
|
|
|
+ iRet = (int)EplRet;
|
|
|
+ break;
|
|
|
+ }
|
|
|
#endif
|
|
|
|
|
|
-
|
|
|
- // ----------------------------------------------------------
|
|
|
- case EPLLIN_CMD_GET_EVENT:
|
|
|
- {
|
|
|
- tEplLinEvent Event;
|
|
|
-
|
|
|
- // save event structure
|
|
|
- iErr = copy_from_user(&Event, (const void*)ulArg_p, sizeof (Event));
|
|
|
- if (iErr != 0)
|
|
|
- {
|
|
|
- iRet = -EIO;
|
|
|
- goto Exit;
|
|
|
- }
|
|
|
-
|
|
|
- // save return code from application's event callback function
|
|
|
- RetCbEvent_g = Event.m_RetCbEvent;
|
|
|
-
|
|
|
- if (RetCbEvent_g == kEplShutdown)
|
|
|
- {
|
|
|
- // pass control to event queue kernel thread, but signal termination
|
|
|
- atomic_set(&AtomicEventState_g, EVENT_STATE_TERM);
|
|
|
- wake_up_interruptible(&WaitQueueCbEvent_g);
|
|
|
- // exit with error -> EplApiProcess() will leave the infinite loop
|
|
|
- iRet = 1;
|
|
|
- goto Exit;
|
|
|
- }
|
|
|
-
|
|
|
- // pass control to event queue kernel thread
|
|
|
- atomic_set(&AtomicEventState_g, EVENT_STATE_IOCTL);
|
|
|
- wake_up_interruptible(&WaitQueueCbEvent_g);
|
|
|
-
|
|
|
- // fall asleep itself in own wait queue
|
|
|
- iErr = wait_event_interruptible(WaitQueueProcess_g,
|
|
|
- (atomic_read(&AtomicEventState_g) == EVENT_STATE_READY)
|
|
|
- || (atomic_read(&AtomicEventState_g) == EVENT_STATE_TERM));
|
|
|
- if (iErr != 0)
|
|
|
- { // waiting was interrupted by signal
|
|
|
- // pass control to event queue kernel thread, but signal termination
|
|
|
- atomic_set(&AtomicEventState_g, EVENT_STATE_TERM);
|
|
|
- wake_up_interruptible(&WaitQueueCbEvent_g);
|
|
|
- // exit with this error -> EplApiProcess() will leave the infinite loop
|
|
|
- iRet = iErr;
|
|
|
- goto Exit;
|
|
|
- }
|
|
|
- else if (atomic_read(&AtomicEventState_g) == EVENT_STATE_TERM)
|
|
|
- { // termination in progress
|
|
|
- // pass control to event queue kernel thread, but signal termination
|
|
|
- wake_up_interruptible(&WaitQueueCbEvent_g);
|
|
|
- // exit with this error -> EplApiProcess() will leave the infinite loop
|
|
|
- iRet = 1;
|
|
|
- goto Exit;
|
|
|
- }
|
|
|
-
|
|
|
- // copy event to user space
|
|
|
- iErr = copy_to_user(Event.m_pEventType, &EventType_g, sizeof (EventType_g));
|
|
|
- if (iErr != 0)
|
|
|
- { // not all data could be copied
|
|
|
- iRet = -EIO;
|
|
|
- goto Exit;
|
|
|
- }
|
|
|
-
|
|
|
- // $$$ d.k. perform SDO event processing
|
|
|
- if (EventType_g == kEplApiEventSdo)
|
|
|
- {
|
|
|
- void* pData;
|
|
|
- tEplLinSdoBufHeader* pBufHeader;
|
|
|
-
|
|
|
- pBufHeader = (tEplLinSdoBufHeader*) pEventArg_g->m_Sdo.m_pUserArg;
|
|
|
- pData = pBufHeader + sizeof (tEplLinSdoBufHeader);
|
|
|
-
|
|
|
- if (pEventArg_g->m_Sdo.m_SdoAccessType == kEplSdoAccessTypeRead)
|
|
|
- {
|
|
|
- // copy read data to user space
|
|
|
- iErr = copy_to_user(pBufHeader->m_pData, pData, pEventArg_g->m_Sdo.m_uiTransferredByte);
|
|
|
- if (iErr != 0)
|
|
|
- { // not all data could be copied
|
|
|
- iRet = -EIO;
|
|
|
- goto Exit;
|
|
|
- }
|
|
|
- }
|
|
|
- pEventArg_g->m_Sdo.m_pUserArg = pBufHeader->m_pUserArg;
|
|
|
- vfree(pBufHeader);
|
|
|
- }
|
|
|
-
|
|
|
- iErr = copy_to_user(Event.m_pEventArg, pEventArg_g, min(sizeof (tEplApiEventArg), Event.m_uiEventArgSize));
|
|
|
- if (iErr != 0)
|
|
|
- { // not all data could be copied
|
|
|
- iRet = -EIO;
|
|
|
- goto Exit;
|
|
|
- }
|
|
|
-
|
|
|
- // return to EplApiProcess(), which will call the application's event callback function
|
|
|
- iRet = 0;
|
|
|
-
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- // ----------------------------------------------------------
|
|
|
- case EPLLIN_CMD_PI_SETUP:
|
|
|
- {
|
|
|
- EplRet = EplApiProcessImageSetup();
|
|
|
- iRet = (int) EplRet;
|
|
|
-
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- // ----------------------------------------------------------
|
|
|
- case EPLLIN_CMD_PI_IN:
|
|
|
- {
|
|
|
- tEplApiProcessImage ProcessImageIn;
|
|
|
-
|
|
|
- // save process image structure
|
|
|
- iErr = copy_from_user(&ProcessImageIn, (const void*)ulArg_p, sizeof (ProcessImageIn));
|
|
|
- if (iErr != 0)
|
|
|
- {
|
|
|
- iRet = -EIO;
|
|
|
- goto Exit;
|
|
|
- }
|
|
|
-
|
|
|
- // pass control to event queue kernel thread
|
|
|
- atomic_set(&AtomicSyncState_g, EVENT_STATE_IOCTL);
|
|
|
-
|
|
|
- // fall asleep itself in own wait queue
|
|
|
- iErr = wait_event_interruptible(WaitQueuePI_In_g,
|
|
|
- (atomic_read(&AtomicSyncState_g) == EVENT_STATE_READY)
|
|
|
- || (atomic_read(&AtomicSyncState_g) == EVENT_STATE_TERM));
|
|
|
- if (iErr != 0)
|
|
|
- { // waiting was interrupted by signal
|
|
|
- // pass control to sync kernel thread, but signal termination
|
|
|
- atomic_set(&AtomicSyncState_g, EVENT_STATE_TERM);
|
|
|
- wake_up_interruptible(&WaitQueueCbSync_g);
|
|
|
- // exit with this error -> application will leave the infinite loop
|
|
|
- iRet = iErr;
|
|
|
- goto Exit;
|
|
|
- }
|
|
|
- else if (atomic_read(&AtomicSyncState_g) == EVENT_STATE_TERM)
|
|
|
- { // termination in progress
|
|
|
- // pass control to sync kernel thread, but signal termination
|
|
|
- wake_up_interruptible(&WaitQueueCbSync_g);
|
|
|
- // exit with this error -> application will leave the infinite loop
|
|
|
- iRet = 1;
|
|
|
- goto Exit;
|
|
|
- }
|
|
|
-
|
|
|
- // exchange process image
|
|
|
- EplRet = EplApiProcessImageExchangeIn(&ProcessImageIn);
|
|
|
-
|
|
|
- // return to EplApiProcessImageExchangeIn()
|
|
|
- iRet = (int) EplRet;
|
|
|
-
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- // ----------------------------------------------------------
|
|
|
- case EPLLIN_CMD_PI_OUT:
|
|
|
- {
|
|
|
- tEplApiProcessImage ProcessImageOut;
|
|
|
-
|
|
|
- // save process image structure
|
|
|
- iErr = copy_from_user(&ProcessImageOut, (const void*)ulArg_p, sizeof (ProcessImageOut));
|
|
|
- if (iErr != 0)
|
|
|
- {
|
|
|
- iRet = -EIO;
|
|
|
- goto Exit;
|
|
|
- }
|
|
|
-
|
|
|
- if (atomic_read(&AtomicSyncState_g) != EVENT_STATE_READY)
|
|
|
- {
|
|
|
- iRet = (int) kEplInvalidOperation;
|
|
|
- goto Exit;
|
|
|
- }
|
|
|
-
|
|
|
- // exchange process image
|
|
|
- EplRet = EplApiProcessImageExchangeOut(&ProcessImageOut);
|
|
|
-
|
|
|
- // pass control to sync kernel thread
|
|
|
- atomic_set(&AtomicSyncState_g, EVENT_STATE_TERM);
|
|
|
- wake_up_interruptible(&WaitQueueCbSync_g);
|
|
|
-
|
|
|
- // return to EplApiProcessImageExchangeout()
|
|
|
- iRet = (int) EplRet;
|
|
|
-
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- // ----------------------------------------------------------
|
|
|
- case EPLLIN_CMD_NMT_COMMAND:
|
|
|
- {
|
|
|
- // forward NMT command to EPL stack
|
|
|
- EplRet = EplApiExecNmtCommand((tEplNmtEvent)ulArg_p);
|
|
|
-
|
|
|
- iRet = (int) EplRet;
|
|
|
-
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- // ----------------------------------------------------------
|
|
|
- default:
|
|
|
- {
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-Exit:
|
|
|
+ // ----------------------------------------------------------
|
|
|
+ case EPLLIN_CMD_GET_EVENT:
|
|
|
+ {
|
|
|
+ tEplLinEvent Event;
|
|
|
+
|
|
|
+ // save event structure
|
|
|
+ iErr =
|
|
|
+ copy_from_user(&Event, (const void *)ulArg_p,
|
|
|
+ sizeof(Event));
|
|
|
+ if (iErr != 0) {
|
|
|
+ iRet = -EIO;
|
|
|
+ goto Exit;
|
|
|
+ }
|
|
|
+ // save return code from application's event callback function
|
|
|
+ RetCbEvent_g = Event.m_RetCbEvent;
|
|
|
+
|
|
|
+ if (RetCbEvent_g == kEplShutdown) {
|
|
|
+ // pass control to event queue kernel thread, but signal termination
|
|
|
+ atomic_set(&AtomicEventState_g,
|
|
|
+ EVENT_STATE_TERM);
|
|
|
+ wake_up_interruptible(&WaitQueueCbEvent_g);
|
|
|
+ // exit with error -> EplApiProcess() will leave the infinite loop
|
|
|
+ iRet = 1;
|
|
|
+ goto Exit;
|
|
|
+ }
|
|
|
+ // pass control to event queue kernel thread
|
|
|
+ atomic_set(&AtomicEventState_g, EVENT_STATE_IOCTL);
|
|
|
+ wake_up_interruptible(&WaitQueueCbEvent_g);
|
|
|
+
|
|
|
+ // fall asleep itself in own wait queue
|
|
|
+ iErr = wait_event_interruptible(WaitQueueProcess_g,
|
|
|
+ (atomic_read
|
|
|
+ (&AtomicEventState_g)
|
|
|
+ == EVENT_STATE_READY)
|
|
|
+ ||
|
|
|
+ (atomic_read
|
|
|
+ (&AtomicEventState_g)
|
|
|
+ == EVENT_STATE_TERM));
|
|
|
+ if (iErr != 0) { // waiting was interrupted by signal
|
|
|
+ // pass control to event queue kernel thread, but signal termination
|
|
|
+ atomic_set(&AtomicEventState_g,
|
|
|
+ EVENT_STATE_TERM);
|
|
|
+ wake_up_interruptible(&WaitQueueCbEvent_g);
|
|
|
+ // exit with this error -> EplApiProcess() will leave the infinite loop
|
|
|
+ iRet = iErr;
|
|
|
+ goto Exit;
|
|
|
+ } else if (atomic_read(&AtomicEventState_g) == EVENT_STATE_TERM) { // termination in progress
|
|
|
+ // pass control to event queue kernel thread, but signal termination
|
|
|
+ wake_up_interruptible(&WaitQueueCbEvent_g);
|
|
|
+ // exit with this error -> EplApiProcess() will leave the infinite loop
|
|
|
+ iRet = 1;
|
|
|
+ goto Exit;
|
|
|
+ }
|
|
|
+ // copy event to user space
|
|
|
+ iErr =
|
|
|
+ copy_to_user(Event.m_pEventType, &EventType_g,
|
|
|
+ sizeof(EventType_g));
|
|
|
+ if (iErr != 0) { // not all data could be copied
|
|
|
+ iRet = -EIO;
|
|
|
+ goto Exit;
|
|
|
+ }
|
|
|
+ // $$$ d.k. perform SDO event processing
|
|
|
+ if (EventType_g == kEplApiEventSdo) {
|
|
|
+ void *pData;
|
|
|
+ tEplLinSdoBufHeader *pBufHeader;
|
|
|
+
|
|
|
+ pBufHeader =
|
|
|
+ (tEplLinSdoBufHeader *) pEventArg_g->m_Sdo.
|
|
|
+ m_pUserArg;
|
|
|
+ pData =
|
|
|
+ pBufHeader + sizeof(tEplLinSdoBufHeader);
|
|
|
+
|
|
|
+ if (pEventArg_g->m_Sdo.m_SdoAccessType ==
|
|
|
+ kEplSdoAccessTypeRead) {
|
|
|
+ // copy read data to user space
|
|
|
+ iErr =
|
|
|
+ copy_to_user(pBufHeader->m_pData,
|
|
|
+ pData,
|
|
|
+ pEventArg_g->m_Sdo.
|
|
|
+ m_uiTransferredByte);
|
|
|
+ if (iErr != 0) { // not all data could be copied
|
|
|
+ iRet = -EIO;
|
|
|
+ goto Exit;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ pEventArg_g->m_Sdo.m_pUserArg =
|
|
|
+ pBufHeader->m_pUserArg;
|
|
|
+ vfree(pBufHeader);
|
|
|
+ }
|
|
|
+
|
|
|
+ iErr =
|
|
|
+ copy_to_user(Event.m_pEventArg, pEventArg_g,
|
|
|
+ min(sizeof(tEplApiEventArg),
|
|
|
+ Event.m_uiEventArgSize));
|
|
|
+ if (iErr != 0) { // not all data could be copied
|
|
|
+ iRet = -EIO;
|
|
|
+ goto Exit;
|
|
|
+ }
|
|
|
+ // return to EplApiProcess(), which will call the application's event callback function
|
|
|
+ iRet = 0;
|
|
|
+
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ // ----------------------------------------------------------
|
|
|
+ case EPLLIN_CMD_PI_SETUP:
|
|
|
+ {
|
|
|
+ EplRet = EplApiProcessImageSetup();
|
|
|
+ iRet = (int)EplRet;
|
|
|
+
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ // ----------------------------------------------------------
|
|
|
+ case EPLLIN_CMD_PI_IN:
|
|
|
+ {
|
|
|
+ tEplApiProcessImage ProcessImageIn;
|
|
|
+
|
|
|
+ // save process image structure
|
|
|
+ iErr =
|
|
|
+ copy_from_user(&ProcessImageIn,
|
|
|
+ (const void *)ulArg_p,
|
|
|
+ sizeof(ProcessImageIn));
|
|
|
+ if (iErr != 0) {
|
|
|
+ iRet = -EIO;
|
|
|
+ goto Exit;
|
|
|
+ }
|
|
|
+ // pass control to event queue kernel thread
|
|
|
+ atomic_set(&AtomicSyncState_g, EVENT_STATE_IOCTL);
|
|
|
+
|
|
|
+ // fall asleep itself in own wait queue
|
|
|
+ iErr = wait_event_interruptible(WaitQueuePI_In_g,
|
|
|
+ (atomic_read
|
|
|
+ (&AtomicSyncState_g) ==
|
|
|
+ EVENT_STATE_READY)
|
|
|
+ ||
|
|
|
+ (atomic_read
|
|
|
+ (&AtomicSyncState_g) ==
|
|
|
+ EVENT_STATE_TERM));
|
|
|
+ if (iErr != 0) { // waiting was interrupted by signal
|
|
|
+ // pass control to sync kernel thread, but signal termination
|
|
|
+ atomic_set(&AtomicSyncState_g,
|
|
|
+ EVENT_STATE_TERM);
|
|
|
+ wake_up_interruptible(&WaitQueueCbSync_g);
|
|
|
+ // exit with this error -> application will leave the infinite loop
|
|
|
+ iRet = iErr;
|
|
|
+ goto Exit;
|
|
|
+ } else if (atomic_read(&AtomicSyncState_g) == EVENT_STATE_TERM) { // termination in progress
|
|
|
+ // pass control to sync kernel thread, but signal termination
|
|
|
+ wake_up_interruptible(&WaitQueueCbSync_g);
|
|
|
+ // exit with this error -> application will leave the infinite loop
|
|
|
+ iRet = 1;
|
|
|
+ goto Exit;
|
|
|
+ }
|
|
|
+ // exchange process image
|
|
|
+ EplRet = EplApiProcessImageExchangeIn(&ProcessImageIn);
|
|
|
+
|
|
|
+ // return to EplApiProcessImageExchangeIn()
|
|
|
+ iRet = (int)EplRet;
|
|
|
+
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ // ----------------------------------------------------------
|
|
|
+ case EPLLIN_CMD_PI_OUT:
|
|
|
+ {
|
|
|
+ tEplApiProcessImage ProcessImageOut;
|
|
|
+
|
|
|
+ // save process image structure
|
|
|
+ iErr =
|
|
|
+ copy_from_user(&ProcessImageOut,
|
|
|
+ (const void *)ulArg_p,
|
|
|
+ sizeof(ProcessImageOut));
|
|
|
+ if (iErr != 0) {
|
|
|
+ iRet = -EIO;
|
|
|
+ goto Exit;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (atomic_read(&AtomicSyncState_g) !=
|
|
|
+ EVENT_STATE_READY) {
|
|
|
+ iRet = (int)kEplInvalidOperation;
|
|
|
+ goto Exit;
|
|
|
+ }
|
|
|
+ // exchange process image
|
|
|
+ EplRet =
|
|
|
+ EplApiProcessImageExchangeOut(&ProcessImageOut);
|
|
|
+
|
|
|
+ // pass control to sync kernel thread
|
|
|
+ atomic_set(&AtomicSyncState_g, EVENT_STATE_TERM);
|
|
|
+ wake_up_interruptible(&WaitQueueCbSync_g);
|
|
|
+
|
|
|
+ // return to EplApiProcessImageExchangeout()
|
|
|
+ iRet = (int)EplRet;
|
|
|
+
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ // ----------------------------------------------------------
|
|
|
+ case EPLLIN_CMD_NMT_COMMAND:
|
|
|
+ {
|
|
|
+ // forward NMT command to EPL stack
|
|
|
+ EplRet = EplApiExecNmtCommand((tEplNmtEvent) ulArg_p);
|
|
|
+
|
|
|
+ iRet = (int)EplRet;
|
|
|
+
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ // ----------------------------------------------------------
|
|
|
+ default:
|
|
|
+ {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ Exit:
|
|
|
|
|
|
// TRACE1("EPL: - EplLinIoctl (iRet=%d)\n", iRet);
|
|
|
- return (iRet);
|
|
|
+ return (iRet);
|
|
|
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
//=========================================================================//
|
|
|
// //
|
|
|
// P R I V A T E F U N C T I O N S //
|
|
|
// //
|
|
|
//=========================================================================//
|
|
|
|
|
|
-
|
|
|
-tEplKernel PUBLIC EplLinCbEvent(
|
|
|
- tEplApiEventType EventType_p, // IN: event type (enum)
|
|
|
- tEplApiEventArg* pEventArg_p, // IN: event argument (union)
|
|
|
- void GENERIC* pUserArg_p)
|
|
|
+tEplKernel PUBLIC EplLinCbEvent(tEplApiEventType EventType_p, // IN: event type (enum)
|
|
|
+ tEplApiEventArg * pEventArg_p, // IN: event argument (union)
|
|
|
+ void GENERIC * pUserArg_p)
|
|
|
{
|
|
|
-tEplKernel EplRet = kEplSuccessful;
|
|
|
-int iErr;
|
|
|
-
|
|
|
- // block any further call to this function, i.e. enter critical section
|
|
|
- iErr = down_interruptible(&SemaphoreCbEvent_g);
|
|
|
- if (iErr != 0)
|
|
|
- { // waiting was interrupted by signal
|
|
|
- EplRet = kEplShutdown;
|
|
|
- goto Exit;
|
|
|
- }
|
|
|
-
|
|
|
- // wait for EplApiProcess() to call ioctl
|
|
|
- // normally it should be waiting already for us to pass a new event
|
|
|
- iErr = wait_event_interruptible(WaitQueueCbEvent_g,
|
|
|
- (atomic_read(&AtomicEventState_g) == EVENT_STATE_IOCTL)
|
|
|
- || (atomic_read(&AtomicEventState_g) == EVENT_STATE_TERM));
|
|
|
- if ((iErr != 0) || (atomic_read(&AtomicEventState_g) == EVENT_STATE_TERM))
|
|
|
- { // waiting was interrupted by signal
|
|
|
- EplRet = kEplShutdown;
|
|
|
- goto LeaveCriticalSection;
|
|
|
- }
|
|
|
-
|
|
|
- // save event information for ioctl
|
|
|
- EventType_g = EventType_p;
|
|
|
- pEventArg_g = pEventArg_p;
|
|
|
-
|
|
|
- // pass control to application's event callback function, i.e. EplApiProcess()
|
|
|
- atomic_set(&AtomicEventState_g, EVENT_STATE_READY);
|
|
|
- wake_up_interruptible(&WaitQueueProcess_g);
|
|
|
-
|
|
|
- // now, the application's event callback function processes the event
|
|
|
-
|
|
|
- // wait for completion of application's event callback function, i.e. EplApiProcess() calls ioctl again
|
|
|
- iErr = wait_event_interruptible(WaitQueueCbEvent_g,
|
|
|
- (atomic_read(&AtomicEventState_g) == EVENT_STATE_IOCTL)
|
|
|
- || (atomic_read(&AtomicEventState_g) == EVENT_STATE_TERM));
|
|
|
- if ((iErr != 0) || (atomic_read(&AtomicEventState_g) == EVENT_STATE_TERM))
|
|
|
- { // waiting was interrupted by signal
|
|
|
- EplRet = kEplShutdown;
|
|
|
- goto LeaveCriticalSection;
|
|
|
- }
|
|
|
-
|
|
|
- // read return code from application's event callback function
|
|
|
- EplRet = RetCbEvent_g;
|
|
|
-
|
|
|
-
|
|
|
-LeaveCriticalSection:
|
|
|
- up(&SemaphoreCbEvent_g);
|
|
|
-
|
|
|
-Exit:
|
|
|
- // check if NMT_GS_OFF is reached
|
|
|
- if (EventType_p == kEplApiEventNmtStateChange)
|
|
|
- {
|
|
|
- if (pEventArg_p->m_NmtStateChange.m_NewNmtState == kEplNmtGsOff)
|
|
|
- { // NMT state machine was shut down
|
|
|
- TRACE0("EPL: EplLinCbEvent(NMT_GS_OFF)\n");
|
|
|
- uiEplState_g = EPL_STATE_SHUTDOWN;
|
|
|
- atomic_set(&AtomicEventState_g, EVENT_STATE_TERM);
|
|
|
- wake_up(&WaitQueueRelease_g);
|
|
|
- }
|
|
|
- else
|
|
|
- { // NMT state machine is running
|
|
|
- uiEplState_g = EPL_STATE_RUNNING;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- return EplRet;
|
|
|
+ tEplKernel EplRet = kEplSuccessful;
|
|
|
+ int iErr;
|
|
|
+
|
|
|
+ // block any further call to this function, i.e. enter critical section
|
|
|
+ iErr = down_interruptible(&SemaphoreCbEvent_g);
|
|
|
+ if (iErr != 0) { // waiting was interrupted by signal
|
|
|
+ EplRet = kEplShutdown;
|
|
|
+ goto Exit;
|
|
|
+ }
|
|
|
+ // wait for EplApiProcess() to call ioctl
|
|
|
+ // normally it should be waiting already for us to pass a new event
|
|
|
+ iErr = wait_event_interruptible(WaitQueueCbEvent_g,
|
|
|
+ (atomic_read(&AtomicEventState_g) ==
|
|
|
+ EVENT_STATE_IOCTL)
|
|
|
+ || (atomic_read(&AtomicEventState_g) ==
|
|
|
+ EVENT_STATE_TERM));
|
|
|
+ if ((iErr != 0) || (atomic_read(&AtomicEventState_g) == EVENT_STATE_TERM)) { // waiting was interrupted by signal
|
|
|
+ EplRet = kEplShutdown;
|
|
|
+ goto LeaveCriticalSection;
|
|
|
+ }
|
|
|
+ // save event information for ioctl
|
|
|
+ EventType_g = EventType_p;
|
|
|
+ pEventArg_g = pEventArg_p;
|
|
|
+
|
|
|
+ // pass control to application's event callback function, i.e. EplApiProcess()
|
|
|
+ atomic_set(&AtomicEventState_g, EVENT_STATE_READY);
|
|
|
+ wake_up_interruptible(&WaitQueueProcess_g);
|
|
|
+
|
|
|
+ // now, the application's event callback function processes the event
|
|
|
+
|
|
|
+ // wait for completion of application's event callback function, i.e. EplApiProcess() calls ioctl again
|
|
|
+ iErr = wait_event_interruptible(WaitQueueCbEvent_g,
|
|
|
+ (atomic_read(&AtomicEventState_g) ==
|
|
|
+ EVENT_STATE_IOCTL)
|
|
|
+ || (atomic_read(&AtomicEventState_g) ==
|
|
|
+ EVENT_STATE_TERM));
|
|
|
+ if ((iErr != 0) || (atomic_read(&AtomicEventState_g) == EVENT_STATE_TERM)) { // waiting was interrupted by signal
|
|
|
+ EplRet = kEplShutdown;
|
|
|
+ goto LeaveCriticalSection;
|
|
|
+ }
|
|
|
+ // read return code from application's event callback function
|
|
|
+ EplRet = RetCbEvent_g;
|
|
|
+
|
|
|
+ LeaveCriticalSection:
|
|
|
+ up(&SemaphoreCbEvent_g);
|
|
|
+
|
|
|
+ Exit:
|
|
|
+ // check if NMT_GS_OFF is reached
|
|
|
+ if (EventType_p == kEplApiEventNmtStateChange) {
|
|
|
+ if (pEventArg_p->m_NmtStateChange.m_NewNmtState == kEplNmtGsOff) { // NMT state machine was shut down
|
|
|
+ TRACE0("EPL: EplLinCbEvent(NMT_GS_OFF)\n");
|
|
|
+ uiEplState_g = EPL_STATE_SHUTDOWN;
|
|
|
+ atomic_set(&AtomicEventState_g, EVENT_STATE_TERM);
|
|
|
+ wake_up(&WaitQueueRelease_g);
|
|
|
+ } else { // NMT state machine is running
|
|
|
+ uiEplState_g = EPL_STATE_RUNNING;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return EplRet;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
tEplKernel PUBLIC EplLinCbSync(void)
|
|
|
{
|
|
|
-tEplKernel EplRet = kEplSuccessful;
|
|
|
-int iErr;
|
|
|
-
|
|
|
- // check if user process waits for sync
|
|
|
- if (atomic_read(&AtomicSyncState_g) == EVENT_STATE_IOCTL)
|
|
|
- {
|
|
|
- // pass control to application, i.e. EplApiProcessImageExchangeIn()
|
|
|
- atomic_set(&AtomicSyncState_g, EVENT_STATE_READY);
|
|
|
- wake_up_interruptible(&WaitQueuePI_In_g);
|
|
|
-
|
|
|
- // now, the application processes the sync event
|
|
|
-
|
|
|
- // wait for call of EplApiProcessImageExchangeOut()
|
|
|
- iErr = wait_event_interruptible(WaitQueueCbSync_g,
|
|
|
- (atomic_read(&AtomicSyncState_g) == EVENT_STATE_IOCTL)
|
|
|
- || (atomic_read(&AtomicSyncState_g) == EVENT_STATE_TERM));
|
|
|
- if ((iErr != 0) || (atomic_read(&AtomicEventState_g) == EVENT_STATE_IOCTL))
|
|
|
- { // waiting was interrupted by signal or application called wrong function
|
|
|
- EplRet = kEplShutdown;
|
|
|
- }
|
|
|
- }
|
|
|
- else
|
|
|
- { // application is currently not waiting for sync
|
|
|
- // continue without interruption
|
|
|
- // TPDO are set valid by caller (i.e. EplEventkProcess())
|
|
|
- }
|
|
|
-
|
|
|
- TGT_DBG_SIGNAL_TRACE_POINT(1);
|
|
|
-
|
|
|
- return EplRet;
|
|
|
+ tEplKernel EplRet = kEplSuccessful;
|
|
|
+ int iErr;
|
|
|
+
|
|
|
+ // check if user process waits for sync
|
|
|
+ if (atomic_read(&AtomicSyncState_g) == EVENT_STATE_IOCTL) {
|
|
|
+ // pass control to application, i.e. EplApiProcessImageExchangeIn()
|
|
|
+ atomic_set(&AtomicSyncState_g, EVENT_STATE_READY);
|
|
|
+ wake_up_interruptible(&WaitQueuePI_In_g);
|
|
|
+
|
|
|
+ // now, the application processes the sync event
|
|
|
+
|
|
|
+ // wait for call of EplApiProcessImageExchangeOut()
|
|
|
+ iErr = wait_event_interruptible(WaitQueueCbSync_g,
|
|
|
+ (atomic_read(&AtomicSyncState_g)
|
|
|
+ == EVENT_STATE_IOCTL)
|
|
|
+ ||
|
|
|
+ (atomic_read(&AtomicSyncState_g)
|
|
|
+ == EVENT_STATE_TERM));
|
|
|
+ if ((iErr != 0) || (atomic_read(&AtomicEventState_g) == EVENT_STATE_IOCTL)) { // waiting was interrupted by signal or application called wrong function
|
|
|
+ EplRet = kEplShutdown;
|
|
|
+ }
|
|
|
+ } else { // application is currently not waiting for sync
|
|
|
+ // continue without interruption
|
|
|
+ // TPDO are set valid by caller (i.e. EplEventkProcess())
|
|
|
+ }
|
|
|
+
|
|
|
+ TGT_DBG_SIGNAL_TRACE_POINT(1);
|
|
|
+
|
|
|
+ return EplRet;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-
|
|
|
// EOF
|
|
|
-
|