module hw.ps2.kbset;

// Uses the HID Usage Table for Keyboards
// 10. Table 12, http://www.usb.org/developers/hidpage/Hut1_12v2.pdf
enum KeyCode : ubyte {
	none,
	errorRollover,
	postFail,
	errorUndefined,

	/* 0x04 / 4 */
	a,
	b,
	c,
	d,
	e,
	f,
	g,
	h,
	i,
	j,
	k,
	l,
	m,
	n,
	o,
	p,
	q,
	r,
	s,
	t,
	u,
	v,
	w,
	x,
	y,
	z,

	/* 0x1E / 30 */
	_1,
	_2,
	_3,
	_4,
	_5,
	_6,
	_7,
	_8,
	_9,
	_0,

	return_,
	escape,
	backspace,
	tab,
	space,
	minus,
	equals,
	squareOpen,
	squareClose,
	backslash,
	nonUsHashTilde,
	semicolon,
	quote,
	graveTilde,
	comma,
	dot,
	slash,
	capsLock,
	f1,
	f2,
	f3,
	f4,
	f5,
	f6,
	f7,
	f8,
	f9,
	f10,
	f11,
	f12,
	printScreen,
	scrollLock,
	pause,
	insert,
	home,
	pageUp,
	delete_,
	end,
	pageDown,
	rightArrow,
	leftArrow,
	downArrow,
	upArrow,

	numLock,
	kpSlash,
	kpStar,
	kpMinus,
	kpPlus,
	kpReturn,
	kp1,
	kp2,
	kp3,
	kp4,
	kp5,
	kp6,
	kp7,
	kp8,
	kp9,
	kp0,
	kpPeriod,

	nonUsBackslash,
	application,
	power,
	kpEquals,

	f13,
	f14,
	f15,
	f16,
	f17,
	f18,
	f19,
	f20,
	f21,
	f22,
	f23,
	f24,
	execute,
	help,
	menu,
	select,
	stop,
	again,
	undo,
	cut,
	copy,
	paste,
	find,
	mute,
	volumeUp,
	volumeDown,
	lockingCaps, /* Physically toggles */
	lockingNum,
	lockingScroll,
	kpComma,
	kpEqualSign,
	international1,
	international2,
	international3,
	international4,
	international5,
	international6,
	international7,
	international8,
	international9,

	lang1,
	lang2,
	lang3,
	lang4,
	lang5,
	lang6,
	lang7,
	lang8,
	lang9,

	altErase,
	sysReq,
	cancle,
	clear,
	prior,
	return2,
	separator,
	out_,
	oper,

	leftCtrl = 0xE0,
	leftShift,
	leftAlt,
	leftGui,
	rightCtrl,
	rightShift,
	rightAlt,
	rightGui,

	maxValue = 0xFF
}

private alias _ps2Layout = _ps2LayoutEN_US;
private alias _shiftedCharTranslation = _shiftedCharTranslationEN_US;
private alias _shiftedEtcTranslation = _shiftedEtcTranslationEN_US;
private alias _keypadTranslation = _keypadTranslationEN_US;
private alias _normalTranslation = _normalTranslationEN_US;

KeyCode findKeycode(ushort id) {
	return _ps2Layout[id];
}

dchar findShiftedCharTranslate(KeyCode key) {
	return _shiftedCharTranslation[key];
}

dchar findShiftedEtcTranslate(KeyCode key) {
	return _shiftedEtcTranslation[key];
}

dchar findKeypadTranslate(KeyCode key) {
	return _keypadTranslation[key];
}

dchar findNormalTranslate(KeyCode key) {
	return _normalTranslation[key];
}

enum e0Bit = 0x80;
enum e1Bit = 0x100;

// dfmt off
private __gshared KeyCode[512] _ps2LayoutEN_US = [
						0x0e: KeyCode.graveTilde,
						0x16: KeyCode._1,
						0x1e: KeyCode._2,
						0x26: KeyCode._3,
						0x25: KeyCode._4,
						0x2e: KeyCode._5,
						0x36: KeyCode._6,
						0x3d: KeyCode._7,
						0x3e: KeyCode._8,
						0x46: KeyCode._9,
						0x45: KeyCode._0,
						0x4e: KeyCode.minus,
						0x55: KeyCode.equals,
						0x66: KeyCode.backspace,

						0x0d: KeyCode.tab,
						0x15: KeyCode.q,
						0x1d: KeyCode.w,
						0x24: KeyCode.e,
						0x2d: KeyCode.r,
						0x2c: KeyCode.t,
						0x35: KeyCode.y,
						0x3c: KeyCode.u,
						0x43: KeyCode.i,
						0x44: KeyCode.o,
						0x4d: KeyCode.p,
						0x54: KeyCode.squareOpen,
						0x5b: KeyCode.squareClose,
						0x5d: KeyCode.backslash,

						0x58: KeyCode.capsLock,
						0x1c: KeyCode.a,
						0x1b: KeyCode.s,
						0x23: KeyCode.d,
						0x2b: KeyCode.f,
						0x34: KeyCode.g,
						0x33: KeyCode.h,
						0x3b: KeyCode.j,
						0x42: KeyCode.k,
						0x4b: KeyCode.l,
						0x4c: KeyCode.semicolon,
						0x52: KeyCode.quote,
						0x5a: KeyCode.return_,

						0x12: KeyCode.leftShift,
						0x1a: KeyCode.z,
						0x22: KeyCode.x,
						0x21: KeyCode.c,
						0x2a: KeyCode.v,
						0x32: KeyCode.b,
						0x31: KeyCode.n,
						0x3a: KeyCode.m,
						0x41: KeyCode.comma,
						0x49: KeyCode.dot,
						0x4a: KeyCode.slash,
						0x59: KeyCode.rightShift,

						0x14: KeyCode.leftCtrl,
						0x11: KeyCode.leftAlt,
						0x29: KeyCode.space,
	e0Bit |	0x11: KeyCode.rightAlt,
	e0Bit |	0x14: KeyCode.rightCtrl,

	e0Bit |	0x70: KeyCode.insert,
	e0Bit |	0x71: KeyCode.delete_,
	e0Bit |	0x6c: KeyCode.home,
	e0Bit |	0x69: KeyCode.end,
	e0Bit |	0x7d: KeyCode.pageUp,
	e0Bit |	0x7a: KeyCode.pageDown,

	e0Bit |	0x6b: KeyCode.leftArrow,
	e0Bit |	0x75: KeyCode.upArrow,
	e0Bit |	0x72: KeyCode.downArrow,
	e0Bit |	0x74: KeyCode.rightArrow,

						0x77: KeyCode.numLock,
						0x6c: KeyCode.kp7,
						0x6b: KeyCode.kp4,
						0x69: KeyCode.kp1,
	e0Bit |	0x4a: KeyCode.kpSlash,
						0x75: KeyCode.kp8,
						0x73: KeyCode.kp5,
						0x72: KeyCode.kp2,
						0x70: KeyCode.kp0,
						0x7c: KeyCode.kpStar,
						0x7d: KeyCode.kp9,
						0x74: KeyCode.kp6,
						0x7a: KeyCode.kp3,
						0x71: KeyCode.kpPeriod,
						0x7b: KeyCode.kpMinus,
						0x79: KeyCode.kpPlus,
	e0Bit |	0x5a: KeyCode.kpReturn,

						0x76: KeyCode.escape,
						0x05: KeyCode.f1,
						0x06: KeyCode.f2,
						0x04: KeyCode.f3,
						0x0c: KeyCode.f4,
						0x03: KeyCode.f5,
						0x0b: KeyCode.f6,
						0x83: KeyCode.f7,
						0x0a: KeyCode.f8,
						0x01: KeyCode.f9,
						0x09: KeyCode.f10,
						0x78: KeyCode.f11,
						0x07: KeyCode.f12,

	e0Bit |	0x7c: KeyCode.printScreen,
						0x84: KeyCode.sysReq,
						0x7e: KeyCode.scrollLock,
	e1Bit |	0x77: KeyCode.pause,

	e0Bit |	0x1f: KeyCode.leftGui,
	e0Bit |	0x27: KeyCode.rightGui,
	e0Bit |	0x2f: KeyCode.menu,
];

private __gshared dchar[KeyCode.max] _normalTranslationEN_US = [
	KeyCode.escape: 27,
	KeyCode.graveTilde: '`',
	KeyCode._1: '1',
	KeyCode._2: '2',
	KeyCode._3: '3',
	KeyCode._4: '4',
	KeyCode._5: '5',
	KeyCode._6: '6',
	KeyCode._7: '7',
	KeyCode._8: '8',
	KeyCode._9: '9',
	KeyCode._0: '0',
	KeyCode.minus: '-',
	KeyCode.equals: '=',
	KeyCode.backspace: '\b',
	KeyCode.tab: '\t',
	KeyCode.q: 'q',
	KeyCode.w: 'w',
	KeyCode.e: 'e',
	KeyCode.r: 'r',
	KeyCode.t: 't',
	KeyCode.y: 'y',
	KeyCode.u: 'u',
	KeyCode.i: 'i',
	KeyCode.o: 'o',
	KeyCode.p: 'p',
	KeyCode.squareOpen: '[',
	KeyCode.squareClose: ']',
	KeyCode.backslash: '\\',
	KeyCode.a: 'a',
	KeyCode.s: 's',
	KeyCode.d: 'd',
	KeyCode.f: 'f',
	KeyCode.g: 'g',
	KeyCode.h: 'h',
	KeyCode.j: 'j',
	KeyCode.k: 'k',
	KeyCode.l: 'l',
	KeyCode.semicolon: ';',
	KeyCode.quote: '\'',
	KeyCode.return_: '\n',
	KeyCode.z: 'z',
	KeyCode.x: 'x',
	KeyCode.c: 'c',
	KeyCode.v: 'v',
	KeyCode.b: 'b',
	KeyCode.n: 'n',
	KeyCode.m: 'm',
	KeyCode.comma: ',',
	KeyCode.dot: '.',
	KeyCode.slash: '/',
	KeyCode.space: ' '
];

private __gshared dchar[KeyCode.max] _keypadTranslationEN_US = [
	KeyCode.kp7: '7',
	KeyCode.kp4: '4',
	KeyCode.kp1: '1',
	KeyCode.kp8: '8',
	KeyCode.kp5: '5',
	KeyCode.kp2: '2',
	KeyCode.kp0: '0',
	KeyCode.kp9: '9',
	KeyCode.kp6: '6',
	KeyCode.kp3: '3',
	KeyCode.kpPeriod: ',',
	KeyCode.kpSlash: '/',
	KeyCode.kpStar: '*',
	KeyCode.kpMinus: '-',
	KeyCode.kpPlus: '+',
	KeyCode.kpReturn: '\n'
];

private __gshared dchar[KeyCode.max] _shiftedEtcTranslationEN_US = [
	KeyCode.graveTilde: '~',
	KeyCode._1: '!',
	KeyCode._2: '@',
	KeyCode._3: '#',
	KeyCode._4: '$',
	KeyCode._5: '%',
	KeyCode._6: '^',
	KeyCode._7: '&',
	KeyCode._8: '*',
	KeyCode._9: '(',
	KeyCode._0: ')',
	KeyCode.minus: '_',
	KeyCode.equals: '+',
	KeyCode.squareOpen: '{',
	KeyCode.squareClose: '}',
	KeyCode.backslash: '|',
	KeyCode.semicolon: ':',
	KeyCode.quote: '"',
	KeyCode.comma: '<',
	KeyCode.dot: '>',
	KeyCode.slash: '?',
];

private __gshared dchar[KeyCode.max] _shiftedCharTranslationEN_US = [
	KeyCode.q: 'Q',
	KeyCode.w: 'W',
	KeyCode.e: 'E',
	KeyCode.r: 'R',
	KeyCode.t: 'T',
	KeyCode.y: 'Y',
	KeyCode.u: 'U',
	KeyCode.i: 'I',
	KeyCode.o: 'O',
	KeyCode.p: 'P',
	KeyCode.a: 'A',
	KeyCode.s: 'S',
	KeyCode.d: 'D',
	KeyCode.f: 'F',
	KeyCode.g: 'G',
	KeyCode.h: 'H',
	KeyCode.j: 'J',
	KeyCode.k: 'K',
	KeyCode.l: 'L',
	KeyCode.z: 'Z',
	KeyCode.x: 'X',
	KeyCode.c: 'C',
	KeyCode.v: 'V',
	KeyCode.b: 'B',
	KeyCode.n: 'N',
	KeyCode.m: 'M',
];
// dfmt on
