123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853 |
- // ===========================================================================
- // Cybook Event Manager - cyevent.c
- // Copyright (C) 2008-2010 Bookeen - All rights reserved
- // ===========================================================================
- #include <linux/init.h>
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/miscdevice.h>
- #include <linux/poll.h>
- #include <linux/sched.h>
- #include <linux/wait.h>
- #include <linux/delay.h>
- #include <linux/interrupt.h>
- #include <linux/pm.h>
- #include <linux/proc_fs.h>
- #include <asm/hardware.h>
- #include <asm/uaccess.h>
- #include <asm/arch/gpio.h>
- #include <asm/arch/regs-gpio.h>
- #include <asm/arch/regs-irq.h>
- #include <asm-arm/arch-s3c2410/irqs.h>
- #include <asm-arm/arch-s3c2410/gpio.h>
- #include <linux/irq.h>
- #include <linux/platform_device.h>
- #include <asm/arch/regs-gpio.h>
- #include <asm/arch/regs-gpioj.h>
- #include <asm/io.h>
- #include <cybook.h>
- #include <linux/cyevent.h>
- // =============================================================================
- //#define DEBUG_MESSAGES
- //#define DEBUG_TRACEFUNC
- //#define VERBOSE_LEVEL INFO_DEBUG
- #define MODULE_NAME "CyEvent"
- // =============================================================================
- #define CYEV_MAX_EVENT 20
- #define CYEV_MAX_DEV 5
- #define CYEV_REPEAT_DELAY (HZ/2) /* ~500ms */
- // =============================================================================
- enum { INVALID = 0, VALID };
- // =============================================================================
- typedef struct sCyEv_PayList
- {
- char valid;
- char wantRepeat;
- char seen;
- char repeat;
- char unique;
- unsigned long repeatDelay;
- CyEvent_t payload;
- } CyEv_PayList;
- CyEv_PayList cyev_eventList[CYEV_MAX_EVENT];
- // =============================================================================
- /* We should change this to a linked list... */
- struct cyevent_device *DevList[CYEV_MAX_DEV];
- // =============================================================================
- struct task_struct *openingTask = 0;
- static atomic_t waitingRepeat;
- // =============================================================================
- #ifdef DEBUG_MESSAGES
- enum InfoLevel
- {
- INFO_ERROR = 0,
- INFO_WARNING,
- INFO_NORMAL,
- INFO_DEBUG,
- INFO_VERBOSE,
- };
- # ifndef VERBOSE_LEVEL
- # define VERBOSE_LEVEL INFO_WARNING
- # endif
- # ifdef DEBUG_TRACEFUNC
- static int _dbg_FunctionLevel = 0;
- # define MSG(str) {\
- int __i;\
- printk(KERN_ALERT "+");\
- for (__i = 0; __i < _dbg_FunctionLevel; __i++)\
- printk("-");\
- printk("||" str "\n");\
- }
- # define DBG(str, ...) {\
- int __i;\
- printk(KERN_ALERT "+");\
- for (__i = 0; __i < _dbg_FunctionLevel; __i++)\
- printk("-");\
- printk("||" str "\n", __VA_ARGS__);\
- }
- # define INFOL(level, s) do {\
- if (level <= VERBOSE_LEVEL) {\
- int __i;\
- printk(KERN_ALERT "+");\
- for (__i = 0; __i < _dbg_FunctionLevel; __i++)\
- printk("-");\
- printk("<%d>%s:%s(): ", level, __FILE__, __func__); printk s; printk("\n");\
- }\
- } while(0)
- # define FUNC_IN() {\
- int __i;\
- _dbg_FunctionLevel++;\
- printk(KERN_ALERT "+");\
- for (__i = 0; __i < _dbg_FunctionLevel; __i++)\
- printk("-");\
- printk(">> %s() >>\n", __func__);\
- }
- # define FUNC_OUT() {\
- int __i;\
- printk(KERN_ALERT "+");\
- for (__i = 0; __i < _dbg_FunctionLevel; __i++)\
- printk("-");\
- printk("<< %s() <<\n", __func__);\
- _dbg_FunctionLevel--;\
- }
- # define FUNC_OUTR(val) {\
- int __i;\
- printk(KERN_ALERT "+");\
- for (__i = 0; __i < _dbg_FunctionLevel; __i++)\
- printk("-");\
- printk("<< %s() = %d <<\n", __func__, val);\
- _dbg_FunctionLevel--;\
- }
- # else /* DEBUG_TRACEFUNC */
- # define MSG(str) do {\
- printk(KERN_ALERT MODULE_NAME ": " str "\n");\
- } while(0)
- # define DBG(str, ...) do {\
- printk(KERN_ALERT MODULE_NAME ": " str "\n", __VA_ARGS__);\
- } while(0)
- # define FUNC_IN() do {\
- } while(0)
- # define FUNC_OUT() do {\
- } while(0)
- # define FUNC_OUTR(val) do {\
- printk(KERN_ALERT MODULE_NAME ": %s() return %d\n", __func__, val);\
- } while(0)
- # define INFOL(level, s) do {\
- if (level <= VERBOSE_LEVEL) {\
- printk("<%d>%s:%s(): ", level, __FILE__, __func__); printk s; printk("\n");\
- }\
- } while(0)
- # endif /* DEBUG_TRACEFUNC */
- #else /* DEBUG_MESSAGES */
- # define MSG(str)
- # define DBG(str, ...)
- # define FUNC_IN()
- # define FUNC_OUT()
- # define FUNC_OUTR(val)
- # define INFOL(level, s)
- # define INFO(s)
- #endif /* DEBUG_MESSAGES */
- #define DUMP_CYEVENT(lvl, ev) INFOL(lvl, ("Event: .type=%c, .flags=%02X, .version=%02X\n" \
- ".data = { 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X }",\
- ev.type, ev.flags, ev.version, ev.data.raw[0], ev.data.raw[1], ev.data.raw[2], ev.data.raw[3], ev.data.raw[4], ev.data.raw[5],\
- ev.data.raw[6], ev.data.raw[7], ev.data.raw[8], ev.data.raw[9], ev.data.raw[10], ev.data.raw[11], ev.data.raw[12]))
- #define DUMP_EVITEM(lvl, evi) INFOL(lvl, ("EvItem: .valid = %d, .wantRepeat = %d, .seen = %d, .repeat = %d, .unique = %d, .repeatDelay = %lu .payload:",\
- evi.valid, evi.wantRepeat, evi.seen, evi.repeat, evi.unique, evi.repeatDelay)); DUMP_CYEVENT(lvl, evi.payload);
- // =============================================================================
- rwlock_t cyev_list_rwlock = RW_LOCK_UNLOCKED;
- // =============================================================================
- static void publish_read_event(unsigned char type);
- static void publish_empty_event(void);
- // =============================================================================
- // List management
- void CyEv_ClearEventList(void)
- {
- int i;
-
- FUNC_IN();
-
- atomic_set(&waitingRepeat, 0);
-
- write_lock(&cyev_list_rwlock);
-
- for (i = 0; i < CYEV_MAX_EVENT; i++)
- {
- cyev_eventList[i].wantRepeat = false;
- cyev_eventList[i].repeat = false;
- cyev_eventList[i].seen = false;
- cyev_eventList[i].unique = false;
- cyev_eventList[i].repeatDelay = 0;
- cyev_eventList[i].valid = INVALID;
- }
-
- write_unlock(&cyev_list_rwlock);
-
- FUNC_OUT();
- }
- int listPos = 0;
- /* Get Next Event will invalidate the event if it is not marked as repeat */
- /* After the event is selected, it will point to the next one */
- /* We first start by the first event of the list then search for the first valid and return it */
- CyEvent_t *CyEv_GetNextEvent(CyEvent_t *ret)
- {
- int i;
- char foundPayload = 0;
- CyEv_PayList *cur;
-
- FUNC_IN();
-
- write_lock(&cyev_list_rwlock);
-
- /* Scan the list starting from the last position stored */
- for(i = listPos; i < (CYEV_MAX_EVENT + listPos); i++)
- {
- /* Stop on the first "VALID" event */
- cur = &(cyev_eventList[i % CYEV_MAX_EVENT]);
- //INFOL(INFO_VERBOSE, ("Position %d / %d", i % CYEV_MAX_EVENT, CYEV_MAX_EVENT));
- if (cur->valid == VALID)
- {
- DUMP_EVITEM(INFO_DEBUG, (*cur));
-
- /* We already send this repeatable event. Did the delay occur ?
- if not, ignore it and go to the next one */
- if ( (cur->seen == true) &&
- (cur->wantRepeat == true) )
- {
- if (cur->repeatDelay > jiffies)
- {
- INFOL(INFO_DEBUG, ("Event delay not occured [%lu vs %lu (%lu)]...",
- cur->repeatDelay, jiffies, cur->repeatDelay - jiffies));
- continue;
- }
- else /* if (cur->repeatDelay >= jiffies) */
- {
- /* Set the Repeat flag to true */
- INFOL(INFO_DEBUG, ("Event repeating... (%d)", atomic_read(&waitingRepeat)));
- if (cur->repeat == false)
- {
- atomic_dec(&waitingRepeat); /* Ack the repeat event */
- }
- INFOL(INFO_DEBUG, ("waiting (%d) (repeat:%d)", atomic_read(&waitingRepeat), cur->repeat));
- cur->payload.flags |= CYEVENT_FLAG_REPEATEVENT;
- cur->repeat = true;
- }
- }
-
- cur->seen = true;
-
- /* Return the event and do not give real access to the list */
- memcpy(ret, &(cur->payload), sizeof(CyEvent_t));
- foundPayload = 1;
- /* If the event is not a repeatable event, invalidate it! */
- if (cur->wantRepeat == false)
- {
- INFOL(INFO_VERBOSE, ("Non-repeat event, will invalidate it"));
- cur->valid = INVALID;
- }
-
- /* Update the index for the next element to scan */
- listPos = (i + 1) % CYEV_MAX_EVENT;
- INFOL(INFO_DEBUG, ("Next event slot: %d", listPos));
- break;
- }
- }
-
- write_unlock(&cyev_list_rwlock);
-
- FUNC_OUT();
- if (foundPayload == 1)
- return ret; /* We will return NULL if no valid payload */
- return NULL;
- }
- int isEventNotDuplicate(CyEvent_t *CyEvent, unsigned char flagMask)
- {
- int i;
- int ret = true;
- CyEvent_t *cur;
-
- FUNC_IN();
-
- read_lock(&cyev_list_rwlock);
-
- for(i = 0; i < CYEV_MAX_EVENT; i++)
- {
- cur = &(cyev_eventList[i].payload);
- /* The event must be valid to be treated as unique, else invalid event are ignored */
- if ( (cyev_eventList[i].valid == VALID) &&
- (cyev_eventList[i].unique == true) )
- {
- if ( (cur->type == CyEvent->type) &&
- ((cyev_eventList[i].payload.flags & flagMask) == (CyEvent->flags & flagMask)) )
- {
- ret = false;
- goto exit;
- }
- }
- }
-
- exit:
- read_unlock(&cyev_list_rwlock);
-
- FUNC_OUTR(ret);
- return ret;
- }
- int CyEv_AddNewEvent(CyEvent_t *CyEvent, char wantRepeat, char wantUnique, unsigned char flagMask)
- {
- /* Search for the first "invalid" event, then put the given CyEvent in it. */
- /* If no slot is valid, return an error */
- int i;
- int ret = -EIO; /* TODO: find a better error code.*/
- FUNC_IN();
-
- /* If wantUnique, first check that there is not another unique event */
- if ((wantUnique) && !isEventNotDuplicate(CyEvent, flagMask))
- goto exit;
-
- write_lock(&cyev_list_rwlock);
-
- /* Scan the list starting from the last position stored */
- for(i = listPos; i < (CYEV_MAX_EVENT + listPos); i++)
- {
- /* Stop on the first "INVALID" event */
- if (cyev_eventList[i].valid == INVALID)
- {
- /* Store the event */
- memcpy(&(cyev_eventList[i].payload), CyEvent, sizeof(CyEvent_t));
- /* Force version in the structure */
- cyev_eventList[i].payload.version = CYEV_CURRENT_VERSION;
- cyev_eventList[i].valid = VALID;
- cyev_eventList[i].seen = false;
- cyev_eventList[i].repeat = false;
-
- if (wantUnique)
- cyev_eventList[i].unique = true;
- else
- cyev_eventList[i].unique = false;
- if (wantRepeat)
- {
- atomic_inc(&waitingRepeat);
- cyev_eventList[i].wantRepeat = true;
- cyev_eventList[i].repeatDelay = jiffies + CYEV_REPEAT_DELAY;
- }
- else
- cyev_eventList[i].wantRepeat = false;
- if (openingTask)
- wake_up_process(openingTask);
- ret = 0;
- break;
- }
- }
- write_unlock(&cyev_list_rwlock);
-
- exit:
- FUNC_OUTR(ret);
- return ret;
- }
- /* Return 0 if event found and updated, or anything else */
- /* We could ONLY update event that are declared as unique */
- int CyEv_UpdateUniqueEvent(CyEvent_t *CyEvent, char wantRepeat, unsigned char flagMask)
- {
- int i;
- int ret = -1;
-
- FUNC_IN();
-
- /* Search for the event */
- write_lock(&cyev_list_rwlock);
- for(i = 0; i < CYEV_MAX_EVENT; i++)
- {
- if ( (cyev_eventList[i].valid == VALID) &&
- (cyev_eventList[i].unique == true) &&
- ((cyev_eventList[i].payload.flags & flagMask) == (CyEvent->flags & flagMask)) &&
- (cyev_eventList[i].payload.type == CyEvent->type) )
- { /* Found it ! Now update the fields */
- memcpy(&(cyev_eventList[i].payload), CyEvent, sizeof(CyEvent_t));
-
- cyev_eventList[i].seen = false;
-
- if (wantRepeat)
- {
- cyev_eventList[i].wantRepeat = true;
- cyev_eventList[i].repeat = false;
- cyev_eventList[i].repeatDelay = jiffies + CYEV_REPEAT_DELAY;
- if (cyev_eventList[i].repeat == true)
- atomic_inc(&waitingRepeat);
- }
- else
- cyev_eventList[i].wantRepeat = false;
- if (openingTask)
- wake_up_process(openingTask);
-
- ret = 0;
- }
- }
- write_unlock(&cyev_list_rwlock);
- FUNC_OUTR(ret);
- return ret;
- }
- int CyEv_InvalidateUniqueEvent (CyEvent_t *CyEvent)
- {
- int i;
- int ret = -1;
- FUNC_IN();
- /* Search for the event */
- write_lock(&cyev_list_rwlock);
- for ( i = 0; i < CYEV_MAX_EVENT; i++ )
- {
- if ( (cyev_eventList[i].valid == VALID) &&
- (cyev_eventList[i].unique == true) &&
- (cyev_eventList[i].payload.type == CyEvent->type) )
- { /* Found it ! Now update the fields */
- INFOL(INFO_DEBUG, ("Found event..."));
- cyev_eventList[i].valid = INVALID;
- ret = 0;
- break;
- }
- }
- write_unlock(&cyev_list_rwlock);
- FUNC_OUTR(ret);
- return ret;
- }
- int CyEv_InvalidateRepeatableEvent(CyEvent_t *CyEvent)
- {
- int i;
- int ret = -1;
-
- FUNC_IN();
-
- /* Search for the event */
- write_lock(&cyev_list_rwlock);
- for(i = 0; i < CYEV_MAX_EVENT; i++)
- {
- if ( (cyev_eventList[i].valid == VALID) &&
- (cyev_eventList[i].wantRepeat == true) &&
- (cyev_eventList[i].payload.type == CyEvent->type) )
- { /* Found it ! Now update the fields */
- INFOL(INFO_DEBUG, ("Found event..."));
- /* In case the event has not been eaten, just remove the "repeat want"
- ie: do not invalidate it */
- cyev_eventList[i].wantRepeat = false;
- if (cyev_eventList[i].repeat == true)
- {
- INFOL(INFO_DEBUG, ("Was repeating..."));
- /* set the event "end of repeat" flag */
- cyev_eventList[i].payload.flags |= CYEVENT_FLAG_ENDOFREPEAT;
- cyev_eventList[i].payload.flags &= ~(CYEVENT_FLAG_REPEATEVENT);
- }
- else
- {
- INFOL(INFO_DEBUG, ("Repeat not done... (%d)", atomic_read(&waitingRepeat)));
- atomic_dec(&waitingRepeat); /* One less waiting event... */
- INFOL(INFO_DEBUG, ("waiting (%d)", atomic_read(&waitingRepeat)));
- if (cyev_eventList[i].seen == true)
- cyev_eventList[i].valid = INVALID;
- }
-
- cyev_eventList[i].seen = false;
- cyev_eventList[i].repeat = false;
-
- if (openingTask)
- wake_up_process(openingTask);
-
- ret = 0;
- break;
- }
- }
- write_unlock(&cyev_list_rwlock);
-
- FUNC_OUTR(ret);
- return ret;
- }
- // ===========================================================================
- // ===========================================================================
- // External event managment
- int CyEvent_PushNewEvent(CyEvent_t *CyEvent, char wantRepeat)
- {
- int ret = -1;
- FUNC_IN();
- if (wantRepeat)
- ret = CyEv_AddNewEvent(CyEvent, wantRepeat, true, 0);
- else
- ret = CyEv_AddNewEvent(CyEvent, wantRepeat, false, 0);
-
- FUNC_OUTR(ret);
- return ret;
- }
- EXPORT_SYMBOL(CyEvent_PushNewEvent);
- int CyEvent_PushNewUniqueEvent(CyEvent_t *CyEvent)
- {
- return CyEv_AddNewEvent(CyEvent, false, true, 0);
- }
- EXPORT_SYMBOL(CyEvent_PushNewUniqueEvent);
- int CyEvent_PushOrUpdateUniqueEventFlaged(CyEvent_t *CyEvent, char wantRepeat, unsigned char flagMask)
- {
- int ret;
- FUNC_IN();
- /* For now a simple call to AddNewEvent */
- ret = CyEv_UpdateUniqueEvent(CyEvent, wantRepeat, flagMask);
- if (ret != 0) /* The event is not present */
- ret = CyEv_AddNewEvent(CyEvent, wantRepeat, true, flagMask);
- FUNC_OUTR(ret);
- return ret;
- }
- EXPORT_SYMBOL(CyEvent_PushOrUpdateUniqueEventFlaged);
- int CyEvent_PushOrUpdateUniqueEvent(CyEvent_t *CyEvent, char wantRepeat)
- {
- int ret;
-
- FUNC_IN();
-
- /* For now a simple call to AddNewEvent */
- ret = CyEv_UpdateUniqueEvent(CyEvent, wantRepeat, 0);
-
- if (ret != 0) /* The event is not present */
- ret = CyEv_AddNewEvent(CyEvent, wantRepeat, true, 0);
- FUNC_OUTR(ret);
- return ret;
- }
- EXPORT_SYMBOL(CyEvent_PushOrUpdateUniqueEvent);
- int CyEvent_InvalidateUniqueEvent(CyEvent_t *CyEvent)
- {
- int ret;
- FUNC_IN();
- ret = CyEv_InvalidateUniqueEvent(CyEvent);
- FUNC_OUTR(ret);
- return ret;
- }
- EXPORT_SYMBOL(CyEvent_InvalidateUniqueEvent);
- int CyEvent_InvalidateRepeatableEvent(CyEvent_t *CyEvent)
- {
- int ret;
- FUNC_IN();
- ret = CyEv_InvalidateRepeatableEvent(CyEvent);
-
- FUNC_OUTR(ret);
- return ret;
- }
- EXPORT_SYMBOL(CyEvent_InvalidateRepeatableEvent);
- // ===========================================================================
- static int ev_open(struct inode *inode, struct file *file)
- {
- FUNC_IN();
-
- /* Clear pending event list... */
- CyEv_ClearEventList();
-
- FUNC_OUT();
- return 0;
- }
- // ---------------------------------------------------------------------------
- static int ev_release(struct inode *inode, struct file *file)
- {
- FUNC_IN();
-
- /* Clear pending event list... */
- CyEv_ClearEventList();
-
- FUNC_OUT();
- return 0;
- }
- // ---------------------------------------------------------------------------
- ssize_t ev_read (struct file *file, char *buf, size_t count, loff_t *ppos)
- {
- int nBytes = sizeof (CyEvent_t);
- int ret = -EIO;
- int waitCount;
- CyEvent_t CyEvent;
- //FUNC_IN();
- if ( count < nBytes )
- {
- ret = -EINVAL;
- goto exit;
- }
- while ( 1 )
- {
- //printk(KERN_ERR "CyEvent: Check new event...\n");
- if ( CyEv_GetNextEvent(&CyEvent) != NULL )
- {
- break;
- }
-
- waitCount = atomic_read(&waitingRepeat);
- if (waitCount == 0) /* If there are some waiting event, the list is not empty */
- publish_empty_event();
- openingTask = current;
- set_current_state(TASK_INTERRUPTIBLE);
- /* If there are some waiting repeat, schedule with a timeout, or else,
- just go out of the schedule queue */
- INFOL(INFO_DEBUG, ("Waiting repeat: %d", waitCount));
- if ( waitCount > 0 )
- schedule_timeout(CYEV_REPEAT_DELAY / 10);
- else
- schedule();
- set_current_state(TASK_RUNNING);
- openingTask = 0;
- if ( signal_pending(current) )
- {
- ret = -ERESTARTSYS;
- break;
- }
- }
- if ( ret != -ERESTARTSYS )
- {
- ret = copy_to_user(buf, &CyEvent, nBytes);
- if ( !ret )
- ret = nBytes;
- publish_read_event(CyEvent.type);
- }
- exit:
- //FUNC_OUTR(ret);
- return ret;
- }
- // ---------------------------------------------------------------------------
- static int ev_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
- {
- int ret = -EINVAL;
- unsigned long value;
- int i;
- FUNC_IN();
-
- switch(cmd)
- {
- default:
- for (i = 0; i < CYEV_MAX_DEV; i++ )
- {
- if ((DevList[i] != NULL) && (DevList[i]->ioctl != NULL))
- {
- if (GET_IOCTL_PREFIX(cmd) == DevList[i]->ioctl_prefix)
- {
- ret = DevList[i]->ioctl(cmd, arg);
- /* if the ioctl called didn't return 0, try to see if there is
- someone else for this one */
- if (ret == 0)
- break;
- }
- }
- }
- printk(KERN_ERR "Bad IOCTL\n");
- break;
- }
-
- FUNC_OUT();
- return ret;
- }
- // =============================================================================
- int CyEvent_RegisterDevice(cyevent_device *dev)
- {
- int i;
- for (i = 0; i < CYEV_MAX_DEV; i++ )
- {
- if (DevList[i] == NULL)
- {
- DevList[i] = dev;
- return 0;
- }
- }
- return -1; /* Too many devices... */
- }
- // -----------------------------------------------------------------------------
- int CyEvent_DeregisterDevice(cyevent_device *dev)
- {
- int i;
- for (i = 0; i < CYEV_MAX_DEV; i++ )
- {
- if (DevList[i] == dev)
- {
- DevList[i] = NULL;
- return 0;
- }
- }
- return -1; /* Not found...*/
- }
- // -----------------------------------------------------------------------------
- static void publish_read_event(unsigned char type)
- {
- int i;
- for (i = 0; i < CYEV_MAX_DEV; i++ )
- {
- if ((DevList[i] != NULL) && (DevList[i]->event_read != NULL))
- {
- if ((DevList[i]->event_read_listen == 0) || (type == DevList[i]->event_read_listen))
- DevList[i]->event_read(type);
- }
- }
- }
- // -----------------------------------------------------------------------------
- static void publish_empty_event(void)
- {
- int i;
- for (i = 0; i < CYEV_MAX_DEV; i++ )
- {
- if ((DevList[i] != NULL) && (DevList[i]->event_listempty != NULL))
- {
- DevList[i]->event_listempty();
- }
- }
- }
- // =============================================================================
- static struct file_operations s_ev_fops =
- {
- owner: THIS_MODULE,
- read: ev_read,
- ioctl: ev_ioctl,
- open: ev_open,
- release: ev_release,
- };
- static struct miscdevice s_ev_dev =
- {
- .minor = 250,
- .name = "cyio",
- .fops = &s_ev_fops,
- };
- // ===========================================================================
- // ---------------------------------------------------------------------------
- static int ev_probe(struct platform_device *dev)
- {
- FUNC_IN();
- FUNC_OUT();
- return 0;
- }
- // ---------------------------------------------------------------------------
- static int ev_remove(struct platform_device *dev)
- {
- FUNC_IN();
-
- misc_deregister(&s_ev_dev);
-
- FUNC_OUT();
- return 0;
- }
- // --------------------------------------------------------------------------
- static int ev_suspend(struct platform_device *dev)
- {
- FUNC_IN();
- FUNC_OUT();
- return 0;
- }
- // --------------------------------------------------------------------------
- static int ev_resume(struct platform_device *dev)
- {
- FUNC_IN();
-
- FUNC_OUT();
- return 0;
- }
- // ---------------------------------------------------------------------------
- static struct platform_driver cyev_driver =
- {
- .driver =
- {
- .name = "cyevent",
- .owner = THIS_MODULE,
- },
- .probe = ev_probe,
- .remove = ev_remove,
- .suspend = NULL, //ev_suspend,
- .resume = ev_resume,
- };
- // ---------------------------------------------------------------------------
- // ===========================================================================
- static int __init cyEv_init(void)
- {
- FUNC_IN();
-
- if (misc_register(&s_ev_dev))
- return -EBUSY;
- platform_driver_register(&cyev_driver);
- FUNC_OUT();
- return 0;
- }
- // ---------------------------------------------------------------------------
- static void __exit cyEv_exit(void)
- {
- FUNC_IN();
-
- platform_driver_unregister(&cyev_driver);
- misc_deregister(&s_ev_dev);
-
- FUNC_OUT();
- }
- // ---------------------------------------------------------------------------
- module_init(cyEv_init);
- module_exit(cyEv_exit);
- // ---------------------------------------------------------------------------
- MODULE_LICENSE("GPL");
- MODULE_AUTHOR("Bookeen <developers@bookeen.com>");
- MODULE_DESCRIPTION("Cybook Event Manager");
- MODULE_VERSION("3.0");
- // ===========================================================================
|