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); }
/* 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 = nitems(default_fkeytab); 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; }
static int sunkbd_configure(int flags) { struct sunkbd_softc *sc; if (uart_cpu_getdev(UART_DEV_KEYBOARD, &uart_keyboard)) return (0); if (uart_probe(&uart_keyboard)) return (0); uart_init(&uart_keyboard); if (sunkbd_probe_keyboard(&uart_keyboard) == -1) return (0); uart_keyboard.type = UART_DEV_KEYBOARD; uart_keyboard.attach = sunkbd_attach; uart_add_sysdev(&uart_keyboard); sc = &sunkbd_softc; callout_init(&sc->sc_repeat_callout, 0); sc->sc_repeat_key = -1; sc->sc_repeating = 0; kbd_init_struct(&sc->sc_kbd, "sunkbd", 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])); sc->sc_mode = K_XLATE; kbd_register(&sc->sc_kbd); sc->sc_sysdev = &uart_keyboard; return (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; }
static int pl050_kmi_attach(device_t dev) { struct kmi_softc *sc = device_get_softc(dev); keyboard_t *kbd; int rid; int i; kbd = &sc->sc_kbd; rid = 0; sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (sc->sc_mem_res == NULL) { device_printf(dev, "could not allocate memory resource\n"); return (ENXIO); } /* Request the IRQ resources */ sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE); if (sc->sc_irq_res == NULL) { device_printf(dev, "Error: could not allocate irq resources\n"); return (ENXIO); } /* Setup and enable the timer */ if (bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_CLK, NULL, pl050_kmi_intr, sc, &sc->sc_intr_hl) != 0) { bus_release_resource(dev, SYS_RES_IRQ, rid, sc->sc_irq_res); device_printf(dev, "Unable to setup the clock irq handler.\n"); return (ENXIO); } /* TODO: clock & divisor */ pl050_kmi_write_4(sc, KMICR, KMICR_EN | KMICR_RXINTREN); kbd_init_struct(kbd, KMI_DRIVER_NAME, KB_OTHER, device_get_unit(dev), 0, 0, 0); kbd->kb_data = (void *)sc; sc->sc_keymap = key_map; sc->sc_accmap = accent_map; for (i = 0; i < KMI_NFKEY; i++) { sc->sc_fkeymap[i] = fkey_tab[i]; } kbd_set_maps(kbd, &sc->sc_keymap, &sc->sc_accmap, sc->sc_fkeymap, KMI_NFKEY); KBD_FOUND_DEVICE(kbd); kmi_clear_state(kbd); KBD_PROBE_DONE(kbd); KBD_INIT_DONE(kbd); if (kbd_register(kbd) < 0) { goto detach; } KBD_CONFIG_DONE(kbd); #ifdef KBD_INSTALL_CDEV if (kbd_attach(kbd)) { goto detach; } #endif if (bootverbose) { genkbd_diag(kbd, bootverbose); } return (0); detach: return (ENXIO); }
/* 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; }
static int chrome_kb_attach(device_t dev) { struct ckb_softc *sc; keyboard_t *kbd; int error; int rid; int i; sc = device_get_softc(dev); sc->dev = dev; if ((error = parse_dts(sc)) != 0) return error; #if 0 device_printf(sc->dev, "Keyboard matrix [%dx%d]\n", sc->cols, sc->rows); #endif /* TODO: take interrupt from DTS */ pad_setup_intr(KB_GPIO_INT, ckb_ec_intr, sc); kbd = &sc->sc_kbd; rid = 0; sc->scan_local = malloc(sc->cols, M_DEVBUF, M_NOWAIT); sc->scan = malloc(sc->cols, M_DEVBUF, M_NOWAIT); for (i = 0; i < sc->cols; i++) { sc->scan_local[i] = 0; sc->scan[i] = 0; }; kbd_init_struct(kbd, KBD_DRIVER_NAME, KB_OTHER, device_get_unit(dev), 0, 0, 0); kbd->kb_data = (void *)sc; sc->sc_keymap = key_map; sc->sc_accmap = accent_map; for (i = 0; i < CKB_NFKEY; i++) { sc->sc_fkeymap[i] = fkey_tab[i]; } kbd_set_maps(kbd, &sc->sc_keymap, &sc->sc_accmap, sc->sc_fkeymap, CKB_NFKEY); KBD_FOUND_DEVICE(kbd); ckb_clear_state(kbd); KBD_PROBE_DONE(kbd); callout_init(&sc->sc_repeat_callout, 0); KBD_INIT_DONE(kbd); if (kbd_register(kbd) < 0) { return (ENXIO); }; KBD_CONFIG_DONE(kbd); return (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; }
/* 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; }
static int adb_kbd_attach(device_t dev) { struct adb_kbd_softc *sc; keyboard_switch_t *sw; uint32_t fkeys; phandle_t handle; sw = kbd_get_switch(KBD_DRIVER_NAME); if (sw == NULL) { return ENXIO; } sc = device_get_softc(dev); sc->sc_dev = dev; sc->sc_mode = K_RAW; sc->sc_state = 0; sc->have_led_control = 0; sc->buffers = 0; /* Try stepping forward to the extended keyboard protocol */ adb_set_device_handler(dev,3); mtx_init(&sc->sc_mutex, KBD_DRIVER_NAME, NULL, MTX_DEF); cv_init(&sc->sc_cv,KBD_DRIVER_NAME); callout_init(&sc->sc_repeater, 0); #ifdef AKBD_EMULATE_ATKBD kbd_init_struct(&sc->sc_kbd, KBD_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 #error ADB raw mode not implemented #endif KBD_FOUND_DEVICE(&sc->sc_kbd); KBD_PROBE_DONE(&sc->sc_kbd); KBD_INIT_DONE(&sc->sc_kbd); KBD_CONFIG_DONE(&sc->sc_kbd); (*sw->enable)(&sc->sc_kbd); kbd_register(&sc->sc_kbd); #ifdef KBD_INSTALL_CDEV if (kbd_attach(&sc->sc_kbd)) { adb_kbd_detach(dev); return ENXIO; } #endif /* Check if we can read out the LED state from this keyboard by reading the key state register */ if (adb_read_register(dev, 2, NULL) == 2) sc->have_led_control = 1; adb_set_autopoll(dev,1); handle = OF_finddevice("mac-io/via-pmu/adb/keyboard"); if (handle != -1 && OF_getprop(handle, "AAPL,has-embedded-fn-keys", &fkeys, sizeof(fkeys)) != -1) { static const char *key_names[] = {"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12"}; struct sysctl_ctx_list *ctx; struct sysctl_oid *tree; int i; if (bootverbose) device_printf(dev, "Keyboard has embedded Fn keys\n"); for (i = 0; i < 12; i++) { uint32_t keyval; char buf[3]; if (OF_getprop(handle, key_names[i], &keyval, sizeof(keyval)) < 0) continue; buf[0] = 1; buf[1] = i+1; buf[2] = keyval; adb_write_register(dev, 0, 3, buf); } adb_write_register(dev, 1, 2, &(uint16_t){0}); ctx = device_get_sysctl_ctx(dev); tree = device_get_sysctl_tree(dev); SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "fn_keys_function_as_primary", CTLTYPE_INT | CTLFLAG_RW, sc, 0, adb_fn_keys, "I", "Set the Fn keys to be their F-key type as default"); } return (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; }
/* 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; }