if (kbd->key_maps[i]) kfree(kbd->key_maps[i]); 
kfree(kbd->key_maps[i]); 
static k_handler_fn K_HANDLERS;static k_handler_fn *k_handler[16] = { K_HANDLERS };/* maximum values each key_handler can handle */static const int kbd_max_vals[] = {	255, ARRAY_SIZE(func_table) - 1, NR_FN_HANDLER - 1, 0,	NR_DEAD - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0};static const int KBD_NR_TYPES = ARRAY_SIZE(kbd_max_vals);static unsigned char ret_diacr[NR_DEAD] = {	'`', '\'', '^', '~', '"', ','};/* * Alloc/free of kbd_data structures. */struct kbd_data *kbd_alloc(void) {	struct kbd_data *kbd;	int i, len;	kbd = kmalloc(sizeof(struct kbd_data), GFP_KERNEL);	if (!kbd)		goto out;	memset(kbd, 0, sizeof(struct kbd_data));	kbd->key_maps = kmalloc(sizeof(key_maps), GFP_KERNEL);	if (!key_maps)		goto out_kbd;	memset(kbd->key_maps, 0, sizeof(key_maps));	for (i = 0; i < ARRAY_SIZE(key_maps); i++) {		if (key_maps[i]) {			kbd->key_maps[i] =				kmalloc(sizeof(u_short)*NR_KEYS, GFP_KERNEL);			if (!kbd->key_maps[i])				goto out_maps;			memcpy(kbd->key_maps[i], key_maps[i],			       sizeof(u_short)*NR_KEYS);		}	}	kbd->func_table = kmalloc(sizeof(func_table), GFP_KERNEL);	if (!kbd->func_table)		goto out_maps;	memset(kbd->func_table, 0, sizeof(func_table));	for (i = 0; i < ARRAY_SIZE(func_table); i++) {		if (func_table[i]) {			len = strlen(func_table[i]) + 1;			kbd->func_table[i] = kmalloc(len, GFP_KERNEL);			if (!kbd->func_table[i])				goto out_func;			memcpy(kbd->func_table[i], func_table[i], len);		}	}	kbd->fn_handler =		kmalloc(sizeof(fn_handler_fn *) * NR_FN_HANDLER, GFP_KERNEL);	if (!kbd->fn_handler)		goto out_func;	memset(kbd->fn_handler, 0, sizeof(fn_handler_fn *) * NR_FN_HANDLER);	kbd->accent_table =		kmalloc(sizeof(struct kbdiacr)*MAX_DIACR, GFP_KERNEL);	if (!kbd->accent_table)		goto out_fn_handler;	memcpy(kbd->accent_table, accent_table,	       sizeof(struct kbdiacr)*MAX_DIACR);	kbd->accent_table_size = accent_table_size;	return kbd;out_fn_handler:	kfree(kbd->fn_handler);out_func:	for (i = 0; i < ARRAY_SIZE(func_table); i++)		if (kbd->func_table[i])			kfree(kbd->func_table[i]);	kfree(kbd->func_table);out_maps:	for (i = 0; i < ARRAY_SIZE(key_maps); i++)		if (kbd->key_maps[i])			kfree(kbd->key_maps[i]);	kfree(kbd->key_maps);out_kbd:	kfree(kbd);out:	return 0;}voidkbd_free(struct kbd_data *kbd){	int i;	kfree(kbd->accent_table);	kfree(kbd->fn_handler);	for (i = 0; i < ARRAY_SIZE(func_table); i++)		if (kbd->func_table[i])			kfree(kbd->func_table[i]);	kfree(kbd->func_table);	for (i = 0; i < ARRAY_SIZE(key_maps); i++)		if (kbd->key_maps[i])			kfree(kbd->key_maps[i]);	kfree(kbd->key_maps);	kfree(kbd);}/* * Generate ascii -> ebcdic translation table from kbd_data. */voidkbd_ascebc(struct kbd_data *kbd, unsigned char *ascebc){	unsigned short *keymap, keysym;	int i, j, k;	memset(ascebc, 0x40, 256);	for (i = 0; i < ARRAY_SIZE(key_maps); i++) {		keymap = kbd->key_maps[i];		if (!keymap)			continue;		for (j = 0; j < NR_KEYS; j++) {			k = ((i & 1) << 7) + j;			keysym = keymap[j];			if (KTYP(keysym) == (KT_LATIN | 0xf0) ||			    KTYP(keysym) == (KT_LETTER | 0xf0))				ascebc[KVAL(keysym)] = k;			else if (KTYP(keysym) == (KT_DEAD | 0xf0))				ascebc[ret_diacr[KVAL(keysym)]] = k;		}	}}/* * Generate ebcdic -> ascii translation table from kbd_data. */voidkbd_ebcasc(struct kbd_data *kbd, unsigned char *ebcasc){	unsigned short *keymap, keysym;	int i, j, k;	memset(ebcasc, ' ', 256);	for (i = 0; i < ARRAY_SIZE(key_maps); i++) {		keymap = kbd->key_maps[i];		if (!keymap)			continue;		for (j = 0; j < NR_KEYS; j++) {			keysym = keymap[j];			k = ((i & 1) << 7) + j;			if (KTYP(keysym) == (KT_LATIN | 0xf0) ||			    KTYP(keysym) == (KT_LETTER | 0xf0))				ebcasc[k] = KVAL(keysym);			else if (KTYP(keysym) == (KT_DEAD | 0xf0))				ebcasc[k] = ret_diacr[KVAL(keysym)];		}	}}/* * We have a combining character DIACR here, followed by the character CH. * If the combination occurs in the table, return the corresponding value. * Otherwise, if CH is a space or equals DIACR, return DIACR. * Otherwise, conclude that DIACR was not combining after all, * queue it and return CH. */static unsigned charhandle_diacr(struct kbd_data *kbd, unsigned char ch){	int i, d;	d = kbd->diacr;	kbd->diacr = 0;	for (i = 0; i < kbd->accent_table_size; i++) {		if (kbd->accent_table[i].diacr == d &&		    kbd->accent_table[i].base == ch)			return kbd->accent_table[i].result;	}	if (ch == ' ' || ch == d)		return d;	kbd_put_queue(kbd->tty, d);	return ch;}/* * Handle dead key. */static voidk_dead(struct kbd_data *kbd, unsigned char value){	value = ret_diacr[value];	kbd->diacr = (kbd->diacr ? handle_diacr(kbd, value) : value);}/* * Normal character handler. */static voidk_self(struct kbd_data *kbd, unsigned char value){	if (kbd->diacr)		value = handle_diacr(kbd, value);	kbd_put_queue(kbd->tty, value);}/* * Special key handlers */static voidk_ignore(struct kbd_data *kbd, unsigned char value){}/* * Function key handler. */static voidk_fn(struct kbd_data *kbd, unsigned char value){	if (kbd->func_table[value])		kbd_puts_queue(kbd->tty, kbd->func_table[value]);}static voidk_spec(struct kbd_data *kbd, unsigned char value){	if (value >= NR_FN_HANDLER)		return;	if (kbd->fn_handler[value])		kbd->fn_handler[value](kbd);}
4520	/local/tlutelli/issta_data/temp/c/2005_temp/2005/4520/17fd682e544556a2a829e94383239c029bb21c5e/keyboard.c/clean/drivers/s390/char/keyboard.c