|
1 /* |
|
2 * Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * naviengine_assp\uart\vserialkeyb.cpp |
|
16 * Serial keyboard driver |
|
17 * |
|
18 */ |
|
19 |
|
20 |
|
21 |
|
22 /** |
|
23 @file |
|
24 @internalTechnology |
|
25 */ |
|
26 |
|
27 #include <e32keys.h> |
|
28 #include <comm.h> |
|
29 #include <assp.h> |
|
30 #include "../naviengine_priv.h" |
|
31 #include "../naviengine.h" |
|
32 #include "uart16550_ne.h" |
|
33 #include "vserialkeyb.h" |
|
34 |
|
35 |
|
36 #define SHIFTED(x) (0x8000|(x)) |
|
37 #define ISSHIFTED(x) (0x8000&(x)) |
|
38 #define FUNCED(x) (0x4000|(x)) |
|
39 #define ISFUNCED(x) (0x4000&(x)) |
|
40 #define CTRLED(x) (0x2000|(x)) |
|
41 #define ISCTRLED(x) (0x2000&(x)) |
|
42 #define STDKEY(x) (0x1FFF&(x)) |
|
43 |
|
44 /* |
|
45 * Definition of the converting table for the receive char |
|
46 * through the serial port. |
|
47 * |
|
48 */ |
|
49 const TUint16 convertCodeSerial[] = |
|
50 { |
|
51 /*00*/ EStdKeyNull, |
|
52 /*01*/ EStdKeyHome, // ^A |
|
53 /*02*/ EStdKeyLeftArrow, // ^B |
|
54 /*03*/ EStdKeyEscape, // ^C |
|
55 /*04*/ SHIFTED(EStdKeyDownArrow), // ^D - move window down |
|
56 /*05*/ EStdKeyEnd, // ^E |
|
57 /*06*/ EStdKeyRightArrow, // ^F |
|
58 /*07*/ EStdKeyNull, |
|
59 /*08*/ EStdKeyBackspace, // ^H - Reserved! |
|
60 /*09*/ EStdKeyTab, // ^I - Reserved! |
|
61 /*0a*/ EStdKeyNull, |
|
62 /*0b*/ EStdKeyIncContrast, // ^K |
|
63 /*0c*/ EStdKeyDecContrast, // ^L |
|
64 /*0d*/ EStdKeyEnter, // ^M - Reserved! |
|
65 /*0e*/ EStdKeyDownArrow, // ^N |
|
66 /*0f*/ EStdKeyNull, // ^O = instant death |
|
67 /*10*/ EStdKeyUpArrow, // ^P |
|
68 /*11*/ CTRLED(EStdKeyLeftArrow), // ^Q - make window narrower |
|
69 /*12*/ CTRLED(FUNCED('5')), // ^R - rotate windows in text window server |
|
70 /*13*/ EStdKeyNull, |
|
71 /*14*/ CTRLED(EStdKeyDownArrow), // ^T - make window taller |
|
72 /*15*/ SHIFTED(EStdKeyUpArrow), // ^U - move window up |
|
73 /*16*/ EStdKeyNull, |
|
74 /*17*/ CTRLED(EStdKeyRightArrow), // ^W - make window wider |
|
75 /*18*/ SHIFTED(EStdKeyRightArrow), // ^X - move window right |
|
76 /*19*/ CTRLED(EStdKeyUpArrow), // ^Y - make window shorter |
|
77 /*1a*/ SHIFTED(EStdKeyLeftArrow), // ^Z - move window left |
|
78 /*1b*/ EStdKeyEscape, // ^[ - Reserved! |
|
79 /*1c*/ EStdKeyNull, |
|
80 /*1d*/ EStdKeyNull, |
|
81 /*1e*/ EStdKeyNull, |
|
82 /*1f*/ EStdKeyNull, |
|
83 /*20*/ EStdKeySpace, |
|
84 /*21*/ SHIFTED('1'), // ! |
|
85 /*22*/ SHIFTED('2'), // " |
|
86 /*23*/ EStdKeyHash, // # |
|
87 /*24*/ SHIFTED('4'), // $ |
|
88 /*25*/ SHIFTED('5'), // % |
|
89 /*26*/ SHIFTED('7'), // & |
|
90 /*27*/ EStdKeySingleQuote, |
|
91 /*28*/ SHIFTED('9'), // ( |
|
92 /*29*/ SHIFTED('0'), // ) |
|
93 /*2a*/ SHIFTED('8'), // * |
|
94 /*2b*/ SHIFTED(EStdKeyEquals), // + |
|
95 /*2c*/ EStdKeyComma, |
|
96 /*2d*/ EStdKeyMinus, |
|
97 /*2e*/ EStdKeyFullStop, |
|
98 /*2f*/ EStdKeyForwardSlash, |
|
99 /*30*/ '0', |
|
100 /*31*/ '1', |
|
101 /*32*/ '2', |
|
102 /*33*/ '3', |
|
103 /*34*/ '4', |
|
104 /*35*/ '5', |
|
105 /*36*/ '6', |
|
106 /*37*/ '7', |
|
107 /*38*/ '8', |
|
108 /*39*/ '9', |
|
109 /*3a*/ SHIFTED(EStdKeySemiColon), // : |
|
110 /*3b*/ EStdKeySemiColon, |
|
111 /*3c*/ SHIFTED(EStdKeyComma), // < |
|
112 /*3d*/ EStdKeyEquals, |
|
113 /*3e*/ SHIFTED(EStdKeyFullStop), // > |
|
114 /*3f*/ SHIFTED(EStdKeyForwardSlash), // ? |
|
115 /*40*/ SHIFTED(EStdKeySingleQuote), // @ |
|
116 /*41*/ SHIFTED('A'), |
|
117 /*42*/ SHIFTED('B'), |
|
118 /*43*/ SHIFTED('C'), |
|
119 /*44*/ SHIFTED('D'), |
|
120 /*45*/ SHIFTED('E'), |
|
121 /*46*/ SHIFTED('F'), |
|
122 /*47*/ SHIFTED('G'), |
|
123 /*48*/ SHIFTED('H'), |
|
124 /*49*/ SHIFTED('I'), |
|
125 /*4a*/ SHIFTED('J'), |
|
126 /*4b*/ SHIFTED('K'), |
|
127 /*4c*/ SHIFTED('L'), |
|
128 /*4d*/ SHIFTED('M'), |
|
129 /*4e*/ SHIFTED('N'), |
|
130 /*4f*/ SHIFTED('O'), |
|
131 /*50*/ SHIFTED('P'), |
|
132 /*51*/ SHIFTED('Q'), |
|
133 /*52*/ SHIFTED('R'), |
|
134 /*53*/ SHIFTED('S'), |
|
135 /*54*/ SHIFTED('T'), |
|
136 /*55*/ SHIFTED('U'), |
|
137 /*56*/ SHIFTED('V'), |
|
138 /*57*/ SHIFTED('W'), |
|
139 /*58*/ SHIFTED('X'), |
|
140 /*59*/ SHIFTED('Y'), |
|
141 /*5a*/ SHIFTED('Z'), |
|
142 /*5b*/ EStdKeySquareBracketLeft, |
|
143 /*5c*/ EStdKeyBackSlash, |
|
144 /*5d*/ EStdKeySquareBracketRight, |
|
145 /*5e*/ SHIFTED('6'), // ^ |
|
146 /*5f*/ SHIFTED(EStdKeyMinus), // _ |
|
147 /*60*/ EStdKeyBacklightToggle, // Actually ` |
|
148 /*61*/ 'A', |
|
149 /*62*/ 'B', |
|
150 /*63*/ 'C', |
|
151 /*64*/ 'D', |
|
152 /*65*/ 'E', |
|
153 /*66*/ 'F', |
|
154 /*67*/ 'G', |
|
155 /*68*/ 'H', |
|
156 /*69*/ 'I', |
|
157 /*6a*/ 'J', |
|
158 /*6b*/ 'K', |
|
159 /*6c*/ 'L', |
|
160 /*6d*/ 'M', |
|
161 /*6e*/ 'N', |
|
162 /*6f*/ 'O', |
|
163 /*70*/ 'P', |
|
164 /*71*/ 'Q', |
|
165 /*72*/ 'R', |
|
166 /*73*/ 'S', |
|
167 /*74*/ 'T', |
|
168 /*75*/ 'U', |
|
169 /*76*/ 'V', |
|
170 /*77*/ 'W', |
|
171 /*78*/ 'X', |
|
172 /*79*/ 'Y', |
|
173 /*7a*/ 'Z', |
|
174 /*7b*/ SHIFTED(EStdKeySquareBracketLeft), |
|
175 /*7c*/ SHIFTED(EStdKeyBackSlash), |
|
176 /*7d*/ SHIFTED(EStdKeySquareBracketRight), |
|
177 /*7e*/ SHIFTED(EStdKeyHash), |
|
178 /*7f*/ EKeyDelete |
|
179 }; /* end of array - convertCodeSerial - */ |
|
180 |
|
181 typedef struct |
|
182 { |
|
183 TUint8 seq[maxSeq+1]; |
|
184 TUint32 convertedCode; |
|
185 } keyType; |
|
186 |
|
187 const keyType escapeCodes[] = |
|
188 { |
|
189 // Three escape codes in a row that completes a sequence |
|
190 { {0x1b, 0x4f, 0x50, 0, 0, 0,}, EStdKeyMenu, }, // F1 gives menu key |
|
191 { {0x1b, 0x4f, 0x51, 0, 0, 0,}, EStdKeyF2, }, // F2 |
|
192 { {0x1b, 0x4f, 0x52, 0, 0, 0,}, EStdKeyF3, }, // F3 |
|
193 { {0x1b, 0x4f, 0x53, 0, 0, 0,}, EStdKeyF4, }, // F4 |
|
194 { {0x1b, 0x4f, 0x74, 0, 0, 0,}, EStdKeyDevice3, }, // F5 gives S60 centre press |
|
195 { {0x1b, 0x4f, 0x75, 0, 0, 0,}, EStdKeyDevice0, }, // F6 gives S60 left softkey |
|
196 { {0x1b, 0x4f, 0x76, 0, 0, 0,}, EStdKeyDevice1, }, // F7 gives S60 right softkey |
|
197 { {0x1b, 0x4f, 0x6c, 0, 0, 0,}, EStdKeyApplication0, }, // F8 gives S60 application softkey |
|
198 { {0x1b, 0x4f, 0x77, 0, 0, 0,}, EStdKeyF9, }, // F9 |
|
199 { {0x1b, 0x4f, 0x78, 0, 0, 0,}, EStdKeyF10, }, // F10 |
|
200 |
|
201 { {0x1b, 0x5b, 0x41, 0, 0, 0,}, EStdKeyUpArrow, }, // Arrow keys |
|
202 { {0x1b, 0x5b, 0x42, 0, 0, 0,}, EStdKeyDownArrow, }, // Arrow keys |
|
203 { {0x1b, 0x5b, 0x43, 0, 0, 0,}, EStdKeyRightArrow, }, // Arrow keys |
|
204 { {0x1b, 0x5b, 0x44, 0, 0, 0,}, EStdKeyLeftArrow, }, // Arrow keys |
|
205 |
|
206 // Four escape codes in a row that completes a sequence |
|
207 { {0x1b, 0x5b, 0x31, 0x7e, 0, 0,}, EStdKeyHome, }, // Home key |
|
208 { {0x1b, 0x5b, 0x34, 0x7e, 0, 0,}, EStdKeyEnd, }, // End key |
|
209 { {0x1b, 0x5b, 0x35, 0x7e, 0, 0,}, EStdKeyPageUp, }, // Page Up key |
|
210 { {0x1b, 0x5b, 0x36, 0x7e, 0, 0,}, EStdKeyPageDown, }, // Page down key |
|
211 { {0x1b, 0x5b, 0x32, 0x7e, 0, 0,}, EStdKeyInsert, }, // Page down key |
|
212 |
|
213 // Five escape codes in a row that completes a sequence |
|
214 { {0x1b, 0x5b, 0x32, 0x33, 0x7e, 0,}, EStdKeyF11, }, // F11 |
|
215 { {0x1b, 0x5b, 0x32, 0x34, 0x7e, 0,}, EStdKeyF12, }, // F12 |
|
216 |
|
217 // end of table - should be all zeros |
|
218 { {0, 0, 0, 0, 0, 0,}, 0, } |
|
219 }; |
|
220 |
|
221 TSerialKeyboard::TSerialKeyboard() |
|
222 : iKeyDfc( KeyDfcFn, this, Kern::DfcQue0(), 1 ), iSeqNum(0) |
|
223 { |
|
224 for (TUint i=0; i<maxSeq; i++) |
|
225 { |
|
226 iCode[i]=0; |
|
227 } |
|
228 } |
|
229 |
|
230 TInt TSerialKeyboard::Create() |
|
231 { |
|
232 // __KTRACE_OPT(KBOOT,Kern::Printf(_L("+TKeyboardSerial::Init"))) ; |
|
233 TUint base; |
|
234 TUint baud; |
|
235 |
|
236 iKeyboardPort = GetSerialPort(baud); |
|
237 |
|
238 switch(iKeyboardPort) |
|
239 { |
|
240 case 1: base=KHwBaseUart1; break; |
|
241 case 2: base=KHwBaseUart2; break; |
|
242 default: base=KHwBaseUart0; |
|
243 iKeyboardPort = 0; //JTAG debug port, use port #0 |
|
244 } |
|
245 |
|
246 __KTRACE_OPT(KBOOT,Kern::Printf("SERIAL KEYBOARD DRIVER: keyboard port=%d", iKeyboardPort )); |
|
247 |
|
248 iUart = new T16550Uart; |
|
249 if (iUart) |
|
250 { |
|
251 iUart->iBase = (TUint8*)base; |
|
252 iUart->SetIER(0); |
|
253 iUart->SetLCR(0); |
|
254 iUart->SetFCR(0); |
|
255 iUart->SetMCR(0); |
|
256 } |
|
257 else |
|
258 return KErrNoMemory; |
|
259 |
|
260 iInterrupt=Interrupt::Bind(KIntIdUart0+iKeyboardPort,Isr,this); |
|
261 if (iInterrupt<0) |
|
262 { |
|
263 delete iUart; |
|
264 return iInterrupt; |
|
265 } |
|
266 |
|
267 iUart->SetLCR(K16550LCR_Data8|K16550LCR_DLAB); |
|
268 iUart->SetBaudRateDivisor((baud==230400) ? KBaudRateDiv_230400 : KBaudRateDiv_default); |
|
269 iUart->SetLCR(K16550LCR_Data8); |
|
270 iUart->SetFCR(K16550FCR_Enable|K16550FCR_RxReset|K16550FCR_TxReset|K16550FCR_RxTrig8); |
|
271 iUart->SetIER(K16550IER_RDAI);// enable receiving data |
|
272 |
|
273 Interrupt::Enable(iInterrupt); |
|
274 |
|
275 return KErrNone; |
|
276 } |
|
277 |
|
278 |
|
279 void TSerialKeyboard::Isr( TAny* aPtr ) |
|
280 // |
|
281 // Interrupt service routine. Called when we receive an interrupt |
|
282 // on the IRQ line it is bound to. If it's a receive, queues DFC |
|
283 // to post the event into the event queue. |
|
284 // |
|
285 { |
|
286 TSerialKeyboard* self = (TSerialKeyboard*)aPtr; |
|
287 T16550Uart& u=*(self->iUart); |
|
288 |
|
289 TUint isr=u.ISR(); |
|
290 if (isr & K16550ISR_NotPending) |
|
291 return; |
|
292 isr&=K16550ISR_IntIdMask; |
|
293 |
|
294 if (isr==K16550ISR_RDAI || isr==K16550ISR_RLSI) |
|
295 { |
|
296 __KTRACE_OPT(KEXTENSION,Kern::Printf("TSerialKeyboard::Isr:RHR")); |
|
297 TUint ch=u.RxData(); |
|
298 if (ch==31) |
|
299 __crash(); // CTRL-? = instant death |
|
300 if (self->iSeqNum < maxSeq) |
|
301 { |
|
302 self->iCode[self->iSeqNum] = ch; |
|
303 self->iSeqNum++; |
|
304 self->iKeyDfc.Add(); |
|
305 Interrupt::Disable(self->iInterrupt); // Can only handle one char at a time |
|
306 } |
|
307 } |
|
308 } |
|
309 |
|
310 void TSerialKeyboard::KeyDfcFn( TAny* aPtr ) |
|
311 // |
|
312 // DFC function. Just calls inline function KeyDfc() |
|
313 // |
|
314 { |
|
315 __KTRACE_OPT(KEXTENSION,Kern::Printf("TSerialKeyboard::KeyDfcFn")); |
|
316 ((TSerialKeyboard*)aPtr)->KeyDfc(); |
|
317 } |
|
318 |
|
319 void TSerialKeyboard::AddConvertedEvent(TUint aKey) |
|
320 { |
|
321 // split aKey into keycode and shift, func, ctrl status |
|
322 TBool isShifted = ISSHIFTED(aKey); |
|
323 TBool isFunced = ISFUNCED(aKey); |
|
324 TBool isCtrled = ISCTRLED(aKey); |
|
325 TUint8 stdKey = STDKEY(aKey); |
|
326 |
|
327 // post it as a sequence of events |
|
328 TRawEvent e; |
|
329 if (isShifted) |
|
330 { |
|
331 e.Set(TRawEvent::EKeyDown,EStdKeyRightShift,0); |
|
332 Kern::AddEvent(e); |
|
333 } |
|
334 if (isCtrled) |
|
335 { |
|
336 e.Set(TRawEvent::EKeyDown,EStdKeyLeftCtrl,0); |
|
337 Kern::AddEvent(e); |
|
338 } |
|
339 if (isFunced) |
|
340 { |
|
341 e.Set(TRawEvent::EKeyDown,EStdKeyLeftFunc,0); |
|
342 Kern::AddEvent(e); |
|
343 } |
|
344 |
|
345 e.Set(TRawEvent::EKeyDown,stdKey,0); |
|
346 Kern::AddEvent(e); |
|
347 |
|
348 e.Set(TRawEvent::EKeyUp,stdKey,0); |
|
349 Kern::AddEvent(e); |
|
350 |
|
351 if (isFunced) |
|
352 { |
|
353 e.Set(TRawEvent::EKeyUp,EStdKeyLeftFunc,0); |
|
354 Kern::AddEvent(e); |
|
355 } |
|
356 if (isCtrled) |
|
357 { |
|
358 e.Set(TRawEvent::EKeyUp,EStdKeyLeftCtrl,0); |
|
359 Kern::AddEvent(e); |
|
360 } |
|
361 if (isShifted) |
|
362 { |
|
363 e.Set(TRawEvent::EKeyUp,EStdKeyRightShift,0); |
|
364 Kern::AddEvent(e); |
|
365 } |
|
366 } |
|
367 |
|
368 void TSerialKeyboard::AddUnconvertedEvent(TUint aKey) |
|
369 { |
|
370 TUint16 convertedKey = convertCodeSerial[aKey]; |
|
371 AddConvertedEvent(convertedKey); |
|
372 } |
|
373 |
|
374 inline void TSerialKeyboard::KeyDfc() |
|
375 // |
|
376 // Processes received characters |
|
377 // |
|
378 { |
|
379 __KTRACE_OPT(KEXTENSION, Kern::Printf("KEY: iSeqNum=%x, key=%x", iSeqNum, iCode[iSeqNum-1])); |
|
380 |
|
381 switch (iSeqNum) |
|
382 { |
|
383 case 1: |
|
384 if (iCode[0] != EEscapingStart) |
|
385 { |
|
386 // Unknown escape sequence - just pass chars as normal events |
|
387 AddUnconvertedEvent(iCode[0]); |
|
388 iSeqNum = 0; |
|
389 } |
|
390 break; |
|
391 case 2: |
|
392 if ((iCode[1] != EEscapingType1) && iCode[1] != EEscapingType2) |
|
393 { |
|
394 // Unknown escape sequence - just pass chars as normal events |
|
395 AddUnconvertedEvent(iCode[0]); |
|
396 AddUnconvertedEvent(iCode[1]); |
|
397 iSeqNum = 0; |
|
398 } |
|
399 break; |
|
400 case 3: |
|
401 case 4: |
|
402 case 5: |
|
403 { |
|
404 TUint escCodeindex = 0; // index into the escape code list |
|
405 TUint seqIndex = 0; // index into the current code sequence |
|
406 TUint bestMatch = 0; // keep a track of the best number of matches so far |
|
407 while (escapeCodes[escCodeindex].seq[0] != 0) |
|
408 { |
|
409 for (seqIndex = 0; seqIndex<iSeqNum; seqIndex++) |
|
410 { |
|
411 if (iCode[seqIndex] != escapeCodes[escCodeindex].seq[seqIndex]) |
|
412 { |
|
413 break; // out of for loop |
|
414 } |
|
415 } |
|
416 if (seqIndex > bestMatch) |
|
417 { |
|
418 bestMatch = seqIndex; |
|
419 } |
|
420 if (escapeCodes[escCodeindex].seq[seqIndex] == 0) |
|
421 { |
|
422 AddConvertedEvent(escapeCodes[escCodeindex].convertedCode); |
|
423 iSeqNum = 0; |
|
424 break; // out of while loop |
|
425 } |
|
426 escCodeindex++; |
|
427 } |
|
428 |
|
429 if ( (bestMatch < iSeqNum) // if we couldn't match all numbers in the sequence so far, this must not be a valid sequence |
|
430 || (iSeqNum == maxSeq) // if we reached the max number of codes in a sequence, this must also not be a valid sequence |
|
431 ) |
|
432 { |
|
433 if (escapeCodes[escCodeindex].seq[0] == 0) |
|
434 { |
|
435 // Unknown escape sequence - just pass chars as normal events |
|
436 for (TUint i=0; i < iSeqNum; i++) |
|
437 { |
|
438 AddUnconvertedEvent(iCode[i]); |
|
439 } |
|
440 } |
|
441 iSeqNum = 0; |
|
442 } |
|
443 } |
|
444 break; |
|
445 default: |
|
446 // Should never reach here! |
|
447 iSeqNum = 0; |
|
448 break; |
|
449 }; |
|
450 Interrupt::Enable(iInterrupt); // Can handle new chars now |
|
451 } /* end of function - KeyDfc - */ |
|
452 |
|
453 // |
|
454 // Kernel Extension entry point |
|
455 // |
|
456 DECLARE_STANDARD_EXTENSION() |
|
457 { |
|
458 __KTRACE_OPT(KEXTENSION,Kern::Printf("Starting keyboard driver")); |
|
459 |
|
460 // create keyboard driver |
|
461 TInt r=KErrNoMemory; |
|
462 TSerialKeyboard* keyboard = new TSerialKeyboard; |
|
463 if ( keyboard ) |
|
464 { |
|
465 r=keyboard->Create(); |
|
466 } |
|
467 |
|
468 __KTRACE_OPT(KEXTENSION,Kern::Printf("Returns %d",r)); |
|
469 return r; |
|
470 } |