Rev 114 | Rev 116 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
#include <stdio.h>#include <conio.h>#include <stdlib.h>#include <string.h>#include <windows.h>#include <tchar.h>#include <strsafe.h>#include <lusb0_usb.h>#include "SimConnect.h"#define sbi(sfr, bit) ((sfr) |= 1 << bit)#define cbi(sfr, bit) ((sfr) &= ~(1 << bit))#define xbi(sfr, bit) ((sfr) ^= 1 << bit)#define rbi(sfr, bit) (((sfr) >> (bit)) & 0x01)// Same as in main.c#define USB_STATE_READ 100#define USB_LEDS_SET 101// Console symbolschar* M_OUT = " :<- "; // message outboundchar* M_IN = "->: "; // message inboundchar* M_NO = " : "; // not a messagechar* I_SP = " "; // spacechar* I_OK = "+"; // ignored, okchar* I_NEX = "?"; // ignored, unexpectedchar* I_EXE = "e"; // exceptionchar* X_SEP = "|"; // separator#define BUTTONS_COM1 0#define BUTTONS_COM2 1#define BUTTONS_COMB 2#define BUTTONS_NAV1 3#define BUTTONS_NAV2 4#define BUTTONS_MKR 5#define BUTTONS_DME 6#define BUTTONS_ADF 7static usb_dev_handle * usbOpenDevice(int vendor, char *vendorName, int product, char *productName);static int usbGetDescriptorString(usb_dev_handle *dev, int index, int langid, char *buf, int buflen);void testCode(usb_dev_handle *handle);void setLed(double value, int bit);void CALLBACK dispatchProc(SIMCONNECT_RECV *pData, DWORD cbData, void *pContext);void Process_Exception(SIMCONNECT_RECV* pData);void Process_Connected();void Process_FSX_Quit();char* Exception_String(DWORD Recv_Exception);char* RECV_Msg_String(DWORD Recv_ID);char* Format_SOL(char* Direction);char* Format_SOL(char* Direction, char* Importance);void Connect();void Disconnect();usb_dev_handle *handle = NULL;HANDLE hSimConnect = NULL;bool keep_going = false;bool Paused = true;char string[80];bool updateLeds = true;char ledStatus = 0x00;int nBytes = 0;char buffer[16];struct CommSelectData {double com1;double com2;double comb;double vor1;double vor2;double mkr;double dme;double adf;};static enum DATA_DEFINE_ID {DEFINITION_1,};static enum DATA_REQUEST_ID {REQUEST_1,};static enum EVENT_ID {EVENT_COM1_TRANSMIT_SELECT,EVENT_COM2_TRANSMIT_SELECT,EVENT_COM_RECEIVE_ALL_TOGGLE,EVENT_RADIO_VOR1_IDENT_TOGGLE,EVENT_RADIO_VOR2_IDENT_TOGGLE,EVENT_MARKER_SOUND_TOGGLE,EVENT_RADIO_DME1_IDENT_TOGGLE,EVENT_RADIO_ADF_IDENT_TOGGLE,};static enum INPUT_ID {INPUT0,};static enum GROUP_ID {GROUP0,};int main(int argc, char **argv) {handle = usbOpenDevice(0x4242, "newioit.com.au", 0xe231, "Comm Selector");if(handle == NULL) {fprintf(stderr, "Could not find USB device\n");exit(1);}//testCode(handle);int i;for (i = 0; i < 15; i++) {buffer[i] = 0x00;}nBytes = usb_control_msg(handle,USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN,USB_LEDS_SET, ledStatus, 0, (char *)buffer, sizeof(buffer), 5000);Connect();if (hSimConnect != NULL) {keep_going = true;unsigned int lastButtons = 0;while(keep_going){HRESULT hr;// Put this in an 'On Event' thing later...//hr = SimConnect_RequestDataOnSimObjectType(hSimConnect, REQUEST_1, DEFINITION_1, 0, SIMCONNECT_SIMOBJECT_TYPE_USER);nBytes = usb_control_msg(handle,USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN,USB_STATE_READ, 0, 0, (char *)buffer, sizeof(buffer), 5000);unsigned int buttons = (unsigned int)buffer[1];for (i=0; i<7; i++) {if (rbi(buttons, i) && rbi(lastButtons, i) == 0) {sbi(lastButtons, i);hr = SimConnect_TransmitClientEvent(hSimConnect,0, i, 1 ,SIMCONNECT_GROUP_PRIORITY_STANDARD,SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY);}if (rbi(lastButtons, i) && ! rbi(buttons, i))cbi(lastButtons, i);}SimConnect_CallDispatch(hSimConnect, dispatchProc, NULL);Sleep(1);}Disconnect();} else {// Implement retrying}usb_close(handle);return 0;}void Connect() {HRESULT hr;if (hSimConnect == NULL) {printf("\n%s Requesting a SimConnect connection", Format_SOL(M_OUT));hr = SimConnect_Open(&hSimConnect, "Comm Selector", NULL, 0, 0, 0);if (hr != S_OK) {// FSX may be inactive, or there is a problemprintf("\n%s Error %d while opening a SimConnect connection", Format_SOL(M_IN, I_OK), hr);} else {// Connection to FSX initializedprintf("\n%s Connection request being processed (%d)", Format_SOL(M_IN), hSimConnect);// (When connection process completes, an OPEN message will be received)}}}void Disconnect() {HRESULT hr;if (hSimConnect != NULL) {if (hr = SimConnect_Close(hSimConnect) == S_OK) {printf("\n%s Connection closed (%d).", Format_SOL(M_IN), hSimConnect);} else {printf("\n%s Error (%d) while closing the connection (%d).", Format_SOL(M_IN, I_NEX), hr, hSimConnect);}}printf("\n%s Resetting internal status to disconnected.", Format_SOL(M_NO));hSimConnect = NULL;keep_going = false;}void CALLBACK dispatchProc(SIMCONNECT_RECV* pData, DWORD cbData, void *pContext){switch(pData->dwID){case SIMCONNECT_RECV_ID_QUIT:// FSX is stoppingProcess_FSX_Quit();break;case SIMCONNECT_RECV_ID_OPEN:// the connection process is completeProcess_Connected();break;case SIMCONNECT_RECV_ID_EVENT: {SIMCONNECT_RECV_EVENT *evt = (SIMCONNECT_RECV_EVENT*)pData;/*switch (evt->uEventID) {default:break;}*/break;}case SIMCONNECT_RECV_ID_SIMOBJECT_DATA: {SIMCONNECT_RECV_SIMOBJECT_DATA_BYTYPE *pObjData = (SIMCONNECT_RECV_SIMOBJECT_DATA_BYTYPE*)pData;switch(pObjData->dwRequestID) {case REQUEST_1: {DWORD ObjectID = pObjData->dwObjectID;CommSelectData *ps = (CommSelectData*)&pObjData->dwData;setLed(ps->com1, BUTTONS_COM1);setLed(ps->com2, BUTTONS_COM2);setLed(ps->comb, BUTTONS_COMB);setLed(ps->vor1, BUTTONS_NAV1);setLed(ps->vor2, BUTTONS_NAV2);setLed(ps->mkr, BUTTONS_MKR);setLed(ps->dme, BUTTONS_DME);setLed(ps->adf, BUTTONS_ADF);nBytes = usb_control_msg(handle,USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN,USB_LEDS_SET, ledStatus, 0, (char *)buffer, sizeof(buffer), 5000);printf("\nSIMOBJECT_DATA %d LED Update" );break;}}break;}case SIMCONNECT_RECV_ID_SIMOBJECT_DATA_BYTYPE: {SIMCONNECT_RECV_SIMOBJECT_DATA_BYTYPE *pObjData = (SIMCONNECT_RECV_SIMOBJECT_DATA_BYTYPE*)pData;switch(pObjData->dwRequestID) {case REQUEST_1: {DWORD ObjectID = pObjData->dwObjectID;CommSelectData *pS = (CommSelectData*)&pObjData->dwData;HRESULT hr;hr = SimConnect_RequestDataOnSimObject(hSimConnect, REQUEST_1, DEFINITION_1, ObjectID,SIMCONNECT_PERIOD_SIM_FRAME, SIMCONNECT_DATA_REQUEST_FLAG_CHANGED);break;}}break;}/* Not foundcase SIMCONNECT_RECV_ID_EVENT_WEATHER_MODE:case SIMCONNECT_RECV_ID_AIRPORT_LIST:case SIMCONNECT_RECV_ID_VOR_LIST:case SIMCONNECT_RECV_ID_NDB_LIST:case SIMCONNECT_RECV_ID_WAYPOINT_LIST:case SIMCONNECT_RECV_ID_EVENT_MULTIPLAYER_SERVER_STARTED:case SIMCONNECT_RECV_ID_EVENT_MULTIPLAYER_CLIENT_STARTED:case SIMCONNECT_RECV_ID_EVENT_MULTIPLAYER_SESSION_ENDED:case SIMCONNECT_RECV_ID_EVENT_RACE_END:case SIMCONNECT_RECV_ID_EVENT_RACE_LAP: */case SIMCONNECT_RECV_ID_EXCEPTION:case SIMCONNECT_RECV_ID_EVENT_OBJECT_ADDREMOVE:case SIMCONNECT_RECV_ID_ASSIGNED_OBJECT_ID:case SIMCONNECT_RECV_ID_EVENT_FILENAME:case SIMCONNECT_RECV_ID_EVENT_FRAME:case SIMCONNECT_RECV_ID_WEATHER_OBSERVATION:case SIMCONNECT_RECV_ID_CLOUD_STATE:case SIMCONNECT_RECV_ID_RESERVED_KEY:case SIMCONNECT_RECV_ID_CUSTOM_ACTION:case SIMCONNECT_RECV_ID_SYSTEM_STATE:case SIMCONNECT_RECV_ID_CLIENT_DATA:printf("\n%s Message ignored (%s)", RECV_Msg_String(pData->dwID), Format_SOL(M_IN, I_OK));break;default:printf("\n%s Message ignored (Unknown RECV_ID)", Format_SOL(M_IN, I_NEX));}}void setLed(double value, int bit) {if (value)sbi(ledStatus, bit);elsecbi(ledStatus, bit);}void Process_Exception(SIMCONNECT_RECV* pData) {// SimConnect cannot process a client requestSIMCONNECT_RECV_EXCEPTION *except = (SIMCONNECT_RECV_EXCEPTION *) pData;printf("\n%s Exception %d on packet %d, argument %d. (%s)", Format_SOL(M_IN, I_EXE),except->dwException, except->dwSendID, except->dwIndex,Exception_String(except->dwException));}void Process_Connected() {printf("\n%s Connected.", Format_SOL(M_IN));HRESULT hr;hr = SimConnect_MapClientEventToSimEvent(hSimConnect, EVENT_COM1_TRANSMIT_SELECT, "COM1_TRANSMIT_SELECT");hr = SimConnect_MapClientEventToSimEvent(hSimConnect, EVENT_COM2_TRANSMIT_SELECT, "COM2_TRANSMIT_SELECT");hr = SimConnect_MapClientEventToSimEvent(hSimConnect, EVENT_COM_RECEIVE_ALL_TOGGLE, "COM_RECEIVE_ALL_TOGGLE");hr = SimConnect_MapClientEventToSimEvent(hSimConnect, EVENT_RADIO_VOR1_IDENT_TOGGLE, "RADIO_VOR1_IDENT_TOGGLE");hr = SimConnect_MapClientEventToSimEvent(hSimConnect, EVENT_RADIO_VOR2_IDENT_TOGGLE, "RADIO_VOR2_IDENT_TOGGLE");hr = SimConnect_MapClientEventToSimEvent(hSimConnect, EVENT_MARKER_SOUND_TOGGLE, "MARKER_SOUND_TOGGLE");hr = SimConnect_MapClientEventToSimEvent(hSimConnect, EVENT_RADIO_DME1_IDENT_TOGGLE, "RADIO_DME1_IDENT_TOGGLE");hr = SimConnect_MapClientEventToSimEvent(hSimConnect, EVENT_RADIO_ADF_IDENT_TOGGLE, "RADIO_ADF_IDENT_TOGGLE");/*hr = SimConnect_AddClientEventToNotificationGroup(hSimConnect, GROUP0, EVENT_COM1_TRANSMIT_SELECT);hr = SimConnect_SetNotificationGroupPriority(hSimConnect, GROUP0, SIMCONNECT_GROUP_PRIORITY_HIGHEST);*/hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_1, "COM TRANSMIT:1", "Bool");hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_1, "COM TRANSMIT:2", "Bool");hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_1, "COM RECIEVE ALL", "Bool");hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_1, "NAV SOUND:1", "Bool");hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_1, "NAV SOUND:2", "Bool");hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_1, "MARKER SOUND", "Bool");hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_1, "DME SOUND", "Bool");hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_1, "ADF SOUND:1", "Bool");hr = SimConnect_RequestDataOnSimObjectType(hSimConnect, REQUEST_1, DEFINITION_1, 0, SIMCONNECT_SIMOBJECT_TYPE_USER);}void Process_FSX_Quit() {// Stop sending commands to SimConnectkeep_going = false;}char* Exception_String(DWORD Recv_Exception){// Names of Exceptionschar* EXCEPTION_String[] ={"NONE", "ERROR", "SIZE_MISMATCH", "UNRECOGNIZED_ID", "UNOPENED", "VERSION_MISMATCH", "TOO_MANY_GROUPS","NAME_UNRECOGNIZED", "TOO_MANY_EVENT_NAMES", "EVENT_ID_DUPLICATE", "TOO_MANY_MAPS","TOO_MANY_OBJECTS", "TOO_MANY_REQUESTS", "WEATHER_INVALID_PORT", "WEATHER_INVALID_METAR","WEATHER_UNABLE_TO_GET_OBSERVATION", "WEATHER_UNABLE_TO_CREATE_STATION","WEATHER_UNABLE_TO_REMOVE_STATION", "INVALID_DATA_TYPE", "INVALID_DATA_SIZE","DATA_ERROR", "INVALID_ARRAY", "CREATE_OBJECT_FAILED", "LOAD_FLIGHTPLAN_FAILED","OPERATION_INVALID_FOR_OBJECT_TYPE", "ILLEGAL_OPERATION", "ALREADY_SUBSCRIBED", "INVALID_ENUM","DEFINITION_ERROR", "DUPLICATE_ID", "DATUM_ID", "OUT_OF_BOUNDS", "ALREADY_CREATED","OBJECT_OUTSIDE_REALITY_BUBBLE", "OBJECT_CONTAINER", "OBJECT_AI", "OBJECT_ATC", "OBJECT_SCHEDULE",};// Return "unknown" if out of boundreturn Recv_Exception > ARRAYSIZE(EXCEPTION_String) ? "unknown" : EXCEPTION_String[Recv_Exception];}// Format the beginning of the console line, one argumentchar* Format_SOL(char* Direction){return Format_SOL(Direction, I_SP);}// Format the beginning of the console line, two argumentschar* Format_SOL(char* Direction, char* Importance){strcpy_s( string, Direction);strcat_s( string, Importance);strcat_s( string, X_SEP);return string;}// Returns the description of the message idchar* RECV_Msg_String(DWORD Recv_ID){// Names of RECV_ID (type of message to dispatch)char* RECV_ID_String[] ={"RECV_ID_EXCEPTION", "RECV_ID_OPEN", "RECV_ID_QUIT", "RECV_ID_EVENT","RECV_ID_EVENT_OBJECT_ADDREMOVE", "RECV_ID_EVENT_FILENAME", "RECV_ID_EVENT_FRAME","RECV_ID_SIMOBJECT_DATA", "RECV_ID_SIMOBJECT_DATA_BYTYPE","RECV_ID_WEATHER_OBSERVATION", "RECV_ID_CLOUD_STATE", "RECV_ID_ASSIGNED_OBJECT_ID","RECV_ID_RESERVED_KEY", "RECV_ID_CUSTOM_ACTION", "RECV_ID_SYSTEM_STATE","RECV_ID_CLIENT_DATA", "RECV_ID_EVENT_WEATHER_MODE", "RECV_ID_AIRPORT_LIST","RECV_ID_VOR_LIST", "RECV_ID_NDB_LIST", "RECV_ID_WAYPOINT_LIST","RECV_ID_EVENT_MULTIPLAYER_SERVER_STARTED", "RECV_ID_EVENT_MULTIPLAYER_CLIENT_STARTED","RECV_ID_EVENT_MULTIPLAYER_SESSION_ENDED", "RECV_ID_EVENT_RACE_END","RECV_ID_EVENT_RACE_LAP",};// Return "unknown" if out of boundreturn Recv_ID > ARRAYSIZE(RECV_ID_String) ? "unknown" : RECV_ID_String[Recv_ID];}/** *** USB Functions ****/static int usbGetDescriptorString(usb_dev_handle *dev, int index, int langid,char *buf, int buflen) {char buffer[256];int rval, i;// make standard request GET_DESCRIPTOR, type string and given index// (e.g. dev->iProduct)rval = usb_control_msg(dev,USB_TYPE_STANDARD | USB_RECIP_DEVICE | USB_ENDPOINT_IN,USB_REQ_GET_DESCRIPTOR, (USB_DT_STRING << 8) + index, langid,buffer, sizeof(buffer), 1000);if(rval < 0) // errorreturn rval;// rval should be bytes read, but buffer[0] contains the actual response sizeif((unsigned char)buffer[0] < rval)rval = (unsigned char)buffer[0]; // string is shorter than bytes readif(buffer[1] != USB_DT_STRING) // second byte is the data typereturn 0; // invalid return type// we're dealing with UTF-16LE here so actual chars is half of rval,// and index 0 doesn't countrval /= 2;/* lossy conversion to ISO Latin1 */for(i = 1; i < rval && i < buflen; i++) {if(buffer[2 * i + 1] == 0)buf[i-1] = buffer[2 * i];elsebuf[i-1] = '?'; /* outside of ISO Latin1 range */}buf[i-1] = 0;return i-1;}static usb_dev_handle * usbOpenDevice(int vendor, char *vendorName,int product, char *productName) {struct usb_bus *bus;struct usb_device *dev;char devVendor[256], devProduct[256];usb_dev_handle * handle = NULL;usb_init();usb_find_busses();usb_find_devices();for(bus=usb_get_busses(); bus; bus=bus->next) {for(dev=bus->devices; dev; dev=dev->next) {if(dev->descriptor.idVendor != vendor ||dev->descriptor.idProduct != product)continue;/* we need to open the device in order to query strings */if(!(handle = usb_open(dev))) {fprintf(stderr, "Warning: cannot open USB device: %s\n",usb_strerror());continue;}/* get vendor name */if(usbGetDescriptorString(handle, dev->descriptor.iManufacturer, 0x4242, devVendor, sizeof(devVendor)) < 0) {fprintf(stderr, "Warning: cannot query manufacturer for device: %s\n", usb_strerror());usb_close(handle);continue;}/* get product name */if(usbGetDescriptorString(handle, dev->descriptor.iProduct, 0xe231, devProduct, sizeof(devVendor)) < 0) {fprintf(stderr, "Warning: cannot query product for device: %s\n", usb_strerror()); usb_close(handle);continue;}if(strcmp(devVendor, vendorName) == 0 && strcmp(devProduct, productName) == 0)return handle;elseusb_close(handle);}}return NULL;}void testCode(usb_dev_handle *handle) {int nBytes = 0;char buffer[16];int i;for (i = 0; i < 15; i++) {buffer[i] = 0x00;}char ledStatus = 0;char keyIn = 0x00;// Return to old testing codeprintf("Press ESC to continue... (Or debug codes)\n");while (1) {keyIn = _getch();printf("Key: %02X\n", keyIn);if (keyIn == 0x1B || keyIn == 0x71) {return;} else if (keyIn >= 0x31 && keyIn <= 0x38) {char j = atoi(&keyIn);xbi(ledStatus, (j-1) );nBytes = usb_control_msg(handle,USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN,USB_LEDS_SET, ledStatus, 0, (char *)buffer, sizeof(buffer), 5000);} else if(keyIn == 'r') {nBytes = usb_control_msg(handle,USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN,USB_STATE_READ, 0, 0, (char *)buffer, sizeof(buffer), 5000);printf("Got %d bytes: %s\n", nBytes, buffer);for (i = 0; i < 15; i++) {if (i>0) printf(":");printf("%02X", buffer[i]);}printf("\n");}Sleep(1);}}