Esempio n. 1
0
/* read one byte from the keyboard if it's allowed */
static int
pckbd_read(keyboard_t *kbd, int wait)
{
	int c;

	if (wait)
		c = read_kbd_data(((pckbd_state_t *)kbd->kb_data)->kbdc);
	else
		c = read_kbd_data_no_wait(((pckbd_state_t *)kbd->kb_data)->kbdc);
	return (KBD_IS_ACTIVE(kbd) ? c : -1);
}
Esempio n. 2
0
/* read one byte from the keyboard if it's allowed */
static int
atkbd_read(keyboard_t *kbd, int wait)
{
	int c, ret;

	if (wait)
		c = read_kbd_data(((atkbd_state_t *)kbd->kb_data)->kbdc);
	else
		c = read_kbd_data_no_wait(((atkbd_state_t *)kbd->kb_data)->kbdc);
	if (c != -1)
		++kbd->kb_count;

	ret = (KBD_IS_ACTIVE(kbd) ? c : -1);

	return ret;
}
Esempio n. 3
0
/* read char from the keyboard */
static u_int
pckbd_read_char(keyboard_t *kbd, int wait)
{
	pckbd_state_t *state;
	u_int action;
	int scancode;
	int keycode;

	state = (pckbd_state_t *)kbd->kb_data;
next_code:
	/* do we have a composed char to return? */
	if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0)) {
		action = state->ks_composed_char;
		state->ks_composed_char = 0;
		if (action > UCHAR_MAX)
			return ERRKEY;
		return action;
	}

	/* see if there is something in the keyboard port */
	if (wait) {
		do {
			scancode = read_kbd_data(state->kbdc);
		} while (scancode == -1);
	} else {
		scancode = read_kbd_data_no_wait(state->kbdc);
		if (scancode == -1)
			return NOKEY;
	}
	++kbd->kb_count;

#if 0
	printf("pckbd_read_char(): scancode:0x%x\n", scancode);
#endif

	/* return the byte as is for the K_RAW mode */
	if (state->ks_mode == K_RAW)
		return scancode;

	/* translate the scan code into a keycode */
	keycode = scancode & 0x7F;
	switch(scancode) {
	case 0xF3:	/* GRPH (compose key) released */
		if (state->ks_flags & COMPOSE) {
			state->ks_flags &= ~COMPOSE;
			if (state->ks_composed_char > UCHAR_MAX)
				state->ks_composed_char = 0;
		}
		break;
	case 0x73:	/* GRPH (compose key) pressed */
		if (!(state->ks_flags & COMPOSE)) {
			state->ks_flags |= COMPOSE;
			state->ks_composed_char = 0;
		}
		break;
	}

	/* return the key code in the K_CODE mode */
	if (state->ks_mode == K_CODE)
		return (keycode | (scancode & 0x80));

	/* compose a character code */
	if (state->ks_flags & COMPOSE) {
		switch (scancode) {
		/* key pressed, process it */
		case 0x42: case 0x43: case 0x44:	/* keypad 7,8,9 */
			state->ks_composed_char *= 10;
			state->ks_composed_char += scancode - 0x3B;
			if (state->ks_composed_char > UCHAR_MAX)
				return ERRKEY;
			goto next_code;
		case 0x46: case 0x47: case 0x48:	/* keypad 4,5,6 */
			state->ks_composed_char *= 10;
			state->ks_composed_char += scancode - 0x42;
			if (state->ks_composed_char > UCHAR_MAX)
				return ERRKEY;
			goto next_code;
		case 0x4A: case 0x4B: case 0x4C:	/* keypad 1,2,3 */
			state->ks_composed_char *= 10;
			state->ks_composed_char += scancode - 0x49;
			if (state->ks_composed_char > UCHAR_MAX)
				return ERRKEY;
			goto next_code;
		case 0x4E:				/* keypad 0 */
			state->ks_composed_char *= 10;
			if (state->ks_composed_char > UCHAR_MAX)
				return ERRKEY;
			goto next_code;

		/* key released, no interest here */
		case 0xC2: case 0xC3: case 0xC4:	/* keypad 7,8,9 */
		case 0xC6: case 0xC7: case 0xC8:	/* keypad 4,5,6 */
		case 0xCA: case 0xCB: case 0xCC:	/* keypad 1,2,3 */
		case 0xCE:				/* keypad 0 */
			goto next_code;

		case 0x73:				/* GRPH key */
			break;

		default:
			if (state->ks_composed_char > 0) {
				state->ks_flags &= ~COMPOSE;
				state->ks_composed_char = 0;
				return ERRKEY;
			}
			break;
		}
	}

	/* keycode to key action */
	action = genkbd_keyaction(kbd, keycode, scancode & 0x80,
				  &state->ks_state, &state->ks_accents);
	if (action == NOKEY)
		goto next_code;
	else
		return action;
}
Esempio n. 4
0
/* read char from the keyboard */
static u_int
atkbd_read_char(keyboard_t *kbd, int wait)
{
    atkbd_state_t *state;
    u_int action;
    int scancode;
    int keycode;

    state = (atkbd_state_t *)kbd->kb_data;
next_code:
    /* do we have a composed char to return? */
    if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0)) {
        action = state->ks_composed_char;
        state->ks_composed_char = 0;
        if (action > UCHAR_MAX)
            return ERRKEY;
        return action;
    }

    /* see if there is something in the keyboard port */
    if (wait) {
        do {
            scancode = read_kbd_data(state->kbdc);
        } while (scancode == -1);
    } else {
        scancode = read_kbd_data_no_wait(state->kbdc);
        if (scancode == -1)
            return NOKEY;
    }
    ++kbd->kb_count;

#if KBDIO_DEBUG >= 10
    printf("atkbd_read_char(): scancode:0x%x\n", scancode);
#endif

    /* return the byte as is for the K_RAW mode */
    if (state->ks_mode == K_RAW)
        return scancode;

    /* translate the scan code into a keycode */
    keycode = scancode & 0x7F;
    switch (state->ks_prefix) {
    case 0x00:	/* normal scancode */
        switch(scancode) {
        case 0xB8:	/* left alt (compose key) released */
            if (state->ks_flags & COMPOSE) {
                state->ks_flags &= ~COMPOSE;
                if (state->ks_composed_char > UCHAR_MAX)
                    state->ks_composed_char = 0;
            }
            break;
        case 0x38:	/* left alt (compose key) pressed */
            if (!(state->ks_flags & COMPOSE)) {
                state->ks_flags |= COMPOSE;
                state->ks_composed_char = 0;
            }
            break;
        case 0xE0:
        case 0xE1:
            state->ks_prefix = scancode;
            goto next_code;
        }
        break;
    case 0xE0:      /* 0xE0 prefix */
        state->ks_prefix = 0;
        switch (keycode) {
        case 0x1C:	/* right enter key */
            keycode = 0x59;
            break;
        case 0x1D:	/* right ctrl key */
            keycode = 0x5A;
            break;
        case 0x35:	/* keypad divide key */
            keycode = 0x5B;
            break;
        case 0x37:	/* print scrn key */
            keycode = 0x5C;
            break;
        case 0x38:	/* right alt key (alt gr) */
            keycode = 0x5D;
            break;
        case 0x46:	/* ctrl-pause/break on AT 101 (see below) */
            keycode = 0x68;
            break;
        case 0x47:	/* grey home key */
            keycode = 0x5E;
            break;
        case 0x48:	/* grey up arrow key */
            keycode = 0x5F;
            break;
        case 0x49:	/* grey page up key */
            keycode = 0x60;
            break;
        case 0x4B:	/* grey left arrow key */
            keycode = 0x61;
            break;
        case 0x4D:	/* grey right arrow key */
            keycode = 0x62;
            break;
        case 0x4F:	/* grey end key */
            keycode = 0x63;
            break;
        case 0x50:	/* grey down arrow key */
            keycode = 0x64;
            break;
        case 0x51:	/* grey page down key */
            keycode = 0x65;
            break;
        case 0x52:	/* grey insert key */
            keycode = 0x66;
            break;
        case 0x53:	/* grey delete key */
            keycode = 0x67;
            break;
        /* the following 3 are only used on the MS "Natural" keyboard */
        case 0x5b:	/* left Window key */
            keycode = 0x69;
            break;
        case 0x5c:	/* right Window key */
            keycode = 0x6a;
            break;
        case 0x5d:	/* menu key */
            keycode = 0x6b;
            break;
        case 0x5e:	/* power key */
            keycode = 0x6d;
            break;
        case 0x5f:	/* sleep key */
            keycode = 0x6e;
            break;
        case 0x63:	/* wake key */
            keycode = 0x6f;
            break;
        default:	/* ignore everything else */
            goto next_code;
        }
        break;
    case 0xE1:	/* 0xE1 prefix */
        /*
         * The pause/break key on the 101 keyboard produces:
         * E1-1D-45 E1-9D-C5
         * Ctrl-pause/break produces:
         * E0-46 E0-C6 (See above.)
         */
        state->ks_prefix = 0;
        if (keycode == 0x1D)
            state->ks_prefix = 0x1D;
        goto next_code;
    /* NOT REACHED */
    case 0x1D:	/* pause / break */
        state->ks_prefix = 0;
        if (keycode != 0x45)
            goto next_code;
        keycode = 0x68;
        break;
    }

    if (kbd->kb_type == KB_84) {
        switch (keycode) {
        case 0x37:	/* *(numpad)/print screen */
            if (state->ks_flags & SHIFTS)
                keycode = 0x5c;	/* print screen */
            break;
        case 0x45:	/* num lock/pause */
            if (state->ks_flags & CTLS)
                keycode = 0x68;	/* pause */
            break;
        case 0x46:	/* scroll lock/break */
            if (state->ks_flags & CTLS)
                keycode = 0x6c;	/* break */
            break;
        }
    } else if (kbd->kb_type == KB_101) {
        switch (keycode) {
        case 0x5c:	/* print screen */
            if (state->ks_flags & ALTS)
                keycode = 0x54;	/* sysrq */
            break;
        case 0x68:	/* pause/break */
            if (state->ks_flags & CTLS)
                keycode = 0x6c;	/* break */
            break;
        }
    }

    /* return the key code in the K_CODE mode */
    if (state->ks_mode == K_CODE)
        return (keycode | (scancode & 0x80));

    /* compose a character code */
    if (state->ks_flags & COMPOSE) {
        switch (keycode | (scancode & 0x80)) {
        /* key pressed, process it */
        case 0x47:
        case 0x48:
        case 0x49:	/* keypad 7,8,9 */
            state->ks_composed_char *= 10;
            state->ks_composed_char += keycode - 0x40;
            if (state->ks_composed_char > UCHAR_MAX)
                return ERRKEY;
            goto next_code;
        case 0x4B:
        case 0x4C:
        case 0x4D:	/* keypad 4,5,6 */
            state->ks_composed_char *= 10;
            state->ks_composed_char += keycode - 0x47;
            if (state->ks_composed_char > UCHAR_MAX)
                return ERRKEY;
            goto next_code;
        case 0x4F:
        case 0x50:
        case 0x51:	/* keypad 1,2,3 */
            state->ks_composed_char *= 10;
            state->ks_composed_char += keycode - 0x4E;
            if (state->ks_composed_char > UCHAR_MAX)
                return ERRKEY;
            goto next_code;
        case 0x52:				/* keypad 0 */
            state->ks_composed_char *= 10;
            if (state->ks_composed_char > UCHAR_MAX)
                return ERRKEY;
            goto next_code;

        /* key released, no interest here */
        case 0xC7:
        case 0xC8:
        case 0xC9:	/* keypad 7,8,9 */
        case 0xCB:
        case 0xCC:
        case 0xCD:	/* keypad 4,5,6 */
        case 0xCF:
        case 0xD0:
        case 0xD1:	/* keypad 1,2,3 */
        case 0xD2:				/* keypad 0 */
            goto next_code;

        case 0x38:				/* left alt key */
            break;

        default:
            if (state->ks_composed_char > 0) {
                state->ks_flags &= ~COMPOSE;
                state->ks_composed_char = 0;
                return ERRKEY;
            }
            break;
        }
    }

    /* keycode to key action */
    action = genkbd_keyaction(kbd, keycode, scancode & 0x80,
                              &state->ks_state, &state->ks_accents);
    if (action == NOKEY)
        goto next_code;
    else
        return action;
}
Esempio n. 5
0
static int
init_keyboard(KBDC kbdc, int *type, int flags)
{
	int codeset;
	int id;
	int c;
	int mux_version;
	int mux_mask;
	int mux_val;

	if (!kbdc_lock(kbdc, TRUE)) {
		/* driver error? */
		return EIO;
	}

	/*
	 * XXX block data transmission from the keyboard.  This can cause
	 * the keyboard to stop sending keystrokes even when re-enabled
	 * under certain circumstances if not followed by a full reset.
	 */
	write_controller_command(kbdc, KBDC_DISABLE_KBD_PORT);

#if 0
	if (atkbd_setmuxmode(kbdc, 1, &mux_version)) {
		kprintf("atkbd: no mux\n");
		mux_version = -1;
	} else {
		kprintf("atkbd: mux present version %d\n", mux_version);
	}
#else
	mux_version = -1;
#endif

	/* save the current controller command byte */
	empty_both_buffers(kbdc, 200);
	c = get_controller_command_byte(kbdc);
	if (c == -1) {
		/* CONTROLLER ERROR */
		kbdc_lock(kbdc, FALSE);
		kprintf("atkbd: unable to get the current command byte value.\n");
		return EIO;
	}
	if (bootverbose)
		kprintf("atkbd: the current kbd controller command byte %04x\n",
		       c);
#if 0
	/* override the keyboard lock switch */
	c |= KBD_OVERRIDE_KBD_LOCK;
#endif

	/* enable the keyboard port, but disable the keyboard intr. */
	if (setup_kbd_port(kbdc, TRUE, FALSE)) {
		/* CONTROLLER ERROR: there is very little we can do... */
		kprintf("atkbd: unable to set the command byte.\n");
		kbdc_lock(kbdc, FALSE);
		return EIO;
	}

	/* default codeset */
	codeset = -1;

	/* reset keyboard hardware */
	if (!(flags & KB_CONF_NO_RESET) && !reset_kbd(kbdc)) {
		/*
		 * KEYBOARD ERROR
		 * Keyboard reset may fail either because the keyboard
		 * doen't exist, or because the keyboard doesn't pass
		 * the self-test, or the keyboard controller on the
		 * motherboard and the keyboard somehow fail to shake hands.
		 * It is just possible, particularly in the last case,
		 * that the keyoard controller may be left in a hung state.
		 * test_controller() and test_kbd_port() appear to bring
		 * the keyboard controller back (I don't know why and how,
		 * though.)
		 */
		empty_both_buffers(kbdc, 10);
		test_controller(kbdc);
		test_kbd_port(kbdc);
		/*
		 * We could disable the keyboard port and interrupt... but,
		 * the keyboard may still exist (see above).
		 */
		set_controller_command_byte(kbdc, KBD_KBD_CONTROL_BITS, c);
		kbdc_lock(kbdc, FALSE);
		if (bootverbose)
			kprintf("atkbd: failed to reset the keyboard.\n");
		return EIO;
	}

	/* 
	 * Check if we have an XT keyboard before we attempt to reset it. 
	 * The procedure assumes that the keyboard and the controller have 
	 * been set up properly by BIOS and have not been messed up 
	 * during the boot process.
	 */
	codeset = -1;
	if (flags & KB_CONF_ALT_SCANCODESET)
		/* the user says there is a XT keyboard */
		codeset = 1;
#ifdef KBD_DETECT_XT_KEYBOARD
	else if ((c & KBD_TRANSLATION) == 0) {
		/* SET_SCANCODE_SET is not always supported; ignore error */
		if (send_kbd_command_and_data(kbdc, KBDC_SET_SCANCODE_SET, 0)
			== KBD_ACK) 
			codeset = read_kbd_data(kbdc);
	}
#endif /* KBD_DETECT_XT_KEYBOARD */
	if (bootverbose)
		kprintf("atkbd: scancode set %d\n", codeset);
 
	/*
	 * Get the keyboard id.
	 */
	*type = KB_OTHER;
	id = get_kbd_id(kbdc, ATKBD_CMD_GETID);
	switch(id) {
	case 0x41ab:	/* 101/102/... Enhanced */
	case 0x83ab:	/* ditto */
	case 0x54ab:	/* SpaceSaver */
	case 0x84ab:	/* ditto */
#if 0
	case 0x90ab:	/* 'G' */
	case 0x91ab:	/* 'P' */
	case 0x92ab:	/* 'A' */
#endif
		*type = KB_101;
		break;
	case -1:	/* AT 84 keyboard doesn't return ID */
		*type = KB_84;
		break;
	default:
		break;
	}
	if (bootverbose)
		kprintf("atkbd: keyboard ID 0x%x (%d)\n", id, *type);

	/*
	 * Allow us to set the XT_KEYBD flag in UserConfig so that keyboards
	 * such as those on the IBM ThinkPad laptop computers can be used
	 * with the standard console driver.
	 */
	if (codeset == 1) {
		if (send_kbd_command_and_data(kbdc,
			KBDC_SET_SCANCODE_SET, codeset) == KBD_ACK) {
			/* XT kbd doesn't need scan code translation */
			c &= ~KBD_TRANSLATION;
		} else {
			/*
			 * KEYBOARD ERROR 
			 * The XT kbd isn't usable unless the proper scan
			 * code set is selected. 
			 */
			set_controller_command_byte(kbdc,
						    KBD_KBD_CONTROL_BITS, c);
			kbdc_lock(kbdc, FALSE);
			kprintf("atkbd: unable to set the XT keyboard mode.\n");
			return EIO;
		}
	}

#if 0
	if (send_kbd_command_and_data(kbdc, ATKBD_CMD_EX_ENABLE, 0x71) != KBD_ACK)
		kprintf("atkbd: can't CMD_EX_ENABLE\n");

	if (send_kbd_command(kbdc, ATKBD_CMD_SETALL_MB) != KBD_ACK)
		kprintf("atkbd: can't SETALL_MB\n");
	if (send_kbd_command(kbdc, ATKBD_CMD_SETALL_MBR) != KBD_ACK)
		kprintf("atkbd: can't SETALL_MBR\n");
#endif
#if 0
	if (send_kbd_command_and_data(kbdc, ATKBD_CMD_SSCANSET, 2) != KBD_ACK)
		kprintf("atkbd: can't SSCANSET\n");
	if (send_kbd_command_and_data(kbdc, ATKBD_CMD_GSCANSET, 0) != KBD_ACK)
		kprintf("atkbd: can't SSCANSET\n");
	else
		kprintf("atkbd: scanset %d\n", read_kbd_data(kbdc));
#endif
#if 0
	kprintf("atkbd: id %04x\n", get_kbd_id(kbdc, ATKBD_CMD_OK_GETID));
	if (send_kbd_command_and_data(kbdc, ATKBD_CMD_SETLEDS, 0) != KBD_ACK)
		kprintf("atkbd: setleds failed\n");
	if (send_kbd_command_and_data(kbdc, ATKBD_CMD_SETREP, 255) != KBD_ACK)
		kprintf("atkbd: setrep failed\n");
	if (send_kbd_command(kbdc, ATKBD_CMD_RESEND) != KBD_ACK)
		kprintf("atkbd: resend failed\n");
#endif
	/*
	 * Some keyboards require a SETLEDS command to be sent after
	 * the reset command before they will send keystrokes to us
	 * (Acer C720).
	 */
	if (send_kbd_command_and_data(kbdc, ATKBD_CMD_SETLEDS, 0) != KBD_ACK)
		kprintf("atkbd: setleds failed\n");
	send_kbd_command(kbdc, ATKBD_CMD_ENABLE);

#if 0
	/* DEBUGGING */
	{
		int retry;
		int c;
		kprintf("atkbd: waiting for keypress");
		for (retry = 0; retry < 10; ++retry) {
			c = read_kbd_data_no_wait(kbdc);
			kprintf(" %d", c);
			tsleep(&c, 0, "wait", hz);
		}
		kprintf("\n");
	}
#endif

	if (mux_version == -1) {
		mux_mask = 0;
		mux_val = 0;
	} else {
		mux_mask = KBD_AUX_CONTROL_BITS;
		mux_val = 0;
		kprintf("atkbd: setaux for multiplexer\n");
	}

	/* enable the keyboard port and intr. */
	if (!set_controller_command_byte(kbdc, 
		KBD_KBD_CONTROL_BITS | KBD_TRANSLATION |
		KBD_OVERRIDE_KBD_LOCK | mux_mask,
		(c & (KBD_TRANSLATION | KBD_OVERRIDE_KBD_LOCK))
		    | KBD_ENABLE_KBD_PORT | KBD_ENABLE_KBD_INT | mux_val)) {
		/*
		 * CONTROLLER ERROR 
		 * This is serious; we are left with the disabled
		 * keyboard intr. 
		 */
		set_controller_command_byte(kbdc,
				KBD_KBD_CONTROL_BITS | KBD_TRANSLATION |
				KBD_OVERRIDE_KBD_LOCK | mux_mask,
				c);
		kbdc_lock(kbdc, FALSE);
		kprintf("atkbd: unable to enable the keyboard port and intr.\n");
		return EIO;
	}

	kbdc_lock(kbdc, FALSE);
	return 0;
}