static int
sunkbd_configure(int flags)
{
    struct sunkbd_softc *sc;

    /*
     * We are only prepared to be used for the high-level console
     * when the keyboard is both configured and attached.
     */
    if (!(flags & KB_CONF_PROBE_ONLY)) {
        if (KBD_IS_INITIALIZED(&sunkbd_softc.sc_kbd))
            goto found;
        else
            return (0);
    }

    if (uart_cpu_getdev(UART_DEV_KEYBOARD, &uart_keyboard))
        return (0);
    if (uart_probe(&uart_keyboard))
        return (0);
    uart_init(&uart_keyboard);

    uart_keyboard.type = UART_DEV_KEYBOARD;
    uart_keyboard.attach = sunkbd_attach;
    uart_add_sysdev(&uart_keyboard);

    if (sunkbd_probe_keyboard(&uart_keyboard) != KB_SUN4)
        return (0);

    sc = &sunkbd_softc;
    callout_init(&sc->sc_repeat_callout, 0);
    sunkbd_clear_state(&sc->sc_kbd);

#if defined(SUNKBD_EMULATE_ATKBD)
    kbd_init_struct(&sc->sc_kbd, SUNKBD_DRIVER_NAME, KB_101, 0, 0, 0, 0);
    kbd_set_maps(&sc->sc_kbd, &key_map, &accent_map, fkey_tab,
                 sizeof(fkey_tab) / sizeof(fkey_tab[0]));
#else
    kbd_init_struct(&sc->sc_kbd, SUNKBD_DRIVER_NAME, KB_OTHER, 0, 0, 0, 0);
    kbd_set_maps(&sc->sc_kbd, &keymap_sun_us_unix_kbd,
                 &accentmap_sun_us_unix_kbd, fkey_tab,
                 sizeof(fkey_tab) / sizeof(fkey_tab[0]));
#endif
    sc->sc_mode = K_XLATE;
    kbd_register(&sc->sc_kbd);

    sc->sc_sysdev = &uart_keyboard;

found:
    /* Return number of found keyboards. */
    return (1);
}
예제 #2
0
/*
 * Reset and initialize the device.  Note that unit 0 (UKBD_DEFAULT) is an
 * always-connected device once it has been initially detected.  We do not
 * deregister it if the usb keyboard is unplugged to avoid losing the 
 * connection to the console.  This feature also handles the USB bus reset
 * which detaches and reattaches USB devices during boot.
 */
static int
ukbd_init(int unit, keyboard_t **kbdp, void *arg, int flags)
{
	keyboard_t *kbd;
	ukbd_state_t *state;
	keymap_t *keymap;
	accentmap_t *accmap;
	fkeytab_t *fkeymap;
	int fkeymap_size;
	void **data = (void **)arg;
	struct usb_attach_arg *uaa = (struct usb_attach_arg *)data[0];

	if (unit == UKBD_DEFAULT) {
		*kbdp = kbd = &default_kbd;
		if (KBD_IS_INITIALIZED(kbd) && KBD_IS_CONFIGURED(kbd)) {
			return 0;
		}
		state = &default_kbd_state;
		keymap = &default_keymap;
		accmap = &default_accentmap;
		fkeymap = default_fkeytab;
		fkeymap_size = NELEM(default_fkeytab);
	} else if (*kbdp == NULL) {
		*kbdp = kbd = kmalloc(sizeof(*kbd), M_DEVBUF, M_INTWAIT | M_ZERO);
		state = kmalloc(sizeof(*state), M_DEVBUF, M_INTWAIT);
		keymap = kmalloc(sizeof(key_map), M_DEVBUF, M_INTWAIT);
		accmap = kmalloc(sizeof(accent_map), M_DEVBUF, M_INTWAIT);
		fkeymap = kmalloc(sizeof(fkey_tab), M_DEVBUF, M_INTWAIT);
		fkeymap_size = NELEM(fkey_tab);
		if ((state == NULL) || (keymap == NULL) || (accmap == NULL)
		     || (fkeymap == NULL)) {
			if (state != NULL)
				kfree(state, M_DEVBUF);
			if (keymap != NULL)
				kfree(keymap, M_DEVBUF);
			if (accmap != NULL)
				kfree(accmap, M_DEVBUF);
			if (fkeymap != NULL)
				kfree(fkeymap, M_DEVBUF);
			kfree(kbd, M_DEVBUF);
			return ENOMEM;
		}
	} else if (KBD_IS_INITIALIZED(*kbdp) && KBD_IS_CONFIGURED(*kbdp)) {
		return 0;
	} else {
		kbd = *kbdp;
		state = (ukbd_state_t *)kbd->kb_data;
		keymap = kbd->kb_keymap;
		accmap = kbd->kb_accentmap;
		fkeymap = kbd->kb_fkeytab;
		fkeymap_size = kbd->kb_fkeytab_size;
	}

	if (!KBD_IS_PROBED(kbd)) {
		kbd_init_struct(kbd, DRIVER_NAME, KB_OTHER,
				unit, flags, KB_PRI_USB,
				0, 0);
		bzero(state, sizeof(*state));
		bcopy(&key_map, keymap, sizeof(key_map));
		bcopy(&accent_map, accmap, sizeof(accent_map));
		bcopy(fkey_tab, fkeymap,
		      imin(fkeymap_size*sizeof(fkeymap[0]), sizeof(fkey_tab)));
		kbd_set_maps(kbd, keymap, accmap, fkeymap, fkeymap_size);
		kbd->kb_data = (void *)state;

		if (probe_keyboard(uaa, flags)) {
			return ENXIO;
		} else {
			KBD_FOUND_DEVICE(kbd);
		}
		ukbd_clear_state(kbd);

		/*
		 * If reattatching to an already open keyboard (e.g. console),
		 * try to restore the translation mode.  Otherwise set the
		 * translation mode to, well, translation mode so we don't
		 * get garbage.
		 */
		state->ks_mode = K_XLATE;
		state->ks_iface = uaa->iface;
		state->ks_uaa = uaa;
		state->ks_ifstate = 0;
		callout_init_mp(&state->ks_timeout);
		/*
		 * FIXME: set the initial value for lock keys in ks_state
		 * according to the BIOS data?
		 */
		KBD_PROBE_DONE(kbd);
	}
	if (!KBD_IS_INITIALIZED(kbd) && !(flags & KB_CONF_PROBE_ONLY)) {
		if (KBD_HAS_DEVICE(kbd)
		    && init_keyboard((ukbd_state_t *)kbd->kb_data,
				     &kbd->kb_type, kbd->kb_flags)) {
			return ENXIO;
		}
		ukbd_ioctl(kbd, KDSETLED, (caddr_t)&(state->ks_state));
	}
	if (!KBD_IS_CONFIGURED(kbd)) {
		if (kbd_register(kbd) < 0) {
			kbd->kb_flags = 0;
			/* XXX: Missing free()'s */
			return ENXIO;
		}
		if (ukbd_enable_intr(kbd, TRUE, (usbd_intr_t *)data[1]) == 0)
			ukbd_timeout((void *)kbd);
		KBD_CONFIG_DONE(kbd);
	}

	return 0;
}
예제 #3
0
/* reset and initialize the device */
static int
pckbd_init(int unit, keyboard_t **kbdp, void *arg, int flags)
{
	keyboard_t *kbd;
	pckbd_state_t *state;
	keymap_t *keymap;
	accentmap_t *accmap;
	fkeytab_t *fkeymap;
	int fkeymap_size;
	int *data = (int *)arg;

	if (unit != PC98KBD_DEFAULT)			/* shouldn't happen */
		return ENXIO;

	*kbdp = kbd = &default_kbd;
	state = &default_kbd_state;
	if (!KBD_IS_PROBED(kbd)) {
		keymap = &default_keymap;
		accmap = &default_accentmap;
		fkeymap = default_fkeytab;
		fkeymap_size =
			sizeof(default_fkeytab)/sizeof(default_fkeytab[0]);

		state->kbdc = kbdc_open(data[0]);
		if (state->kbdc == NULL)
			return ENXIO;
		kbd_init_struct(kbd, DRIVER_NAME, KB_OTHER, unit, flags,
				data[0], IO_KBDSIZE);
		bcopy(&key_map, keymap, sizeof(key_map));
		bcopy(&accent_map, accmap, sizeof(accent_map));
		bcopy(fkey_tab, fkeymap,
		      imin(fkeymap_size*sizeof(fkeymap[0]), sizeof(fkey_tab)));
		kbd_set_maps(kbd, keymap, accmap, fkeymap, fkeymap_size);
		kbd->kb_data = (void *)state;

		if (probe_keyboard(state->kbdc, flags)) {/* shouldn't happen */
			if (flags & KB_CONF_FAIL_IF_NO_KBD)
				return ENXIO;
		} else {
			KBD_FOUND_DEVICE(kbd);
		}
		pckbd_clear_state(kbd);
		state->ks_mode = K_XLATE;
		KBD_PROBE_DONE(kbd);
	}
	if (!KBD_IS_INITIALIZED(kbd) && !(flags & KB_CONF_PROBE_ONLY)) {
		if (KBD_HAS_DEVICE(kbd)
		    && init_keyboard(state->kbdc, &kbd->kb_type, kbd->kb_config)
		    && (kbd->kb_config & KB_CONF_FAIL_IF_NO_KBD))
			return ENXIO;
		pckbd_ioctl(kbd, KDSETLED, (caddr_t)&state->ks_state);
		KBD_INIT_DONE(kbd);
	}
	if (!KBD_IS_CONFIGURED(kbd)) {
		if (kbd_register(kbd) < 0)
			return ENXIO;
		KBD_CONFIG_DONE(kbd);
	}

	return 0;
}
예제 #4
0
/* reset and initialize the device */
static int
atkbd_init(int unit, keyboard_t **kbdp, void *arg, int flags)
{
    keyboard_t *kbd;
    atkbd_state_t *state;
    keymap_t *keymap;
    accentmap_t *accmap;
    fkeytab_t *fkeymap;
    int fkeymap_size;
    int delay[2];
    int *data = (int *)arg;	/* data[0]: controller, data[1]: irq */
    int error, needfree;

    /* XXX */
    if (unit == ATKBD_DEFAULT) {
        *kbdp = kbd = &default_kbd;
        if (KBD_IS_INITIALIZED(kbd) && KBD_IS_CONFIGURED(kbd))
            return 0;
        state = &default_kbd_state;
        keymap = &default_keymap;
        accmap = &default_accentmap;
        fkeymap = default_fkeytab;
        fkeymap_size =
            sizeof(default_fkeytab)/sizeof(default_fkeytab[0]);
        needfree = 0;
    } else if (*kbdp == NULL) {
        *kbdp = kbd = malloc(sizeof(*kbd), M_DEVBUF, M_NOWAIT | M_ZERO);
        state = malloc(sizeof(*state), M_DEVBUF, M_NOWAIT | M_ZERO);
        /* NB: these will always be initialized 'cuz !KBD_IS_PROBED */
        keymap = malloc(sizeof(key_map), M_DEVBUF, M_NOWAIT);
        accmap = malloc(sizeof(accent_map), M_DEVBUF, M_NOWAIT);
        fkeymap = malloc(sizeof(fkey_tab), M_DEVBUF, M_NOWAIT);
        fkeymap_size = sizeof(fkey_tab)/sizeof(fkey_tab[0]);
        needfree = 1;
        if ((kbd == NULL) || (state == NULL) || (keymap == NULL)
                || (accmap == NULL) || (fkeymap == NULL)) {
            error = ENOMEM;
            goto bad;
        }
    } else if (KBD_IS_INITIALIZED(*kbdp) && KBD_IS_CONFIGURED(*kbdp)) {
        return 0;
    } else {
        kbd = *kbdp;
        state = (atkbd_state_t *)kbd->kb_data;
        bzero(state, sizeof(*state));
        keymap = kbd->kb_keymap;
        accmap = kbd->kb_accentmap;
        fkeymap = kbd->kb_fkeytab;
        fkeymap_size = kbd->kb_fkeytab_size;
        needfree = 0;
    }

    if (!KBD_IS_PROBED(kbd)) {
        state->kbdc = atkbdc_open(data[0]);
        if (state->kbdc == NULL) {
            error = ENXIO;
            goto bad;
        }
        kbd_init_struct(kbd, ATKBD_DRIVER_NAME, KB_OTHER, unit, flags,
                        0, 0);
        bcopy(&key_map, keymap, sizeof(key_map));
        bcopy(&accent_map, accmap, sizeof(accent_map));
        bcopy(fkey_tab, fkeymap,
              imin(fkeymap_size*sizeof(fkeymap[0]), sizeof(fkey_tab)));
        kbd_set_maps(kbd, keymap, accmap, fkeymap, fkeymap_size);
        kbd->kb_data = (void *)state;

        if (probe_keyboard(state->kbdc, flags)) { /* shouldn't happen */
            if (flags & KB_CONF_FAIL_IF_NO_KBD) {
                error = ENXIO;
                goto bad;
            }
        } else {
            KBD_FOUND_DEVICE(kbd);
        }
        atkbd_clear_state(kbd);
        state->ks_mode = K_XLATE;
        /*
         * FIXME: set the initial value for lock keys in ks_state
         * according to the BIOS data?
         */
        KBD_PROBE_DONE(kbd);
    }
    if (!KBD_IS_INITIALIZED(kbd) && !(flags & KB_CONF_PROBE_ONLY)) {
        kbd->kb_config = flags & ~KB_CONF_PROBE_ONLY;
        if (KBD_HAS_DEVICE(kbd)
                && init_keyboard(state->kbdc, &kbd->kb_type, kbd->kb_config)
                && (kbd->kb_config & KB_CONF_FAIL_IF_NO_KBD)) {
            kbd_unregister(kbd);
            error = ENXIO;
            goto bad;
        }
        atkbd_ioctl(kbd, KDSETLED, (caddr_t)&state->ks_state);
        get_typematic(kbd);
        delay[0] = kbd->kb_delay1;
        delay[1] = kbd->kb_delay2;
        atkbd_ioctl(kbd, KDSETREPEAT, (caddr_t)delay);
        KBD_INIT_DONE(kbd);
    }
    if (!KBD_IS_CONFIGURED(kbd)) {
        if (kbd_register(kbd) < 0) {
            error = ENXIO;
            goto bad;
        }
        KBD_CONFIG_DONE(kbd);
    }

    return 0;
bad:
    if (needfree) {
        if (state != NULL)
            free(state, M_DEVBUF);
        if (keymap != NULL)
            free(keymap, M_DEVBUF);
        if (accmap != NULL)
            free(accmap, M_DEVBUF);
        if (fkeymap != NULL)
            free(fkeymap, M_DEVBUF);
        if (kbd != NULL) {
            free(kbd, M_DEVBUF);
            *kbdp = NULL;	/* insure ref doesn't leak to caller */
        }
    }
    return error;
}
예제 #5
0
/* reset and initialize the device */
static int
atkbd_init(int unit, keyboard_t **kbdp, void *arg, int flags)
{
	keyboard_t *kbd;
	atkbd_state_t *state;
	keymap_t *keymap;
	accentmap_t *accmap;
	fkeytab_t *fkeymap;
	int fkeymap_size;
	int delay[2];
	int *data = (int *)arg;	/* data[0]: controller, data[1]: irq */

	/* XXX */
	if (unit == ATKBD_DEFAULT) {
		*kbdp = kbd = &default_kbd;
		if (KBD_IS_INITIALIZED(kbd) && KBD_IS_CONFIGURED(kbd)) {
			return 0;
		}
		state = &default_kbd_state;
		keymap = &default_keymap;
		accmap = &default_accentmap;
		fkeymap = default_fkeytab;
		fkeymap_size = NELEM(default_fkeytab);
	} else if (*kbdp == NULL) {
		*kbdp = kbd = kmalloc(sizeof(*kbd), M_DEVBUF, M_WAITOK|M_ZERO);
		state = kmalloc(sizeof(*state), M_DEVBUF, M_WAITOK|M_ZERO);
		keymap = kmalloc(sizeof(key_map), M_DEVBUF, M_WAITOK);
		accmap = kmalloc(sizeof(accent_map), M_DEVBUF, M_WAITOK);
		fkeymap = kmalloc(sizeof(fkey_tab), M_DEVBUF, M_WAITOK);
		fkeymap_size = NELEM(fkey_tab);
	} else if (KBD_IS_INITIALIZED(*kbdp) && KBD_IS_CONFIGURED(*kbdp)) {
		return 0;
	} else {
		kbd = *kbdp;
		state = (atkbd_state_t *)kbd->kb_data;
		bzero(state, sizeof(*state));
		keymap = kbd->kb_keymap;
		accmap = kbd->kb_accentmap;
		fkeymap = kbd->kb_fkeytab;
		fkeymap_size = kbd->kb_fkeytab_size;
	}

	if (!KBD_IS_PROBED(kbd)) {
		state->kbdc = atkbdc_open(data[0]);
		if (state->kbdc == NULL) {
			return ENXIO;
		}
		kbd_init_struct(kbd, ATKBD_DRIVER_NAME, KB_OTHER, unit, flags,
				KB_PRI_ATKBD, 0, 0);
		bcopy(&key_map, keymap, sizeof(key_map));
		bcopy(&accent_map, accmap, sizeof(accent_map));
		bcopy(fkey_tab, fkeymap,
		      imin(fkeymap_size*sizeof(fkeymap[0]), sizeof(fkey_tab)));
		kbd_set_maps(kbd, keymap, accmap, fkeymap, fkeymap_size);
		kbd->kb_data = (void *)state;
	
		if (probe_keyboard(state->kbdc, flags)) { /* shouldn't happen */
			if (flags & KB_CONF_FAIL_IF_NO_KBD) {
				return ENXIO;
			}
		} else {
			KBD_FOUND_DEVICE(kbd);
		}
		atkbd_clear_state(kbd);
		state->ks_mode = K_XLATE;
		/* 
		 * FIXME: set the initial value for lock keys in ks_state
		 * according to the BIOS data?
		 */
		KBD_PROBE_DONE(kbd);
	}
	if (!KBD_IS_INITIALIZED(kbd) && !(flags & KB_CONF_PROBE_ONLY)) {
		kbd->kb_config = flags & ~KB_CONF_PROBE_ONLY;
		if (!KBD_HAS_DEVICE(kbd)
		    && init_keyboard(state->kbdc, &kbd->kb_type, kbd->kb_config)
		    && (kbd->kb_config & KB_CONF_FAIL_IF_NO_KBD)) {
			return ENXIO;
		}
		atkbd_ioctl(kbd, KDSETLED, (caddr_t)&state->ks_state);
		get_typematic(kbd);
		delay[0] = kbd->kb_delay1;
		delay[1] = kbd->kb_delay2;
		atkbd_ioctl(kbd, KDSETREPEAT, (caddr_t)delay);
		KBD_FOUND_DEVICE(kbd);
		KBD_INIT_DONE(kbd);
	}
	if (!KBD_IS_CONFIGURED(kbd)) {
		if (kbd_register(kbd) < 0) {
			return ENXIO;
		}
		KBD_CONFIG_DONE(kbd);
	}

	return 0;
}
예제 #6
0
/* reset and initialize the device */
static int
atkbd_init(int unit, keyboard_t **kbdp, void *arg, int flags)
{
	keyboard_t *kbd;
	atkbd_state_t *state;
	keymap_t *keymap;
	accentmap_t *accmap;
	fkeytab_t *fkeymap;
	int fkeymap_size;
	int *data = (int *)arg;

	/* XXX */
	if (unit == ATKBD_DEFAULT) {
		*kbdp = kbd = &default_kbd;
		if (KBD_IS_INITIALIZED(kbd) && KBD_IS_CONFIGURED(kbd))
			return 0;
		state = &default_kbd_state;
		keymap = &default_keymap;
		accmap = &default_accentmap;
		fkeymap = default_fkeytab;
		fkeymap_size =
			sizeof(default_fkeytab)/sizeof(default_fkeytab[0]);
	} else if (*kbdp == NULL) {
		*kbdp = kbd = malloc(sizeof(*kbd), M_DEVBUF, M_NOWAIT);
		if (kbd == NULL)
			return ENOMEM;
		bzero(kbd, sizeof(*kbd));
		state = malloc(sizeof(*state), M_DEVBUF, M_NOWAIT);
		keymap = malloc(sizeof(key_map), M_DEVBUF, M_NOWAIT);
		accmap = malloc(sizeof(accent_map), M_DEVBUF, M_NOWAIT);
		fkeymap = malloc(sizeof(fkey_tab), M_DEVBUF, M_NOWAIT);
		fkeymap_size = sizeof(fkey_tab)/sizeof(fkey_tab[0]);
		if ((state == NULL) || (keymap == NULL) || (accmap == NULL)
		     || (fkeymap == NULL)) {
			if (state != NULL)
				free(state, M_DEVBUF);
			if (keymap != NULL)
				free(keymap, M_DEVBUF);
			if (accmap != NULL)
				free(accmap, M_DEVBUF);
			if (fkeymap != NULL)
				free(fkeymap, M_DEVBUF);
			free(kbd, M_DEVBUF);
			return ENOMEM;
		}
		bzero(state, sizeof(*state));
	} else if (KBD_IS_INITIALIZED(*kbdp) && KBD_IS_CONFIGURED(*kbdp)) {
		return 0;
	} else {
		kbd = *kbdp;
		state = (atkbd_state_t *)kbd->kb_data;
		bzero(state, sizeof(*state));
		keymap = kbd->kb_keymap;
		accmap = kbd->kb_accentmap;
		fkeymap = kbd->kb_fkeytab;
		fkeymap_size = kbd->kb_fkeytab_size;
	}

	if (!KBD_IS_PROBED(kbd)) {
		state->kbdc = kbdc_open(data[0]);
		if (state->kbdc == NULL)
			return ENXIO;
		kbd_init_struct(kbd, ATKBD_DRIVER_NAME, KB_OTHER, unit, flags,
				data[0], IO_KBDSIZE);
		bcopy(&key_map, keymap, sizeof(key_map));
		bcopy(&accent_map, accmap, sizeof(accent_map));
		bcopy(fkey_tab, fkeymap,
		      imin(fkeymap_size*sizeof(fkeymap[0]), sizeof(fkey_tab)));
		kbd_set_maps(kbd, keymap, accmap, fkeymap, fkeymap_size);
		kbd->kb_data = (void *)state;
	
		if (probe_keyboard(state->kbdc, flags)) { /* shouldn't happen */
			if (flags & KB_CONF_FAIL_IF_NO_KBD)
				return ENXIO;
		} else {
			KBD_FOUND_DEVICE(kbd);
		}
		atkbd_clear_state(kbd);
		state->ks_mode = K_XLATE;
		/* 
		 * FIXME: set the initial value for lock keys in ks_state
		 * according to the BIOS data?
		 */
		KBD_PROBE_DONE(kbd);
	}
	if (!KBD_IS_INITIALIZED(kbd) && !(flags & KB_CONF_PROBE_ONLY)) {
		if (KBD_HAS_DEVICE(kbd)
	    	    && init_keyboard(state->kbdc, &kbd->kb_type, kbd->kb_config)
	    	    && (kbd->kb_config & KB_CONF_FAIL_IF_NO_KBD))
			return ENXIO;
		atkbd_ioctl(kbd, KDSETLED, (caddr_t)&state->ks_state);
		KBD_INIT_DONE(kbd);
	}
	if (!KBD_IS_CONFIGURED(kbd)) {
		if (kbd_register(kbd) < 0)
			return ENXIO;
		KBD_CONFIG_DONE(kbd);
	}

	return 0;
}
예제 #7
0
/* reset and initialize the device */
static int
ukbd_init(int unit, keyboard_t **kbdp, void *arg, int flags)
{
	keyboard_t *kbd;
	ukbd_state_t *state;
	keymap_t *keymap;
	accentmap_t *accmap;
	fkeytab_t *fkeymap;
	int fkeymap_size;
	void **data = (void **)arg;
	struct usb_attach_arg *uaa = (struct usb_attach_arg *)data[0];

	/* XXX */
	if (unit == UKBD_DEFAULT) {
		*kbdp = kbd = &default_kbd;
		if (KBD_IS_INITIALIZED(kbd) && KBD_IS_CONFIGURED(kbd))
			return 0;
		state = &default_kbd_state;
		keymap = &default_keymap;
		accmap = &default_accentmap;
		fkeymap = default_fkeytab;
		fkeymap_size =
			sizeof(default_fkeytab)/sizeof(default_fkeytab[0]);
	} else if (*kbdp == NULL) {
		*kbdp = kbd = malloc(sizeof(*kbd), M_DEVBUF, M_NOWAIT);
		if (kbd == NULL)
			return ENOMEM;
		bzero(kbd, sizeof(*kbd));
		state = malloc(sizeof(*state), M_DEVBUF, M_NOWAIT);
		keymap = malloc(sizeof(key_map), M_DEVBUF, M_NOWAIT);
		accmap = malloc(sizeof(accent_map), M_DEVBUF, M_NOWAIT);
		fkeymap = malloc(sizeof(fkey_tab), M_DEVBUF, M_NOWAIT);
		fkeymap_size = sizeof(fkey_tab)/sizeof(fkey_tab[0]);
		if ((state == NULL) || (keymap == NULL) || (accmap == NULL)
		     || (fkeymap == NULL)) {
			if (state != NULL)
				free(state, M_DEVBUF);
			if (keymap != NULL)
				free(keymap, M_DEVBUF);
			if (accmap != NULL)
				free(accmap, M_DEVBUF);
			if (fkeymap != NULL)
				free(fkeymap, M_DEVBUF);
			free(kbd, M_DEVBUF);
			return ENOMEM;
		}
	} else if (KBD_IS_INITIALIZED(*kbdp) && KBD_IS_CONFIGURED(*kbdp)) {
		return 0;
	} else {
		kbd = *kbdp;
		state = (ukbd_state_t *)kbd->kb_data;
		keymap = kbd->kb_keymap;
		accmap = kbd->kb_accentmap;
		fkeymap = kbd->kb_fkeytab;
		fkeymap_size = kbd->kb_fkeytab_size;
	}

	if (!KBD_IS_PROBED(kbd)) {
		kbd_init_struct(kbd, DRIVER_NAME, KB_OTHER, unit, flags, 0, 0);
		bzero(state, sizeof(*state));
		bcopy(&key_map, keymap, sizeof(key_map));
		bcopy(&accent_map, accmap, sizeof(accent_map));
		bcopy(fkey_tab, fkeymap,
		      imin(fkeymap_size*sizeof(fkeymap[0]), sizeof(fkey_tab)));
		kbd_set_maps(kbd, keymap, accmap, fkeymap, fkeymap_size);
		kbd->kb_data = (void *)state;

		if (probe_keyboard(uaa, flags))
			return ENXIO;
		else
			KBD_FOUND_DEVICE(kbd);
		ukbd_clear_state(kbd);
		state->ks_mode = K_XLATE;
		state->ks_iface = uaa->iface;
		state->ks_uaa = uaa;
		state->ks_ifstate = 0;
		callout_handle_init(&state->ks_timeout_handle);
		/* 
		 * FIXME: set the initial value for lock keys in ks_state
		 * according to the BIOS data?
		 */
		KBD_PROBE_DONE(kbd);
	}
	if (!KBD_IS_INITIALIZED(kbd) && !(flags & KB_CONF_PROBE_ONLY)) {
		if (KBD_HAS_DEVICE(kbd)
		    && init_keyboard((ukbd_state_t *)kbd->kb_data,
				     &kbd->kb_type, kbd->kb_flags))
			return ENXIO;
		ukbd_ioctl(kbd, KDSETLED, (caddr_t)&(state->ks_state));
		KBD_INIT_DONE(kbd);
	}
	if (!KBD_IS_CONFIGURED(kbd)) {
		if (kbd_register(kbd) < 0)
			return ENXIO;
		if (ukbd_enable_intr(kbd, TRUE, (usbd_intr_t *)data[1]) == 0)
			ukbd_timeout((void *)kbd);
		KBD_CONFIG_DONE(kbd);
	}

	return 0;
}
예제 #8
0
/* reset and initialize the device */
static int
atkbd_init(int unit, keyboard_t **kbdp, void *arg, int flags)
{
	keyboard_t *kbd;
	atkbd_state_t *state;
	keymap_t *keymap;
	accentmap_t *accmap;
	fkeytab_t *fkeymap;
	int fkeymap_size;
	int delay[2];
	int *data = (int *)arg;	/* data[0]: controller, data[1]: irq */
	int error, needfree;
#ifdef EVDEV_SUPPORT
	struct evdev_dev *evdev;
	char phys_loc[8];
#endif

	/* XXX */
	if (unit == ATKBD_DEFAULT) {
		*kbdp = kbd = &default_kbd;
		if (KBD_IS_INITIALIZED(kbd) && KBD_IS_CONFIGURED(kbd))
			return 0;
		state = &default_kbd_state;
		keymap = &default_keymap;
		accmap = &default_accentmap;
		fkeymap = default_fkeytab;
		fkeymap_size = nitems(default_fkeytab);
		needfree = 0;
	} else if (*kbdp == NULL) {
		*kbdp = kbd = malloc(sizeof(*kbd), M_DEVBUF, M_NOWAIT | M_ZERO);
		state = malloc(sizeof(*state), M_DEVBUF, M_NOWAIT | M_ZERO);
		/* NB: these will always be initialized 'cuz !KBD_IS_PROBED */
		keymap = malloc(sizeof(key_map), M_DEVBUF, M_NOWAIT);
		accmap = malloc(sizeof(accent_map), M_DEVBUF, M_NOWAIT);
		fkeymap = malloc(sizeof(fkey_tab), M_DEVBUF, M_NOWAIT);
		fkeymap_size = sizeof(fkey_tab)/sizeof(fkey_tab[0]);
		needfree = 1;
		if ((kbd == NULL) || (state == NULL) || (keymap == NULL)
		     || (accmap == NULL) || (fkeymap == NULL)) {
			error = ENOMEM;
			goto bad;
		}
	} else if (KBD_IS_INITIALIZED(*kbdp) && KBD_IS_CONFIGURED(*kbdp)) {
		return 0;
	} else {
		kbd = *kbdp;
		state = (atkbd_state_t *)kbd->kb_data;
		bzero(state, sizeof(*state));
		keymap = kbd->kb_keymap;
		accmap = kbd->kb_accentmap;
		fkeymap = kbd->kb_fkeytab;
		fkeymap_size = kbd->kb_fkeytab_size;
		needfree = 0;
	}

	if (!KBD_IS_PROBED(kbd)) {
		state->kbdc = atkbdc_open(data[0]);
		if (state->kbdc == NULL) {
			error = ENXIO;
			goto bad;
		}
		kbd_init_struct(kbd, ATKBD_DRIVER_NAME, KB_OTHER, unit, flags,
				0, 0);
		bcopy(&key_map, keymap, sizeof(key_map));
		bcopy(&accent_map, accmap, sizeof(accent_map));
		bcopy(fkey_tab, fkeymap,
		    imin(fkeymap_size * sizeof(fkeymap[0]), sizeof(fkey_tab)));
		kbd_set_maps(kbd, keymap, accmap, fkeymap, fkeymap_size);
		kbd->kb_data = (void *)state;
	
		if (probe_keyboard(state->kbdc, flags)) { /* shouldn't happen */
			if (flags & KB_CONF_FAIL_IF_NO_KBD) {
				error = ENXIO;
				goto bad;
			}
		} else {
			KBD_FOUND_DEVICE(kbd);
		}
		atkbd_clear_state(kbd);
		state->ks_mode = K_XLATE;
		/* 
		 * FIXME: set the initial value for lock keys in ks_state
		 * according to the BIOS data?
		 */
		KBD_PROBE_DONE(kbd);
	}
	if (!KBD_IS_INITIALIZED(kbd) && !(flags & KB_CONF_PROBE_ONLY)) {
		kbd->kb_config = flags & ~KB_CONF_PROBE_ONLY;
		if (KBD_HAS_DEVICE(kbd)
		    && init_keyboard(state->kbdc, &kbd->kb_type, kbd->kb_config)
		    && (kbd->kb_config & KB_CONF_FAIL_IF_NO_KBD)) {
			kbd_unregister(kbd);
			error = ENXIO;
			goto bad;
		}
		atkbd_ioctl(kbd, KDSETLED, (caddr_t)&state->ks_state);
		set_typematic(kbd);
		delay[0] = kbd->kb_delay1;
		delay[1] = kbd->kb_delay2;
		atkbd_ioctl(kbd, KDSETREPEAT, (caddr_t)delay);

#ifdef EVDEV_SUPPORT
		/* register as evdev provider on first init */
		if (state->ks_evdev == NULL) {
			snprintf(phys_loc, sizeof(phys_loc), "atkbd%d", unit);
			evdev = evdev_alloc();
			evdev_set_name(evdev, "AT keyboard");
			evdev_set_phys(evdev, phys_loc);
			evdev_set_id(evdev, BUS_I8042, PS2_KEYBOARD_VENDOR,
			    PS2_KEYBOARD_PRODUCT, 0);
			evdev_set_methods(evdev, kbd, &atkbd_evdev_methods);
			evdev_support_event(evdev, EV_SYN);
			evdev_support_event(evdev, EV_KEY);
			evdev_support_event(evdev, EV_LED);
			evdev_support_event(evdev, EV_REP);
			evdev_support_all_known_keys(evdev);
			evdev_support_led(evdev, LED_NUML);
			evdev_support_led(evdev, LED_CAPSL);
			evdev_support_led(evdev, LED_SCROLLL);

			if (evdev_register_mtx(evdev, &Giant))
				evdev_free(evdev);
			else
				state->ks_evdev = evdev;
			state->ks_evdev_state = 0;
		}
#endif

		KBD_INIT_DONE(kbd);
	}
	if (!KBD_IS_CONFIGURED(kbd)) {
		if (kbd_register(kbd) < 0) {
			error = ENXIO;
			goto bad;
		}
		KBD_CONFIG_DONE(kbd);
	}

	return 0;
bad:
	if (needfree) {
		if (state != NULL)
			free(state, M_DEVBUF);
		if (keymap != NULL)
			free(keymap, M_DEVBUF);
		if (accmap != NULL)
			free(accmap, M_DEVBUF);
		if (fkeymap != NULL)
			free(fkeymap, M_DEVBUF);
		if (kbd != NULL) {
			free(kbd, M_DEVBUF);
			*kbdp = NULL;	/* insure ref doesn't leak to caller */
		}
	}
	return error;
}