summaryrefslogtreecommitdiffstats
path: root/module
diff options
context:
space:
mode:
Diffstat (limited to 'module')
-rwxr-xr-xmodule/kernel-module-evklib/Makefile30
-rwxr-xr-xmodule/kernel-module-evklib/agldd/agldd.h94
-rwxr-xr-xmodule/kernel-module-evklib/agldd/ev_common.h135
-rwxr-xr-xmodule/kernel-module-evklib/agldd/ev_id.h104
-rwxr-xr-xmodule/kernel-module-evklib/agldd/evk_lib.h116
-rwxr-xr-xmodule/kernel-module-evklib/agldd/moduleid.h69
-rwxr-xr-xmodule/kernel-module-evklib/evk_lib.c2282
7 files changed, 2830 insertions, 0 deletions
diff --git a/module/kernel-module-evklib/Makefile b/module/kernel-module-evklib/Makefile
new file mode 100755
index 0000000..2c37667
--- /dev/null
+++ b/module/kernel-module-evklib/Makefile
@@ -0,0 +1,30 @@
+# @copyright Copyright (c) 2016-2019 TOYOTA MOTOR CORPORATION.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Makefile for linux/drivers/agl
+#
+CFILES = evk_lib.c
+
+obj-m := evk_lib.o
+evklib-objs := $(CFILES:.c=.o)
+
+U_INCLUDE += -I$(PWD)
+U_INCLUDE += -I$(KERNEL_SRC)/include
+ccflags-y += $(U_INCLUDE)
+
+all:
+ make -C $(KERNEL_SRC) M=$(PWD) modules
+clean:
+ make -C $(KERNEL_SRC) M=$(PWD) clean
+
diff --git a/module/kernel-module-evklib/agldd/agldd.h b/module/kernel-module-evklib/agldd/agldd.h
new file mode 100755
index 0000000..112dbae
--- /dev/null
+++ b/module/kernel-module-evklib/agldd/agldd.h
@@ -0,0 +1,94 @@
+/*
+ * adcpf common header
+ *
+ * @copyright Copyright (c) 2016-2019 TOYOTA MOTOR CORPORATION.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _AGLDD_H_
+#define _AGLDD_H_
+#ifdef __KERNEL__
+#include <linux/types.h>
+#else
+#include <stdint.h>
+#if !defined(__cplusplus)
+#include <stdbool.h>
+#endif /* !defined(__cplusplus) */
+#endif /* __KERNEL__ */
+
+#ifndef __KERNEL__
+#define __LINUX_ARM_ARCH__ 7
+#define BITS_PER_LONG 32
+
+#define __AGLDD_TYPEDEF_I64
+typedef long long i64; /* 8-byte signed integer */
+
+#define __AGLDD_TYPEDEF_U64
+typedef unsigned long long u64; /* 8-byte unsigned integer */
+
+#define __AGLDD_TYPEDEF_U32
+typedef unsigned long u32; /* 4-byte unsigned integer */
+
+#define __AGLDD_TYPEDEF_U16
+typedef unsigned short u16; /* 2-byte unsigned integer */
+
+#define __AGLDD_TYPEDEF_I16
+typedef short i16; /* 2-byte signed integer */
+
+#define __AGLDD_TYPEDEF_U8
+typedef unsigned char u8; /* 1-byte unsigned integer */
+
+#define __AGLDD_TYPEDEF_I8
+typedef char i8; /* 1-byte signed integer */
+#endif
+
+#define __AGLDD_TYPEDEF_INT8
+typedef signed char INT8;
+
+#define __AGLDD_TYPEDEF_INT16
+typedef signed short INT16;
+
+#define __AGLDD_TYPEDEF_INT32
+typedef signed int INT32;
+
+#define __AGLDD_TYPEDEF_INT64
+typedef signed long long INT64;
+
+#define __AGLDD_TYPEDEF_UINT8
+typedef unsigned char UINT8;
+
+#define __AGLDD_TYPEDEF_UINT16
+typedef unsigned short UINT16;
+
+#define __AGLDD_TYPEDEF_UINT32
+typedef unsigned int UINT32;
+
+#define __AGLDD_TYPEDEF_UINT64
+typedef unsigned long long UINT64;
+
+#ifndef __KERNEL__
+#if !defined __WIN_TYPEDEF_BOOL
+#define __AGLDD_TYPEDEF_BOOL
+typedef UINT32 BOOL;
+#endif
+#endif
+
+#ifndef TRUE
+#define TRUE true
+#endif
+#ifndef FALSE
+#define FALSE false
+#endif
+
+#endif/* _AGLDD_H_ */
diff --git a/module/kernel-module-evklib/agldd/ev_common.h b/module/kernel-module-evklib/agldd/ev_common.h
new file mode 100755
index 0000000..0cc1183
--- /dev/null
+++ b/module/kernel-module-evklib/agldd/ev_common.h
@@ -0,0 +1,135 @@
+/**
+ * @file ev_common.h
+ * @brief Event library -- User kernel common data structure
+ *
+ * @copyright Copyright (c) 2016-2019 TOYOTA MOTOR CORPORATION.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _ev_common_h_
+#define _ev_common_h_
+
+#include <agldd/ev_id.h>
+
+/** @addtogroup EV
+ * @{ */
+/** @brief Maximum number of bytes for message event */
+#define EV_MAX_MESSAGE_LENGTH 2048
+
+/** @brief -Maximum number of flag queue that can be created within a thread */
+#define EV_MAX_IDS_IN_THREAD 24
+
+/** @brief -Muximum number of threads that can be registered to the EV in a process */
+#define EV_MAX_THREADS_IN_PROCESS 16
+
+/** @brief -Maximum number of flag queue that can be creat within a process
+ */
+#define EV_MAX_IDS_IN_PROCESS \
+ (EV_MAX_IDS_IN_THREAD * EV_MAX_THREADS_IN_PROCESS)
+
+/** @brief Return values for even library function
+ *
+ * @see EV_ERR
+ */
+enum ev_err
+{
+ EV_OK = 0, /**< Normal completion */
+ EV_ERR_Exist, /**< The specified flag message queue does exist */
+ EV_ERR_Invalid_ID, /**< The specified flag message queue does not exist */
+ EV_ERR_Busy, /**< Message queue full failed to send */
+ EV_ERR_Interrupted, /**< Waiting function was interrupted by an interrupt */
+ EV_ERR_Thread_Over, /**< Exceeding the number of threads in the process */
+ EV_ERR_Invalid_Thread, /**< Invalid thread ID */
+ EV_ERR_Fatal, /**< Fatal error */
+};
+/** @brief Return values type for even library function
+ *
+ * @see ev_err
+ */
+typedef INT32 EV_ERR;
+
+/** @brief Event type
+ *
+ * Use in the type of EV_Event structs
+ * @see ev_type
+ */
+typedef UINT32 EV_Type;
+
+/** @brief Bit value representing the type of event */
+enum ev_type {
+ EV_EVENT_None = 0x00000000,
+
+ /** Flag event: Judged by EV_EVENT_IS_FLAG() */
+ EV_EVENT_Flag = 0x0001,
+#define EV_EVENT_IS_FLAG(tp) (((tp) & EV_EVENT_Flag) != 0)
+
+ /** Message event: Judged by EV_EVENT_IS_MESSAGE() */
+ EV_EVENT_Message = 0x0002,
+#define EV_EVENT_IS_MESSAGE(tp) (((tp) & EV_EVENT_Message) != 0)
+
+ /** 64bit flag event: Judged by EV_EVENT_IS_FLAG64() */
+ EV_EVENT_Flag64 = 0x0003,
+#define EV_EVENT_IS_FLAG64(tp) (((tp) & EV_EVENT_Flag64) != 0)
+
+};
+
+/** @brief Flag event structure */
+typedef struct {
+ EV_ID flagID;/**< Flag ID */
+ UINT32 bits;/**< Bit pattern */
+} EV_Flag;
+
+/** @brief 64bit flag event structure */
+typedef struct {
+ EV_ID flagID;/**< Flag ID */
+ UINT64 bits;/**< Bit pattern */
+} EV_Flag64;
+
+/** @brief Message event structure */
+typedef struct {
+ EV_ID queueID;/**< queue ID */
+ UINT32 senderInfo;/**< Source information */
+ UINT32 length;/**< Number of bytes in the message */
+ UINT32 dummy;/** dummy for pading */
+ UINT8 message[EV_MAX_MESSAGE_LENGTH];/**< Message */
+} EV_Message;
+
+/** @brief Event structure */
+typedef struct {
+ EV_Type type; /**< Event type */
+ union {
+ EV_Flag flag; /**< Flag event structure */
+ EV_Flag64 flag64; /**< Flag event structure */
+ EV_Message message; /**< Message event structure */
+ } u; /**< Union of structures per eventtype */
+} EV_Event;
+
+/** @brief Message event queue type
+ *
+ * Specify the action to be taken when the queue overflows (more events are received when the queue is full).
+ */
+enum ev_message_queue_type {
+ EV_MESSAGE_QUEUE_TYPE_BUSY,/**< Return a BUSY to the source */
+ EV_MESSAGE_QUEUE_TYPE_FIFO,/**< Delete the oldest event */
+ EV_MESSAGE_QUEUE_TYPE_REPLACE,/**< Replace the most recent event */
+};
+
+/** @brief Messge event queue type
+ *
+ * @see ev_message_queue_type
+ */
+typedef UINT8 EV_Message_Queue_Type;
+
+/** @} */
+
+#endif /* !_ev_common_h_ */
diff --git a/module/kernel-module-evklib/agldd/ev_id.h b/module/kernel-module-evklib/agldd/ev_id.h
new file mode 100755
index 0000000..2026ef7
--- /dev/null
+++ b/module/kernel-module-evklib/agldd/ev_id.h
@@ -0,0 +1,104 @@
+/**
+ * @file ev_id.h
+ * @brief Event library(kernel) -- Defining flag queue ID
+ *
+ * @copyright Copyright (c) 2016-2019 TOYOTA MOTOR CORPORATION.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _ev_id_h_
+#define _ev_id_h_
+
+/** @addtogroup EV_ID_spec
+ * @{ */
+
+/** @brief Flag ID and queue ID types used when sending and receiving events
+ *
+ * Assign a 32-bit value as follows
+ *
+ * - Most significant 8 bits: Reserved
+ * - Next 16 bits: Modue ID
+ * - Lower 8 bits: Define in module
+ *
+ * Where module is the modules that creates the queue.
+ * The modules define ID according to the above assignments using EV_Flag_ID_Base and EV_Queue_ID_Base macros.
+ * @see EV_Flag_ID_Base
+ * @see EV_Queue_ID_Base
+ */
+typedef UINT32 EV_ID;
+
+#define EV_ID_BIT 0x80000000UL
+#define EV_FLAG64_BIT 0x40000000UL
+#define EV_FLAG_BIT 0x20000000UL
+#define EV_QUEUE_BIT 0x10000000UL
+#define EV_AUTO_ID_BIT 0x08000000UL
+#define EV_RESERVED_BIT 0xff000000UL
+#define EV_INVALID_ID EV_ID_BIT
+#define EV_NO_ID EV_INVALID_ID
+
+#define EV_ID_IS_FLAG(queueID) \
+ (((queueID) & (EV_ID_BIT|EV_FLAG_BIT)) == (EV_ID_BIT|EV_FLAG_BIT))
+#define EV_ID_IS_FLAG64(queueID) \
+ (((queueID) & (EV_ID_BIT|EV_FLAG64_BIT)) == (EV_ID_BIT|EV_FLAG64_BIT))
+#define EV_ID_IS_QUEUE(queueID) \
+ (((queueID) & (EV_ID_BIT|EV_QUEUE_BIT)) == (EV_ID_BIT|EV_QUEUE_BIT))
+#define EV_ID_IS_AUTO_ID(queueID) \
+ (((queueID) & (EV_ID_BIT|EV_AUTO_ID_BIT)) == (EV_ID_BIT|EV_AUTO_ID_BIT))
+#define EV_ID_IS_VALID(queueID) \
+ (EV_ID_IS_FLAG(queueID) || EV_ID_IS_FLAG64(queueID) || EV_ID_IS_QUEUE(queueID))
+
+/** @brief Macros for defining flag ID
+ *
+ * Define the module ID as an argument as follows.
+ * - #define XXX_Module_ID 1
+ * - #define XXX_Flag_ID_Base EV_Flag_ID_Base(XXX_Module_ID)
+ * -
+ * - #define XXX_Flag_foo (XXX_Flag_ID_Base + 1)
+ * - #define XXX_Flag_bar (XXX_Flag_ID_Base + 2)
+ *
+ * The module ID is 16 bits and 0 to 65535 can be specified.
+ * In addition, 0 to 255 added to Base can be defined as ID.
+ */
+#define EV_Flag_ID_Base(mod) (EV_ID_BIT|EV_FLAG_BIT|((mod)<<8))
+
+/** @brief Macros for defining 64 bits flag ID
+ *
+ * Define the module ID as an argument as follows.
+ * - #define XXX_Module_ID 1
+ * - #define XXX_Flag64_ID_Base EV_Flag64_ID_Base(XXX_Module_ID)
+ * -
+ * - #define XXX_Flag64_foo (XXX_Flag64_ID_Base + 1)
+ * - #define XXX_Flag64_bar (XXX_Flag64_ID_Base + 2)
+ *
+ * The module ID is 16 bits and 0 to 65535 can be specified.
+ * In addition, 0 to 255 added to Base can be defined as ID.
+ */
+#define EV_Flag64_ID_Base(mod) (EV_ID_BIT|EV_FLAG64_BIT|((mod)<<8))
+
+/** @brief Macros for defining mesage queue ID
+ *
+ * Define the module ID as an argument as follows.
+ * - #define XXX_Module_ID 1
+ * - #define XXX_Queue_ID_Base EV_Queue_ID_Base(XXX_Module_ID)
+ * -
+ * - #define XXX_Queue_foo (XXX_Queue_ID_Base + 1)
+ * - #define XXX_Queue_bar (XXX_Queue_ID_Base + 2)
+ *
+ * The module ID is 16 bits and 0 to 65535 can be specified.
+ * In addition, 0 to 255 added to Base can be defined as ID.
+ */
+#define EV_Queue_ID_Base(mod) (EV_ID_BIT|EV_QUEUE_BIT|((mod)<<8))
+
+/** @} */
+
+#endif /* ! _ev_id_h_ */
diff --git a/module/kernel-module-evklib/agldd/evk_lib.h b/module/kernel-module-evklib/agldd/evk_lib.h
new file mode 100755
index 0000000..416fb0f
--- /dev/null
+++ b/module/kernel-module-evklib/agldd/evk_lib.h
@@ -0,0 +1,116 @@
+/**
+ * @file evk_lib.h
+ * @brief Event library -- API specifications for kernel modules
+ *
+ * @copyright Copyright (c) 2016-2019 TOYOTA MOTOR CORPORATION.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _evk_lib_h_
+#define _evk_lib_h_
+
+#include <agldd/ev_common.h>
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+/* API definition */
+
+/** @addtogroup EV
+ * @{ */
+#ifdef __KERNEL__
+/* Flag message queue create/delete */
+EV_ERR EVK_create_flag(EV_ID flagID);
+EV_ERR EVK_create_flag64(EV_ID flagID);
+EV_ERR EVK_create_queue(EV_ID queueID,
+ UINT8 length,
+ UINT16 max_bytes,
+ EV_Message_Queue_Type type);
+
+EV_ERR EVK_create_flag_auto_id(/* OUT */EV_ID *flagID);
+EV_ERR EVK_create_flag64_auto_id(/* OUT */EV_ID *flagID);
+EV_ERR EVK_create_queue_auto_id(/* OUT */EV_ID *queueID,
+ UINT8 length,
+ UINT16 max_bytes,
+ EV_Message_Queue_Type type);
+
+EV_ERR EVK_destroy_flag(EV_ID flagID);
+EV_ERR EVK_destroy_queue(EV_ID queueID);
+
+/* Send events */
+EV_ERR EVK_set_flag(EV_ID flagID, UINT32 bits);
+EV_ERR EVK_set_flag64(EV_ID flagID, UINT64 bits);
+EV_ERR EVK_send_message(EV_ID queueID, UINT16 bytes, const void *message,
+ UINT32 senderInfo);
+
+/* Get event(with search conditions) */
+EV_ERR EVK_get_flag(EV_ID flagID, /* OUT */EV_Flag *flag);
+EV_ERR EVK_wait_flag(EV_ID flagID, /* OUT */EV_Flag *flag);/* block */
+EV_ERR EVK_peek_flag(EV_ID flagID, /* OUT */EV_Flag *flag);
+EV_ERR EVK_get_flag64(EV_ID flagID, /* OUT */EV_Flag64 *flag);
+EV_ERR EVK_wait_flag64(EV_ID flagID, /* OUT */EV_Flag64 *flag);/* block */
+EV_ERR EVK_peek_flag64(EV_ID flagID, /* OUT */EV_Flag64 *flag);
+
+EV_ERR EVK_get_message(EV_ID queueID, /* OUT */EV_Message *message);
+EV_ERR EVK_wait_message(EV_ID queueID, /* OUT */EV_Message *message);/* block */
+EV_ERR EVK_peek_message(EV_ID queueID, /* OUT */EV_Message *message);
+
+EV_ERR EVK_find_message_by_sender(EV_ID queueID, UINT32 senderInfo,
+ /* OUT */EV_Message *message);
+EV_ERR EVK_find_message_by_content(EV_ID queueID, UINT16 length,
+ const void *compare_bytes,
+ /* OUT */EV_Message *message);
+#endif
+
+/** @} */
+
+/** @addtogroup EVK_in
+ * @{ */
+#define EVK_NAME "evk"
+#define EVK_DEV_NAME "/dev/agl/"EVK_NAME
+#define EVK_DEV_MAJOR (1033 % 256)
+#define EVK_IOC_MAGIC 0xE7
+
+#define EVK_IOC_CREATE_FLAG _IO(EVK_IOC_MAGIC, 0x00)
+#define EVK_IOC_CREATE_FLAG64 _IO(EVK_IOC_MAGIC, 0x01)
+#define EVK_IOC_CREATE_MESSAGE_QUEUE _IO(EVK_IOC_MAGIC, 0x02)
+#define EVK_IOC_ALLOC_FLAG_ID _IO(EVK_IOC_MAGIC, 0x03)
+#define EVK_IOC_ALLOC_FLAG64_ID _IO(EVK_IOC_MAGIC, 0x04)
+#define EVK_IOC_ALLOC_QUEUE_ID _IO(EVK_IOC_MAGIC, 0x05)
+#define EVK_IOC_DESTROY_QUEUE _IO(EVK_IOC_MAGIC, 0x06)
+#define EVK_IOC_STORE_FLAG _IO(EVK_IOC_MAGIC, 0x07)
+#define EVK_IOC_STORE_FLAG64 _IO(EVK_IOC_MAGIC, 0x08)
+#define EVK_IOC_STORE_MESSAGE _IO(EVK_IOC_MAGIC, 0x09)
+#define EVK_IOC_SET_POLL _IO(EVK_IOC_MAGIC, 0x0a)
+#define EVK_IOC_GET_EVENT _IO(EVK_IOC_MAGIC, 0x0b)
+#define EVK_IOC_PEEK_EVENT _IO(EVK_IOC_MAGIC, 0x0c)
+#define EVK_IOC_WAIT_EVENT _IO(EVK_IOC_MAGIC, 0x0d)
+#define EVK_IOC_GET_NEXT_EVENT _IO(EVK_IOC_MAGIC, 0x0e)
+#define EVK_IOC_PEEK_NEXT_EVENT _IO(EVK_IOC_MAGIC, 0x0f)
+#define EVK_IOC_DEBUG_LIST _IO(EVK_IOC_MAGIC, 0x10)
+
+typedef struct {
+ EV_ID queueID;/**< Queue ID */
+ UINT32 max_bytes;/**< Maximum number of bytes for an event */
+ UINT8 length;/**< Queue length */
+ EV_Message_Queue_Type type;/**< Type */
+} EVK_Message_Queue_Request;
+
+typedef struct {
+ INT32 num; /**< Number of queue ID of search */
+ EV_ID ids[EV_MAX_IDS_IN_PROCESS]; /**< Queue ID of search */
+ EV_Event ev; /**< [OUT] First event that occured */
+} EVK_Next_Event_Query;
+
+/** @} */
+
+#endif /* !_evk_lib_h */
diff --git a/module/kernel-module-evklib/agldd/moduleid.h b/module/kernel-module-evklib/agldd/moduleid.h
new file mode 100755
index 0000000..b18c1a1
--- /dev/null
+++ b/module/kernel-module-evklib/agldd/moduleid.h
@@ -0,0 +1,69 @@
+/*
+ * @copyright Copyright (c) 2016-2019 TOYOTA MOTOR CORPORATION.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <linux/autoconf.h>
+#ifndef _AGLDD_MODULEID_H_
+#define _AGLDD_MODULEID_H_
+
+/*
+ * Define module ID to be used by programs in moduleid_id.h .
+ * Define in the format of "#define XXX_MID ID number" (XXX is the module name).
+ *
+ * MID allocation policy shall be as follows.
+ * - UI Application : 0xxxh
+ * - Application Service : 1xxxh to 2xxxh
+ * + HMI : 10xxh
+ * + AV : 12xxh
+ * + Radio : 14xxh
+ * + Connectivity : 16xxh
+ * + Navigation/Location: 18xxh
+ * + Vehicle : 1Axxh
+ * + Communication : 1Cxxh
+ * + BasePF : 1Exxh
+ * + System : 20xxh
+ * + Other : 22xxh
+ * - Common Service : 3xxxh
+ * - Extension Service : 4xxxh
+ * - System/Device Driver : 5xxxh
+ */
+
+/* UI Application : 0xxxh */
+
+/* Application Service : 1xxxh to 2xxxh */
+#define MODEMANAGER_MID 0x1000
+#define ACTIVITYMANAGER_MID 0x1001
+
+/* Common Service : 3xxxh */
+#define IPMANAGER_MID 0x3000
+#define DEVICEMANAGER_MID 0x3001
+#define MSGBRK_MID 0x3002
+#define TIMERENTRYDRV_MID 0x3003
+#define SOUNDAGENT_MID 0x3004
+#define CAN_MID 0x3006
+#define _CWORD83__MID 0x3007
+#define SENSOR_MID 0x3008
+#define GPS_MID 0x3009
+#define RESMGR_MID 0x300A
+#define GRAPHICS_MID 0x300B
+
+/* Extension Service : 4xxxh */
+
+/* System/Device Driver : 5xxxh */
+#define EV_MID 0x5001
+#define RPC_MID 0x5002
+#define EVK_MID 0x5801
+
+#endif /* !_AGLDD_MODULEID_H_ */
diff --git a/module/kernel-module-evklib/evk_lib.c b/module/kernel-module-evklib/evk_lib.c
new file mode 100755
index 0000000..05d881a
--- /dev/null
+++ b/module/kernel-module-evklib/evk_lib.c
@@ -0,0 +1,2282 @@
+/*
+ * drivers/agl/evk_lib.c
+ *
+ * Event library (kernel space part)
+ *
+ * @copyright Copyright (c) 2016-2019 TOYOTA MOTOR CORPORATION.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <generated/autoconf.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/poll.h>
+#include <linux/list.h>
+#include <asm/uaccess.h>
+#include <linux/errno.h>
+#include <linux/vmalloc.h>
+
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+
+#include <linux/device.h>
+#include <linux/cdev.h>
+
+#ifndef STANDARD_INT_DEFINITIONS
+#define STANDARD_INT_DEFINITIONS
+typedef __u8 UINT8;
+typedef __u16 UINT16;
+typedef __u32 UINT32;
+typedef __u64 UINT64;
+typedef __s8 INT8;
+typedef __s16 INT16;
+typedef __s32 INT32;
+typedef __s64 INT64;
+#endif /* !STANDARD_INT_DEFINITIONS */
+
+#define ENABLE_PROC_FS 1
+
+#include <agldd/evk_lib.h>
+
+/** @addtogroup EV_in */
+/** @{ */
+/** In Linux2.4, list_for_each_entry is not provided, so it is prepared by self (in 2.6)
+ */
+#ifdef list_for_each_entry
+#define __LINUX_26_OR_HIGHER
+#endif
+
+#ifndef __LINUX_26_OR_HIGHER /* linux v2.4 */
+
+#define list_for_each_entry(pos, head, member) \
+ for (pos = list_entry((head)->next, typeof(*pos), member), \
+ prefetch(pos->member.next); \
+ &pos->member != (head); \
+ pos = list_entry(pos->member.next, typeof(*pos), member), \
+ prefetch(pos->member.next))
+
+#define list_for_each_entry_safe(pos, n, head, member) \
+ for (pos = list_entry((head)->next, typeof(*pos), member), \
+ n = list_entry(pos->member.next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = n, n = list_entry(n->member.next, typeof(*n), member))
+
+#else /* linux v2.6 */
+
+#include <linux/jiffies.h>
+
+#endif /* linux v2.6 */
+
+#define EVK_assert(cond, mesg) \
+ if (!(cond)) { \
+ printk(KERN_ALERT "[EVK]ASSERT(pid:%d): " #cond " at %s:%d; " \
+ #mesg "\n", current->pid, __FILE__, __LINE__); \
+ do {} while(1); \
+ }
+
+#define EVK_BUG(mesg) \
+ printk(KERN_ALERT "[EVK]BUG: " mesg); \
+ do {} while(1);
+
+#if 0
+#define EVK_info0(s) printk(KERN_ALERT "[EVK]INFO: " s)
+#define EVK_info1(s, t) printk(KERN_ALERT "[EVK]INFO: " s, t)
+#else
+#define EVK_info0(s)
+#define EVK_info1(s, t)
+#endif
+
+static int devmajor = EVK_DEV_MAJOR;
+static int devminor = 0;
+static int nrdevs = 1;
+static struct cdev cdev;
+static struct class *pClass;
+
+DEFINE_SEMAPHORE(evk_mtx);
+static int down_pid;
+static int down_line;
+#define EVK_mutex_lock() { \
+ down(&evk_mtx); \
+ down_pid = current->pid; \
+ down_line = __LINE__; \
+}
+#define EVK_mutex_unlock() (up(&evk_mtx))
+
+#ifdef EVK_USE_KMALLOC
+#define evk_malloc(s) kmalloc((s), GFP_KERNEL)
+#define evk_free kfree
+#else // use vmalloc (this is the default)
+#define evk_malloc(s) vmalloc((s))
+#define evk_free vfree
+#endif
+
+enum {
+ evk_mem_user = 0,
+ evk_mem_kernel,
+};
+
+enum {
+ evk_enum_flag,
+ evk_enum_flag64,
+ evk_enum_queue,
+};
+
+#define GET_USER_OR_KERNEL(to, from) \
+({ \
+ int err; \
+ if (mem == evk_mem_user) { \
+ err = __get_user((to), &(from)); \
+ } else { \
+ (to) = (from); \
+ err = 0; \
+ } \
+ err; \
+})
+
+#define PUT_USER_OR_KERNEL(value, to) \
+({ \
+ int err; \
+ if (mem == evk_mem_user) { \
+ err = __put_user((value), &(to)); \
+ } else { \
+ (to) = (value); \
+ err = 0; \
+ } \
+ err; \
+})
+
+
+/** @brief Common part of the flag structure and message queue structure */
+#define EVK_COMMON_QUEUE_ELEMS \
+ struct list_head list; /**< List structure */ \
+ wait_queue_head_t wq_head; /**< Wait_queue of a process waiting for a queue */\
+ EV_ID queueID; /**< Flag ID/Queue ID */ \
+ UINT32 seq_num; /**< Order of event arrival */ \
+ pid_t read_pid; /**< Read process ID */ \
+ pid_t pid; /**< Owning process ID */
+
+/** @brief Common part of the flag structure and message queue structure */
+struct common_queue {
+ EVK_COMMON_QUEUE_ELEMS
+};
+
+/** @brief Flag structure */
+struct flag {
+ EVK_COMMON_QUEUE_ELEMS
+ UINT32 value;/**< Flags value */
+};
+#define EVK_PFLAG(queue) ((struct flag*)queue)
+
+/** @brief 64-bit flag structure */
+struct flag64 {
+ EVK_COMMON_QUEUE_ELEMS
+ UINT64 value;/**< Flags value */
+};
+#define EVK_PFLAG64(queue) ((struct flag64*)queue)
+
+/** @brief Message queue structure */
+struct message_queue {
+ EVK_COMMON_QUEUE_ELEMS
+ UINT8 type;/**< Type */
+ UINT8 length;/**< Queue length */
+ UINT8 num;/**< Number of messages stored */
+ UINT8 readptr;/**< Next read position(0~length-1) */
+ UINT32 max_bytes;/**< -Maximum bytes per message */
+ UINT8 *message;/**< Message storage area (ring buffer) */
+};
+#define EVK_PQUEUE(queue) ((struct message_queue*)queue)
+
+/** @brief Number of bytes to allocate per message
+ *
+ * This function allocates an area to store the number of bytes actually stored, the time of occurrence,
+ * and the senderInfo, in addition to the number of bytes specified by max_bytes.
+ */
+#define EVK_message_block_size(max_bytes) (sizeof(UINT32) * 3 + (max_bytes))
+
+#define HASH_KEY 15
+
+/** @brief Maximum number of flags used by all systems */
+#define EVK_MAX_FLAGS 48
+/** @brief Maximum number of 64-bit flags used by all systems */
+#define EVK_MAX_FLAG64S 4
+/** @brief Maximum number of message event queues used by all systems */
+/* M1SP BM3547 MESSAGE_QUEUES 128->144 */
+/* M9AT BM2066 MESSAGE_QUEUES 144->218 */
+#define EVK_MAX_MESSAGE_QUEUES 224
+
+/** @brief Allocate flag structure statically */
+static struct flag _flag_pool[EVK_MAX_FLAGS];
+/** @brief Statically allocates a 64-bit flag structure */
+static struct flag64 _flag64_pool[EVK_MAX_FLAG64S];
+/** @brief Beginning of the list of unused flags */
+static LIST_HEAD(flag_pool);
+/** @brief Beginning of the list of unused 64-bit flags */
+static LIST_HEAD(flag64_pool);
+
+/** @brief Allocate message queue structure statically */
+static struct message_queue _message_queue_pool[EVK_MAX_MESSAGE_QUEUES];
+/** @brief Top of the list of unused message queues */
+static LIST_HEAD(message_queue_pool);
+
+/** @brief List of Flags/Message Queues in Use
+ *
+ * Connects the usage flag/message queue to a list for each hash value obtained from the ID.
+ * The hash value is the remainder of the ID divided by HASH_KEY.
+ */
+static struct list_head queue_entry[HASH_KEY];
+
+/** @brief Sequence number to use during automatic ID assignment */
+static EV_ID sequence_id = 0;
+
+/** @brief Number to be assigned in order of occurrence of the event */
+static UINT32 sequence_number = 0;
+
+unsigned int
+evk_get_queue_entry(struct list_head **entries)
+{
+ if (entries) {
+ *entries = queue_entry;
+ return HASH_KEY;
+ }
+ return 0;
+}
+
+static __inline__ int
+calc_hash(UINT32 val)
+{
+ return val % HASH_KEY;
+}
+
+static __inline__
+struct flag *
+alloc_flag(void)
+{
+ struct flag *queue;
+ //EVK_assert(!list_empty(&flag_pool), "flag pool empty");
+ if (list_empty(&flag_pool)) {
+ printk("%s ERROR: flag pool empty\n", __func__);
+ return NULL;
+ }
+ queue = (struct flag *)flag_pool.next;
+ list_del_init(&(queue->list));
+ return queue;
+}
+
+static __inline__
+struct flag64 *
+alloc_flag64(void)
+{
+ struct flag64 *queue;
+ //EVK_assert(!list_empty(&flag64_pool), "flag64 pool empty");
+ if (list_empty(&flag64_pool)) {
+ printk("%s ERROR: flag64 pool empty\n", __func__);
+ return NULL;
+ }
+ queue = (struct flag64 *)flag64_pool.next;
+ list_del_init(&(queue->list));
+ return queue;
+}
+
+static __inline__ void
+free_flag(struct flag *queue)
+{
+ list_add((struct list_head *)queue, &flag_pool);
+}
+
+static __inline__ void
+free_flag64(struct flag64 *queue)
+{
+ list_add((struct list_head *)queue, &flag64_pool);
+}
+
+static __inline__
+struct message_queue *
+alloc_message_queue(void)
+{
+ struct message_queue *queue;
+ //EVK_assert(!list_empty(&message_queue_pool), "message queue pool empty");
+ if (list_empty(&message_queue_pool)) {
+ printk("%s ERROR: message queue pool empty\n", __func__);
+ return NULL;
+ }
+ queue = (struct message_queue *)message_queue_pool.next;
+ list_del_init(&(queue->list));
+ queue->message = NULL;
+ return queue;
+}
+
+static __inline__ void
+free_message_queue(struct message_queue *queue)
+{
+ if (queue->message != NULL) {
+ evk_free(queue->message);
+ queue->message = NULL;
+ }
+ list_add((struct list_head *)queue, &message_queue_pool);
+}
+
+static __inline__
+struct common_queue *
+find_queue_entry(EV_ID queueID)
+{
+ struct list_head *list;
+ struct common_queue *queue;
+ int hash = calc_hash(queueID);
+ list = &(queue_entry[hash]);
+ list_for_each_entry(queue, list, list) { /* pgr0060 */ /* pgr0039 */
+ if (queue->queueID == queueID) {
+ return queue;
+ }
+ }
+ return NULL;
+}
+
+static __inline__ void
+attach_queue_entry(struct common_queue *queue, EV_ID queueID)
+{
+ int hash = calc_hash(queueID);
+ list_add_tail((struct list_head *)queue, &(queue_entry[hash]));
+}
+
+static __inline__ void
+detach_queue_entry(struct common_queue *queue)
+{
+ list_del_init((struct list_head *)queue);
+}
+
+static __inline__ void
+init_common_queue(struct common_queue *queue, EV_ID queueID)
+{
+ queue->queueID = queueID;
+ queue->pid = current->pid;
+ queue->read_pid = 0;
+ init_waitqueue_head(&(queue->wq_head));
+}
+
+static __inline__ void
+evk_init_flag(struct flag *queue, EV_ID queueID)
+{
+ init_common_queue((struct common_queue *)queue, queueID);
+ queue->value = 0;
+}
+
+static __inline__ void
+evk_init_flag64(struct flag64 *queue, EV_ID queueID)
+{
+ init_common_queue((struct common_queue *)queue, queueID);
+ queue->value = 0;
+}
+
+static __inline__ int
+evk_init_message_queue(struct message_queue *queue, EV_ID queueID,
+ UINT8 length, UINT32 max_bytes, UINT8 type)
+{
+ init_common_queue((struct common_queue *)queue, queueID);
+ queue->type = type;
+ queue->length = length;
+ queue->max_bytes = max_bytes;
+ queue->num = 0;
+ queue->readptr = 0;
+ EVK_assert(queue->message == NULL, "message buffer was not freed");
+ queue->message = evk_malloc(length * EVK_message_block_size(max_bytes));
+ EVK_assert(queue->message != NULL, "can't alloc message buffer");
+ return 0;
+}
+
+static void
+__list_queues(void)
+{
+ struct list_head *list;
+ struct common_queue *queue;
+ int i;
+ for(i = 0 ; i < HASH_KEY ; i++) {
+ list = &(queue_entry[i]);
+ if (!list_empty(list)) {
+ printk(KERN_ALERT "%d->", i);
+ list_for_each_entry(queue, list, list) { /* pgr0060 */ /* pgr0039 */
+ printk("%x[%x] ", queue->queueID, queue->seq_num);
+ }
+ printk("\n");
+ }
+ }
+}
+
+static int
+evk_destroy_queue(EV_ID queueID)
+{
+ struct common_queue *queue;
+ int err = 0;
+ EVK_info1("flag destroy %x\n", queueID);
+
+ EVK_mutex_lock(); /*************************************/
+ queue = find_queue_entry(queueID);
+ if (queue == NULL) {
+ err = -ENOENT;
+ goto finish;
+ }
+
+ detach_queue_entry(queue);
+
+ /* wake up processes before destruction */
+ wake_up_interruptible(&(queue->wq_head));
+
+ init_common_queue(queue, EV_INVALID_ID);
+
+ if (EV_ID_IS_FLAG(queueID)) {
+ free_flag((struct flag *)queue);
+ } else if (EV_ID_IS_FLAG64(queueID)) {
+ free_flag64((struct flag64 *)queue);
+ } else if (EV_ID_IS_QUEUE(queueID)) {
+ free_message_queue((struct message_queue *)queue);
+ }
+ //__list_queues();
+ finish:
+ EVK_mutex_unlock(); /*************************************/
+ return err;
+}
+
+static int
+evk_open(struct inode *inode, struct file *file)
+{
+ // Recording of current and measures not to be read or deleted from others are required. */
+ file->private_data = (void *)EV_INVALID_ID;
+ return 0;
+}
+
+static int
+evk_close(struct inode *inode, struct file *file)
+{
+ if (EV_ID_IS_VALID((EV_ID)file->private_data)) {
+ evk_destroy_queue((EV_ID)file->private_data);
+ }
+ file->private_data = (void *)EV_INVALID_ID;
+ return 0;
+}
+
+static int
+evk_create_flag(EV_ID queueID)
+{
+ struct flag *queue;
+ int err = 0;
+ EVK_info1("flag create %x\n", queueID);
+
+ EVK_mutex_lock(); /*************************************/
+
+ queue = (struct flag *)find_queue_entry(queueID);
+ if (queue != NULL) {
+ err = -EEXIST;
+ goto finish;
+ }
+
+ queue = alloc_flag();
+ if (queue == NULL) {
+ err = -ENOMEM;
+ goto finish;
+ }
+
+ evk_init_flag(queue, queueID);
+ attach_queue_entry((struct common_queue *)queue, queueID);
+
+ //__list_queues();
+ finish:
+ EVK_mutex_unlock(); /***********************************/
+ return err;
+}
+
+static int
+evk_create_flag64(EV_ID queueID)
+{
+ struct flag64 *queue;
+ int err = 0;
+ EVK_info1("flag64 create %x\n", queueID);
+
+ EVK_mutex_lock(); /*************************************/
+
+ queue = (struct flag64 *)find_queue_entry(queueID);
+ if (queue != NULL) {
+ err = -EEXIST;
+ goto finish;
+ }
+
+ queue = alloc_flag64();
+ if (queue == NULL) {
+ err = -ENOMEM;
+ goto finish;
+ }
+
+ evk_init_flag64(queue, queueID);
+ attach_queue_entry((struct common_queue *)queue, queueID);
+
+ //__list_queues();
+ finish:
+ EVK_mutex_unlock(); /***********************************/
+ return err;
+}
+
+static int
+evk_create_message_queue(EV_ID queueID, UINT8 length,
+ UINT32 max_bytes, EV_Message_Queue_Type type)
+{
+ struct message_queue *queue;
+ int err;
+ EVK_info1("message create %x\n", queueID);
+
+ err = 0;
+
+ EVK_mutex_lock(); /*************************************/
+
+ queue = (struct message_queue *)find_queue_entry(queueID);
+ if (queue != NULL) {
+ err = -EEXIST;
+ goto finish;
+ }
+
+ queue = alloc_message_queue();
+ if (queue == NULL) {
+ err = -ENOMEM;
+ goto finish;
+ }
+
+ err = evk_init_message_queue(queue, queueID, length, max_bytes, type);
+ if (err == 0) {
+ attach_queue_entry((struct common_queue *)queue, queueID);
+ } else {
+ free_message_queue(queue);
+ }
+
+ //__list_queues();
+ finish:
+ EVK_mutex_unlock(); /***********************************/
+ return err;
+}
+
+static EV_ID
+get_seq_id(void)
+{
+ EV_ID ret;
+ sequence_id++;
+ if ((sequence_id & EV_RESERVED_BIT) != 0) {/* round to 1 */
+ sequence_id = 1;
+ EVK_info0("auto ID rounded\n");
+ }
+ ret = sequence_id;
+ return ret;
+}
+
+static int
+evk_alloc_flagID(EV_ID *queueID)
+{
+ EV_ID seq_id;
+
+ EVK_mutex_lock(); /*************************************/
+ do {
+ seq_id = get_seq_id();
+ seq_id |= (EV_ID_BIT | EV_FLAG_BIT | EV_AUTO_ID_BIT);
+ } while(find_queue_entry(seq_id) != NULL);
+ EVK_mutex_unlock(); /*************************************/
+
+ *queueID = seq_id;
+ return 0;
+}
+
+static int
+evk_alloc_flag64ID(EV_ID *queueID)
+{
+ EV_ID seq_id;
+
+ EVK_mutex_lock(); /*************************************/
+ do {
+ seq_id = get_seq_id();
+ seq_id |= (EV_ID_BIT | EV_FLAG64_BIT | EV_AUTO_ID_BIT);
+ } while(find_queue_entry(seq_id) != NULL);
+ EVK_mutex_unlock(); /*************************************/
+
+ *queueID = seq_id;
+ return 0;
+}
+
+static int
+evk_alloc_queueID(EV_ID *queueID)
+{
+ EV_ID seq_id;
+
+ EVK_mutex_lock(); /*************************************/
+ do {
+ seq_id = get_seq_id();
+ seq_id |= (EV_ID_BIT | EV_QUEUE_BIT | EV_AUTO_ID_BIT);
+ } while(find_queue_entry(seq_id) != NULL);
+ EVK_mutex_unlock(); /*************************************/
+
+ *queueID = seq_id;
+ return 0;
+}
+
+static int
+evk_store_flag(EV_Flag *ev, int mem)
+{
+ struct flag *queue;
+ int ret = 0;
+ EV_ID flagID;
+ UINT32 bits;
+
+ if (GET_USER_OR_KERNEL(flagID, ev->flagID)) /* pgr0039 */
+ return -EFAULT;
+ if (GET_USER_OR_KERNEL(bits, ev->bits)) /* pgr0039 */
+ return -EFAULT;
+
+ EVK_mutex_lock(); /*************************************/
+
+ queue = (struct flag *)find_queue_entry(flagID); /* pgr0000 */
+ if (queue == NULL) {
+ EVK_info1("set_flag: No such ID %x\n", flagID);
+ ret = -ENOENT;
+ goto finish;
+ }
+
+ if (queue->value == 0) {
+ queue->seq_num = sequence_number++;
+ }
+ queue->value |= bits; /* pgr0000 */
+
+ wake_up_interruptible(&(queue->wq_head));
+
+ finish:
+ EVK_mutex_unlock(); /***********************************/
+ return ret;
+}
+
+static int
+evk_store_flag64(EV_Flag64 *ev, int mem)
+{
+ struct flag64 *queue;
+ int ret = 0;
+ EV_ID flagID;
+ UINT64 bits = 0;
+
+ if (GET_USER_OR_KERNEL(flagID, ev->flagID)) /* pgr0039 */
+ return -EFAULT;
+ //GET_USER_OR_KERNEL(bits, ev->bits); /* pgr0039 */
+ if (mem == evk_mem_user) {
+ if (copy_from_user(&bits, &(ev->bits), sizeof(bits)))
+ return -EFAULT;
+ } else {
+ bits = ev->bits;
+ }
+
+ EVK_mutex_lock(); /*************************************/
+
+ queue = (struct flag64 *)find_queue_entry(flagID); /* pgr0000 */
+ if (queue == NULL) {
+ EVK_info1("set_flag64: No such ID %x\n", flagID);
+ ret = -ENOENT;
+ goto finish;
+ }
+
+ if (queue->value == 0) {
+ queue->seq_num = sequence_number++;
+ }
+ queue->value |= bits; /* pgr0000 */
+
+ wake_up_interruptible(&(queue->wq_head));
+
+ finish:
+ EVK_mutex_unlock(); /***********************************/
+ return ret;
+}
+
+static int
+evk_store_message(EV_Message *ev, int mem)
+{
+ struct message_queue *queue;
+ UINT8 *ptr;
+ UINT8 writeptr;
+ int ret = 0;
+ EV_ID queueID;
+ UINT32 length, senderInfo, seq;
+
+ if (GET_USER_OR_KERNEL(queueID, ev->queueID)) /* pgr0039 */
+ return -EFAULT;
+ if (GET_USER_OR_KERNEL(length, ev->length)) /* pgr0039 */
+ return -EFAULT;
+ if (GET_USER_OR_KERNEL(senderInfo, ev->senderInfo)) /* pgr0039 */
+ return -EFAULT;
+
+ EVK_mutex_lock(); /*************************************/
+
+ queue = (struct message_queue *)find_queue_entry(queueID); /* pgr0000 */
+ if (queue == NULL) {
+ EVK_info1("store_message: No such queueID %x\n", queueID);
+ ret = -ENOENT;
+ goto finish;
+ }
+
+ if (length > queue->max_bytes) { /* pgr0000 */
+ EVK_info0("store_message: message is too long for the queue");
+ ret = -EINVAL;
+ goto finish;
+ }
+
+ if (queue->num == queue->length) {
+
+ switch(queue->type) {
+ case EV_MESSAGE_QUEUE_TYPE_BUSY:
+ EVK_info1("store_message: queue %x BUSY\n", queueID);
+ ret = -EBUSY;
+ goto finish;
+ break;
+
+ case EV_MESSAGE_QUEUE_TYPE_FIFO:
+ queue->readptr++;
+ queue->readptr %= queue->length;
+ queue->num--;
+ break;
+
+ case EV_MESSAGE_QUEUE_TYPE_REPLACE:
+ queue->num--;
+ break;
+
+ default:
+ EVK_BUG("internal error in store_message\n");
+ ret = -EINVAL;
+ goto finish;
+ break;
+ }
+ }
+
+ writeptr = (queue->readptr + queue->num) % queue->length;
+ ptr = queue->message + writeptr * EVK_message_block_size(queue->max_bytes);
+
+ memcpy(ptr, &length, sizeof(length));
+ ptr += sizeof(length);
+ memcpy(ptr, &senderInfo, sizeof(senderInfo));
+ ptr += sizeof(senderInfo);
+ seq = sequence_number++;
+ memcpy(ptr, &seq, sizeof(seq));
+ ptr += sizeof(seq);
+
+ if (queue->num == 0) {
+ queue->seq_num = seq;
+ }
+ queue->num++;
+
+ if (mem == evk_mem_user) {
+ if (copy_from_user(ptr, ev->message, length)) {
+ ret = -EFAULT;
+ goto finish;
+ }
+ } else {
+ memcpy(ptr, ev->message, length);
+ }
+
+ wake_up_interruptible(&(queue->wq_head));
+
+ finish:
+ EVK_mutex_unlock(); /***********************************/
+
+ return ret;
+}
+
+static int
+evk_set_poll(struct file *filp, EV_ID queueID)
+{
+ struct common_queue *queue;
+ int err = 0;
+
+ EVK_mutex_lock(); /*************************************/
+
+ queue = find_queue_entry(queueID);
+ if (queue == NULL) {
+ EVK_info1("set_poll: ID %x not found.\n", queueID);
+ err = -ENOENT;
+ goto finish;
+ }
+
+ filp->private_data = (void *)queueID;
+
+ finish:
+ EVK_mutex_unlock(); /*************************************/
+ return err;
+}
+
+static int
+evk_get_flag_event(EV_Event *ev, int peek_only, int wait, int mem)
+{
+ struct flag *queue, *queue2;
+ int err = 0;
+ int found = 0;
+ EV_ID flagID;
+
+ if (GET_USER_OR_KERNEL(flagID, ev->u.flag.flagID)) /* pgr0039 */
+ return -EFAULT;
+
+ retry:
+
+ queue = (struct flag *)find_queue_entry(flagID); /* pgr0000 */
+ if (queue == NULL) {
+ EVK_info1("get_flag: No such flag %x\n", flagID);
+ err = -ENOENT;
+ goto finish;
+ }
+
+ if (queue->value != 0) {
+ UINT32 bits;
+
+ if (GET_USER_OR_KERNEL(bits, ev->u.flag.bits)) { /* pgr0039 */
+ err = -EFAULT;
+ goto finish;
+ }
+
+ if (bits == 0 || ((bits & queue->value) != 0)) { /* pgr0000 */
+
+ if (PUT_USER_OR_KERNEL(EV_EVENT_Flag, ev->type)) { /* pgr0039 */
+ err = -EFAULT;
+ goto finish;
+ }
+ if (PUT_USER_OR_KERNEL(queue->value, ev->u.flag.bits)) { /* pgr0039 */
+ err = -EFAULT;
+ goto finish;
+ }
+ found = 1;
+
+ queue->read_pid = current->pid;
+ if (peek_only) {
+ ;
+ } else {
+ queue->value = 0;
+ }
+ }
+ }
+ finish:
+
+ if (queue != NULL && wait != 0 && found == 0) {
+ int wait_ret;
+ EVK_mutex_unlock(); /*************************************/
+
+ wait_ret
+ = wait_event_interruptible(queue->wq_head,
+ ((queue2 = (struct flag *)find_queue_entry(flagID)) == NULL
+ || queue2->value != 0));
+
+ EVK_mutex_lock(); /*************************************/
+
+ if (wait_ret != 0) {
+ EVK_info1("Interrupted while waiting for flag %x\n", flagID);
+ err = -EINTR;
+ } else if (queue2 == NULL) { /* pgr0039 */
+ EVK_info1("flag %x was destroyed while waiting for it\n", flagID);
+ err = -ENOENT;
+ } else {
+ goto retry;
+ }
+ }
+ return err;
+}
+
+static int
+evk_get_flag64_event(EV_Event *ev, int peek_only, int wait, int mem)
+{
+ struct flag64 *queue, *queue2;
+ int err = 0;
+ int found = 0;
+ EV_ID flagID;
+
+ if (GET_USER_OR_KERNEL(flagID, ev->u.flag64.flagID)) /* pgr0039 */
+ return -EFAULT;
+
+ retry:
+
+ queue = (struct flag64 *)find_queue_entry(flagID); /* pgr0000 */
+ if (queue == NULL) {
+ EVK_info1("get_flag64: No such flag %x\n", flagID);
+ err = -ENOENT;
+ goto finish;
+ }
+
+ if (queue->value != 0) {
+ UINT64 bits = 0;
+
+ //GET_USER_OR_KERNEL(bits, ev->u.flag64.bits); /* pgr0039 */
+ if (mem == evk_mem_user) {
+ if (copy_from_user(&bits, &(ev->u.flag64.bits), sizeof(bits))) {
+ err = -EFAULT;
+ goto finish;
+ }
+ } else {
+ bits = ev->u.flag64.bits;
+ }
+
+ if (bits == 0 || ((bits & queue->value) != 0)) { /* pgr0000 */
+
+ if (PUT_USER_OR_KERNEL(EV_EVENT_Flag64, ev->type)) { /* pgr0039 */
+ err = -EFAULT;
+ goto finish;
+ }
+ if (PUT_USER_OR_KERNEL(queue->value, ev->u.flag64.bits)) { /* pgr0039 */
+ err = -EFAULT;
+ goto finish;
+ }
+ found = 1;
+
+ queue->read_pid = current->pid;
+ if (peek_only) {
+ ;
+ } else {
+ queue->value = 0;
+ }
+ }
+ }
+ finish:
+
+ if (queue != NULL && wait != 0 && found == 0) {
+ int wait_ret;
+ EVK_mutex_unlock(); /*************************************/
+
+ wait_ret
+ = wait_event_interruptible(queue->wq_head,
+ ((queue2 = (struct flag64 *)find_queue_entry(flagID)) == NULL
+ || queue2->value != 0));
+
+ EVK_mutex_lock(); /*************************************/
+
+ if (wait_ret != 0) {
+ EVK_info1("Interrupted while waiting for flag %x\n", flagID);
+ err = -EINTR;
+ } else if (queue2 == NULL) { /* pgr0039 */
+ EVK_info1("flag %x was destroyed while waiting for it\n", flagID);
+ err = -ENOENT;
+ } else {
+ goto retry;
+ }
+ }
+ return err;
+}
+
+static __inline__ void
+remove_message_event(struct message_queue *queue, UINT8 removeptr)
+{
+ UINT8 *ptr;
+ int i, from, to;
+ UINT8 *pFrom, *pTo;
+ UINT32 size;
+ int offset;
+
+ queue->num--;
+ offset = (int)removeptr - (int)(queue->readptr);
+
+ if (offset == 0) {/* To remove the head of the queue, advance the queue by one readptr only */
+ queue->readptr++;
+ queue->readptr %= queue->length;
+
+ if (queue->num > 0) {
+ /* Reset the occurrence time of the first message in the queue to the occurrence time of the queue. */
+ ptr = (queue->message
+ + queue->readptr * EVK_message_block_size(queue->max_bytes));
+ ptr += sizeof(UINT32) * 2;
+ memcpy(&(queue->seq_num), ptr, sizeof(UINT32));
+ }
+ return;
+ }
+ if (offset < 0) {
+ offset += queue->length;
+ }
+ if (offset == queue->num) {/* Do nothing to delete the end of the queue */
+ return;
+ }
+
+ /* To delete a message in the middle of the queue, pack the following messages. */
+ to = removeptr;
+ size = EVK_message_block_size(queue->max_bytes);
+
+ for(i = 0 ; i < queue->num - offset ; i++, to++) {
+ to %= queue->length;
+ from = (to + 1) % queue->length;
+ pFrom = queue->message + from * size;
+ pTo = queue->message + to * size;
+ memcpy(pTo, pFrom, size);
+ }
+}
+
+static int
+evk_get_message_event(EV_Event *ev, int peek_only, int wait, int mem)
+{
+ struct message_queue *queue, *queue2;
+ int err = 0;
+ EV_ID queueID;
+ UINT8 num;
+ UINT8 readptr;
+ UINT8 i, *ptr;
+ int matched = 0;
+
+ if (GET_USER_OR_KERNEL(queueID, ev->u.message.queueID)) /* pgr0039 */
+ return -EFAULT;
+
+ retry:
+ queue = (struct message_queue *)find_queue_entry(queueID); /* pgr0000 */
+ if (queue == NULL) {
+ EVK_info1("get_message: No such queue %x\n", queueID);
+ err = -ENOENT;
+ goto finish;
+ }
+
+ num = queue->num;
+ readptr = queue->readptr;
+ for(i = 0 ; i < num ; i++, readptr = (readptr + 1) % queue->length) {
+ UINT32 size, senderInfo, seq;
+ UINT32 length, q_senderInfo;
+
+ ptr = (queue->message
+ + readptr * EVK_message_block_size(queue->max_bytes));
+
+ memcpy(&size, ptr, sizeof(size));
+ ptr += sizeof(size);
+ memcpy(&senderInfo, ptr, sizeof(senderInfo));
+ ptr += sizeof(senderInfo);
+ memcpy(&seq, ptr, sizeof(seq));
+ ptr += sizeof(seq);
+
+ if (GET_USER_OR_KERNEL(length, ev->u.message.length)) { /* pgr0039 */
+ err = -EFAULT;
+ goto finish;
+ }
+ if (GET_USER_OR_KERNEL(q_senderInfo, ev->u.message.senderInfo)) { /* pgr0039 */
+ err = -EFAULT;
+ goto finish;
+ }
+
+ if (q_senderInfo == 0 && length == 0) { /* pgr0000 */
+ matched = 1;
+ } else if (q_senderInfo != 0 && q_senderInfo == senderInfo) {
+ matched = 1;
+ } else if (length > 0 && size >= length) { /* pgr0000 */
+
+ if (mem == evk_mem_user) {
+ void *compbytes;
+ compbytes = evk_malloc(length);
+ if (compbytes != NULL) {
+ if (copy_from_user(compbytes, &(ev->u.message.message), length)) {
+ err = -EFAULT;
+ evk_free(compbytes);
+ goto finish;
+ }
+ if (memcmp(ptr, compbytes, length) == 0) {
+ matched = 1;
+ }
+ evk_free(compbytes);
+ }
+ } else {
+ if (memcmp(ptr, ev->u.message.message, length) == 0) {
+ matched = 1;
+ }
+ }
+ }
+
+ if (matched) {
+
+ if (PUT_USER_OR_KERNEL(EV_EVENT_Message, ev->type)) { /* pgr0039 */
+ err = -EFAULT;
+ goto finish;
+ }
+ if (PUT_USER_OR_KERNEL(size, ev->u.message.length)) { /* pgr0039 */
+ err = -EFAULT;
+ goto finish;
+ }
+ if (PUT_USER_OR_KERNEL(senderInfo, ev->u.message.senderInfo)) { /* pgr0039 */
+ err = -EFAULT;
+ goto finish;
+ }
+ if (mem == evk_mem_user) {
+ if (copy_to_user(ev->u.message.message, ptr, size)) {
+ err = -EFAULT;
+ goto finish;
+ }
+ } else {
+ memcpy(ev->u.message.message, ptr, size);
+ }
+
+ queue->read_pid = current->pid;
+ if (peek_only) {
+ ;
+ } else {
+ remove_message_event(queue, readptr);
+ }
+ goto finish;
+ }
+ }
+
+ finish:
+
+ if (queue != NULL && wait != 0 && matched == 0) {
+ int wait_ret;
+ EVK_mutex_unlock(); /*************************************/
+ wait_ret
+ = wait_event_interruptible(queue->wq_head,
+ ((queue2 = (struct message_queue *)find_queue_entry(queueID))==NULL
+ || queue2->num > 0));
+
+ EVK_mutex_lock(); /*************************************/
+
+ if (wait_ret != 0) {
+ EVK_info1("Interrupted while waiting for queue %x\n", queueID);
+ err = -EINTR;
+ } else if (queue2 == NULL) { /* pgr0039 */
+ EVK_info1("queue %x was destroyed while waiting for it\n", queueID);
+ err = -ENOENT;
+ } else {
+ goto retry;
+ }
+ }
+
+ return err;
+}
+
+static int
+evk_get_event(EV_Event *ev, int peek_only, int wait, int mem)
+{
+ EV_Type type;
+ int ret = -EINVAL;
+
+ if (GET_USER_OR_KERNEL(type, ev->type)) /* pgr0039 */
+ return -EFAULT;
+ if (PUT_USER_OR_KERNEL(EV_EVENT_None, ev->type)) /* pgr0039 */
+ return -EFAULT;
+
+ switch(type) { /* pgr0000 */
+ case EV_EVENT_Flag:
+ EVK_mutex_lock(); /*************************************/
+ ret = evk_get_flag_event(ev, peek_only, wait, mem);
+ EVK_mutex_unlock(); /*************************************/
+ break;
+
+ case EV_EVENT_Flag64:
+ EVK_mutex_lock(); /*************************************/
+ ret = evk_get_flag64_event(ev, peek_only, wait, mem);
+ EVK_mutex_unlock(); /*************************************/
+ break;
+
+ case EV_EVENT_Message:
+ EVK_mutex_lock(); /*************************************/
+ ret = evk_get_message_event(ev, peek_only, wait, mem);
+ EVK_mutex_unlock(); /*************************************/
+ break;
+
+ default:
+ break;
+ }
+ return ret;
+}
+
+static int
+evk_get_next_event(EVK_Next_Event_Query *query /* user */, int peek_only)
+{
+ EV_ID *ids;
+ int i, num, ret, first, found;
+ struct common_queue *queue;
+ UINT32 seq_oldest = 0;
+
+ ids = (EV_ID *)kmalloc( (sizeof(EV_ID)*EV_MAX_IDS_IN_PROCESS), GFP_KERNEL );
+ if( ids == NULL ){
+ return -ENOMEM;
+ }
+
+ if (__get_user(num, &(query->num))) { /* pgr0039 */
+ ret = -EFAULT;
+ goto finish0;
+ }
+ if (copy_from_user(&ids[0], query->ids, num * sizeof(EV_ID))) { /* pgr0039 */
+ ret = -EFAULT;
+ goto finish0;
+ }
+ if (__put_user(EV_EVENT_None, &(query->ev.type))) { /* pgr0039 */
+ ret = -EFAULT;
+ goto finish0;
+ }
+
+ ret = 0;
+ first = 1;
+ found = -1;
+
+ EVK_mutex_lock(); /*************************************/
+
+ for(i = 0 ; i < num /* pgr0039 */ ; i++) {
+ queue = find_queue_entry(ids[i]);
+ if (queue != NULL) {/* Have the specified queue ID */
+ if ((EV_ID_IS_FLAG(ids[i])
+ && ((struct flag *)queue)->value != 0)
+ || (EV_ID_IS_FLAG64(ids[i])
+ && ((struct flag64 *)queue)->value != 0)
+ || (EV_ID_IS_QUEUE(ids[i])
+ && ((struct message_queue *)queue)->num > 0)) {/*There are events.*/
+ /* Compare with time_before macros for round 0 */
+ if (first || time_before((unsigned long)queue->seq_num, /* pgr0006 */ /* pgr0039 */
+ (unsigned long)seq_oldest)) {
+ first = 0;
+ seq_oldest = queue->seq_num;
+ found = i;
+ }
+ }
+ }
+ }
+
+ if (found >= 0) {
+ if (EV_ID_IS_FLAG(ids[found])) {
+ if (__put_user(ids[found], &(query->ev.u.flag.flagID))) { /* pgr0039 */
+ ret = -EFAULT;
+ goto finish1;
+ }
+ ret = evk_get_flag_event(&(query->ev), peek_only, 0, evk_mem_user);
+ } else if (EV_ID_IS_FLAG64(ids[found])) {
+ if (__put_user(ids[found], &(query->ev.u.flag64.flagID))) { /* pgr0039 */
+ ret = -EFAULT;
+ goto finish1;
+ }
+ ret = evk_get_flag64_event(&(query->ev), peek_only, 0, evk_mem_user);
+ } else if (EV_ID_IS_QUEUE(ids[found])) {
+ if (__put_user(ids[found], &(query->ev.u.message.queueID))) { /* pgr0039 */
+ ret = -EFAULT;
+ goto finish1;
+ }
+ ret = evk_get_message_event(&(query->ev), peek_only, 0, evk_mem_user);
+ }
+ }
+
+ finish1:
+ EVK_mutex_unlock(); /*************************************/
+ finish0:
+ kfree(ids);
+ return ret;
+}
+
+static long
+evk_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ EVK_Message_Queue_Request mesq;
+ int peek_only, wait;
+ EV_ID queueID;
+ int ret = -EINVAL;
+
+ //lock_kernel();
+
+ switch(cmd) {
+ case EVK_IOC_CREATE_FLAG:
+ queueID = (EV_ID)arg;
+ ret = evk_create_flag(queueID);
+ break;
+
+ case EVK_IOC_CREATE_FLAG64:
+ queueID = (EV_ID)arg;
+ ret = evk_create_flag64(queueID);
+ break;
+
+ case EVK_IOC_CREATE_MESSAGE_QUEUE:
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0))
+ if (access_ok(arg, sizeof(mesq))) { /* pgr0039 */
+#else
+ if (access_ok(VERIFY_READ, arg, sizeof(mesq))) { /* pgr0039 */
+#endif
+ if (copy_from_user(&mesq, (EV_Flag *)arg, sizeof(mesq))) {
+ ret = -EFAULT;
+ break;
+ }
+
+ ret = evk_create_message_queue(mesq.queueID, mesq.length,
+ mesq.max_bytes, mesq.type);
+ } else {
+ ret = -EFAULT;
+ }
+ break;
+
+ case EVK_IOC_ALLOC_FLAG_ID:
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0))
+ if (access_ok(arg, sizeof(queueID))) { /* pgr0039 */
+#else
+ if (access_ok(VERIFY_WRITE, arg, sizeof(queueID))) { /* pgr0039 */
+#endif
+ evk_alloc_flagID(&queueID);
+ if (put_user(queueID, (EV_ID *)arg)) { /* pgr0039 */
+ ret = -EFAULT;
+ break;
+ }
+ ret = 0;
+ } else {
+ ret = -EFAULT;
+ }
+ break;
+
+ case EVK_IOC_ALLOC_FLAG64_ID:
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0))
+ if (access_ok(arg, sizeof(queueID))) { /* pgr0039 */
+#else
+ if (access_ok(VERIFY_WRITE, arg, sizeof(queueID))) { /* pgr0039 */
+#endif
+ evk_alloc_flag64ID(&queueID);
+ if (put_user(queueID, (EV_ID *)arg)) { /* pgr0039 */
+ ret = -EFAULT;
+ break;
+ }
+ ret = 0;
+ } else {
+ ret = -EFAULT;
+ }
+ break;
+
+ case EVK_IOC_ALLOC_QUEUE_ID:
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0))
+ if (access_ok(arg, sizeof(queueID))) { /* pgr0039 */
+#else
+ if (access_ok(VERIFY_WRITE, arg, sizeof(queueID))) { /* pgr0039 */
+#endif
+ evk_alloc_queueID(&queueID);
+ if (put_user(queueID, (EV_ID *)arg)) { /* pgr0039 */
+ ret = -EFAULT;
+ break;
+ }
+ ret = 0;
+ } else {
+ ret = -EFAULT;
+ }
+ break;
+
+ case EVK_IOC_DESTROY_QUEUE:
+ queueID = (EV_ID)arg;
+ ret = evk_destroy_queue(queueID);
+ break;
+
+ case EVK_IOC_STORE_FLAG:
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0))
+ if (access_ok(arg, sizeof(EV_Flag))) { /* pgr0039 */
+#else
+ if (access_ok(VERIFY_READ, arg, sizeof(EV_Flag))) { /* pgr0039 */
+#endif
+ ret = evk_store_flag((EV_Flag *)arg, evk_mem_user);
+ } else {
+ ret = -EFAULT;
+ }
+ break;
+
+ case EVK_IOC_STORE_FLAG64:
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0))
+ if (access_ok(arg, sizeof(EV_Flag64))) { /* pgr0039 */
+#else
+ if (access_ok(VERIFY_READ, arg, sizeof(EV_Flag64))) { /* pgr0039 */
+#endif
+ ret = evk_store_flag64((EV_Flag64 *)arg, evk_mem_user);
+ } else {
+ ret = -EFAULT;
+ }
+ break;
+
+ case EVK_IOC_STORE_MESSAGE:
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0))
+ if (access_ok(arg, sizeof(EV_Message))) { /* pgr0039 */
+#else
+ if (access_ok(VERIFY_READ, arg, sizeof(EV_Message))) { /* pgr0039 */
+#endif
+ ret = evk_store_message((EV_Message *)arg, evk_mem_user);
+ } else {
+ ret = -EFAULT;
+ }
+ break;
+
+ case EVK_IOC_SET_POLL:
+ queueID = (EV_ID)arg;
+ ret = evk_set_poll(filp, queueID);
+ break;
+
+ case EVK_IOC_PEEK_EVENT:
+ peek_only = 1;
+ wait = 0;
+ goto get_event;
+ break;
+
+ case EVK_IOC_WAIT_EVENT:
+ peek_only = 0;
+ wait = 1;
+ goto get_event;
+ break;
+
+ case EVK_IOC_GET_EVENT:
+ peek_only = 0;
+ wait = 0;
+ get_event:
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0))
+ if (access_ok(arg, sizeof(EV_Event))) { /* pgr0039 */
+#else
+ if (access_ok(VERIFY_WRITE, arg, sizeof(EV_Event))) { /* pgr0039 */
+#endif
+ ret = evk_get_event((EV_Event *)arg, peek_only, wait, evk_mem_user);
+ } else {
+ ret = -EFAULT;
+ }
+ break;
+
+ case EVK_IOC_PEEK_NEXT_EVENT:
+ peek_only = 1;
+ goto get_next;
+ break;
+
+ case EVK_IOC_GET_NEXT_EVENT:
+ peek_only = 0;
+ get_next:
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0))
+ if (access_ok(arg, sizeof(EVK_Next_Event_Query))) { /* pgr0039 */
+#else
+ if (access_ok(VERIFY_WRITE, arg, sizeof(EVK_Next_Event_Query))) { /* pgr0039 */
+#endif
+ ret = evk_get_next_event((EVK_Next_Event_Query *)arg, peek_only);
+ } else {
+ ret = -EFAULT;
+ }
+ break;
+
+ case EVK_IOC_DEBUG_LIST:
+ __list_queues();
+ //__list_message();
+ ret = 0;
+ break;
+
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ //unlock_kernel();
+ return ret;
+}
+
+static unsigned int
+evk_poll(struct file *filp, poll_table *wait)
+{
+ unsigned int ret = 0;
+ struct common_queue *queue;
+
+ EV_ID queueID = (EV_ID)(filp->private_data);
+ // Returns errors without stopping at assert if queueID is invalid
+ // (Troubleshooting for Continuous Printing)
+ if (!EV_ID_IS_VALID(queueID)) {
+ printk("evk_poll ERROR: invalid queueID=%x\n", queueID);
+ return POLLERR|POLLHUP;
+ }
+ //EVK_assert(EV_ID_IS_VALID(queueID), "poll: flag/queueID not set");
+
+ EVK_mutex_lock();/*****************************************/
+
+ queue = find_queue_entry(queueID);
+ if (queue == NULL) {
+ EVK_info1("poll: No such flag/queueID %x\n", queueID);
+ ret = POLLERR|POLLHUP;
+ goto finish;
+ }
+
+ poll_wait(filp, &(queue->wq_head), wait);
+
+ if (EV_ID_IS_FLAG(queueID)) {
+ if (((struct flag *)queue)->value != 0) {
+ ret = POLLIN;
+ }
+ } else if (EV_ID_IS_FLAG64(queueID)) {
+ if (((struct flag64 *)queue)->value != 0) {
+ ret = POLLIN;
+ }
+ } else {
+ if (((struct message_queue *)queue)->num > 0) {
+ ret = POLLIN;
+ }
+ }
+
+ finish:
+ EVK_mutex_unlock(); /***************************************/
+
+ return ret;
+}
+
+/** List of system call corresponding function registrations */
+static struct file_operations evk_fops = {
+ .open = evk_open,
+ .release = evk_close,
+ .unlocked_ioctl = evk_ioctl,
+ .poll = evk_poll,
+};
+
+#ifdef ENABLE_PROC_FS
+static int
+evk_procFS_show(struct seq_file *m, int mode)
+{
+ int i, num;
+ struct list_head *list, *entries;
+ struct common_queue *queue;
+
+ seq_printf(m, "[ev library status ");
+
+ switch(mode) {
+ case evk_enum_flag:
+ seq_printf(m, "(flag)]\n");
+ seq_printf(m, "PID moduleID flagID[hash] value\n");
+ break;
+ case evk_enum_flag64:
+ seq_printf(m, "(flag64)]\n");
+ seq_printf(m, "PID moduleID flagID[hash] value\n");
+ break;
+ case evk_enum_queue:
+ seq_printf(m, "(queue)]\n");
+ seq_printf(m, "PID moduleID queueID[hash] maxbytes remain type\n");
+ break;
+ }
+
+ EVK_mutex_lock();
+
+ num = evk_get_queue_entry(&entries);
+
+ for (i = 0 ; i < num ; i++) {
+ list = &(entries[i]);
+ if (!list_empty(list)) {
+ list_for_each_entry(queue, list, list) {
+ if ((mode == evk_enum_flag && (!EV_ID_IS_FLAG(queue->queueID)))
+ || (mode == evk_enum_flag64 && (!EV_ID_IS_FLAG64(queue->queueID)))
+ || (mode == evk_enum_queue && (!EV_ID_IS_QUEUE(queue->queueID))))
+ {
+ continue;
+ }
+
+ seq_printf(m, "%08d ", queue->pid);
+ seq_printf(m, "%05d(%04x) ", ((queue->queueID & 0x00ffff00) >> 8), ((queue->queueID & 0x00ffff00) >> 8));
+ seq_printf(m, "0x%08x[%2d] ", queue->queueID, calc_hash(queue->queueID));
+
+ switch(mode) {
+ case evk_enum_flag:
+ seq_printf(m, "0x%x", EVK_PFLAG(queue)->value);
+ break;
+
+ case evk_enum_flag64:
+ seq_printf(m, "0x%llx", EVK_PFLAG64(queue)->value);
+ break;
+
+ case evk_enum_queue:
+ seq_printf(m, "%04d %02d ", EVK_PQUEUE(queue)->max_bytes, EVK_PQUEUE(queue)->length);
+ seq_printf(m, "%02d ", EVK_PQUEUE(queue)->num);
+ seq_printf(m, "%d ", EVK_PQUEUE(queue)->type);
+ break;
+ }
+ seq_printf(m, "\n");
+ }
+ }
+ }
+
+ EVK_mutex_unlock();
+ return 0;
+}
+
+static int
+evk_procFS_flag_show(struct seq_file *m, void *v)
+{
+ return evk_procFS_show(m, evk_enum_flag);
+}
+
+static int
+evk_procFS_flag64_show(struct seq_file *m, void *v)
+{
+ return evk_procFS_show(m, evk_enum_flag64);
+}
+
+static int
+evk_procFS_queue_show(struct seq_file *m, void *v)
+{
+ return evk_procFS_show(m, evk_enum_queue);
+}
+
+static int
+evk_procFS_flag_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, evk_procFS_flag_show, NULL);
+}
+
+static int
+evk_procFS_flag64_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, evk_procFS_flag64_show, NULL);
+}
+
+static int
+evk_procFS_queue_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, evk_procFS_queue_show, NULL);
+}
+
+static struct file_operations evk_proc_flag_fops = {
+ .owner = THIS_MODULE,
+ .open = evk_procFS_flag_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static struct file_operations evk_proc_flag64_fops = {
+ .owner = THIS_MODULE,
+ .open = evk_procFS_flag64_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static struct file_operations evk_proc_queue_fops = {
+ .owner = THIS_MODULE,
+ .open = evk_procFS_queue_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+#endif /*ENABLE_PROC_FS*/
+
+__init int
+EVK_init(void)
+{
+ int err;
+#ifdef CONFIG_PROC_FS
+#ifdef ENABLE_PROC_FS
+ struct proc_dir_entry *ret;
+#endif /* ENABLE_PROC_FS */
+#endif /* CONFIG_PROC_FS */
+ int i;
+ dev_t dev;
+
+ dev = MKDEV(devmajor, devminor);
+ err = register_chrdev_region(dev, nrdevs, EVK_NAME);
+ if (err) {
+ EVK_info1("register_chrdev_region error %d\n", -err);
+ return -EBUSY;
+ }
+
+ cdev_init(&cdev, &evk_fops);
+ cdev.owner = THIS_MODULE;
+ cdev.ops = &evk_fops;
+
+ err = cdev_add(&cdev, dev, 1);
+ if (err) {
+ EVK_info1("cdev_add error %d\n", -err);
+ return -EBUSY;
+ }
+
+ /* Initialization */
+ for(i = 0 ; i < EVK_MAX_FLAGS ; i++) {
+ list_add_tail((struct list_head *)&(_flag_pool[i]),
+ &flag_pool);
+ }
+ for(i = 0 ; i < EVK_MAX_FLAG64S ; i++) {
+ list_add_tail((struct list_head *)&(_flag64_pool[i]),
+ &flag64_pool);
+ }
+ for(i = 0 ; i < EVK_MAX_MESSAGE_QUEUES ; i++) {
+ list_add_tail((struct list_head *)&(_message_queue_pool[i]),
+ &message_queue_pool);
+ }
+ for(i = 0 ; i < HASH_KEY ; i++) {
+ INIT_LIST_HEAD(&(queue_entry[i]));
+ }
+
+#ifdef CONFIG_PROC_FS
+#ifdef ENABLE_PROC_FS
+ ret = proc_create("driver/ev_flag", 0, NULL, &evk_proc_flag_fops);
+ if( ret == NULL ) {
+ EVK_info1("Unable to initialize /proc entry %d\n", -err);
+ return -EBUSY;
+ }
+
+ ret = proc_create("driver/ev_flag64", 0, NULL, &evk_proc_flag64_fops);
+ if( ret == NULL ) {
+ EVK_info1("Unable to initialize /proc entry %d\n", -err);
+ return -EBUSY;
+ }
+
+ ret = proc_create("driver/ev_queue", 0, NULL, &evk_proc_queue_fops);
+ if( ret == NULL ) {
+ EVK_info1("Unable to initialize /proc entry %d\n", -err);
+ return -EBUSY;
+ }
+#endif /* ENABLE_PROC_FS */
+#endif /* CONFIG_PROC_FS */
+
+ pClass = class_create(THIS_MODULE, EVK_NAME);
+ device_create(pClass, NULL, dev, NULL, "agl/"EVK_NAME);
+
+ return 0;
+}
+
+void
+//#ifndef CONFIG_COMBINE_MODULES
+//__exit
+//#endif
+EVK_exit(void)
+{
+ dev_t dev = MKDEV(devmajor, devminor);
+ device_destroy(pClass, dev);
+ class_destroy(pClass);
+
+ cdev_del(&cdev);
+
+ unregister_chrdev_region(dev, nrdevs);
+
+ remove_proc_entry( "driver/ev_flag", 0 );
+ remove_proc_entry( "driver/ev_flag64", 0 );
+ remove_proc_entry( "driver/ev_queue", 0 );
+}
+
+/** @} */
+/** @addtogroup EV
+ * @{ */
+static EV_ERR
+EVK_create_flag_in(EV_ID flagID)
+{
+ int ret = evk_create_flag(flagID);
+
+ if (ret == -EEXIST) {
+ return EV_ERR_Exist;
+ } else if (ret < 0) {
+ return EV_ERR_Fatal;
+ } else {
+ return EV_OK;
+ }
+}
+
+static EV_ERR
+EVK_create_flag64_in(EV_ID flagID)
+{
+ int ret = evk_create_flag64(flagID);
+
+ if (ret == -EEXIST) {
+ return EV_ERR_Exist;
+ } else if (ret < 0) {
+ return EV_ERR_Fatal;
+ } else {
+ return EV_OK;
+ }
+}
+
+/** @see EV_create_flag */
+EV_ERR
+EVK_create_flag(EV_ID flagID)
+{
+ if (!EV_ID_IS_FLAG(flagID) || EV_ID_IS_AUTO_ID(flagID)) {
+ return EV_ERR_Invalid_ID;
+ }
+ return EVK_create_flag_in(flagID);
+}
+
+/** @see EV_create_flag64 */
+EV_ERR
+EVK_create_flag64(EV_ID flagID)
+{
+ if (!EV_ID_IS_FLAG64(flagID) || EV_ID_IS_AUTO_ID(flagID)) {
+ return EV_ERR_Invalid_ID;
+ }
+ return EVK_create_flag64_in(flagID);
+}
+
+static EV_ERR
+EVK_create_queue_in(EV_ID queueID, UINT8 length, UINT16 max_bytes,
+ EV_Message_Queue_Type type)
+{
+ int ret = evk_create_message_queue(queueID, length, max_bytes, type);
+
+ if (ret == -EEXIST) {
+ return EV_ERR_Exist;
+ } else if (ret < 0) {
+ return EV_ERR_Fatal;
+ } else {
+ return EV_OK;
+ }
+}
+
+/** @see EV_create_queue */
+EV_ERR
+EVK_create_queue(EV_ID queueID, UINT8 length, UINT16 max_bytes,
+ EV_Message_Queue_Type type)
+{
+ if (!EV_ID_IS_QUEUE(queueID) || EV_ID_IS_AUTO_ID(queueID)) {
+ return EV_ERR_Invalid_ID;
+ }
+ return EVK_create_queue_in(queueID, length, max_bytes, type);
+}
+
+/** @see EV_create_flag_auto_id */
+EV_ERR
+EVK_create_flag_auto_id(/* OUT */EV_ID *flagID)
+{
+ EV_ERR err;
+ EVK_assert(flagID != NULL, "NULL pointer was specified");
+
+ if (evk_alloc_flagID(flagID) < 0) {
+ return EV_ERR_Fatal;
+ }
+
+ err = EVK_create_flag_in(*flagID);
+ if (err != EV_OK) {
+ *flagID = EV_NO_ID;
+ }
+ return err;
+}
+
+/** @see EV_create_flag64_auto_id */
+EV_ERR
+EVK_create_flag64_auto_id(/* OUT */EV_ID *flagID)
+{
+ EV_ERR err;
+ EVK_assert(flagID != NULL, "NULL pointer was specified");
+
+ if (evk_alloc_flag64ID(flagID) < 0) {
+ return EV_ERR_Fatal;
+ }
+
+ err = EVK_create_flag64_in(*flagID);
+ if (err != EV_OK) {
+ *flagID = EV_NO_ID;
+ }
+ return err;
+}
+
+/** @see EV_create_queue_auto_id */
+EV_ERR
+EVK_create_queue_auto_id(/* OUT */EV_ID *queueID, UINT8 length,
+ UINT16 max_bytes, EV_Message_Queue_Type type)
+{
+ EV_ERR err;
+ EVK_assert(queueID != NULL, "NULL pointer was specified");
+
+ if (evk_alloc_queueID(queueID) < 0) {
+ return EV_ERR_Fatal;
+ }
+
+ err = EVK_create_queue_in(*queueID, length, max_bytes, type);
+ if (err != EV_OK) {
+ *queueID = EV_NO_ID;
+ }
+ return err;
+}
+
+/** @see EV_destroy_flag */
+EV_ERR
+EVK_destroy_flag(EV_ID flagID)
+{
+ int err;
+ err = evk_destroy_queue(flagID);
+
+ if (err == -ENOENT) {
+ return EV_ERR_Invalid_ID;
+ } else if (err < 0) {
+ return EV_ERR_Fatal;
+ } else {
+ return EV_OK;
+ }
+}
+
+/** @see EV_destroy_queue */
+EV_ERR
+EVK_destroy_queue(EV_ID queueID)
+{
+ return EVK_destroy_flag(queueID);
+}
+
+/* Sending the event */
+/** @see EV_set_flag */
+EV_ERR
+EVK_set_flag(EV_ID flagID, UINT32 bits)
+{
+ EV_Flag flag;
+ int ret;
+
+ if (!EV_ID_IS_FLAG(flagID)) {
+ return EV_ERR_Invalid_ID;
+ }
+ flag.flagID = flagID;
+ flag.bits = bits;
+
+ ret = evk_store_flag(&flag, evk_mem_kernel);
+ if (ret == -ENOENT) {
+ return EV_ERR_Invalid_ID;
+ } else if (ret < 0) {
+ return EV_ERR_Fatal;
+ } else {
+ return EV_OK;
+ }
+}
+
+/** @see EV_set_flag64 */
+EV_ERR
+EVK_set_flag64(EV_ID flagID, UINT64 bits)
+{
+ EV_Flag64 flag;
+ int ret;
+
+ if (!EV_ID_IS_FLAG64(flagID)) {
+ return EV_ERR_Invalid_ID;
+ }
+ flag.flagID = flagID;
+ flag.bits = bits;
+
+ ret = evk_store_flag64(&flag, evk_mem_kernel);
+ if (ret == -ENOENT) {
+ return EV_ERR_Invalid_ID;
+ } else if (ret < 0) {
+ return EV_ERR_Fatal;
+ } else {
+ return EV_OK;
+ }
+}
+
+/** @see EV_send_message */
+EV_ERR
+EVK_send_message(EV_ID queueID, UINT16 bytes, const void *message,
+ UINT32 senderInfo)
+{
+ EV_Message *msg = NULL;
+ EV_ERR ev_ret;
+ int ret;
+
+ msg = evk_malloc( sizeof( EV_Message ) );
+ if( msg == NULL )
+ {
+ ev_ret = EV_ERR_Fatal;
+ goto L_END;
+ }
+
+ if (!EV_ID_IS_QUEUE(queueID)) {
+ ev_ret = EV_ERR_Invalid_ID;
+ goto L_END;
+ }
+ EVK_assert(message != NULL, "NULL pointer was specified");
+ EVK_assert(bytes <= EV_MAX_MESSAGE_LENGTH, "send_message: message too long");
+
+ msg->queueID = queueID;
+ msg->senderInfo = senderInfo;
+ msg->length = bytes;
+ memcpy(msg->message, message, bytes);
+
+ ret = evk_store_message(msg, evk_mem_kernel);
+ if (ret == -ENOENT) {
+ ev_ret = EV_ERR_Invalid_ID;
+ } else if (ret == -EBUSY) {
+ ev_ret = EV_ERR_Busy;
+ } else if (ret < 0) {
+ ev_ret = EV_ERR_Fatal;
+ } else {
+ ev_ret = EV_OK;
+ }
+
+L_END:
+ if( msg != NULL )
+ {
+ evk_free( msg );
+ }
+ return ev_ret;
+}
+
+/* Event acquisition(Order of arrival time) */
+//EV_ERR EV_get_next_event(/* OUT */EV_Event *ev);
+
+static EV_ERR
+EVK_get_flag_in(EV_ID flagID, EV_Flag *flag, int peek_only, int wait)
+{
+ EV_Event *ev = NULL;
+ EV_ERR ev_ret;
+ int ret;
+
+ ev = evk_malloc( sizeof( EV_Event ) );
+ if( ev == NULL )
+ {
+ ev_ret = EV_ERR_Fatal;
+ goto L_END;
+ }
+
+ EVK_assert(flag != NULL, "get_flag: NULL pointer was specified");
+ flag->flagID = EV_NO_ID;
+ flag->bits = 0;
+
+ if (!EV_ID_IS_FLAG(flagID)) {
+ ev_ret = EV_ERR_Invalid_ID;
+ goto L_END;
+ }
+
+ ev->type = EV_EVENT_Flag;
+ ev->u.flag.flagID = flagID;
+ ev->u.flag.bits = 0;
+
+ ret = evk_get_event(ev, peek_only, wait, evk_mem_kernel);
+
+ if (ret < 0) {
+ if (ret == -ENOENT) {
+ ev_ret = EV_ERR_Invalid_ID;
+ } else if (ret == -EINTR) {
+ ev_ret = EV_ERR_Interrupted;
+ } else {
+ ev_ret = EV_ERR_Fatal;
+ }
+ goto L_END;
+ }
+
+ if (ev->type == EV_EVENT_Flag) {
+ flag->flagID = ev->u.flag.flagID;
+ flag->bits = ev->u.flag.bits;
+ }
+ ev_ret = EV_OK;
+
+L_END:
+ if( ev != NULL )
+ {
+ evk_free( ev );
+ }
+ return ev_ret;
+}
+
+static EV_ERR
+EVK_get_flag64_in(EV_ID flagID, EV_Flag64 *flag, int peek_only, int wait)
+{
+ EV_Event *ev = NULL;
+ EV_ERR ev_ret;
+ int ret;
+
+ ev = evk_malloc( sizeof( EV_Event ) );
+ if( ev == NULL )
+ {
+ ev_ret = EV_ERR_Fatal;
+ goto L_END;
+ }
+
+ EVK_assert(flag != NULL, "get_flag64: NULL pointer was specified");
+ flag->flagID = EV_NO_ID;
+ flag->bits = 0;
+
+ if (!EV_ID_IS_FLAG64(flagID)) {
+ ev_ret = EV_ERR_Invalid_ID;
+ goto L_END;
+ }
+
+ ev->type = EV_EVENT_Flag64;
+ ev->u.flag64.flagID = flagID;
+ ev->u.flag64.bits = 0;
+
+ ret = evk_get_event(ev, peek_only, wait, evk_mem_kernel);
+
+ if (ret < 0) {
+ if (ret == -ENOENT) {
+ ev_ret = EV_ERR_Invalid_ID;
+ } else if (ret == -EINTR) {
+ ev_ret = EV_ERR_Interrupted;
+ } else {
+ ev_ret = EV_ERR_Fatal;
+ }
+ goto L_END;
+ }
+
+ if (ev->type == EV_EVENT_Flag64) {
+ flag->flagID = ev->u.flag64.flagID;
+ flag->bits = ev->u.flag64.bits;
+ }
+ ev_ret = EV_OK;
+
+L_END:
+ if( ev != NULL )
+ {
+ evk_free( ev );
+ }
+ return ev_ret;
+}
+
+/* Event acquisition(With Search Criteria) */
+/** @see EV_get_flag */
+EV_ERR
+EVK_get_flag(EV_ID flagID, /* OUT */EV_Flag *flag)
+{
+ return EVK_get_flag_in(flagID, flag, 0, 0);
+}
+
+/** @see EV_get_flag64 */
+EV_ERR
+EVK_get_flag64(EV_ID flagID, /* OUT */EV_Flag64 *flag)
+{
+ return EVK_get_flag64_in(flagID, flag, 0, 0);
+}
+
+/** @see EV_wait_flag */
+EV_ERR
+EVK_wait_flag(EV_ID flagID, /* OUT */EV_Flag *flag)/* block */
+{
+ return EVK_get_flag_in(flagID, flag, 0, 1);
+}
+
+/** @see EV_wait_flag64 */
+EV_ERR
+EVK_wait_flag64(EV_ID flagID, /* OUT */EV_Flag64 *flag)/* block */
+{
+ return EVK_get_flag64_in(flagID, flag, 0, 1);
+}
+
+/** @see EV_peek_flag */
+EV_ERR
+EVK_peek_flag(EV_ID flagID, /* OUT */EV_Flag *flag)
+{
+ return EVK_get_flag_in(flagID, flag, 1, 0);
+}
+
+/** @see EV_peek_flag64 */
+EV_ERR
+EVK_peek_flag64(EV_ID flagID, /* OUT */EV_Flag64 *flag)
+{
+ return EVK_get_flag64_in(flagID, flag, 1, 0);
+}
+
+static EV_ERR
+EVK_get_message_in(EV_ID queueID, EV_Message *message, UINT32 senderInfo,
+ UINT32 length, const void *compare_bytes,
+ int peek_only, int wait)
+{
+ EV_Event *ev = NULL;
+ EV_ERR ev_ret;
+ int ret;
+
+ ev = evk_malloc( sizeof( EV_Event ) );
+ if( ev == NULL )
+ {
+ ev_ret = EV_ERR_Fatal;
+ goto L_END;
+ }
+
+ EVK_assert(message != NULL, "get_message: NULL pointer was specified");
+ if (!EV_ID_IS_QUEUE(queueID)) {
+ ev_ret = EV_ERR_Invalid_ID;
+ goto L_END;
+ }
+ message->queueID = EV_NO_ID;
+ message->senderInfo = 0;
+ message->length = 0;
+
+ ev->type = EV_EVENT_Message;
+ ev->u.message.queueID = queueID;
+ ev->u.message.senderInfo = senderInfo;
+ if (compare_bytes != NULL) {
+ ev->u.message.length = length;
+ memcpy(ev->u.message.message, compare_bytes, length);
+ } else {
+ ev->u.message.length = 0;
+ }
+
+ ret = evk_get_event(ev, peek_only, wait, evk_mem_kernel);
+
+ if (ret < 0) {
+ if (ret == -ENOENT) {
+ ev_ret = EV_ERR_Invalid_ID;
+ } else if (ret == -EINTR) {
+ ev_ret = EV_ERR_Interrupted;
+ } else {
+ ev_ret = EV_ERR_Fatal;
+ }
+ goto L_END;
+ }
+
+ if (ev->type == EV_EVENT_Message) {
+ message->queueID = ev->u.message.queueID;
+ message->senderInfo = ev->u.message.senderInfo;
+ message->length = ev->u.message.length;
+ memcpy(message->message, ev->u.message.message, ev->u.message.length);
+ }
+ ev_ret = EV_OK;
+
+L_END:
+ if( ev != NULL )
+ {
+ evk_free( ev );
+ }
+ return ev_ret;
+}
+
+/** @see EV_get_message */
+EV_ERR
+EVK_get_message(EV_ID queueID, /* OUT */EV_Message *message)
+{
+ return EVK_get_message_in(queueID, message, 0, 0, NULL, 0, 0);
+}
+
+/** @see EV_wait_message */
+EV_ERR
+EVK_wait_message(EV_ID queueID, /* OUT */EV_Message *message)/* block */
+{
+ return EVK_get_message_in(queueID, message, 0, 0, NULL, 0, 1);
+}
+
+/** @see EV_peek_message */
+EV_ERR
+EVK_peek_message(EV_ID queueID, /* OUT */EV_Message *message)
+{
+ return EVK_get_message_in(queueID, message, 0, 0, NULL, 1, 0);
+}
+
+/** @see EV_find_message_by_sender */
+EV_ERR
+EVK_find_message_by_sender(EV_ID queueID, UINT32 senderInfo,
+ /* OUT */EV_Message *message)
+{
+ // Not mounted
+ return EV_ERR_Fatal;
+}
+
+/** @see EV_find_message_by_content */
+EV_ERR
+EVK_find_message_by_content(EV_ID queueID, UINT16 length,
+ const void *compare_bytes,
+ /* OUT */EV_Message *message)
+{
+ // Not mounted
+ return EV_ERR_Fatal;
+}
+/** @} */
+
+EXPORT_SYMBOL(evk_get_queue_entry);
+EXPORT_SYMBOL(EVK_init);
+EXPORT_SYMBOL(EVK_exit);
+
+EXPORT_SYMBOL(EVK_create_flag);
+EXPORT_SYMBOL(EVK_create_flag64);
+EXPORT_SYMBOL(EVK_create_queue);
+EXPORT_SYMBOL(EVK_create_flag_auto_id);
+EXPORT_SYMBOL(EVK_create_flag64_auto_id);
+EXPORT_SYMBOL(EVK_create_queue_auto_id);
+EXPORT_SYMBOL(EVK_destroy_flag);
+EXPORT_SYMBOL(EVK_destroy_queue);
+EXPORT_SYMBOL(EVK_set_flag);
+EXPORT_SYMBOL(EVK_set_flag64);
+EXPORT_SYMBOL(EVK_send_message);
+EXPORT_SYMBOL(EVK_get_flag);
+EXPORT_SYMBOL(EVK_wait_flag);
+EXPORT_SYMBOL(EVK_peek_flag);
+EXPORT_SYMBOL(EVK_get_flag64);
+EXPORT_SYMBOL(EVK_wait_flag64);
+EXPORT_SYMBOL(EVK_peek_flag64);
+EXPORT_SYMBOL(EVK_get_message);
+EXPORT_SYMBOL(EVK_wait_message);
+EXPORT_SYMBOL(EVK_peek_message);
+
+#ifndef CONFIG_COMBINE_MODULES
+//MODULE_LICENSE("proprietary");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("EVent library for Kernel");
+//MODULE_SUPPORTED_DEVICE(name);
+//MODULE_PARM(var,type)
+//MODULE_PARM_DESC(var,desc)
+module_init(EVK_init);
+module_exit(EVK_exit);
+#endif /* !CONFIG_COMBINE_MODULES */