cyio.c 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193
  1. // ===========================================================================
  2. // cyio.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 <cybook.h>
  17. #include <linux/cyio.h>
  18. #define CYIO_TIMER
  19. //#define CYIO_REPEAT
  20. //#define CYIO_POLLING
  21. //#define CYIO_ALTERNATE_KEY
  22. //#define DEBUG_MESSAGES
  23. //#define DBG_IRQ
  24. #include <asm/hardware.h>
  25. #include <asm/delay.h>
  26. #include <asm/uaccess.h>
  27. #include <asm-arm/irq.h>
  28. #include <asm/arch/gpio.h>
  29. #include <asm/arch/regs-gpio.h>
  30. #include <asm/arch/regs-irq.h>
  31. #include <asm-arm/arch-s3c2410/irqs.h>
  32. #include <asm-arm/arch-s3c2410/gpio.h>
  33. #include <linux/irq.h>
  34. #include <linux/platform_device.h>
  35. // ===========================================================================
  36. spinlock_t io_lock = SPIN_LOCK_UNLOCKED;
  37. static unsigned long io_status = 0;
  38. struct task_struct *ptsk = 0;
  39. #ifdef CYIO_POLLING
  40. #define GPROCFS_ROOTFOLDER "cybook"
  41. #define GPROCFS_MODULEFOLDER "gsensor"
  42. #define GPROCFS_CALIBFILE "calibration"
  43. #define GPROCFS_IOFILE "io"
  44. #define GPROCFS_STATUSFILE "status"
  45. #define GPROCFS_AXISFILE "axis"
  46. #define GPROCFS_THDXFILE "thdx"
  47. #define GPROCFS_THDYFILE "thdy"
  48. #define GPROCFS_DIRECTIONFILE "direction"
  49. #define GPROCFS_DEBUGFILE "debug"
  50. unsigned long tiltRotation;
  51. static struct proc_dir_entry *rootDir, *ioProcEntry;
  52. #endif
  53. #ifdef CYIO_TIMER
  54. #define IO_TIMER_DELAY_1 ((HZ * 1) / 2) /* 500 ms */
  55. #define IO_TIMER_DELAY_2 ((HZ * 2) / 1) /* 2 s */
  56. #define IO_TIMER_DELAY_3 ((HZ * 1) / 1) /* 1 s */
  57. static struct timer_list io_timer;
  58. #ifdef CYIO_POLLING
  59. static struct timer_list io_btn_timer;
  60. #endif
  61. static int timer_inited = 0;
  62. static int timer_run = 0;
  63. #endif
  64. static volatile int CyIO_Running = 0;
  65. #define TRUE (1==1)
  66. #define FALSE (0==1)
  67. #define PFX "CyIO:"
  68. typedef struct _cyIrq_
  69. {
  70. int nIrq;
  71. u32 nGpio;
  72. u8 bActive;
  73. u8 bKeyIrq; // IRQ generated by a key?
  74. u8 bIsAltKey;
  75. u8 nCodeActive; // All interrupts generate a code when active
  76. u8 nCodeInactive; // Some interrupts generate a code when inactive
  77. u8 nCodeAlternate;
  78. char* sName;
  79. } cyIrq;
  80. #ifdef CYIO_POLLING
  81. typedef struct _cyPoll_
  82. {
  83. u32 nGpio;
  84. u8 oldState;
  85. u8 nCodeActive;
  86. u8 nCodeInactive;
  87. char *sName;
  88. } cyPoll;
  89. #endif
  90. typedef struct _cyEvent_
  91. {
  92. u8 nCode;
  93. u8 nKeyEvent;
  94. u8 bValid;
  95. void* pNext;
  96. } cyEvent;
  97. static cyEvent s_nEvents[20];
  98. static int s_nEventMax = sizeof(s_nEvents)/sizeof(s_nEvents[0]);
  99. static int s_nEventCnt = 0;
  100. static int s_nKeyLogMax = 1;
  101. static int s_nKeyLogCnt = 0;
  102. static cyEvent* s_pEventR = 0;
  103. static cyEvent* s_pEventW = 0;
  104. #ifdef CYIO_REPEAT
  105. static u8 s_nPrevKey = 0;
  106. static u8 s_bRepMode = 0;
  107. #endif
  108. #ifdef CYIO_ALTERNATE_KEY
  109. static u8 s_altKeyPress = 0;
  110. static u32 s_altKeyGpio = 0;
  111. static u8 s_altKeyPresent = FALSE; /* By default we don't have a Alt Key */
  112. #endif
  113. #define GPIO_F0 S3C2410_GPF0
  114. #define GPIO_F1 S3C2410_GPF1
  115. #define GPIO_F2 S3C2410_GPF2
  116. #define GPIO_F3 S3C2410_GPF3
  117. #define GPIO_F4 S3C2410_GPF4
  118. #define GPIO_F5 S3C2410_GPF5
  119. #define GPIO_F6 S3C2410_GPF6
  120. #define GPIO_F7 S3C2410_GPF7
  121. #define GPIO_F8 S3C2410_GPF8
  122. #define GPIO_F9 S3C2410_GPF9
  123. #define GPIO_F10 S3C2410_GPF10
  124. #define GPIO_G0 S3C2410_GPG0
  125. #define GPIO_G1 S3C2410_GPG1
  126. #define GPIO_G2 S3C2410_GPG2
  127. #define GPIO_G3 S3C2410_GPG3
  128. #define GPIO_G4 S3C2410_GPG4
  129. #define GPIO_G5 S3C2410_GPG5
  130. #define GPIO_G6 S3C2410_GPG6
  131. #define GPIO_G7 S3C2410_GPG7
  132. #define GPIO_G8 S3C2410_GPG8
  133. #define GPIO_G9 S3C2410_GPG9
  134. #define GPIO_D10 S3C2410_GPD10
  135. #define GPIO_D11 S3C2410_GPD11
  136. #define GPIO_D14 S3C2410_GPD14
  137. #define GPIO_H4 S3C2410_GPH4
  138. #define GPIO_H5 S3C2410_GPH5
  139. static cyIrq *s_nIrq ;
  140. static int nCnt;
  141. #ifdef CYIO_POLLING
  142. static int nPCnt;
  143. static cyPoll *s_nPio;
  144. #endif
  145. static cyIrq s_nIrq_GEN4[] =
  146. { /* Event structure for the Cybook Gen3 (2440) */
  147. /* IRQ GPIO A B C Depress Event Release Event Alt Event Name Number */
  148. { IRQ_EINT0, GPIO_F0, 0, 1, 0, CYEVENT_KEY_OFF, 0, 0, "PowerBtn" } //0
  149. , { IRQ_EINT7, GPIO_F7, 0, 1, 0, CYEVENT_KEY_DOWN, 0, 0, "Down" } //1
  150. , { IRQ_EINT15, GPIO_G7, 0, 1, 0, CYEVENT_KEY_UP, 0, 0, "Up" } //2
  151. , { IRQ_EINT8, GPIO_G0, 0, 1, 0, CYEVENT_KEY_LEFT, 0, 0, "Left" } //3
  152. , { IRQ_EINT10, GPIO_G2, 0, 1, 0, CYEVENT_KEY_RIGHT, 0, 0, "Right" } //4
  153. , { IRQ_EINT14, GPIO_G6, 0, 1, 0, CYEVENT_KEY_ENTER, 0, 0, "Center" } //5
  154. , { IRQ_EINT9, GPIO_G1, 0, 0, 0, CYEVENT_USB_OUT, CYEVENT_USB_IN, 0, "USB" } //6
  155. /* IRQ GPIO A B C Depress Event Release Event Alt Event Name Number */
  156. /* A:Reserved (must be 0) - B: Is Keypress Event? (or Allow Repeat?) (1: Yes, 0: No) - C: Is Alt Key? (1: Yes 0: No) */
  157. };
  158. #ifdef CYIO_POLLING
  159. static cyPoll s_nPoll_GEN4[] =
  160. {
  161. /* GPIO, Must 0 Depress Event, Release Event Name */
  162. // { GPIO_H4, 0, CYEVENT_KEY_LEFT, 0, "Left" }
  163. //, { GPIO_H5, 0, CYEVENT_KEY_RIGHT, 0, "Right" }
  164. //, { GPIO_D14, 0, CYEVENT_KEY_ENTER, 0, "Enter" }
  165. /* GPIO, Must 0 Depress Event, Release Event, Name */
  166. };
  167. #endif
  168. static u8* s_pbUsbPowered = NULL;
  169. static u8* s_pbPowerOff = NULL;
  170. static u8* s_pbVolMinus = NULL;
  171. static irqreturn_t io_interrupt(int irq, void *dev_id);
  172. #ifdef CYIO_TIMER
  173. static void io_timer_handler(unsigned long nData);
  174. #ifdef CYIO_POLLING
  175. static void io_btn_timer_handler(unsigned long nData);
  176. #endif
  177. #endif
  178. #ifdef CYIO_POLLING
  179. static int procReadIo (char *page, char **start, off_t off, int count,
  180. int *eof, void *data);
  181. static int procWriteIo (struct file *file, const char *buffer,
  182. unsigned long count, void *data);
  183. #endif
  184. #undef MSG
  185. #undef DBG
  186. #ifdef DEBUG_MESSAGES
  187. #define MSG(str) { printk(KERN_ALERT str "\n"); }
  188. #define DBG(str, ...) { printk(KERN_ALERT str "\n", __VA_ARGS__); }
  189. #else
  190. #define MSG(str)
  191. #define DBG(str, ...)
  192. #endif
  193. //#define DEBUG_SPINLOCK
  194. #ifdef DEBUG_SPINLOCK
  195. #define spinLock(spin) {\
  196. printk(KERN_ALERT ")))))))))))) (%s:%d) Wait for %p\n", __func__, __LINE__, spin);\
  197. spin_lock(spin); \
  198. printk(KERN_ALERT ")))))))))))) (%s:%d) Gain %p\n", __func__, __LINE__, spin);\
  199. }
  200. #define spinUnlock(spin) {\
  201. printk(KERN_ALERT ")))))))))))) (%s:%d) Free %p\n", __func__, __LINE__, spin);\
  202. spin_unlock(spin);\
  203. }
  204. #else
  205. #define spinLock(spin) spin_lock(spin)
  206. #define spinUnlock(spin) spin_unlock(spin)
  207. #endif
  208. /* Allow other modules/driver to push cyio event */
  209. int Cyio_PushEvent(char eventId, char unique)
  210. {
  211. cyEvent *pEventC;
  212. int ret = 0;
  213. spinLock(&io_lock);
  214. /* CyIO is not running, ie no one take it, so don't accept events */
  215. if (CyIO_Running == 0)
  216. {
  217. spinUnlock(&io_lock);
  218. return -1;
  219. }
  220. if (unique != 0)
  221. {
  222. pEventC = s_pEventR;
  223. do
  224. {
  225. if (pEventC->nCode == eventId)
  226. {
  227. ret = -EEXIST;
  228. goto exit;
  229. }
  230. pEventC = pEventC->pNext;
  231. } while ((pEventC != s_pEventW) && (s_pEventR != s_pEventW));
  232. }
  233. DBG("New Pushed event '%c'\n", eventId>8);
  234. if (s_pEventW)
  235. {
  236. ++s_nEventCnt;
  237. s_pEventW->nCode = eventId;
  238. s_pEventW->nKeyEvent = 0;
  239. s_pEventW->bValid = 1;
  240. s_pEventW = s_pEventW->pNext;
  241. }
  242. spinUnlock(&io_lock);
  243. ret = 0;
  244. exit:
  245. if (ptsk)
  246. wake_up_process(ptsk);
  247. return ret;
  248. }
  249. EXPORT_SYMBOL(Cyio_PushEvent);
  250. #ifdef CYIO_TIMER
  251. /* Allow other module/driver to reset the timer event */
  252. void Cyio_ResetTimer(void)
  253. {
  254. if (timer_inited == 0)
  255. return;
  256. if (timer_run == 0)
  257. return;
  258. #ifndef ALTERNATE_TIMER_CHANGE
  259. del_timer(&io_timer);
  260. if (io_timer.data == CYEVENT_SUSPEND_SCREEN)
  261. {
  262. io_timer.expires = IO_TIMER_DELAY_1;
  263. }
  264. else //if (io_timer.data == CYEVENT_SUSPEND_DEVICE)
  265. {
  266. io_timer.expires = IO_TIMER_DELAY_2 - IO_TIMER_DELAY_1;
  267. }
  268. io_timer.expires += jiffies;
  269. add_timer(&io_timer);
  270. timer_run = 1;
  271. #else
  272. //io_timer.expires += IO_TIMER_DELAY_3;
  273. mod_timer(&io_timer, IO_TIMER_DELAY_3 + io_timer.expires);
  274. #endif
  275. }
  276. EXPORT_SYMBOL(Cyio_ResetTimer);
  277. #endif /* CYIO_TIMER */
  278. // ===========================================================================
  279. void io_initEventList(void)
  280. {
  281. int i;
  282. s_pEventR = 0;
  283. s_nEventCnt = 0;
  284. s_nKeyLogCnt = 0;
  285. for (i=0; i<s_nEventMax; ++i)
  286. {
  287. cyEvent* pEvent = &s_nEvents[i];
  288. pEvent->nCode = 0;
  289. pEvent->nKeyEvent = 0;
  290. pEvent->bValid = 0;
  291. if (s_pEventR)
  292. s_pEventR->pNext = pEvent;
  293. s_pEventR = pEvent;
  294. }
  295. s_pEventR = &s_nEvents[0];
  296. s_nEvents[s_nEventMax-1].pNext = s_pEventR;
  297. s_pEventW = s_pEventR;
  298. #ifdef CYIO_REPEAT
  299. s_nPrevKey = 0;
  300. s_bRepMode = 0;
  301. #endif
  302. }
  303. // ---------------------------------------------------------------------------
  304. u8 io_factoryPowerOff(void)
  305. {
  306. return (s_pbPowerOff &&
  307. s_pbVolMinus &&
  308. (*s_pbPowerOff) &&
  309. (*s_pbVolMinus))
  310. ? 1
  311. : 0;
  312. }
  313. // ---------------------------------------------------------------------------
  314. void io_initIrq(void)
  315. {
  316. int i;
  317. cyIrq *pIrq, *pIrq0;
  318. int ret;
  319. #ifdef CYIO_POLLING
  320. cyPoll *pPoll, *pPoll0;
  321. pPoll0 = &s_nPio[0];
  322. #endif
  323. pIrq0 = &s_nIrq[0];
  324. DBG(">>%s()\n", __func__);
  325. #ifdef CYIO_POLLING
  326. tiltRotation = 90;
  327. for (i=0, pPoll=pPoll0; i<nPCnt; ++i, ++pPoll)
  328. {
  329. s3c2410_gpio_cfgpin(pPoll->nGpio, 0);
  330. s3c2410_gpio_pullup(pPoll->nGpio, 0);
  331. }
  332. s3c2410_gpio_cfgpin(GPIO_D10, 0);
  333. s3c2410_gpio_pullup(GPIO_D10, 0);
  334. s3c2410_gpio_cfgpin(GPIO_D11, 0);
  335. s3c2410_gpio_pullup(GPIO_D11, 0);
  336. #endif
  337. // Read state as fast as possible (important when resuming)
  338. for (i=0, pIrq=pIrq0; i<nCnt; ++i, ++pIrq)
  339. {
  340. #if 1
  341. pIrq->bActive = !gpio_get_value(pIrq->nGpio);
  342. #else
  343. int j, nUp = 0;
  344. for (j=0; j<4; ++j)
  345. if (gpio_get_value(pIrq->nGpio))
  346. ++nUp;
  347. pIrq->bActive = (nUp < 2);
  348. #endif
  349. }
  350. // Preparatory pass
  351. for (i=0, pIrq=pIrq0; i<nCnt; ++i, ++pIrq)
  352. {
  353. switch (pIrq->nCodeActive)
  354. {
  355. case CYEVENT_USB_IN:
  356. case CYEVENT_USB_OUT:
  357. s_pbUsbPowered = &pIrq->bActive;
  358. break;
  359. case CYEVENT_AC_IN:
  360. break;
  361. case CYEVENT_KEY_OFF:
  362. s_pbPowerOff = &pIrq->bActive;
  363. break;
  364. case CYEVENT_KEY_VOLN:
  365. s_pbVolMinus = &pIrq->bActive;
  366. break;
  367. }
  368. #ifdef CYIO_ALTERNATE_KEY
  369. if (pIrq->bIsAltKey)
  370. { /* If this event is configured as the Alt key, just fill the needed variables */
  371. DBG("Found Alt key as '%s'\n", pIrq->sName);
  372. s_altKeyPresent = TRUE;
  373. s_altKeyGpio = pIrq->nGpio;
  374. }
  375. #endif
  376. }
  377. if (io_factoryPowerOff())
  378. { // Special case
  379. spinLock(&io_lock);
  380. if (s_pEventW)
  381. {
  382. ++s_nEventCnt;
  383. ++s_nKeyLogCnt;
  384. s_pEventW->nCode = CYEVENT_FACTORY_OFF;
  385. s_pEventW->nKeyEvent = 1;
  386. s_pEventW->bValid = 0;
  387. s_pEventW = s_pEventW->pNext;
  388. }
  389. spinUnlock(&io_lock);
  390. }
  391. else
  392. { // Register events as if they had just occurred (esp. when resuming)
  393. spinLock(&io_lock);
  394. for (i=0, pIrq=pIrq0; i<nCnt; ++i, ++pIrq)
  395. {
  396. if (!pIrq->bActive && pIrq->bKeyIrq)
  397. continue;
  398. if ((s_nEventMax <= s_nEventCnt) ||
  399. (pIrq->bKeyIrq && s_nKeyLogMax <= s_nKeyLogCnt))
  400. {
  401. //break;
  402. // !!! BUGBUG (we might miss system events once a key event is queued)
  403. continue;
  404. }
  405. if (s_pEventW)
  406. {
  407. ++s_nEventCnt;
  408. if (pIrq->bKeyIrq)
  409. ++s_nKeyLogCnt;
  410. s_pEventW->nCode = pIrq->bActive ? pIrq->nCodeActive : pIrq->nCodeInactive;
  411. s_pEventW->nKeyEvent = pIrq->bKeyIrq;
  412. s_pEventW->bValid = 0;
  413. s_pEventW = s_pEventW->pNext;
  414. }
  415. }
  416. spinUnlock(&io_lock);
  417. }
  418. for (i=0, pIrq=pIrq0; i<nCnt; ++i, ++pIrq)
  419. {
  420. int nIrq = pIrq->nIrq;
  421. set_irq_type(nIrq, IRQT_BOTHEDGE);
  422. /* Set no Pullup and no Pulldown */
  423. s3c2410_gpio_pullup(pIrq->nGpio, 0);
  424. DBG(".. io_initIrq [%s][%c] bActive[%d]", pIrq->sName, pIrq->bActive || !pIrq->nCodeInactive ? (char)pIrq->nCodeActive : (char)pIrq->nCodeInactive, pIrq->bActive);
  425. ret = request_irq(nIrq, io_interrupt, SA_INTERRUPT|SA_SHIRQ, pIrq->sName, pIrq);
  426. enable_irq_wake(nIrq);
  427. if (ret != 0)
  428. {
  429. printk(KERN_ERR PFX "Error registering IRQ %d [%s]!\n", nIrq, pIrq->sName);
  430. }
  431. }
  432. #ifdef CYIO_TIMER
  433. init_timer(&io_timer);
  434. timer_inited = 1;
  435. io_timer.function = io_timer_handler;
  436. io_timer.data = CYEVENT_SUSPEND_SCREEN;
  437. #ifdef CYIO_POLLING
  438. init_timer(&io_btn_timer);
  439. io_btn_timer.function = io_btn_timer_handler;
  440. io_btn_timer.expires = jiffies + HZ/8;
  441. add_timer(&io_btn_timer);
  442. #endif
  443. #endif
  444. spinLock(&io_lock);
  445. CyIO_Running = 1;
  446. spinUnlock(&io_lock);
  447. }
  448. // ---------------------------------------------------------------------------
  449. void io_deinitIrq(void)
  450. {
  451. int i;
  452. cyIrq *pIrq, *pIrq0;
  453. spinLock(&io_lock);
  454. CyIO_Running = 0;
  455. spinUnlock(&io_lock);
  456. #ifdef CYIO_TIMER
  457. del_timer(&io_timer);
  458. timer_run = 0;
  459. # ifdef CYIO_POLLING
  460. del_timer(&io_btn_timer);
  461. # endif
  462. #endif
  463. //nCnt = sizeof(s_nIrq)/sizeof(s_nIrq[0]);
  464. pIrq0 = &s_nIrq[0];
  465. for (i=0, pIrq=pIrq0; i<nCnt; ++i, ++pIrq)
  466. {
  467. disable_irq_wake(pIrq->nIrq);
  468. free_irq(pIrq->nIrq, pIrq);
  469. }
  470. }
  471. // ---------------------------------------------------------------------------
  472. static irqreturn_t io_interrupt(int irq, void *dev_id)
  473. {
  474. cyIrq* pIrq = (cyIrq*)dev_id;
  475. u8 bActive;
  476. u8 blCodeActive;
  477. unsigned long flags;
  478. spinlock_t lock = SPIN_LOCK_UNLOCKED;
  479. #ifdef CYIO_ALTERNATE_KEY
  480. static int bAltKeyUsed = FALSE;
  481. #endif
  482. #ifdef DBG_IRQ
  483. static int s_nIrq_dbg = 0;
  484. ++s_nIrq_dbg;
  485. #endif
  486. spin_lock_irqsave(&lock, flags);
  487. { // Avoid bounces
  488. int i, nUp = 0;
  489. for (i=0; i<10000; ++i)
  490. if (gpio_get_value(pIrq->nGpio))
  491. ++nUp;
  492. bActive = (nUp < 5000);
  493. }
  494. spin_unlock_irqrestore(&lock, flags);
  495. if (pIrq->bActive == bActive)
  496. return IRQ_HANDLED;
  497. #ifdef DBG_IRQ
  498. #ifdef CYIO_ALTERNATE_KEY
  499. DBG(".. io_irq #%d [%s][%c] alt[%d:%d] bActive[%d]", s_nIrq_dbg, pIrq->sName, bActive || !pIrq->nCodeInactive ? (char)pIrq->nCodeActive : (char)pIrq->nCodeInactive, (s_altKeyPress && pIrq->bKeyIrq) ? pIrq->nCodeAlternate : (bActive ? pIrq->nCodeActive : pIrq->nCodeInactive), s_altKeyPress, bActive);
  500. #else
  501. DBG(".. io_irq #%d [%s][%c] bActive[%d]", s_nIrq_dbg, pIrq->sName, bActive || !pIrq->nCodeInactive ? (char)pIrq->nCodeActive : (char)pIrq->nCodeInactive, (bActive ? pIrq->nCodeActive : pIrq->nCodeInactive), bActive);
  502. #endif
  503. #endif
  504. #ifdef CYIO_ALTERNATE_KEY
  505. blCodeActive = (s_altKeyPress && pIrq->bKeyIrq) ? pIrq->nCodeAlternate : (bActive ? pIrq->nCodeActive : pIrq->nCodeInactive);
  506. if (s_altKeyPresent)
  507. {
  508. s_altKeyPress = !gpio_get_value(s_altKeyGpio);
  509. DBG("alt status: %d", s_altKeyPress);
  510. }
  511. #else
  512. blCodeActive = bActive ? pIrq->nCodeActive : pIrq->nCodeInactive;
  513. #endif
  514. spinLock(&io_lock);
  515. pIrq->bActive = bActive;
  516. if (pIrq->bKeyIrq)
  517. {
  518. #ifdef CYIO_REPEAT
  519. DBG("bfr: s_nPrevKey = %d", s_nPrevKey);
  520. if (s_nPrevKey)
  521. {
  522. DBG("s_nPrevKey is != 0 [%d]", s_nPrevKey);
  523. if (!pIrq->bActive /*|| s_nPrevKey != blCodeActive*/)
  524. s_nPrevKey = 0;
  525. DBG("s_nPrevKey == %d (s_bRepMode:%d, pIrq->bActive:%d)", s_nPrevKey, s_bRepMode, pIrq->bActive);
  526. if (s_bRepMode && !s_nPrevKey)
  527. {
  528. MSG("Exit repeat mode...");
  529. s_bRepMode = 0;
  530. if (s_pEventW)
  531. { // NB: This is considered as a system event
  532. ++s_nEventCnt;
  533. s_pEventW->nCode = CYEVENT_KEY_REPEAT_END;
  534. s_pEventW->nKeyEvent = 0;
  535. s_pEventW->bValid = 0;
  536. s_pEventW = s_pEventW->pNext;
  537. }
  538. if (ptsk)
  539. wake_up_process(ptsk);
  540. }
  541. }
  542. #endif
  543. #ifdef CYIO_ALTERNATE_KEY
  544. if ((!pIrq->bActive) && (pIrq->nGpio != s_altKeyGpio))
  545. #else
  546. if (!pIrq->bActive)
  547. #endif
  548. {
  549. spinUnlock(&io_lock);
  550. MSG("Exiting IRQ Handler");
  551. #ifdef CYIO_KERNEL_2_4
  552. return;
  553. #else
  554. return IRQ_HANDLED;
  555. #endif
  556. }
  557. }
  558. spinUnlock(&io_lock);
  559. //#ifdef DBG_IRQ
  560. // DBG(".. io_irq #%d [%s][%c] bActive[%d]", s_nIrq_dbg, pIrq->sName, bActive || !pIrq->nCodeInactive ? (char)pIrq->nCodeActive : (char)pIrq->nCodeInactive, bActive);
  561. //#endif
  562. if (io_factoryPowerOff())
  563. { // Special case
  564. spinLock(&io_lock);
  565. MSG("Request Factory Setting...\n");
  566. if (s_pEventW)
  567. {
  568. ++s_nEventCnt;
  569. ++s_nKeyLogCnt;
  570. s_pEventW->nCode = CYEVENT_FACTORY_OFF;
  571. s_pEventW->nKeyEvent = 1;
  572. s_pEventW->bValid = 0;
  573. s_pEventW = s_pEventW->pNext;
  574. }
  575. spinUnlock(&io_lock);
  576. }
  577. else
  578. {
  579. spinLock(&io_lock);
  580. if ((s_nEventMax <= s_nEventCnt) ||
  581. (pIrq->bKeyIrq && s_nKeyLogMax <= s_nKeyLogCnt))
  582. {
  583. spinUnlock(&io_lock);
  584. DBG("s_nEventMax:%d, s_nEventCnt:%d, s_nKeyLogMax:%d, s_nKeyLogCnt:%d",s_nEventMax,s_nEventCnt,s_nKeyLogMax,s_nKeyLogCnt);
  585. MSG("!!! Event list full !!!");
  586. return IRQ_HANDLED;
  587. }
  588. #ifdef CYIO_ALTERNATE_KEY
  589. if (s_altKeyPresent && bAltKeyUsed && !s_altKeyPress && (pIrq->nGpio == s_altKeyGpio))
  590. { /* If the released key is the Alt Key and it was used as the Alt Key, do not send an event */
  591. MSG("Alt Key released... Do Nothing");
  592. bAltKeyUsed = FALSE;
  593. s_nPrevKey = 0;
  594. spinUnlock(&io_lock);
  595. return IRQ_HANDLED;
  596. }
  597. if (s_altKeyPresent && (pIrq->nGpio == s_altKeyGpio))
  598. { /* If the altKey is pressed, we have to do a little trick: Inverse it's active state */
  599. MSG("Alt key event...");
  600. /* To be sure */
  601. s_nPrevKey = 0;
  602. s_bRepMode = 0;
  603. bActive = !bActive;
  604. }
  605. else if (s_altKeyPresent && s_altKeyPress && pIrq->bKeyIrq)
  606. {/* The event is a keypress and the AltKey is pressed, set our internal value to prevent Alt to send an event */
  607. MSG("Button press with Alt...");
  608. if (pIrq->nCodeAlternate != 0)
  609. bAltKeyUsed = TRUE;
  610. }
  611. MSG("Hum...");
  612. #endif
  613. if (s_pEventW)
  614. {
  615. MSG("Will push another event...");
  616. ++s_nEventCnt;
  617. if (pIrq->bKeyIrq)
  618. ++s_nKeyLogCnt;
  619. #ifdef CYIO_ALTERNATE_KEY
  620. s_pEventW->nCode = (s_altKeyPress && pIrq->bKeyIrq) ? pIrq->nCodeAlternate : (bActive ? pIrq->nCodeActive : pIrq->nCodeInactive);
  621. #else
  622. s_pEventW->nCode = bActive ? pIrq->nCodeActive : pIrq->nCodeInactive;
  623. #endif
  624. s_pEventW->nKeyEvent = pIrq->bKeyIrq;
  625. s_pEventW->bValid = 0;
  626. s_pEventW = s_pEventW->pNext;
  627. }
  628. spinUnlock(&io_lock);
  629. }
  630. if (ptsk)
  631. wake_up_process(ptsk);
  632. return IRQ_HANDLED;
  633. }
  634. // ---------------------------------------------------------------------------
  635. #ifdef CYIO_TIMER
  636. #ifdef CYIO_POLLING
  637. static void io_btn_timer_handler(unsigned long nData)
  638. {
  639. /* read buttons */
  640. cyPoll *pPoll, *pPoll0;
  641. int i;
  642. int curState;
  643. int currentTilt, tE1, tE2;
  644. pPoll0 = &s_nPio[0];
  645. DBG(">>%s()\n", __func__);
  646. for (i=0, pPoll=pPoll0; i<nPCnt; ++i, ++pPoll)
  647. {
  648. curState = !gpio_get_value(pPoll->nGpio);
  649. DBG("|| Btn '%s' [current: %d, old: %d, gpio: %d]\n", pPoll->sName, curState, pPoll->oldState, pPoll->nGpio);
  650. /* If button found pressed, then push event 'bout them */
  651. if (pPoll->oldState != curState)
  652. {
  653. if (curState != 0)
  654. Cyio_PushEvent(pPoll->nCodeActive, 1);
  655. /*else
  656. Cyio_PushEvent(CYEVENT_KEY_REPEAT_END, 1);*/
  657. }
  658. else if (pPoll->oldState != 0)
  659. {
  660. /* Push event with repeat flag */
  661. //Cyio_PushEvent(pPoll->nCodeActive | CYEVENT_KEY_REPEAT_FLAG, 1);
  662. }
  663. pPoll->oldState = curState;
  664. }
  665. /* special case, look at the tilt sensor */
  666. tE1 = !gpio_get_value(GPIO_D11);
  667. tE2 = !gpio_get_value(GPIO_D10);
  668. currentTilt = 0;
  669. if (!tE2)
  670. currentTilt |= 1 << 1;
  671. if (!tE1)
  672. currentTilt |= 1 << 0;
  673. switch(currentTilt)
  674. {
  675. case 0x00: /* 90 */
  676. currentTilt = 90;
  677. break;
  678. case 0x01: /* 0 */
  679. currentTilt = 0;
  680. break;
  681. case 0x02: /* 180 */
  682. currentTilt = 180;
  683. break;
  684. case 0x03: /* 270 */
  685. currentTilt = 270;
  686. break;
  687. }
  688. if (currentTilt != tiltRotation)
  689. { /* We move */
  690. tiltRotation = currentTilt;
  691. printk("New tilt: %d\n", tiltRotation);
  692. Cyio_PushEvent(CYEVENT_ORIENTATIONCHANGED, 1);
  693. }
  694. /* Update the timer */
  695. io_btn_timer.expires = jiffies + HZ/8;
  696. mod_timer(&io_btn_timer, io_btn_timer.expires);
  697. DBG("<<%s()\n", __func__);
  698. }
  699. #endif
  700. static void io_timer_handler(unsigned long nData)
  701. {
  702. DBG("Timer [%ld] tick...\n", nData);
  703. spin_lock_irq(&io_lock);
  704. del_timer(&io_timer);
  705. timer_run = 0;
  706. if (s_nEventCnt < s_nEventMax)
  707. {
  708. if (s_pEventW)
  709. {
  710. ++s_nEventCnt;
  711. s_pEventW->nCode = (u8)nData;
  712. s_pEventW->nKeyEvent = 0;
  713. s_pEventW->bValid = 0;
  714. s_pEventW = s_pEventW->pNext;
  715. }
  716. }
  717. spin_unlock_irq(&io_lock);
  718. if (ptsk)
  719. wake_up_process(ptsk);
  720. //end_timer:
  721. return;
  722. }
  723. #endif
  724. // ===========================================================================
  725. static int io_open(struct inode *inode, struct file *file)
  726. {
  727. //MSG(">> io_open");
  728. //spin_lock_irq(&io_lock);
  729. spinLock(&io_lock);
  730. if (io_status)
  731. {
  732. //spin_unlock_irq(&io_lock);
  733. spinUnlock(&io_lock);
  734. //MSG(".. io_open !!! Busy");
  735. return -EBUSY;
  736. }
  737. io_status = 1;
  738. //spin_unlock_irq(&io_lock);
  739. spinUnlock(&io_lock);
  740. io_initIrq();
  741. return 0;
  742. }
  743. // ---------------------------------------------------------------------------
  744. static int io_release(struct inode *inode, struct file *file)
  745. {
  746. MSG(">> io_release");
  747. io_deinitIrq();
  748. spin_lock_irq(&io_lock);
  749. io_status = 0;
  750. // The driver is likely to be closed & reopened within suspend sequences
  751. // Only initialize the list when registering the driver and when closing it
  752. // This allows for a quicker opening of the driver
  753. io_initEventList();
  754. spin_unlock_irq(&io_lock);
  755. MSG("<< io_release");
  756. return 0;
  757. }
  758. // ---------------------------------------------------------------------------
  759. ssize_t io_read(struct file *file, char *buf, size_t count, loff_t *ppos)
  760. {
  761. int nBytes = sizeof(unsigned long);
  762. unsigned long nData;
  763. ssize_t nRes = 0;
  764. u8 bDataValid = 0;
  765. if (count < sizeof(unsigned long))
  766. return -EINVAL;
  767. while (1)
  768. {
  769. //spin_lock_irq(&io_lock);
  770. spinLock(&io_lock);
  771. nData = 0;
  772. if (s_nEventCnt)
  773. {
  774. nData = s_pEventR->nCode;
  775. bDataValid = s_pEventR->bValid;
  776. s_pEventR->nCode = 0;
  777. --s_nEventCnt;
  778. if (s_pEventR->nKeyEvent)
  779. {
  780. --s_nKeyLogCnt;
  781. #ifdef CYIO_REPEAT
  782. if (nData != CYEVENT_KEY_OFF)
  783. {
  784. s_nPrevKey = nData;
  785. s_bRepMode = 0;
  786. }
  787. #endif
  788. }
  789. s_pEventR = s_pEventR->pNext;
  790. }
  791. #ifdef CYIO_REPEAT
  792. if (!nData && s_nPrevKey)
  793. { // Check new status
  794. int i;
  795. cyIrq *pIrq, *pIrq0;
  796. pIrq0 = &s_nIrq[0];
  797. for (i=0, pIrq=pIrq0; i<nCnt; ++i, ++pIrq)
  798. {
  799. #ifdef CYIO_ALTERNATE_KEY
  800. if ((pIrq->nCodeActive != s_nPrevKey) && (pIrq->nCodeAlternate != s_nPrevKey))
  801. #else
  802. if (pIrq->nCodeActive != s_nPrevKey)
  803. #endif
  804. {
  805. continue;
  806. }
  807. if (!pIrq->bActive || gpio_get_value(pIrq->nGpio))
  808. {
  809. s_nPrevKey = 0;
  810. }
  811. break;
  812. }
  813. if (s_nPrevKey)
  814. {
  815. nData = s_nPrevKey | CYEVENT_KEY_REPEAT_FLAG;
  816. s_bRepMode = 1;
  817. }
  818. }
  819. #endif
  820. spinUnlock(&io_lock);
  821. if ((nData != 0) | (bDataValid == 1))
  822. {
  823. #ifdef CYIO_TIMER
  824. del_timer(&io_timer);
  825. timer_run = 0;
  826. io_timer.data = (nData == CYEVENT_SUSPEND_SCREEN) ? CYEVENT_SUSPEND_DEVICE : CYEVENT_SUSPEND_SCREEN;
  827. #endif
  828. break;
  829. }
  830. #ifdef CYIO_TIMER
  831. if (s_pbUsbPowered && (*s_pbUsbPowered))
  832. {
  833. del_timer(&io_timer);
  834. timer_run = 0;
  835. if (io_timer.data == CYEVENT_SUSPEND_SCREEN)
  836. {
  837. io_timer.expires = IO_TIMER_DELAY_1;
  838. io_timer.expires += jiffies;
  839. add_timer(&io_timer);
  840. }
  841. else //if (io_timer.data == CYEVENT_SUSPEND_DEVICE)
  842. {
  843. io_timer.expires = IO_TIMER_DELAY_2 - IO_TIMER_DELAY_1;
  844. io_timer.expires += jiffies;
  845. add_timer(&io_timer);
  846. }
  847. timer_run = 1;
  848. }
  849. #endif
  850. ptsk = current;
  851. set_current_state(TASK_INTERRUPTIBLE);
  852. schedule();
  853. set_current_state(TASK_RUNNING);
  854. ptsk = 0;
  855. if (signal_pending(current))
  856. {
  857. nRes = -ERESTARTSYS;
  858. break;
  859. }
  860. }
  861. if ((nData != 0) | (bDataValid == 1))
  862. {
  863. nRes = copy_to_user(buf,&nData,nBytes);
  864. if (!nRes)
  865. nRes = nBytes;
  866. }
  867. return nRes;
  868. }
  869. // ---------------------------------------------------------------------------
  870. static int io_ioctl(struct inode *inode, struct file *file,
  871. unsigned int cmd, unsigned long arg)
  872. {
  873. return -EINVAL;
  874. }
  875. // ===========================================================================
  876. static struct file_operations s_io_fops =
  877. {
  878. owner: THIS_MODULE,
  879. read: io_read,
  880. ioctl: io_ioctl,
  881. open: io_open,
  882. release: io_release,
  883. };
  884. static struct miscdevice s_io_dev =
  885. {
  886. .minor = 250,
  887. .name = "cyio",
  888. .fops = &s_io_fops,
  889. };
  890. // ===========================================================================
  891. // ---------------------------------------------------------------------------
  892. static int io_probe(struct platform_device *dev)
  893. {
  894. return 0;
  895. }
  896. // ---------------------------------------------------------------------------
  897. static int io_remove(struct platform_device *dev)
  898. {
  899. misc_deregister(&s_io_dev);
  900. return 0;
  901. }
  902. // --------------------------------------------------------------------------
  903. static int io_resume(struct platform_device *dev)
  904. {
  905. //cyIrq *pIrq;
  906. //u8 bSdCd;
  907. MSG(">>Resume() .......\n");
  908. #if 0
  909. if ((platform_type == CYBOOK_GEN3) || (platform_type == CYBOOK_GEN3GOLD))
  910. {
  911. pIrq = &s_nIrq[13];
  912. }
  913. else
  914. {
  915. pIrq = &s_nIrq[11];
  916. }
  917. bSdCd = !read_gpio_bit(pIrq->nGpio);
  918. //MSG(">>Resume() .......bSdCd 0x%x\n",bSdCd);
  919. if (pIrq->bActive == bSdCd)
  920. return 0;
  921. spinLock(&io_lock);
  922. pIrq->bActive = bSdCd;
  923. if (s_pEventW)
  924. {
  925. ++s_nEventCnt;
  926. s_pEventW->nCode = pIrq->bActive ? pIrq->nCodeActive : pIrq->nCodeInactive;
  927. s_pEventW->nKeyEvent = pIrq->bKeyIrq;
  928. s_pEventW = s_pEventW->pNext;
  929. }
  930. spinUnlock(&io_lock);
  931. if (ptsk)
  932. wake_up_process(ptsk);
  933. #endif
  934. MSG("<<Resume() .......\n");
  935. return 0;
  936. }
  937. // ---------------------------------------------------------------------------
  938. static struct platform_driver cyio_driver =
  939. {
  940. .driver =
  941. {
  942. .name = "cyio",
  943. .owner = THIS_MODULE,
  944. },
  945. .probe = io_probe,
  946. .remove = io_remove,
  947. .suspend = NULL,
  948. .resume = io_resume,
  949. };
  950. // ---------------------------------------------------------------------------
  951. // ===========================================================================
  952. static int __init cyIo_init(void)
  953. {
  954. #if 0
  955. if(platform_type == CYBOOK_OPUS)
  956. {
  957. s_nIrq = s_nIrq_OPUS;
  958. nCnt = sizeof(s_nIrq_OPUS)/sizeof(s_nIrq_OPUS[0]);
  959. }
  960. else if (/* GEN3 && GEN3GOLD */
  961. {
  962. s_nIrq = s_nIrq_GEN3;
  963. nCnt = sizeof(s_nIrq_GEN3)/sizeof(s_nIrq_GEN3[0]);
  964. }
  965. #endif
  966. s_nIrq = s_nIrq_GEN4;
  967. #ifdef CYIO_POLLING
  968. s_nPio = s_nPoll_GEN4;
  969. nPCnt = sizeof(s_nPoll_GEN4)/sizeof(s_nPoll_GEN4[0]);
  970. #endif
  971. nCnt = sizeof(s_nIrq_GEN4)/sizeof(s_nIrq_GEN4[0]);
  972. DBG("s_nEventMax:%d, s_nEventCnt:%d, s_nKeyLogMax:%d, s_nKeyLogCnt:%d",s_nEventMax,s_nEventCnt,s_nKeyLogMax,s_nKeyLogCnt);
  973. #ifdef CYIO_POLLING
  974. rootDir = proc_mkdir(GPROCFS_MODULEFOLDER, proc_root_driver);
  975. ioProcEntry = create_proc_entry(GPROCFS_IOFILE, 0644, rootDir);
  976. ioProcEntry->read_proc = procReadIo;
  977. ioProcEntry->write_proc = procWriteIo;
  978. ioProcEntry->owner = THIS_MODULE;
  979. #endif
  980. io_initEventList();
  981. if (misc_register(&s_io_dev))
  982. return -EBUSY;
  983. platform_driver_register(&cyio_driver);
  984. return 0;
  985. }
  986. // ---------------------------------------------------------------------------
  987. static void __exit cyIo_exit(void)
  988. {
  989. platform_driver_unregister(&cyio_driver);
  990. misc_deregister(&s_io_dev);
  991. //MSG("<< cyIo_exit");
  992. }
  993. #ifdef CYIO_POLLING
  994. static int procReadIo (char *page, char **start, off_t off, int count,
  995. int *eof, void *data)
  996. {
  997. int len;
  998. char tmp = 0;
  999. //printk("Read IO Tilt [%d]", tiltRotation);
  1000. switch (tiltRotation)
  1001. {
  1002. case 270:
  1003. tmp++;
  1004. case 180:
  1005. tmp++;
  1006. case 90:
  1007. tmp++;
  1008. default:
  1009. break;
  1010. }
  1011. len = sprintf (page, "%02X", tmp);
  1012. DBG("io readed value: %02X", tmp);
  1013. return len;
  1014. }
  1015. static int procWriteIo (struct file *file, const char *buffer,
  1016. unsigned long count, void *data)
  1017. {
  1018. char cmd;
  1019. /* in case of... */
  1020. if ( count < 1 )
  1021. return 0;
  1022. cmd = buffer[0];
  1023. switch(cmd)
  1024. {
  1025. case G_SENSOR_CAL:
  1026. case G_SENSOR_ON:
  1027. case G_SENSOR_OFF:
  1028. case 254:
  1029. break;
  1030. default:
  1031. printk(KERN_ERR "ProcIO: Unknown command '%c'\n",cmd);
  1032. break;
  1033. }
  1034. return count;
  1035. }
  1036. #endif
  1037. // ---------------------------------------------------------------------------
  1038. module_init(cyIo_init);
  1039. module_exit(cyIo_exit);
  1040. // ---------------------------------------------------------------------------
  1041. MODULE_LICENSE("GPL");
  1042. MODULE_AUTHOR("Bookeen <developers@bookeen.com>");
  1043. MODULE_DESCRIPTION("Cybook Event Manager");
  1044. MODULE_VERSION("3.0");
  1045. // ===========================================================================