Преглед на файлове

Return ANSI sequences for special keys

tags/v0.9.3
Michael Brown преди 17 години
родител
ревизия
dbb7b30cca
променени са 1 файла, в които са добавени 80 реда и са изтрити 6 реда
  1. 80
    6
      src/arch/i386/firmware/pcbios/bios_console.c

+ 80
- 6
src/arch/i386/firmware/pcbios/bios_console.c Целия файл

@@ -176,20 +176,90 @@ static void bios_putchar ( int character ) {
176 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 229
  * Get character from BIOS console
181 230
  *
182 231
  * @ret character	Character read from console
183 232
  */
184 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 245
 	__asm__ __volatile__ ( REAL_CODE ( "sti\n\t"
188 246
 					   "int $0x16\n\t"
189 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,7 +271,12 @@ static int bios_getchar ( void ) {
201 271
 static int bios_iskey ( void ) {
202 272
 	unsigned int discard_a;
203 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 280
 	__asm__ __volatile__ ( REAL_CODE ( "sti\n\t"
206 281
 					   "int $0x16\n\t"
207 282
 					   "pushfw\n\t"
@@ -209,7 +284,6 @@ static int bios_iskey ( void ) {
209 284
 					   "cli\n\t" )
210 285
 			       : "=r" ( flags ), "=a" ( discard_a )
211 286
 			       : "a" ( 0x0100 ) );
212
-	
213 287
 	return ( ! ( flags & ZF ) );
214 288
 }
215 289
 

Loading…
Отказ
Запис