#include #include "stringutils.h" #include "debug.h" #include "util/process.h" #include #include #include "deviceinfo.h" int g_devtype; class StartrekNotifications : public process { HANDLE _hQueue; HANDLE _hDev; boost::mutex _mtx; DWORD _listenid; enum { // topaz defines scanid fl time keycode TOPAZ_POWER = 0x0,// 2 2000 0xDF 0xDF short/long TOPAZ_SEND = 0x1,// 2 1000 0x72 0x72 short/long TOPAZ_END = 0x2,// 2 1000 0x73 0x73 short/long TOPAZ_VOLUP = 0x3,// 1 0 0x75 0x75 repeats TOPAZ_VOLDOWN = 0x4,// 1 0 0x76 0x76 repeats TOPAZ_START = 0x5,// 0 1000 0x5B 0xC3 - TOPAZ_BACK = 0x6,// 3 0 0x5C 0xC4 repeats }; enum { VIVA_DIAL = 0, VIVA_HANGUP = 1, VIVA_VOLUP = 2, VIVA_VOLDOWN = 3, VIVA_POWER = 4, VIVA_UP = 5, VIVA_DOWN = 6, VIVA_LEFT = 7, VIVA_RIGHT = 8, VIVA_CENTER = 9, }; enum { // startrek defines STARTREK_5 = 0x00, STARTREK_POC = 0x01, STARTREK_AUD_NEXT = 0x02, STARTREK_AUD_PREV = 0x03, STARTREK_SOFT_1 = 0x04, STARTREK_0 = 0x05, STARTREK_HOME = 0x06, STARTREK_AUD_PLAY_PAUSE = 0x07, STARTREK_VolDown = 0x08, STARTREK_SOFT_2 = 0x09, STARTREK_SEND = 0x0a, STARTREK_BACK = 0x0b, STARTREK_Camera = 0x0c, STARTREK_VolUp = 0x0d, STARTREK_STAR = 0x0e, STARTREK_1 = 0x0f, STARTREK_3 = 0x10, STARTREK_7 = 0x11, STARTREK_9 = 0x12, STARTREK_POUND = 0x13, STARTREK_2 = 0x14, STARTREK_4 = 0x15, STARTREK_6 = 0x16, STARTREK_8 = 0x17, STARTREK_RESV0 = 0x18, STARTREK_UP = 0x19, STARTREK_DOWN = 0x1a, STARTREK_LEFT = 0x1b, STARTREK_RIGHT = 0x1c, STARTREK_ACTION = 0x1d, STARTREK_END = 0x1e, }; enum { KEYPADSRC_CLAMSHELL = 1, KEYPADSRC_SOFTEVENT = 2, KEYPADSRC_KEY = 4, KEYPADSRC_SPECIAL = 8, }; enum { STARTREK_CLAMCLOSE = 0, STARTREK_CLAMOPEN = 1, }; enum { KEYPADTYPE_KEYUP = 0, KEYPADTYPE_KEYDOWN = 1, KEYPADTYPE_SHORT = 2, KEYPADTYPE_LONG = 3, KEYPADTYPE_REPEAT = 4, }; public: StartrekNotifications() : _hQueue(0), _hDev(0), _listenid(0) { opendev(); open_queue(); kbd_register_listener(-1); start(); } virtual ~StartrekNotifications() { stop(); } virtual void processstop() { kbd_unregister_listener(); } void opendev() { _hDev= CreateFile(_T("KBD1:"), GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, NULL); if (_hDev==NULL || _hDev==INVALID_HANDLE_VALUE) { error("CreateFile-KBD1"); } debug("kbd dev=%08x\n", _hDev); } bool kbd_ioctl(DWORD code, void *req, int reqlen, void *reply, int replen) { DWORD nReturned=0; if (!DeviceIoControl(_hDev, code, req, reqlen, reply, replen, &nReturned, NULL)) { error("kbd_ioctl 0x%x: err=%08lx", code, GetLastError()); return false; } return true; } struct kbd_msg { DWORD dwSource; DWORD dwCode; DWORD dwType; DWORD dwUnknown; }; static std::string keymsg_source_string(DWORD dw) { if (dw==KEYPADSRC_CLAMSHELL) return "CLAMSHELL"; if (dw==KEYPADSRC_SOFTEVENT) return "SOFTEVENT"; if (dw==KEYPADSRC_KEY ) return "KEY"; if (dw==KEYPADSRC_SPECIAL ) return "SPECIAL"; return stringformat("SRC_%x", dw); } static std::string keymsg_code_string(DWORD src, DWORD dw) { if (src==KEYPADSRC_CLAMSHELL) { if (dw==STARTREK_CLAMCLOSE) return "CLOSE"; if (dw==STARTREK_CLAMOPEN ) return "OPEN"; return stringformat("CODE_%d", dw); } if (g_devtype==HTC_VIVA) switch(dw) { case VIVA_DIAL: return "DIAL"; case VIVA_HANGUP: return "HANGUP"; case VIVA_VOLUP: return "VOLUP"; case VIVA_VOLDOWN: return "VOLDOWN"; case VIVA_POWER: return "POWER"; case VIVA_UP: return "UP"; case VIVA_DOWN: return "DOWN"; case VIVA_LEFT: return "LEFT"; case VIVA_RIGHT: return "RIGHT"; case VIVA_CENTER: return "CENTER"; default: return stringformat("TOPAZ_0x%x", dw); } else if (g_devtype==HTC_TOPAZ) switch(dw) { case TOPAZ_POWER: return "POWER"; case TOPAZ_SEND: return "SEND"; case TOPAZ_END: return "END"; case TOPAZ_VOLUP: return "VOLUP"; case TOPAZ_VOLDOWN: return "VOLDOWN"; case TOPAZ_START: return "START"; case TOPAZ_BACK: return "BACK"; default: return stringformat("TOPAZ_0x%x", dw); } else if (g_devtype==HTC_STARTREK) switch(dw) { case STARTREK_5: return "5"; case STARTREK_POC: return "POC"; case STARTREK_AUD_NEXT: return "AUD_NEXT"; case STARTREK_AUD_PREV: return "AUD_PREV"; case STARTREK_SOFT_1: return "SOFT_1"; case STARTREK_0: return "0"; case STARTREK_HOME: return "HOME"; case STARTREK_AUD_PLAY_PAUSE: return "AUD_PLAY_PAUSE"; case STARTREK_VolDown: return "VolDown"; case STARTREK_SOFT_2: return "SOFT_2"; case STARTREK_SEND: return "SEND"; case STARTREK_BACK: return "BACK"; case STARTREK_Camera: return "Camera"; case STARTREK_VolUp: return "VolUp"; case STARTREK_STAR: return "STAR"; case STARTREK_1: return "1"; case STARTREK_3: return "3"; case STARTREK_7: return "7"; case STARTREK_9: return "9"; case STARTREK_POUND: return "POUND"; case STARTREK_2: return "2"; case STARTREK_4: return "4"; case STARTREK_6: return "6"; case STARTREK_8: return "8"; case STARTREK_RESV0: return "RESV0"; case STARTREK_UP: return "UP"; case STARTREK_DOWN: return "DOWN"; case STARTREK_LEFT: return "LEFT"; case STARTREK_RIGHT: return "RIGHT"; case STARTREK_ACTION: return "ACTION"; case STARTREK_END: return "END"; default: return stringformat("STARTREK_0x%x", dw); } else return stringformat("0x%x", dw); } static std::string keymsg_type_string(DWORD dw) { if (dw==KEYPADTYPE_KEYUP ) return "KEYUP"; if (dw==KEYPADTYPE_KEYDOWN) return "KEYDOWN"; if (dw==KEYPADTYPE_SHORT ) return "SHORT"; if (dw==KEYPADTYPE_LONG ) return "LONG"; if (dw==KEYPADTYPE_REPEAT ) return "REPEAT"; return stringformat("TYPE_%x", dw); } void open_queue() { MSGQUEUEOPTIONS opts= { 0x14, // dwSize 0, // dwFlags 0x14, // dwMaxMessages sizeof(kbd_msg), // cbMaxMessages 1, // bReadAccess }; _hQueue = CreateMsgQueue(NULL, &opts); if (_hQueue==NULL) throw boost::win32_error("CreateMsgQueue"); debug("msg queue=%08lx\n", _hQueue); } void close_queue() { debugt("close_queue()\n"); if (!CloseMsgQueue(_hQueue)) throw boost::win32_error("CloseMsgQueue"); _hQueue= NULL; } // use this to find who is registered: // [startrek] pmemdump -n device.exe 0x1E3B658 0x60 -4 -x -w 4 // [viva] pmemdump -n device.exe 0x1E6C8B0 0x60 -4 -x -w 4 bool kbd_register_listener(DWORD dwMask) { struct kbd_register { HANDLE hMsgQueue; DWORD dwEventMask; } request= { _hQueue, dwMask }; debugt("kbd_register_listener(%08lx)\n", dwMask); if (!kbd_ioctl(0xb2000, &request, sizeof(request), &_listenid, sizeof(_listenid))) return false; debugt("registered -> id=%d\n", _listenid); return true; } bool kbd_unregister_listener() { debugt("kbd_unregister_listener(%d)\n", _listenid); if (!kbd_ioctl(0xb2004, &_listenid, sizeof(_listenid), 0, 0)) return false; return true; } virtual void handle_error() { debug("ERROR in service\n"); } virtual const char*name() { return "HTCKeypadNotifications"; } virtual void service() { DWORD nRead; DWORD dwMsgFlags; struct kbd_msg msg; if (!ReadMsgQueue(_hQueue, &msg, sizeof(msg), &nRead, INFINITE, &dwMsgFlags)) throw boost::win32_error("ReadMsgQueue"); printf("keypadmessage: (%x,%x,%x,%x) : %s %s %s\n", msg.dwSource, msg.dwCode, msg.dwType, msg.dwUnknown, keymsg_source_string(msg.dwSource).c_str(), keymsg_code_string(msg.dwSource, msg.dwCode).c_str(), keymsg_type_string(msg.dwType).c_str()); } }; int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { DebugSetLogfile("teststartrek.log"); try { deviceinfo di; g_devtype= di.devtype(); debugt("startrek: registering key events\n"); StartrekNotifications kn; debugt("monitoring\n"); Sleep(120000); debugt("stopped\n"); } catch(...) { debugt("EXCEPTION\n"); } return 0; }