cyevent.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853
  1. // ===========================================================================
  2. // Cybook Event Manager - cyevent.c
  3. // Copyright (C) 2008-2010 Bookeen - All rights reserved
  4. // ===========================================================================
  5. #include <linux/init.h>
  6. #include <linux/kernel.h>
  7. #include <linux/module.h>
  8. #include <linux/miscdevice.h>
  9. #include <linux/poll.h>
  10. #include <linux/sched.h>
  11. #include <linux/wait.h>
  12. #include <linux/delay.h>
  13. #include <linux/interrupt.h>
  14. #include <linux/pm.h>
  15. #include <linux/proc_fs.h>
  16. #include <asm/hardware.h>
  17. #include <asm/uaccess.h>
  18. #include <asm/arch/gpio.h>
  19. #include <asm/arch/regs-gpio.h>
  20. #include <asm/arch/regs-irq.h>
  21. #include <asm-arm/arch-s3c2410/irqs.h>
  22. #include <asm-arm/arch-s3c2410/gpio.h>
  23. #include <linux/irq.h>
  24. #include <linux/platform_device.h>
  25. #include <asm/arch/regs-gpio.h>
  26. #include <asm/arch/regs-gpioj.h>
  27. #include <asm/io.h>
  28. #include <cybook.h>
  29. #include <linux/cyevent.h>
  30. // =============================================================================
  31. //#define DEBUG_MESSAGES
  32. //#define DEBUG_TRACEFUNC
  33. //#define VERBOSE_LEVEL INFO_DEBUG
  34. #define MODULE_NAME "CyEvent"
  35. // =============================================================================
  36. #define CYEV_MAX_EVENT 20
  37. #define CYEV_MAX_DEV 5
  38. #define CYEV_REPEAT_DELAY (HZ/2) /* ~500ms */
  39. // =============================================================================
  40. enum { INVALID = 0, VALID };
  41. // =============================================================================
  42. typedef struct sCyEv_PayList
  43. {
  44. char valid;
  45. char wantRepeat;
  46. char seen;
  47. char repeat;
  48. char unique;
  49. unsigned long repeatDelay;
  50. CyEvent_t payload;
  51. } CyEv_PayList;
  52. CyEv_PayList cyev_eventList[CYEV_MAX_EVENT];
  53. // =============================================================================
  54. /* We should change this to a linked list... */
  55. struct cyevent_device *DevList[CYEV_MAX_DEV];
  56. // =============================================================================
  57. struct task_struct *openingTask = 0;
  58. static atomic_t waitingRepeat;
  59. // =============================================================================
  60. #ifdef DEBUG_MESSAGES
  61. enum InfoLevel
  62. {
  63. INFO_ERROR = 0,
  64. INFO_WARNING,
  65. INFO_NORMAL,
  66. INFO_DEBUG,
  67. INFO_VERBOSE,
  68. };
  69. # ifndef VERBOSE_LEVEL
  70. # define VERBOSE_LEVEL INFO_WARNING
  71. # endif
  72. # ifdef DEBUG_TRACEFUNC
  73. static int _dbg_FunctionLevel = 0;
  74. # define MSG(str) {\
  75. int __i;\
  76. printk(KERN_ALERT "+");\
  77. for (__i = 0; __i < _dbg_FunctionLevel; __i++)\
  78. printk("-");\
  79. printk("||" str "\n");\
  80. }
  81. # define DBG(str, ...) {\
  82. int __i;\
  83. printk(KERN_ALERT "+");\
  84. for (__i = 0; __i < _dbg_FunctionLevel; __i++)\
  85. printk("-");\
  86. printk("||" str "\n", __VA_ARGS__);\
  87. }
  88. # define INFOL(level, s) do {\
  89. if (level <= VERBOSE_LEVEL) {\
  90. int __i;\
  91. printk(KERN_ALERT "+");\
  92. for (__i = 0; __i < _dbg_FunctionLevel; __i++)\
  93. printk("-");\
  94. printk("<%d>%s:%s(): ", level, __FILE__, __func__); printk s; printk("\n");\
  95. }\
  96. } while(0)
  97. # define FUNC_IN() {\
  98. int __i;\
  99. _dbg_FunctionLevel++;\
  100. printk(KERN_ALERT "+");\
  101. for (__i = 0; __i < _dbg_FunctionLevel; __i++)\
  102. printk("-");\
  103. printk(">> %s() >>\n", __func__);\
  104. }
  105. # define FUNC_OUT() {\
  106. int __i;\
  107. printk(KERN_ALERT "+");\
  108. for (__i = 0; __i < _dbg_FunctionLevel; __i++)\
  109. printk("-");\
  110. printk("<< %s() <<\n", __func__);\
  111. _dbg_FunctionLevel--;\
  112. }
  113. # define FUNC_OUTR(val) {\
  114. int __i;\
  115. printk(KERN_ALERT "+");\
  116. for (__i = 0; __i < _dbg_FunctionLevel; __i++)\
  117. printk("-");\
  118. printk("<< %s() = %d <<\n", __func__, val);\
  119. _dbg_FunctionLevel--;\
  120. }
  121. # else /* DEBUG_TRACEFUNC */
  122. # define MSG(str) do {\
  123. printk(KERN_ALERT MODULE_NAME ": " str "\n");\
  124. } while(0)
  125. # define DBG(str, ...) do {\
  126. printk(KERN_ALERT MODULE_NAME ": " str "\n", __VA_ARGS__);\
  127. } while(0)
  128. # define FUNC_IN() do {\
  129. } while(0)
  130. # define FUNC_OUT() do {\
  131. } while(0)
  132. # define FUNC_OUTR(val) do {\
  133. printk(KERN_ALERT MODULE_NAME ": %s() return %d\n", __func__, val);\
  134. } while(0)
  135. # define INFOL(level, s) do {\
  136. if (level <= VERBOSE_LEVEL) {\
  137. printk("<%d>%s:%s(): ", level, __FILE__, __func__); printk s; printk("\n");\
  138. }\
  139. } while(0)
  140. # endif /* DEBUG_TRACEFUNC */
  141. #else /* DEBUG_MESSAGES */
  142. # define MSG(str)
  143. # define DBG(str, ...)
  144. # define FUNC_IN()
  145. # define FUNC_OUT()
  146. # define FUNC_OUTR(val)
  147. # define INFOL(level, s)
  148. # define INFO(s)
  149. #endif /* DEBUG_MESSAGES */
  150. #define DUMP_CYEVENT(lvl, ev) INFOL(lvl, ("Event: .type=%c, .flags=%02X, .version=%02X\n" \
  151. ".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 }",\
  152. 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],\
  153. 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]))
  154. #define DUMP_EVITEM(lvl, evi) INFOL(lvl, ("EvItem: .valid = %d, .wantRepeat = %d, .seen = %d, .repeat = %d, .unique = %d, .repeatDelay = %lu .payload:",\
  155. evi.valid, evi.wantRepeat, evi.seen, evi.repeat, evi.unique, evi.repeatDelay)); DUMP_CYEVENT(lvl, evi.payload);
  156. // =============================================================================
  157. rwlock_t cyev_list_rwlock = RW_LOCK_UNLOCKED;
  158. // =============================================================================
  159. static void publish_read_event(unsigned char type);
  160. static void publish_empty_event(void);
  161. // =============================================================================
  162. // List management
  163. void CyEv_ClearEventList(void)
  164. {
  165. int i;
  166. FUNC_IN();
  167. atomic_set(&waitingRepeat, 0);
  168. write_lock(&cyev_list_rwlock);
  169. for (i = 0; i < CYEV_MAX_EVENT; i++)
  170. {
  171. cyev_eventList[i].wantRepeat = false;
  172. cyev_eventList[i].repeat = false;
  173. cyev_eventList[i].seen = false;
  174. cyev_eventList[i].unique = false;
  175. cyev_eventList[i].repeatDelay = 0;
  176. cyev_eventList[i].valid = INVALID;
  177. }
  178. write_unlock(&cyev_list_rwlock);
  179. FUNC_OUT();
  180. }
  181. int listPos = 0;
  182. /* Get Next Event will invalidate the event if it is not marked as repeat */
  183. /* After the event is selected, it will point to the next one */
  184. /* We first start by the first event of the list then search for the first valid and return it */
  185. CyEvent_t *CyEv_GetNextEvent(CyEvent_t *ret)
  186. {
  187. int i;
  188. char foundPayload = 0;
  189. CyEv_PayList *cur;
  190. FUNC_IN();
  191. write_lock(&cyev_list_rwlock);
  192. /* Scan the list starting from the last position stored */
  193. for(i = listPos; i < (CYEV_MAX_EVENT + listPos); i++)
  194. {
  195. /* Stop on the first "VALID" event */
  196. cur = &(cyev_eventList[i % CYEV_MAX_EVENT]);
  197. //INFOL(INFO_VERBOSE, ("Position %d / %d", i % CYEV_MAX_EVENT, CYEV_MAX_EVENT));
  198. if (cur->valid == VALID)
  199. {
  200. DUMP_EVITEM(INFO_DEBUG, (*cur));
  201. /* We already send this repeatable event. Did the delay occur ?
  202. if not, ignore it and go to the next one */
  203. if ( (cur->seen == true) &&
  204. (cur->wantRepeat == true) )
  205. {
  206. if (cur->repeatDelay > jiffies)
  207. {
  208. INFOL(INFO_DEBUG, ("Event delay not occured [%lu vs %lu (%lu)]...",
  209. cur->repeatDelay, jiffies, cur->repeatDelay - jiffies));
  210. continue;
  211. }
  212. else /* if (cur->repeatDelay >= jiffies) */
  213. {
  214. /* Set the Repeat flag to true */
  215. INFOL(INFO_DEBUG, ("Event repeating... (%d)", atomic_read(&waitingRepeat)));
  216. if (cur->repeat == false)
  217. {
  218. atomic_dec(&waitingRepeat); /* Ack the repeat event */
  219. }
  220. INFOL(INFO_DEBUG, ("waiting (%d) (repeat:%d)", atomic_read(&waitingRepeat), cur->repeat));
  221. cur->payload.flags |= CYEVENT_FLAG_REPEATEVENT;
  222. cur->repeat = true;
  223. }
  224. }
  225. cur->seen = true;
  226. /* Return the event and do not give real access to the list */
  227. memcpy(ret, &(cur->payload), sizeof(CyEvent_t));
  228. foundPayload = 1;
  229. /* If the event is not a repeatable event, invalidate it! */
  230. if (cur->wantRepeat == false)
  231. {
  232. INFOL(INFO_VERBOSE, ("Non-repeat event, will invalidate it"));
  233. cur->valid = INVALID;
  234. }
  235. /* Update the index for the next element to scan */
  236. listPos = (i + 1) % CYEV_MAX_EVENT;
  237. INFOL(INFO_DEBUG, ("Next event slot: %d", listPos));
  238. break;
  239. }
  240. }
  241. write_unlock(&cyev_list_rwlock);
  242. FUNC_OUT();
  243. if (foundPayload == 1)
  244. return ret; /* We will return NULL if no valid payload */
  245. return NULL;
  246. }
  247. int isEventNotDuplicate(CyEvent_t *CyEvent, unsigned char flagMask)
  248. {
  249. int i;
  250. int ret = true;
  251. CyEvent_t *cur;
  252. FUNC_IN();
  253. read_lock(&cyev_list_rwlock);
  254. for(i = 0; i < CYEV_MAX_EVENT; i++)
  255. {
  256. cur = &(cyev_eventList[i].payload);
  257. /* The event must be valid to be treated as unique, else invalid event are ignored */
  258. if ( (cyev_eventList[i].valid == VALID) &&
  259. (cyev_eventList[i].unique == true) )
  260. {
  261. if ( (cur->type == CyEvent->type) &&
  262. ((cyev_eventList[i].payload.flags & flagMask) == (CyEvent->flags & flagMask)) )
  263. {
  264. ret = false;
  265. goto exit;
  266. }
  267. }
  268. }
  269. exit:
  270. read_unlock(&cyev_list_rwlock);
  271. FUNC_OUTR(ret);
  272. return ret;
  273. }
  274. int CyEv_AddNewEvent(CyEvent_t *CyEvent, char wantRepeat, char wantUnique, unsigned char flagMask)
  275. {
  276. /* Search for the first "invalid" event, then put the given CyEvent in it. */
  277. /* If no slot is valid, return an error */
  278. int i;
  279. int ret = -EIO; /* TODO: find a better error code.*/
  280. FUNC_IN();
  281. /* If wantUnique, first check that there is not another unique event */
  282. if ((wantUnique) && !isEventNotDuplicate(CyEvent, flagMask))
  283. goto exit;
  284. write_lock(&cyev_list_rwlock);
  285. /* Scan the list starting from the last position stored */
  286. for(i = listPos; i < (CYEV_MAX_EVENT + listPos); i++)
  287. {
  288. /* Stop on the first "INVALID" event */
  289. if (cyev_eventList[i].valid == INVALID)
  290. {
  291. /* Store the event */
  292. memcpy(&(cyev_eventList[i].payload), CyEvent, sizeof(CyEvent_t));
  293. /* Force version in the structure */
  294. cyev_eventList[i].payload.version = CYEV_CURRENT_VERSION;
  295. cyev_eventList[i].valid = VALID;
  296. cyev_eventList[i].seen = false;
  297. cyev_eventList[i].repeat = false;
  298. if (wantUnique)
  299. cyev_eventList[i].unique = true;
  300. else
  301. cyev_eventList[i].unique = false;
  302. if (wantRepeat)
  303. {
  304. atomic_inc(&waitingRepeat);
  305. cyev_eventList[i].wantRepeat = true;
  306. cyev_eventList[i].repeatDelay = jiffies + CYEV_REPEAT_DELAY;
  307. }
  308. else
  309. cyev_eventList[i].wantRepeat = false;
  310. if (openingTask)
  311. wake_up_process(openingTask);
  312. ret = 0;
  313. break;
  314. }
  315. }
  316. write_unlock(&cyev_list_rwlock);
  317. exit:
  318. FUNC_OUTR(ret);
  319. return ret;
  320. }
  321. /* Return 0 if event found and updated, or anything else */
  322. /* We could ONLY update event that are declared as unique */
  323. int CyEv_UpdateUniqueEvent(CyEvent_t *CyEvent, char wantRepeat, unsigned char flagMask)
  324. {
  325. int i;
  326. int ret = -1;
  327. FUNC_IN();
  328. /* Search for the event */
  329. write_lock(&cyev_list_rwlock);
  330. for(i = 0; i < CYEV_MAX_EVENT; i++)
  331. {
  332. if ( (cyev_eventList[i].valid == VALID) &&
  333. (cyev_eventList[i].unique == true) &&
  334. ((cyev_eventList[i].payload.flags & flagMask) == (CyEvent->flags & flagMask)) &&
  335. (cyev_eventList[i].payload.type == CyEvent->type) )
  336. { /* Found it ! Now update the fields */
  337. memcpy(&(cyev_eventList[i].payload), CyEvent, sizeof(CyEvent_t));
  338. cyev_eventList[i].seen = false;
  339. if (wantRepeat)
  340. {
  341. cyev_eventList[i].wantRepeat = true;
  342. cyev_eventList[i].repeat = false;
  343. cyev_eventList[i].repeatDelay = jiffies + CYEV_REPEAT_DELAY;
  344. if (cyev_eventList[i].repeat == true)
  345. atomic_inc(&waitingRepeat);
  346. }
  347. else
  348. cyev_eventList[i].wantRepeat = false;
  349. if (openingTask)
  350. wake_up_process(openingTask);
  351. ret = 0;
  352. }
  353. }
  354. write_unlock(&cyev_list_rwlock);
  355. FUNC_OUTR(ret);
  356. return ret;
  357. }
  358. int CyEv_InvalidateUniqueEvent (CyEvent_t *CyEvent)
  359. {
  360. int i;
  361. int ret = -1;
  362. FUNC_IN();
  363. /* Search for the event */
  364. write_lock(&cyev_list_rwlock);
  365. for ( i = 0; i < CYEV_MAX_EVENT; i++ )
  366. {
  367. if ( (cyev_eventList[i].valid == VALID) &&
  368. (cyev_eventList[i].unique == true) &&
  369. (cyev_eventList[i].payload.type == CyEvent->type) )
  370. { /* Found it ! Now update the fields */
  371. INFOL(INFO_DEBUG, ("Found event..."));
  372. cyev_eventList[i].valid = INVALID;
  373. ret = 0;
  374. break;
  375. }
  376. }
  377. write_unlock(&cyev_list_rwlock);
  378. FUNC_OUTR(ret);
  379. return ret;
  380. }
  381. int CyEv_InvalidateRepeatableEvent(CyEvent_t *CyEvent)
  382. {
  383. int i;
  384. int ret = -1;
  385. FUNC_IN();
  386. /* Search for the event */
  387. write_lock(&cyev_list_rwlock);
  388. for(i = 0; i < CYEV_MAX_EVENT; i++)
  389. {
  390. if ( (cyev_eventList[i].valid == VALID) &&
  391. (cyev_eventList[i].wantRepeat == true) &&
  392. (cyev_eventList[i].payload.type == CyEvent->type) )
  393. { /* Found it ! Now update the fields */
  394. INFOL(INFO_DEBUG, ("Found event..."));
  395. /* In case the event has not been eaten, just remove the "repeat want"
  396. ie: do not invalidate it */
  397. cyev_eventList[i].wantRepeat = false;
  398. if (cyev_eventList[i].repeat == true)
  399. {
  400. INFOL(INFO_DEBUG, ("Was repeating..."));
  401. /* set the event "end of repeat" flag */
  402. cyev_eventList[i].payload.flags |= CYEVENT_FLAG_ENDOFREPEAT;
  403. cyev_eventList[i].payload.flags &= ~(CYEVENT_FLAG_REPEATEVENT);
  404. }
  405. else
  406. {
  407. INFOL(INFO_DEBUG, ("Repeat not done... (%d)", atomic_read(&waitingRepeat)));
  408. atomic_dec(&waitingRepeat); /* One less waiting event... */
  409. INFOL(INFO_DEBUG, ("waiting (%d)", atomic_read(&waitingRepeat)));
  410. if (cyev_eventList[i].seen == true)
  411. cyev_eventList[i].valid = INVALID;
  412. }
  413. cyev_eventList[i].seen = false;
  414. cyev_eventList[i].repeat = false;
  415. if (openingTask)
  416. wake_up_process(openingTask);
  417. ret = 0;
  418. break;
  419. }
  420. }
  421. write_unlock(&cyev_list_rwlock);
  422. FUNC_OUTR(ret);
  423. return ret;
  424. }
  425. // ===========================================================================
  426. // ===========================================================================
  427. // External event managment
  428. int CyEvent_PushNewEvent(CyEvent_t *CyEvent, char wantRepeat)
  429. {
  430. int ret = -1;
  431. FUNC_IN();
  432. if (wantRepeat)
  433. ret = CyEv_AddNewEvent(CyEvent, wantRepeat, true, 0);
  434. else
  435. ret = CyEv_AddNewEvent(CyEvent, wantRepeat, false, 0);
  436. FUNC_OUTR(ret);
  437. return ret;
  438. }
  439. EXPORT_SYMBOL(CyEvent_PushNewEvent);
  440. int CyEvent_PushNewUniqueEvent(CyEvent_t *CyEvent)
  441. {
  442. return CyEv_AddNewEvent(CyEvent, false, true, 0);
  443. }
  444. EXPORT_SYMBOL(CyEvent_PushNewUniqueEvent);
  445. int CyEvent_PushOrUpdateUniqueEventFlaged(CyEvent_t *CyEvent, char wantRepeat, unsigned char flagMask)
  446. {
  447. int ret;
  448. FUNC_IN();
  449. /* For now a simple call to AddNewEvent */
  450. ret = CyEv_UpdateUniqueEvent(CyEvent, wantRepeat, flagMask);
  451. if (ret != 0) /* The event is not present */
  452. ret = CyEv_AddNewEvent(CyEvent, wantRepeat, true, flagMask);
  453. FUNC_OUTR(ret);
  454. return ret;
  455. }
  456. EXPORT_SYMBOL(CyEvent_PushOrUpdateUniqueEventFlaged);
  457. int CyEvent_PushOrUpdateUniqueEvent(CyEvent_t *CyEvent, char wantRepeat)
  458. {
  459. int ret;
  460. FUNC_IN();
  461. /* For now a simple call to AddNewEvent */
  462. ret = CyEv_UpdateUniqueEvent(CyEvent, wantRepeat, 0);
  463. if (ret != 0) /* The event is not present */
  464. ret = CyEv_AddNewEvent(CyEvent, wantRepeat, true, 0);
  465. FUNC_OUTR(ret);
  466. return ret;
  467. }
  468. EXPORT_SYMBOL(CyEvent_PushOrUpdateUniqueEvent);
  469. int CyEvent_InvalidateUniqueEvent(CyEvent_t *CyEvent)
  470. {
  471. int ret;
  472. FUNC_IN();
  473. ret = CyEv_InvalidateUniqueEvent(CyEvent);
  474. FUNC_OUTR(ret);
  475. return ret;
  476. }
  477. EXPORT_SYMBOL(CyEvent_InvalidateUniqueEvent);
  478. int CyEvent_InvalidateRepeatableEvent(CyEvent_t *CyEvent)
  479. {
  480. int ret;
  481. FUNC_IN();
  482. ret = CyEv_InvalidateRepeatableEvent(CyEvent);
  483. FUNC_OUTR(ret);
  484. return ret;
  485. }
  486. EXPORT_SYMBOL(CyEvent_InvalidateRepeatableEvent);
  487. // ===========================================================================
  488. static int ev_open(struct inode *inode, struct file *file)
  489. {
  490. FUNC_IN();
  491. /* Clear pending event list... */
  492. CyEv_ClearEventList();
  493. FUNC_OUT();
  494. return 0;
  495. }
  496. // ---------------------------------------------------------------------------
  497. static int ev_release(struct inode *inode, struct file *file)
  498. {
  499. FUNC_IN();
  500. /* Clear pending event list... */
  501. CyEv_ClearEventList();
  502. FUNC_OUT();
  503. return 0;
  504. }
  505. // ---------------------------------------------------------------------------
  506. ssize_t ev_read (struct file *file, char *buf, size_t count, loff_t *ppos)
  507. {
  508. int nBytes = sizeof (CyEvent_t);
  509. int ret = -EIO;
  510. int waitCount;
  511. CyEvent_t CyEvent;
  512. //FUNC_IN();
  513. if ( count < nBytes )
  514. {
  515. ret = -EINVAL;
  516. goto exit;
  517. }
  518. while ( 1 )
  519. {
  520. //printk(KERN_ERR "CyEvent: Check new event...\n");
  521. if ( CyEv_GetNextEvent(&CyEvent) != NULL )
  522. {
  523. break;
  524. }
  525. waitCount = atomic_read(&waitingRepeat);
  526. if (waitCount == 0) /* If there are some waiting event, the list is not empty */
  527. publish_empty_event();
  528. openingTask = current;
  529. set_current_state(TASK_INTERRUPTIBLE);
  530. /* If there are some waiting repeat, schedule with a timeout, or else,
  531. just go out of the schedule queue */
  532. INFOL(INFO_DEBUG, ("Waiting repeat: %d", waitCount));
  533. if ( waitCount > 0 )
  534. schedule_timeout(CYEV_REPEAT_DELAY / 10);
  535. else
  536. schedule();
  537. set_current_state(TASK_RUNNING);
  538. openingTask = 0;
  539. if ( signal_pending(current) )
  540. {
  541. ret = -ERESTARTSYS;
  542. break;
  543. }
  544. }
  545. if ( ret != -ERESTARTSYS )
  546. {
  547. ret = copy_to_user(buf, &CyEvent, nBytes);
  548. if ( !ret )
  549. ret = nBytes;
  550. publish_read_event(CyEvent.type);
  551. }
  552. exit:
  553. //FUNC_OUTR(ret);
  554. return ret;
  555. }
  556. // ---------------------------------------------------------------------------
  557. static int ev_ioctl(struct inode *inode, struct file *file,
  558. unsigned int cmd, unsigned long arg)
  559. {
  560. int ret = -EINVAL;
  561. unsigned long value;
  562. int i;
  563. FUNC_IN();
  564. switch(cmd)
  565. {
  566. default:
  567. for (i = 0; i < CYEV_MAX_DEV; i++ )
  568. {
  569. if ((DevList[i] != NULL) && (DevList[i]->ioctl != NULL))
  570. {
  571. if (GET_IOCTL_PREFIX(cmd) == DevList[i]->ioctl_prefix)
  572. {
  573. ret = DevList[i]->ioctl(cmd, arg);
  574. /* if the ioctl called didn't return 0, try to see if there is
  575. someone else for this one */
  576. if (ret == 0)
  577. break;
  578. }
  579. }
  580. }
  581. printk(KERN_ERR "Bad IOCTL\n");
  582. break;
  583. }
  584. FUNC_OUT();
  585. return ret;
  586. }
  587. // =============================================================================
  588. int CyEvent_RegisterDevice(cyevent_device *dev)
  589. {
  590. int i;
  591. for (i = 0; i < CYEV_MAX_DEV; i++ )
  592. {
  593. if (DevList[i] == NULL)
  594. {
  595. DevList[i] = dev;
  596. return 0;
  597. }
  598. }
  599. return -1; /* Too many devices... */
  600. }
  601. // -----------------------------------------------------------------------------
  602. int CyEvent_DeregisterDevice(cyevent_device *dev)
  603. {
  604. int i;
  605. for (i = 0; i < CYEV_MAX_DEV; i++ )
  606. {
  607. if (DevList[i] == dev)
  608. {
  609. DevList[i] = NULL;
  610. return 0;
  611. }
  612. }
  613. return -1; /* Not found...*/
  614. }
  615. // -----------------------------------------------------------------------------
  616. static void publish_read_event(unsigned char type)
  617. {
  618. int i;
  619. for (i = 0; i < CYEV_MAX_DEV; i++ )
  620. {
  621. if ((DevList[i] != NULL) && (DevList[i]->event_read != NULL))
  622. {
  623. if ((DevList[i]->event_read_listen == 0) || (type == DevList[i]->event_read_listen))
  624. DevList[i]->event_read(type);
  625. }
  626. }
  627. }
  628. // -----------------------------------------------------------------------------
  629. static void publish_empty_event(void)
  630. {
  631. int i;
  632. for (i = 0; i < CYEV_MAX_DEV; i++ )
  633. {
  634. if ((DevList[i] != NULL) && (DevList[i]->event_listempty != NULL))
  635. {
  636. DevList[i]->event_listempty();
  637. }
  638. }
  639. }
  640. // =============================================================================
  641. static struct file_operations s_ev_fops =
  642. {
  643. owner: THIS_MODULE,
  644. read: ev_read,
  645. ioctl: ev_ioctl,
  646. open: ev_open,
  647. release: ev_release,
  648. };
  649. static struct miscdevice s_ev_dev =
  650. {
  651. .minor = 250,
  652. .name = "cyio",
  653. .fops = &s_ev_fops,
  654. };
  655. // ===========================================================================
  656. // ---------------------------------------------------------------------------
  657. static int ev_probe(struct platform_device *dev)
  658. {
  659. FUNC_IN();
  660. FUNC_OUT();
  661. return 0;
  662. }
  663. // ---------------------------------------------------------------------------
  664. static int ev_remove(struct platform_device *dev)
  665. {
  666. FUNC_IN();
  667. misc_deregister(&s_ev_dev);
  668. FUNC_OUT();
  669. return 0;
  670. }
  671. // --------------------------------------------------------------------------
  672. static int ev_suspend(struct platform_device *dev)
  673. {
  674. FUNC_IN();
  675. FUNC_OUT();
  676. return 0;
  677. }
  678. // --------------------------------------------------------------------------
  679. static int ev_resume(struct platform_device *dev)
  680. {
  681. FUNC_IN();
  682. FUNC_OUT();
  683. return 0;
  684. }
  685. // ---------------------------------------------------------------------------
  686. static struct platform_driver cyev_driver =
  687. {
  688. .driver =
  689. {
  690. .name = "cyevent",
  691. .owner = THIS_MODULE,
  692. },
  693. .probe = ev_probe,
  694. .remove = ev_remove,
  695. .suspend = NULL, //ev_suspend,
  696. .resume = ev_resume,
  697. };
  698. // ---------------------------------------------------------------------------
  699. // ===========================================================================
  700. static int __init cyEv_init(void)
  701. {
  702. FUNC_IN();
  703. if (misc_register(&s_ev_dev))
  704. return -EBUSY;
  705. platform_driver_register(&cyev_driver);
  706. FUNC_OUT();
  707. return 0;
  708. }
  709. // ---------------------------------------------------------------------------
  710. static void __exit cyEv_exit(void)
  711. {
  712. FUNC_IN();
  713. platform_driver_unregister(&cyev_driver);
  714. misc_deregister(&s_ev_dev);
  715. FUNC_OUT();
  716. }
  717. // ---------------------------------------------------------------------------
  718. module_init(cyEv_init);
  719. module_exit(cyEv_exit);
  720. // ---------------------------------------------------------------------------
  721. MODULE_LICENSE("GPL");
  722. MODULE_AUTHOR("Bookeen <developers@bookeen.com>");
  723. MODULE_DESCRIPTION("Cybook Event Manager");
  724. MODULE_VERSION("3.0");
  725. // ===========================================================================