Explorar el Código

Return ANSI sequences for special keys

tags/v0.9.3
Michael Brown hace 17 años
padre
commit
dbb7b30cca
Se han modificado 1 ficheros con 80 adiciones y 6 borrados
  1. 80
    6
      src/arch/i386/firmware/pcbios/bios_console.c

+ 80
- 6
src/arch/i386/firmware/pcbios/bios_console.c Ver fichero

176
 			       : "ebp" );
176
 			       : "ebp" );
177
 }
177
 }
178
 
178
 
179
+/**
180
+ * Pointer to current ANSI output sequence
181
+ *
182
+ * While we are in the middle of returning an ANSI sequence for a
183
+ * special key, this will point to the next character to return.  When
184
+ * not in the middle of such a sequence, this will point to a NUL
185
+ * (note: not "will be NULL").
186
+ */
187
+static const char *ansi_input = "";
188
+
189
+/**
190
+ * Lowest BIOS scancode of interest
191
+ *
192
+ * Most of the BIOS key scancodes that we are interested in are in a
193
+ * dense range, so subtracting a constant and treating them as offsets
194
+ * into an array works efficiently.
195
+ */
196
+#define BIOS_KEY_MIN 0x47
197
+
198
+/** Offset into list of interesting BIOS scancodes */
199
+#define BIOS_KEY(scancode) ( (scancode) - BIOS_KEY_MIN )
200
+
201
+/** Mapping from BIOS scan codes to ANSI escape sequences */
202
+static const char *ansi_sequences[] = {
203
+	[ BIOS_KEY ( 0x47 ) ] = "[H",	/* Home */
204
+	[ BIOS_KEY ( 0x48 ) ] = "[A",	/* Up arrow */
205
+	[ BIOS_KEY ( 0x4b ) ] = "[D",	/* Left arrow */
206
+	[ BIOS_KEY ( 0x4d ) ] = "[C",	/* Right arrow */
207
+	[ BIOS_KEY ( 0x4f ) ] = "[F",	/* End */
208
+	[ BIOS_KEY ( 0x50 ) ] = "[B",	/* Down arrow */
209
+	[ BIOS_KEY ( 0x53 ) ] = "[3~",	/* Delete */
210
+};
211
+
212
+/**
213
+ * Get ANSI escape sequence corresponding to BIOS scancode
214
+ *
215
+ * @v scancode		BIOS scancode
216
+ * @ret ansi_seq	ANSI escape sequence, if any, otherwise NULL
217
+ */
218
+static const char * scancode_to_ansi_seq ( unsigned int scancode ) {
219
+	unsigned int bios_key = BIOS_KEY ( scancode );
220
+	
221
+	if ( bios_key < ( sizeof ( ansi_sequences ) /
222
+			  sizeof ( ansi_sequences[0] ) ) ) {
223
+		return ansi_sequences[bios_key];
224
+	}
225
+	return NULL;
226
+}
227
+
179
 /**
228
 /**
180
  * Get character from BIOS console
229
  * Get character from BIOS console
181
  *
230
  *
182
  * @ret character	Character read from console
231
  * @ret character	Character read from console
183
  */
232
  */
184
 static int bios_getchar ( void ) {
233
 static int bios_getchar ( void ) {
185
-	uint8_t character;
186
-	
234
+	uint16_t keypress;
235
+	unsigned int character;
236
+	char *ansi_seq;
237
+
238
+	/* If we are mid-sequence, pass out the next byte */
239
+	if ( ( character = *ansi_input ) ) {
240
+		ansi_input++;
241
+		return character;
242
+	}
243
+
244
+	/* Read character from real BIOS console */
187
 	__asm__ __volatile__ ( REAL_CODE ( "sti\n\t"
245
 	__asm__ __volatile__ ( REAL_CODE ( "sti\n\t"
188
 					   "int $0x16\n\t"
246
 					   "int $0x16\n\t"
189
 					   "cli\n\t" )
247
 					   "cli\n\t" )
190
-			       : "=a" ( character ) : "a" ( 0x0000 ) );
248
+			       : "=a" ( keypress ) : "a" ( 0x1000 ) );
249
+	character = ( keypress & 0xff );
191
 
250
 
192
-	return character;
251
+	/* If it's a normal character, just return it */
252
+	if ( character )
253
+		return character;
254
+
255
+	/* Otherwise, check for a special key that we know about */
256
+	if ( ( ansi_seq = scancode_to_ansi_seq ( keypress >> 8 ) ) ) {
257
+		/* Start of escape sequence: return ESC (0x1b) */
258
+		ansi_input = ansi_seq;
259
+		return 0x1b;
260
+	}
261
+
262
+	return 0;
193
 }
263
 }
194
 
264
 
195
 /**
265
 /**
201
 static int bios_iskey ( void ) {
271
 static int bios_iskey ( void ) {
202
 	unsigned int discard_a;
272
 	unsigned int discard_a;
203
 	unsigned int flags;
273
 	unsigned int flags;
204
-	
274
+
275
+	/* If we are mid-sequence, we are always ready */
276
+	if ( *ansi_input )
277
+		return 1;
278
+
279
+	/* Otherwise check the real BIOS console */
205
 	__asm__ __volatile__ ( REAL_CODE ( "sti\n\t"
280
 	__asm__ __volatile__ ( REAL_CODE ( "sti\n\t"
206
 					   "int $0x16\n\t"
281
 					   "int $0x16\n\t"
207
 					   "pushfw\n\t"
282
 					   "pushfw\n\t"
209
 					   "cli\n\t" )
284
 					   "cli\n\t" )
210
 			       : "=r" ( flags ), "=a" ( discard_a )
285
 			       : "=r" ( flags ), "=a" ( discard_a )
211
 			       : "a" ( 0x0100 ) );
286
 			       : "a" ( 0x0100 ) );
212
-	
213
 	return ( ! ( flags & ZF ) );
287
 	return ( ! ( flags & ZF ) );
214
 }
288
 }
215
 
289
 

Loading…
Cancelar
Guardar