docker: source checking container
[gnuk/gnuk.git] / src / pin-cir.c
1 /*
2  * pin-cir.c -- PIN input device support (Consumer Infra-Red)
3  *
4  * Copyright (C) 2010, 2011, 2013 Free Software Initiative of Japan
5  * Author: NIIBE Yutaka <gniibe@fsij.org>
6  *
7  * This file is a part of Gnuk, a GnuPG USB Token implementation.
8  *
9  * Gnuk is free software: you can redistribute it and/or modify it
10  * under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * Gnuk is distributed in the hope that it will be useful, but WITHOUT
15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
17  * License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  *
22  */
23
24 #include <stdint.h>
25 #include <string.h>
26 #include <chopstx.h>
27
28 #include "config.h"
29 #include "board.h"
30 #include "gnuk.h"
31 #include "mcu/stm32f103.h"
32
33 #ifdef DEBUG
34 #define DEBUG_CIR 1
35 #endif
36
37 static int
38 cir_ext_disable (void)
39 {
40   int rcvd = (EXTI->PR & EXTI_PR) != 0;
41
42   EXTI->IMR &= ~EXTI_IMR;
43   EXTI->PR = EXTI_PR;
44   return rcvd;
45 }
46
47 static void
48 cir_ext_enable (void)
49 {
50   EXTI->PR = EXTI_PR;
51   EXTI->IMR |= EXTI_IMR;
52 }
53
54 static chopstx_mutex_t cir_input_mtx;
55 static chopstx_cond_t cir_input_cnd;
56 static int input_avail;
57
58 uint8_t pin_input_buffer[MAX_PIN_CHARS];
59 uint8_t pin_input_len;
60
61 /*
62  * Supported/tested TV controllers:
63  *
64  *   Controller of Toshiba REGZA
65  *   Controller of Sony BRAVIA
66  *   Controller of Sharp AQUOS
67  *   Dell Wireless Travel Remote MR425
68  *
69  * The code supports RC-5 protocol in fact, but I don't have any
70  * controller at hand which I can test with, so I don't have any data
71  * for controller of RC-5.
72  *
73  * Current code assumes following mapping:
74  *
75  *  --------------------------------------
76  *    Protocol          Controller
77  *  --------------------------------------
78  *     RC-6               Dell MR425
79  *     NEC                Toshiba REGZA
80  *     Sharp              Sharp AQUOS
81  *     Sony               Sony BRAVIA
82  *  --------------------------------------
83  *
84  * In future, when I will have other controllers, this mapping will be
85  * (should be) configurable, at compile time at least, preferably at
86  * runtime.
87  */
88
89 /*
90  * Philips RC-5 Protocol: 14-bit (MSB first)
91  *
92  * Philips RC-6 Protocol: (START + 1 + MODE + TR + 32-bit / 16-bit) (MSB first)
93  *                                     3-bit      (mode 6 / mode 0)
94  *      Example: Controller of DELL (mode 6)
95  *
96  * NEC Protocol: (START + 32-bit + STOP) + (START + STOP) x N  (LSB first)
97  *      32-bit: 8-bit command inverted + 8-bit command + 16-bit address
98  *      Example: Controller of Toshiba REGZA
99  *      Example: Controller of Ceiling Light by NEC
100  *
101  * Sony Protocol: (START + 12-bit) or (START + 15-bit)  (LSB first)
102  *      12-bit: 5-bit address + 7-bit command
103  *      Example: Controller of Sony BRAVIA
104  *
105  * Sharp Protocol: (START + 48-bit + STOP) x N  (LSB first)
106  *      48-bit: 32-bit address + 12-bit command + 4-bit parity
107  *      Example: Controller of Sharp AQUOS
108  *      Example: Controller of Ceiling Light by Mitsubishi
109  *
110  * Unsupported:
111  *
112  * Unknown Protocol 2: (START + 112-bit + STOP)  (LSB first)
113  *      Example: Controller of Mitsubishi air conditioner
114  *
115  * Unknown Protocol 3: (START + 128-bit + STOP)  (LSB first)
116  *      Example: Controller of Fujitsu air conditioner
117  *
118  * Unknown Protocol 4: (START + 152-bit + STOP)  (LSB first)
119  *      Example: Controller of Sanyo air conditioner
120  *
121  */
122
123 /*
124  * The implementation note of CIR signal decoding (on STM32).
125  *
126  * (1) Use EXTI interrupt to detect the first edge of signal.
127  * (2) Use Timer (with PWM input mode) to measure timings of square wave.
128  *
129  */
130
131 /*
132  * Timer settings.
133  *
134  * See THE reference manual (RM0008) section 15.3.6 PWM input mode.
135  *
136  * 72MHz
137  * Prescaler = 72
138  *
139  * 1us
140  *
141  * TIMx_CR1
142  *  CKD  = 00 (tDTS = tCK_INT)
143  *  ARPE = 1  (buffered)
144  *  CMS  = 00 (up counter)
145  *  DIR  = 0  (up counter)
146  *  OPM  = 0  (up counter)
147  *  URS  = 1  (update request source: overflow only)
148  *  UDIS = 0  (UEV (update event) enabled)
149  *  CEN  = 1  (counter enable)
150  *
151  * TIMx_CR2
152  *  TI1S = 1 (TI1 is XOR of ch1, ch2, ch3)
153  *  MMS  = 000 (TRGO at Reset)
154  *  CCDS = 0 (DMA on capture)
155  *  RSVD = 000
156  *
157  * TIMx_SMCR
158  *  ETP  = 0
159  *  ECE  = 0
160  *  ETPS = 00
161  *  ETF  = 0000
162  *  MSM  = 0
163  *  TS   = 101 (TI1FP1 selected)
164  *  RSVD = 0
165  *  SMS  = 100 (Reset-mode)
166  *
167  * TIMx_DIER
168  *
169  * TIMx_SR
170  *
171  * TIMx_EGR
172  *
173  * TIMx_CCMR1
174  *  CC1S = 01 (TI1 selected)
175  *  CC2S = 10 (TI1 selected)
176  *  IC1F = 1001 (fSAMPLING=fDTS/8, N=8)
177  *  IC2F = 1001 (fSAMPLING=fDTS/8, N=8)
178  *
179  * TIMx_CCMR2
180  *
181  * TIMx_CCER
182  *  CC2P = 1 (polarity = falling edge: TI1FP1)
183  *  CC2E = 1
184  *  CC1P = 0 (polarity = rising edge: TI1FP1)
185  *  CC1E = 1
186  *
187  * TIMx_CNT
188  * TIMx_PSC = 71
189  * TIMx_ARR = 18000
190  *
191  * TIMx_CCR1  period
192  * TIMx_CCR2  duty
193  *
194  * TIMx_DCR
195  * TIMx_DMAR
196  */
197
198 #if defined(DEBUG_CIR)
199 static uint16_t intr_ext;
200 static uint16_t intr_trg;
201 static uint16_t intr_ovf;
202 static uint16_t intr_err;
203
204 #define MAX_CIRINPUT_BIT 512
205 static uint16_t cirinput[MAX_CIRINPUT_BIT];
206 static uint16_t *cirinput_p;
207 #endif
208
209 static uint32_t cir_data;
210 static uint16_t cir_data_more;
211 static uint8_t cir_proto;
212 #define CIR_PROTO_RC5   1
213 #define CIR_PROTO_RC6   2
214 #define CIR_PROTO_OTHER 3
215 #define CIR_PROTO_SONY  4
216 #define CIR_PROTO_NEC   5
217 #define CIR_PROTO_SHARP 6
218
219
220 /* CIR_DATA_ZERO: Used for zero-bit handling of RC-5/RC-6 */
221 static uint8_t cir_data_zero;
222
223 static uint8_t cir_seq;
224
225 static void
226 cir_ll_init (void)
227 {
228   cir_data = 0;
229   cir_seq = 0;
230   /* Don't touch cir_proto here */
231   cir_ext_enable ();
232 }
233
234
235 #define CH_RETURN    0x0d
236 #define CH_BACKSPACE 0x08
237
238 struct codetable {
239   uint16_t cir_code;
240   uint8_t  char_code;
241 };
242
243 /* NOTE: no way to input '0' */
244 static const struct codetable
245 cir_codetable_dell_mr425[] = {
246   {0x10, '7' },          /* Speaker Louder       */
247   {0x11, '8' },          /* Speaker Quieter      */
248   {0x0d, '9' },          /* Speaker Mute         */
249   {0xce, 'a' },          /* Black triangle UP    */
250   {0xcf, 'b' },          /* Black triangle DOWN  */
251   {0x58, 'c' },          /* White triangle UP    */
252   {0x5a, 'd' },          /* White triangle LEFT  */
253   {0x5c, CH_RETURN },    /* Check                */
254   {0x5b, 'e' },          /* White triangle RIGHT */
255   {0xa4, CH_BACKSPACE }, /* Back                 */
256   {0x59, 'f' },          /* White triangle DOWN  */
257   {0x2f, '1' },          /* Rewind               */
258   {0x2c, '2' },          /* Play / Pause         */
259   {0x2e, '3' },          /* Forward              */
260   {0x21, '4' },          /* Skip backward        */
261   {0x31, '5' },          /* Stop                 */
262   {0x20, '6' },          /* Skip forward         */
263
264   {0, 0} /* <<END>>   */
265 };
266
267 #define CIR_ADDR_SHARP_AQUOS 0x028f
268 static const struct codetable
269 cir_codetable_aquos[] = {
270   { 0x0116, ' ' }, /* Power */
271   { 0x025e, '0' }, /* d */
272   { 0x024e, '1' }, /* 1 */
273   { 0x024f, '2' }, /* 2 */
274   { 0x0250, '3' }, /* 3 */
275   { 0x0251, '4' }, /* 4 */
276   { 0x0252, '5' }, /* 5 */
277   { 0x0253, '6' }, /* 6 */
278   { 0x0254, '7' }, /* 7 */
279   { 0x0255, '8' }, /* 8 */
280   { 0x0256, '9' }, /* 9 */
281   { 0x0257, 'a' }, /* 10/0 */
282   { 0x0258, 'b' }, /* 11 */
283   { 0x0259, 'c' }, /* 12 */
284   { 0x0111, 'd' }, /* Ch ^ */
285   { 0x0112, 'e' }, /* Ch v */
286   { 0x0114, 'f' }, /* Vol + */
287   { 0x0115, 'g' }, /* Vol - */
288   { 0x0117, 'h' }, /* Mute */
289   { 0x0280, 'i' }, /* BLUE */
290   { 0x0281, 'j' }, /* RED */
291   { 0x0282, 'k' }, /* GREEN */
292   { 0x0283, 'l' }, /* YELLOW */
293   { 0x011b, 'm' }, /* DISPLAY CONTROL (gamen hyouji) */
294   { 0x01d5, 'n' }, /* DISPLAY SIZE */
295   { 0x0157, 'o' }, /* UP */
296   { 0x01d7, 'p' }, /* LEFT */
297   { 0x01d8, 'q' }, /* RIGHT */
298   { 0x0120, 'r' }, /* DOWN */
299   { 0x0152, CH_RETURN }, /* Commit (kettei) */
300   { 0x01e4, CH_BACKSPACE }, /* Back (modoru) */
301   { 0x01f5, 's' }, /* Quit (shuuryou) */
302   { 0x0b03, 't' }, /* Rewind (hayamodoshi) */
303   { 0x0b01, 'u' }, /* Play (saisei) */
304   { 0x0b04, 'v' }, /* Forward (hayaokuri) */
305   { 0x0b02, 'w' }, /* Stop (teishi) */
306   { 0x028a, 'x' }, /* BS */
307   { 0x028b, 'y' }, /* CS */
308   { 0x025f, 'z' }, /* Program information (bangumi jouhou) */
309   { 0x0260, '\\' }, /* Program table (bangumi hyou) */
310   { 0x0118, '|' }, /* Sound channel (onsei kirikae) */
311   { 0x028e, '[' }, /* Ground Analog (chijou A) */
312   { 0x0289, ']' }, /* Ground Digital (chijou D) */
313
314   { 0x0b07, '\"' }, /* Feature select (kinou sentaku) */
315   { 0x026b, '.' }, /* TV/Radio/Data (terebi/rajio/data) */
316   { 0x025a, ',' }, /* 3 code input (3 keta nyuuryoku) */
317   { 0x0267, ':' }, /* subtitle (jimaku) */
318   { 0x0159, ';' }, /* hold (seishi) */
319
320   { 0x01c4, 'A' }, /* Menu */
321   { 0x011a, 'B' }, /* Off timer */
322   { 0x0121, 'C' }, /* CATV */
323   { 0x0b05, 'D' }, /* Record */
324   { 0x0b06, 'E' }, /* Recording stop */
325   { 0x0113, 'F' }, /* Inputs (nyuuryoku kirikae) */
326   { 0x0275, 'G' }, /* other programs (ura bangumi) */
327   { 0x0266, 'H' }, /* signal control (eizou kirikae) */
328   { 0x01e7, 'I' }, /* AV position */
329   { 0x027f, 'J' }, /* i.LINK */
330   { 0x0b00, 'K' }, /* Recorder power */
331   { 0x028f, 'L' }, /* as you like it (okonomi senkyoku) */
332
333   {0, 0} /* <<END>>   */
334 };
335
336 #define CIR_ADDR_TOSHIBA_REGZA 0xbf40
337 static const struct codetable
338 cir_codetable_regza[] = {
339   { 0x12, ' ' }, /* Power */
340   { 0x14, '0' }, /* d (data) */
341   { 0x01, '1' }, /* 1 */
342   { 0x02, '2' }, /* 2 */
343   { 0x03, '3' }, /* 3 */
344   { 0x04, '4' }, /* 4 */
345   { 0x05, '5' }, /* 5 */
346   { 0x06, '6' }, /* 6 */
347   { 0x07, '7' }, /* 7 */
348   { 0x08, '8' }, /* 8 */
349   { 0x09, '9' }, /* 9 */
350   { 0x0a, 'a' }, /* 10 */
351   { 0x0b, 'b' }, /* 11 */
352   { 0x0c, 'c' }, /* 12 */
353   { 0x1b, 'd' }, /* Ch ^ */
354   { 0x1f, 'e' }, /* Ch v */
355   { 0x1a, 'f' }, /* Vol + */
356   { 0x1e, 'g' }, /* Vol - */
357   { 0x10, 'h' }, /* Mute */
358   { 0x73, 'i' }, /* BLUE */
359   { 0x74, 'j' }, /* RED */
360   { 0x75, 'k' }, /* GREEN */
361   { 0x76, 'l' }, /* YELLOW */
362   { 0x1c, 'm' }, /* Display control */
363   { 0x2b, 'n' }, /* Display size */
364   { 0x3e, 'o' }, /* UP */
365   { 0x5f, 'p' }, /* LEFT */
366   { 0x5b, 'q' }, /* RIGHT */
367   { 0x3f, 'r' }, /* DOWN */
368   { 0x3d, CH_RETURN }, /* Commit (kettei) */
369   { 0x3b, CH_BACKSPACE }, /* Back (modoru) */
370   { 0x3c, 's' }, /* Quit (shuuryou) */
371   { 0x2c, 't' }, /* << (Rewind) */
372   { 0x2d, 'u' }, /* >/|| (Play/Stop) */
373   { 0x2e, 'v' }, /* >> (Forward) */
374   { 0x2b, 'w' }, /* Stop (teishi) */
375   { 0x7c, 'x' }, /* BS */
376   { 0x7d, 'y' }, /* CS */
377   { 0x71, 'z' }, /* Program information (bangumi setsumei) */
378   { 0x77, '\\' }, /* Mini program table (mini bangumihyou) */
379   { 0x13, '|' }, /* Sound (onta kirikae) */
380   { 0x7a, '[' }, /* Ground Digital (chideji) */
381   { 0x7b, ']' }, /* Ground Analog (chiana) */
382
383   { 0xd0, '\"' }, /* Settings Menu (settei menu) */
384   { 0x6d, '.' }, /* Radio/Data (rajio/data) */
385   { 0x60, ',' }, /* CH 10-key input (search) */
386   { 0x52, ':' }, /* subtitle (jimaku) */
387   { 0x50, ';' }, /* hold (seishi) */
388
389   { 0x3a, 'A' }, /* Input- (nyuuryokukirikae-) */
390   { 0x0f, 'B' }, /* Input+ (nyuuryokukirikae+) */
391   { 0x29, 'C' }, /* Two screens (nigamen) */
392   { 0x25, 'D' }, /* Broadband */
393   { 0x27, 'E' }, /* |<< Skip backward */
394   { 0x26, 'F' }, /* >>| Skip forward  */
395   { 0x61, '!' }, /* 1 NHK1 */
396   { 0x62, '@' }, /* 2 NHK2 */
397   { 0x63, '#' }, /* 3 NHKh */
398   { 0x64, '$' }, /* 4 BS Nihon TV */
399   { 0x65, '%' }, /* 5 BS Asahi */
400   { 0x66, '^' }, /* 6 BS-i */
401   { 0x67, '&' }, /* 7 BSJ */
402   { 0x68, '*' }, /* 8 BS Fuji */
403   { 0x69, '(' }, /* 9 WOW */
404   { 0x6a, ')' }, /* 10 Star */
405   { 0x6b, '-' }, /* 11 BS11 */
406   { 0x6c, '+' }, /* 12 TwellV */
407   { 0x27, '=' }, /* Quick (Delete) */
408   { 0x34, '<' }, /* REGZA link */
409   { 0x6e, '>' }, /* Program Table */
410   { 0x20, '/' }, /* ^^ */
411   { 0x22, '\'' }, /* << */
412   { 0x23, '?' }, /* >> */
413   { 0x21, '_' }, /* vv */
414
415   {0, 0} /* <<END>>   */
416 };
417
418 static const struct codetable
419 cir_codetable_bravia[] = {
420   { 0x15, ' ' }, /* Power */
421   { 0x95, '0' }, /* d (16-bit: 0x4b) */
422   { 0x00, '1' }, /* 1 */
423   { 0x01, '2' }, /* 2 */
424   { 0x02, '3' }, /* 3 */
425   { 0x03, '4' }, /* 4 */
426   { 0x04, '5' }, /* 5 */
427   { 0x05, '6' }, /* 6 */
428   { 0x06, '7' }, /* 7 */
429   { 0x07, '8' }, /* 8 */
430   { 0x08, '9' }, /* 9 */
431   { 0x09, 'a' }, /* 10 */
432   { 0x0a, 'b' }, /* 11 */
433   { 0x0b, 'c' }, /* 12 */
434   { 0x10, 'd' }, /* CH+ */
435   { 0x11, 'd' }, /* CH- */
436   { 0x12, 'f' }, /* Vol+ */
437   { 0x13, 'g' }, /* Vol- */
438   { 0x14, 'h' }, /* Mute */
439   { 0xa4, 'i' }, /* BLUE (16-bit: 0x4b) */
440   { 0xa5, 'j' }, /* RED (16-bit: 0x4b) */
441   { 0xa6, 'k' }, /* GREEN (16-bit: 0x4b) */
442   { 0xa7, 'l' }, /* YELLOW (16-bit: 0x4b) */
443   { 0x3a, 'm' }, /* DISPLAY control (gamen hyouji) */
444   { 0x3d, 'n' }, /* Display Wide (waido kirikae) */
445   { 0x74, 'o' }, /* UP */
446   { 0x75, 'p' }, /* DOWN */
447   { 0x33, 'q' }, /* RIGHT */
448   { 0x34, 'r' }, /* LEFT */
449   { 0x65, CH_RETURN }, /* Commit (kettei) */
450   { 0xa3, CH_BACKSPACE }, /* Back (modoru) (16-bit: 0x4b) */
451   { 0xac, 's' }, /* BS (16-bit: 0x4b) */
452   { 0xab, 't' }, /* CS (16-bit: 0x4b) */
453   { 0x5b, 'u' }, /* Program table (bangumi hyou) (16-bit: 0x52) */
454   { 0x17, 'v' }, /* Sound channel (onsei kirikae) */
455   { 0xa8, 'w' }, /* subtitle (jimaku) (16-bit: 0x4b) */
456   { 0x5c, 'x' }, /* hold (memo) */
457   { 0xb6, 'y' }, /* Tool (16-bit: 0x4b) */
458   { 0x8c, 'z' }, /* 10 key input (10ki-) (16-bit: 0x4b) */
459   { 0x60, '!' }, /* Menu */
460   { 0xae, '@' }, /* Analog (16-bit: 0x4b) */
461   { 0xb2, '#' }, /* Digital (16-bit: 0x4b) */
462   { 0x25, '$' }, /* Input (nyuuryoku kirikae) */
463
464   {0, 0} /* <<END>>   */,
465 };
466
467 static int
468 ch_is_backspace (int ch)
469 {
470   return ch == CH_BACKSPACE;
471 }
472
473 static int
474 ch_is_enter (int ch)
475 {
476   return ch == CH_RETURN;
477 }
478
479 /* liner search is good enough for this small amount of data */
480 static uint8_t
481 find_char_codetable (uint32_t cir_code, const struct codetable *ctp)
482 {
483   while (ctp->cir_code != 0x0000 || ctp->char_code != 0x00)
484     if (ctp->cir_code == cir_code)
485       return ctp->char_code;
486     else
487       ctp++;
488
489   /* Not found */
490   return cir_code & 0xff;
491 }
492
493 static int
494 hex (int x)
495 {
496   if (x < 10)
497     return x + '0';
498   else
499     return (x - 10) + 'a';
500 }
501
502 static int
503 check_input (void *arg)
504 {
505   (void)arg;
506   return input_avail;
507 }
508
509 static int
510 cir_getchar (uint32_t timeout)
511 {
512   chopstx_poll_cond_t poll_desc;
513   struct chx_poll_head *pd_array[1] = { (struct chx_poll_head *)&poll_desc };
514   uint16_t cir_addr;
515 #if defined(DEBUG_CIR)
516   uint16_t *p;
517 #endif
518
519 #if defined(DEBUG_CIR)
520   cirinput_p = cirinput;
521 #endif
522
523   cir_ll_init ();
524
525   poll_desc.type = CHOPSTX_POLL_COND;
526   poll_desc.ready = 0;
527   poll_desc.cond = &cir_input_cnd;
528   poll_desc.mutex = &cir_input_mtx;
529   poll_desc.check = check_input;
530   poll_desc.arg = NULL;
531
532   input_avail = 0;
533   if (chopstx_poll (&timeout, 1, pd_array) == 0)
534     return -1;
535
536   /* Sleep 200ms to avoid detecting chatter inputs.  */
537   chopstx_usec_wait (200 * 1000);
538
539 #if defined(DEBUG_CIR)
540   DEBUG_INFO ("****\r\n");
541   DEBUG_SHORT (intr_ext);
542   DEBUG_SHORT (intr_trg);
543   DEBUG_SHORT (intr_ovf);
544   DEBUG_INFO ("----\r\n");
545   for (p = cirinput; p < cirinput_p; p++)
546     {
547       DEBUG_SHORT (*p);
548     }
549   DEBUG_INFO ("====\r\n");
550
551   cirinput_p = cirinput;
552
553   DEBUG_INFO ("**** CIR data:");
554   DEBUG_WORD (cir_data);
555   if (cir_seq > 48)
556     {
557       DEBUG_SHORT (cir_data_more);
558     }
559   DEBUG_BYTE (cir_seq);
560 #endif
561
562   switch (cir_proto)
563     {
564     case CIR_PROTO_RC5:
565       cir_data &= 0x003f;
566       goto err;
567     case CIR_PROTO_RC6:
568       cir_addr = cir_data >> 8; /* in case of cir_seq == 16.  32??? */
569       cir_data &= 0x00ff;
570       return find_char_codetable (cir_data, cir_codetable_dell_mr425);
571     case CIR_PROTO_NEC:
572       cir_addr = cir_data&0xffff;
573       if (cir_addr == CIR_ADDR_TOSHIBA_REGZA)
574         {
575           cir_data = (cir_data >> 16) & 0x00ff;
576           return find_char_codetable (cir_data, cir_codetable_regza);
577         }
578       else
579         goto err;
580     case CIR_PROTO_SHARP:
581       cir_addr = cir_data&0x0fff;
582       if (cir_addr == CIR_ADDR_SHARP_AQUOS)
583         {
584           cir_data = (cir_data>>16)&0x0fff;
585           return find_char_codetable (cir_data, cir_codetable_aquos);
586         }
587       else
588         goto err;
589     case CIR_PROTO_SONY:
590       /* Remove ADDRESS bits and filter COMMAND bits */
591       if (cir_seq == 1 + 12)
592         {
593           cir_addr = cir_data >> 7;
594           cir_data = cir_data & 0x007f;
595           /* ADDRESS = 0x01 (5-bit) */
596         }
597       else
598         {
599           cir_addr = cir_data >> 8;
600           cir_data = cir_data & 0x00ff;
601           /* ADDRESS = 0x4b or 0x52 (7-bit) */
602         }
603       return find_char_codetable (cir_data, cir_codetable_bravia);
604     err:
605     default:
606       /* encode debug information */
607       pin_input_len = 16;
608       pin_input_buffer[0] = hex (cir_proto >> 4);
609       pin_input_buffer[1] = hex (cir_proto & 0x0f);
610       pin_input_buffer[2] = ':';
611       pin_input_buffer[3] = hex ((cir_data >> 28) & 0x0f);
612       pin_input_buffer[4] = hex ((cir_data >> 24) & 0x0f);
613       pin_input_buffer[5] = hex ((cir_data >> 20) & 0x0f);
614       pin_input_buffer[6] = hex ((cir_data >> 16) & 0x0f);
615       pin_input_buffer[7] = hex ((cir_data >> 12) & 0x0f);
616       pin_input_buffer[8] = hex ((cir_data >> 8) & 0x0f);
617       pin_input_buffer[9] = hex ((cir_data >> 4) & 0x0f);
618       pin_input_buffer[10] = hex (cir_data & 0x0f);
619       pin_input_buffer[11] = ':';
620       pin_input_buffer[12] = hex ((cir_data_more >> 12) & 0x0f);
621       pin_input_buffer[13] = hex ((cir_data_more >> 8) & 0x0f);
622       pin_input_buffer[14] = hex ((cir_data_more >> 4) & 0x0f);
623       pin_input_buffer[15] = hex (cir_data_more & 0x0f);
624       return CH_RETURN;
625     }
626 }
627
628 /*
629  * RC-5 protocol doesn't have a start bit, while any other protocols
630  * have the one.
631  */
632 #define CIR_BIT_START_RC5_DETECT 1600 /* RC-5: 889us, Sony start: 2400us */
633
634 #define CIR_BIT_START_RC5_LENGTH (889 + 889/2)
635 #define CIR_BIT_PERIOD_RC6 444
636 #define CIR_BIT_PERIOD 1500
637 #define CIR_BIT_SIRC_PERIOD_ON 1000
638
639 /*
640  * Let user input PIN string.
641  * Return length of the string.
642  * The string itself is in PIN_INPUT_BUFFER.
643  */
644 int
645 pinpad_getline (int msg_code, uint32_t timeout)
646 {
647   (void)msg_code;
648
649   DEBUG_INFO (">>>\r\n");
650
651   pin_input_len = 0;
652   while (1)
653     {
654       int ch;
655
656       ch = cir_getchar (timeout);
657       if (ch < 0)
658         return 0;               /* timeout */
659
660       if (ch_is_backspace (ch))
661         {
662           led_blink (LED_TWOSHOTS);
663           if (pin_input_len > 0)
664             pin_input_len--;
665         }
666       else if (ch_is_enter (ch))
667         break;
668       else if (pin_input_len < MAX_PIN_CHARS)
669         {
670           led_blink (LED_ONESHOT);
671           pin_input_buffer[pin_input_len++] = ch;
672         }
673     }
674
675   cir_ext_disable ();
676
677   return pin_input_len;
678 }
679
680 /**
681  * @brief  Interrupt handler of EXTI.
682  * @note   This handler will be invoked at the beginning of signal.
683  *         Setup timer to measure period and duty using PWM input mode.
684  */
685 static void
686 cir_ext_interrupt (void)
687 {
688   int rcvd = cir_ext_disable ();
689
690   if (!rcvd)
691     return;
692
693 #if defined(DEBUG_CIR)
694   intr_ext++;
695   if (cirinput_p - cirinput < MAX_CIRINPUT_BIT)
696     *cirinput_p++ = 0x0000;
697 #endif
698
699   TIMx->EGR = TIM_EGR_UG;       /* Generate UEV to load PSC and ARR */
700   /* Enable Timer */
701   TIMx->SR &= ~(TIM_SR_UIF
702                 | TIM_SR_CC1IF | TIM_SR_CC2IF
703                 | TIM_SR_TIF
704                 | TIM_SR_CC1OF | TIM_SR_CC2OF);
705   TIMx->DIER = TIM_DIER_UIE /*overflow*/ | TIM_DIER_TIE /*trigger*/;
706   TIMx->CR1 |= TIM_CR1_CEN;
707 }
708
709 #define CIR_PERIOD_ON_RC5_OR_RC6 (((cir_proto == CIR_PROTO_RC5) ? 2 : 1) \
710                                   * CIR_BIT_PERIOD_RC6 * 3 / 2)
711
712 /**
713  * @brief  Interrupt handler of timer.
714  * @note   Timer is PWM input mode, this handler will be invoked on each cycle
715  */
716 static void
717 cir_timer_interrupt (void)
718 {
719   uint16_t period, on, off;
720
721   period = TIMx->CCR1;
722   on = TIMx->CCR2;
723   off = period - on;
724
725   if ((TIMx->SR & TIM_SR_TIF))
726     {
727       if (cir_seq == 0)
728         {
729           if (on >= CIR_BIT_START_RC5_DETECT)
730             {
731               cir_proto = CIR_PROTO_OTHER;
732               cir_data_zero = 0;
733             }
734           else
735             {
736               cir_proto = CIR_PROTO_RC5;
737               cir_data = 1;
738               if (on >= CIR_BIT_START_RC5_LENGTH)
739                 {
740                   cir_data <<= 1;
741                   cir_seq++;
742                   if (off >= CIR_BIT_START_RC5_LENGTH)
743                     cir_data_zero = 0;
744                   else
745                     cir_data_zero = 1;
746                 }
747               else
748                 cir_data_zero = 0;
749             }
750         }
751       else if (cir_proto == CIR_PROTO_OTHER)
752         {
753           if (cir_seq == 1 + 16)
754             cir_data_more = (uint16_t)(cir_data >> 16);
755
756           cir_data >>= 1;
757           cir_data |= (period >= CIR_BIT_PERIOD) ? 0x80000000 : 0;
758
759           /* Detection of RC-6 protocol */
760           if (cir_data_zero && on > CIR_BIT_PERIOD_RC6*3/2)
761             /* TR-bit 0 is detected */
762             {
763               cir_proto = CIR_PROTO_RC6;
764               cir_seq = 0;
765               cir_data = 0;     /* ignore MODE bits */
766               if (on > CIR_BIT_PERIOD_RC6*5/2)
767                 {
768                   cir_data = 1;
769                   if (off > CIR_BIT_PERIOD_RC6*3/2)
770                     cir_data_zero = 1;
771                   else
772                     cir_data_zero = 0;
773                 }
774               else              /* Off must be short */
775                 {
776                   cir_data_zero = 1;
777                 }
778             }
779           else if ((!cir_data_zero
780                && on > CIR_BIT_PERIOD_RC6*3/2 && off > CIR_BIT_PERIOD_RC6*3/2))
781             /* TR-bit 1 is detected */
782             {
783               cir_proto = CIR_PROTO_RC6;
784               cir_seq = 0;
785               cir_data = 0;     /* ignore MODE bits */
786               cir_data_zero = 0;
787             }
788           else
789             {
790               /* Check if it looks like TR-bit of RC6 protocol */
791               if (off <= CIR_BIT_PERIOD_RC6*3/2)
792                 cir_data_zero = 0;
793               else
794                 cir_data_zero = 1;
795             }
796         }
797       else if (cir_proto == CIR_PROTO_RC5 || cir_proto == CIR_PROTO_RC6)
798         {
799           if (cir_data_zero)
800             {
801               cir_data <<= 1;
802
803               if (on > CIR_PERIOD_ON_RC5_OR_RC6)
804                 {
805                   cir_data <<= 1;
806                   cir_data |= 1;
807                   cir_seq++;
808                   if (off > CIR_PERIOD_ON_RC5_OR_RC6)
809                     cir_data_zero = 1;
810                   else
811                     cir_data_zero = 0;
812                 }
813               else              /* Off must be short */
814                 cir_data_zero = 1;
815             }
816           else
817             {
818               cir_data <<= 1;
819               cir_data |= 1;
820
821               /* On must be short */
822               if (off > CIR_PERIOD_ON_RC5_OR_RC6)
823                 cir_data_zero = 1;
824               else
825                 cir_data_zero = 0;
826             }
827         }
828
829       cir_seq++;
830
831 #if defined(DEBUG_CIR)
832       if (cirinput_p - cirinput < MAX_CIRINPUT_BIT)
833         {
834           *cirinput_p++ = on;
835           *cirinput_p++ = off;
836         }
837       intr_trg++;
838 #endif
839
840       TIMx->EGR = TIM_EGR_UG;   /* Generate UEV */
841       TIMx->SR &= ~TIM_SR_TIF;
842     }
843   else if ((TIMx->SR & TIM_SR_UIF))
844     /* overflow occurred */
845     {
846       TIMx->SR &= ~TIM_SR_UIF;
847
848       if (on > 0)
849         {
850           uint8_t ignore_input = 0;
851
852           /* Disable the timer */
853           TIMx->CR1 &= ~TIM_CR1_CEN;
854           TIMx->DIER = 0;
855
856           if (cir_seq == 12 || cir_seq == 15)
857             {
858 #if defined(DEBUG_CIR)
859               if (cirinput_p - cirinput < MAX_CIRINPUT_BIT)
860                 {
861                   *cirinput_p++ = on;
862                   *cirinput_p++ = 0xffff;
863                 }
864 #endif
865               cir_proto = CIR_PROTO_SONY;
866               cir_data >>= 1;
867               cir_data |= (on >= CIR_BIT_SIRC_PERIOD_ON) ? 0x80000000 : 0;
868               cir_data >>= (32 - cir_seq);
869               cir_seq++;
870             }
871           else
872             {
873               if (cir_proto == CIR_PROTO_RC5 || cir_proto == CIR_PROTO_RC6)
874                 {
875                   cir_data <<= 1;
876                   cir_seq++;
877                   if (cir_data_zero)
878                     {
879                       if (on > CIR_PERIOD_ON_RC5_OR_RC6)
880                         {
881                           cir_data <<= 1;
882                           cir_data |= 1;
883                           cir_seq++;
884                         }
885                     }
886                   else
887                     cir_data |= 1;
888                 }
889               /* Or else, it must be the stop bit, just ignore */
890             }
891
892           if (cir_proto == CIR_PROTO_SONY)
893             {
894               if (cir_seq != 1 + 12 && cir_seq != 1 + 15)
895                 ignore_input = 1;
896             }
897           else if (cir_proto == CIR_PROTO_OTHER)
898             {
899               if (cir_seq == 1 + 32)
900                 {
901                   if (((cir_data >> 16) & 0xff) == ((cir_data >> 24) ^ 0xff))
902                     cir_proto = CIR_PROTO_NEC;
903                   else
904                     ignore_input = 1;
905                 }
906               else if (cir_seq == 1 + 48)
907                 {
908                   if ((cir_data >> 28) ==
909                       (((cir_data_more >> 12) & 0x0f)
910                        ^ ((cir_data_more >> 8) & 0x0f)
911                        ^ ((cir_data_more >> 4) & 0x0f)
912                        ^ (cir_data_more & 0x0f)
913                        ^ ((cir_data >> 24) & 0x0f)
914                        ^ ((cir_data >> 20) & 0x0f) ^ ((cir_data >> 16) & 0x0f)
915                        ^ ((cir_data >> 12) & 0x0f) ^ ((cir_data >> 8) & 0x0f)
916                        ^ ((cir_data >> 4) & 0x0f) ^ (cir_data & 0x0f)))
917                     cir_proto = CIR_PROTO_SHARP;
918                   else
919                     ignore_input = 1;
920                 }
921               else
922                 ignore_input = 1;
923             }
924           else if (cir_proto == CIR_PROTO_RC6)
925             {
926               if (cir_seq != 16 && cir_seq != 32)
927                 ignore_input = 1;
928             }
929           else if (cir_proto == CIR_PROTO_RC5)
930             {
931               if (cir_seq != 14)
932                 ignore_input = 1;
933             }
934           else
935             ignore_input = 1;
936
937           if (ignore_input)
938             /* Ignore data received and enable CIR again */
939             cir_ll_init ();
940           else
941             {
942               /*
943                * Notify the thread, when it's waiting the input.
944                * If else, the input is thrown away.
945                */
946               chopstx_mutex_lock (&cir_input_mtx);
947               input_avail = 1;
948               chopstx_cond_signal (&cir_input_cnd);
949               chopstx_mutex_unlock (&cir_input_mtx);
950             }
951
952 #if defined(DEBUG_CIR)
953           if (cirinput_p - cirinput < MAX_CIRINPUT_BIT)
954             *cirinput_p++ = 0xffff;
955
956           intr_ovf++;
957 #endif
958         }
959     }
960 #if defined(DEBUG_CIR)
961   else
962     intr_err++;
963 #endif
964 }
965
966
967 extern uint8_t __process6_stack_base__[], __process6_stack_size__[];
968 #define STACK_ADDR_TIM ((uint32_t)__process6_stack_base__)
969 #define STACK_SIZE_TIM ((uint32_t)__process6_stack_size__)
970 #define PRIO_TIM 4
971
972 static void *
973 tim_main (void *arg)
974 {
975   chopstx_intr_t interrupt;
976
977   (void)arg;
978   chopstx_claim_irq (&interrupt, INTR_REQ_TIM);
979
980   while (1)
981     {
982       chopstx_intr_wait (&interrupt);
983       cir_timer_interrupt ();
984     }
985
986   return NULL;
987 }
988
989 extern uint8_t __process7_stack_base__, __process7_stack_size__;
990 const uint32_t __stackaddr_ext = (uint32_t)&__process7_stack_base__;
991 const size_t __stacksize_ext = (size_t)&__process7_stack_size__;
992 #define PRIO_EXT 4
993
994 static void *
995 ext_main (void *arg)
996 {
997   chopstx_intr_t interrupt;
998
999   (void)arg;
1000   chopstx_claim_irq (&interrupt, INTR_REQ_EXTI);
1001
1002   while (1)
1003     {
1004       chopstx_intr_wait (&interrupt);
1005       cir_ext_interrupt ();
1006     }
1007
1008   return NULL;
1009 }
1010
1011
1012 void
1013 cir_init (void)
1014 {
1015   chopstx_mutex_init (&cir_input_mtx);
1016   chopstx_cond_init (&cir_input_cnd);
1017
1018   /*
1019    * We use XOR function for three signals: TIMx_CH1, TIMx_CH2, and TIMx_CH3.
1020    *
1021    * This is because we want to invert the signal (of Vout from CIR
1022    * receiver module) for timer.
1023    *
1024    * For FST-01, TIM2_CH3 is the signal.  We set TIM2_CH1 = 1 and
1025    * TIM2_CH2 = 0.
1026    *
1027    * For STM8S, TIM2_CH2 is the signal.  We set TIM2_CH1 = 1 and
1028    * TIMx_CH3 = 0.
1029    */
1030
1031   /* EXTIx <= Py */
1032   AFIO->EXTICR[AFIO_EXTICR_INDEX] = AFIO_EXTICR1_EXTIx_Py;
1033   EXTI->IMR = 0;
1034   EXTI->FTSR = EXTI_FTSR_TR;
1035
1036   /* TIM */
1037 #ifdef ENABLE_RCC_APB1
1038   RCC->APB1ENR |= RCC_APBnENR_TIMxEN;
1039   RCC->APB1RSTR = RCC_APBnRSTR_TIMxRST;
1040   RCC->APB1RSTR = 0;
1041 #elif ENABLE_RCC_APB2
1042   RCC->APB2ENR |= RCC_APBnENR_TIMxEN;
1043   RCC->APB2RSTR = RCC_APBnRSTR_TIMxRST;
1044   RCC->APB2RSTR = 0;
1045 #endif
1046
1047   TIMx->CR1 = TIM_CR1_URS | TIM_CR1_ARPE;
1048   TIMx->CR2 = TIM_CR2_TI1S;
1049   TIMx->SMCR = TIM_SMCR_TS_0 | TIM_SMCR_TS_2 | TIM_SMCR_SMS_2;
1050   TIMx->DIER = 0;               /* Disable interrupt for now */
1051   TIMx->CCMR1 = TIM_CCMR1_CC1S_0 | TIM_CCMR1_IC1F_0 | TIM_CCMR1_IC1F_3
1052     | TIM_CCMR1_CC2S_1 | TIM_CCMR1_IC2F_0 | TIM_CCMR1_IC2F_3;
1053   TIMx->CCMR2 = 0;
1054   TIMx->CCER =  TIM_CCER_CC1E | TIM_CCER_CC2E | TIM_CCER_CC2P;
1055   TIMx->PSC = 72 - 1;           /* 1 MHz */
1056   TIMx->ARR = 18000;            /* 18 ms */
1057   /* Generate UEV to upload PSC and ARR */
1058   TIMx->EGR = TIM_EGR_UG;
1059
1060   chopstx_create (PRIO_TIM, STACK_ADDR_TIM, STACK_SIZE_TIM, tim_main, NULL);
1061   chopstx_create (PRIO_EXT, STACK_ADDR_EXT, STACK_SIZE_EXT, ext_main, NULL);
1062 }