146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* 246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL - Simple DirectMedia Layer 346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Copyright (C) 1997-2006 Sam Lantinga 446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner This library is free software; you can redistribute it and/or 646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner modify it under the terms of the GNU Lesser General Public 746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner License as published by the Free Software Foundation; either 846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner version 2.1 of the License, or (at your option) any later version. 946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 1046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner This library is distributed in the hope that it will be useful, 1146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner but WITHOUT ANY WARRANTY; without even the implied warranty of 1246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Lesser General Public License for more details. 1446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 1546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner You should have received a copy of the GNU Lesser General Public 1646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner License along with this library; if not, write to the Free Software 1746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 1846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 1946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Sam Lantinga 2046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner slouken@libsdl.org 2146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/ 2246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_config.h" 2346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 2446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <sys/types.h> 2546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <dev/wscons/wsdisplay_usl_io.h> 2646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <sys/ioctl.h> 2746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <fcntl.h> 2846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <unistd.h> 2946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <termios.h> 3046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <errno.h> 3146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <string.h> 3246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 3346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL.h" 3446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "../../events/SDL_sysevents.h" 3546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "../../events/SDL_events_c.h" 3646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_wsconsvideo.h" 3746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_wsconsevents_c.h" 3846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 3946be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int posted = 0; 4046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 4146be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerint WSCONS_InitKeyboard(_THIS) 4246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 4346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner struct termios tty; 4446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 4546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if (ioctl(private->fd, WSKBDIO_GTYPE, &private->kbdType) == -1) { 4646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner WSCONS_ReportError("cannot get keyboard type: %s", strerror(errno)); 4746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return -1; 4846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 4946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 5046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if (tcgetattr(private->fd, &private->saved_tty) == -1) { 5146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner WSCONS_ReportError("cannot get terminal attributes: %s", strerror(errno)); 5246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return -1; 5346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 5446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner private->did_save_tty = 1; 5546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner tty = private->saved_tty; 5646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner tty.c_iflag = IGNPAR | IGNBRK; 5746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner tty.c_oflag = 0; 5846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner tty.c_cflag = CREAD | CS8; 5946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner tty.c_lflag = 0; 6046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner tty.c_cc[VTIME] = 0; 6146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner tty.c_cc[VMIN] = 1; 6246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner cfsetispeed(&tty, 9600); 6346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner cfsetospeed(&tty, 9600); 6446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if (tcsetattr(private->fd, TCSANOW, &tty) < 0) { 6546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner WSCONS_ReportError("cannot set terminal attributes: %s", strerror(errno)); 6646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return -1; 6746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 6846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if (ioctl(private->fd, KDSKBMODE, K_RAW) == -1) { 6946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner WSCONS_ReportError("cannot set raw keyboard mode: %s", strerror(errno)); 7046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return -1; 7146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 7246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 7346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return 0; 7446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 7546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 7646be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid WSCONS_ReleaseKeyboard(_THIS) 7746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 7846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if (private->fd != -1) { 7946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if (ioctl(private->fd, KDSKBMODE, K_XLATE) == -1) { 8046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner WSCONS_ReportError("cannot restore keyboard to translated mode: %s", 8146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner strerror(errno)); 8246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 8346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if (private->did_save_tty) { 8446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if (tcsetattr(private->fd, TCSANOW, &private->saved_tty) < 0) { 8546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner WSCONS_ReportError("cannot restore keynoard attributes: %s", 8646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner strerror(errno)); 8746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 8846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 8946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 9046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 9146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 9246be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void updateMouse() 9346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 9446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 9546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 9646be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic SDLKey keymap[128]; 9746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 9846be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic SDL_keysym *TranslateKey(int scancode, SDL_keysym *keysym) 9946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 10046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keysym->scancode = scancode; 10146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keysym->sym = SDLK_UNKNOWN; 10246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keysym->mod = KMOD_NONE; 10346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 10446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if (scancode < SDL_arraysize(keymap)) 10546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keysym->sym = keymap[scancode]; 10646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 10746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if (keysym->sym == SDLK_UNKNOWN) 10846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner printf("Unknown mapping for scancode %d\n", scancode); 10946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 11046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return keysym; 11146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 11246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 11346be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void updateKeyboard(_THIS) 11446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 11546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner unsigned char buf[100]; 11646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_keysym keysym; 11746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int n, i; 11846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 11946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ((n = read(private->fd, buf, sizeof(buf))) > 0) { 12046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner for (i = 0; i < n; i++) { 12146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner unsigned char c = buf[i] & 0x7f; 12246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if (c == 224) // special key prefix -- what should we do with it? 12346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner continue; 12446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner posted += SDL_PrivateKeyboard((buf[i] & 0x80) ? SDL_RELEASED : SDL_PRESSED, 12546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner TranslateKey(c, &keysym)); 12646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 12746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 12846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 12946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 13046be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid WSCONS_PumpEvents(_THIS) 13146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 13246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner do { 13346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner posted = 0; 13446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner updateMouse(); 13546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner updateKeyboard(this); 13646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } while (posted); 13746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 13846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 13946be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid WSCONS_InitOSKeymap(_THIS) 14046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 14146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int i; 14246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 14346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Make sure unknown keys are mapped correctly */ 14446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner for (i=0; i < SDL_arraysize(keymap); i++) { 14546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[i] = SDLK_UNKNOWN; 14646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 14746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 14846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner switch (private->kbdType) { 14946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef WSKBD_TYPE_ZAURUS 15046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner case WSKBD_TYPE_ZAURUS: 15146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* top row */ 15246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[2] = SDLK_1; 15346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[3] = SDLK_2; 15446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[4] = SDLK_3; 15546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[5] = SDLK_4; 15646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[6] = SDLK_5; 15746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[7] = SDLK_6; 15846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[8] = SDLK_7; 15946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[9] = SDLK_8; 16046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[10] = SDLK_9; 16146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[11] = SDLK_0; 16246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[14] = SDLK_BACKSPACE; 16346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 16446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* second row */ 16546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[16] = SDLK_q; 16646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[17] = SDLK_w; 16746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[18] = SDLK_e; 16846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[19] = SDLK_r; 16946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[20] = SDLK_t; 17046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[21] = SDLK_y; 17146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[22] = SDLK_u; 17246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[23] = SDLK_i; 17346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[24] = SDLK_o; 17446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[25] = SDLK_p; 17546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 17646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* third row */ 17746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[15] = SDLK_TAB; 17846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[30] = SDLK_a; 17946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[31] = SDLK_s; 18046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[32] = SDLK_d; 18146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[33] = SDLK_f; 18246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[34] = SDLK_g; 18346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[35] = SDLK_h; 18446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[36] = SDLK_j; 18546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[37] = SDLK_k; 18646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[38] = SDLK_l; 18746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 18846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* fourth row */ 18946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[42] = SDLK_LSHIFT; 19046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[44] = SDLK_z; 19146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[45] = SDLK_x; 19246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[46] = SDLK_c; 19346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[47] = SDLK_v; 19446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[48] = SDLK_b; 19546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[49] = SDLK_n; 19646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[50] = SDLK_m; 19746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[54] = SDLK_RSHIFT; 19846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[28] = SDLK_RETURN; 19946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 20046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* fifth row */ 20146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[56] = SDLK_LALT; 20246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[29] = SDLK_LCTRL; 20346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* keymap[56] = ; */ 20446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[0] = SDLK_LSUPER; 20546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[12] = SDLK_MINUS; 20646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[57] = SDLK_SPACE; 20746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[51] = SDLK_COMMA; 20846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[52] = SDLK_PERIOD; 20946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 21046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* misc */ 21146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[59] = SDLK_F1; 21246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[60] = SDLK_F2; 21346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[61] = SDLK_F3; 21446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[62] = SDLK_F4; 21546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[63] = SDLK_F5; 21646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[1] = SDLK_ESCAPE; 21746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* keymap[28] = SDLK_KP_ENTER; */ 21846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[72] = SDLK_UP; 21946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[75] = SDLK_LEFT; 22046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[77] = SDLK_RIGHT; 22146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner keymap[80] = SDLK_DOWN; 22246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 22346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* WSKBD_TYPE_ZAURUS */ 22446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 22546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner default: 22646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner WSCONS_ReportError("Unable to map keys for keyboard type %u", 22746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner private->kbdType); 22846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 22946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 23046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 23146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 23246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* end of SDL_wsconsevents.c ... */ 23346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 234