diff options
Diffstat (limited to 'drivers/staging/epl/EplApiLinuxKernel.c')
-rw-r--r-- | drivers/staging/epl/EplApiLinuxKernel.c | 1871 |
1 files changed, 907 insertions, 964 deletions
diff --git a/drivers/staging/epl/EplApiLinuxKernel.c b/drivers/staging/epl/EplApiLinuxKernel.c index 4941760..05ca062 100644 --- a/drivers/staging/epl/EplApiLinuxKernel.c +++ b/drivers/staging/epl/EplApiLinuxKernel.c @@ -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 - |