Rev 114 | 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_BOTH 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 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();HANDLE hSimConnect = NULL;bool keep_going = false;bool Paused = true;char string[80];bool updateLeds = true;char ledStatus = 0x00;struct Struct1 {double comm_1;double comm_2;double comm_both;};static enum DATA_DEFINE_ID {DEFINITION_1,};static enum DATA_REQUEST_ID {REQUEST_1,};static enum EVENT_ID {EVENT_BRAKES,EVENT_COM1_TRANSMIT_SELECT,EVENT_COM2_TRANSMIT_SELECT,EVENT_COM_RECEIVE_ALL_TOGGLE,};static enum INPUT_ID {INPUT0,};static enum GROUP_ID {GROUP0,};int main(int argc, char **argv) {usb_dev_handle *handle = NULL;handle = usbOpenDevice(0x4242, "newioit.com.au", 0xe231, "Comm Selector");if(handle == NULL) {fprintf(stderr, "Could not find USB device\n");exit(1);}//testCode(handle);Connect();if (hSimConnect != NULL) {keep_going = true;int nBytes = 0;char buffer[16];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);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_LEDS_SET, ledStatus, 0, (char *)buffer, sizeof(buffer), 5000);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];if (rbi(buttons, BUTTONS_COM1) && rbi(lastButtons, BUTTONS_COM1) == 0) {sbi(lastButtons, BUTTONS_COM1);hr = SimConnect_TransmitClientEvent(hSimConnect,0,EVENT_COM1_TRANSMIT_SELECT, 1 ,SIMCONNECT_GROUP_PRIORITY_STANDARD,SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY);printf("\n%s COM1 pressed.", Format_SOL(M_IN));}if (rbi(lastButtons, BUTTONS_COM1) && rbi(buttons, BUTTONS_COM1) == 0x00) {cbi(lastButtons, BUTTONS_COM1);printf("\n%s COM1 released.", Format_SOL(M_IN));}if (rbi(buttons, BUTTONS_COM2) && rbi(lastButtons, BUTTONS_COM2) == 0) {sbi(lastButtons, BUTTONS_COM2);hr = SimConnect_TransmitClientEvent(hSimConnect,0,EVENT_COM2_TRANSMIT_SELECT, 1 ,SIMCONNECT_GROUP_PRIORITY_STANDARD,SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY);printf("\n%s COM2 pressed.", Format_SOL(M_IN));}if (rbi(lastButtons, BUTTONS_COM2) && rbi(buttons, BUTTONS_COM2) == 0x00) {cbi(lastButtons, BUTTONS_COM2);printf("\n%s COM2 released.", Format_SOL(M_IN));}if (rbi(buttons, BUTTONS_BOTH) && rbi(lastButtons, BUTTONS_BOTH) == 0) {sbi(lastButtons, BUTTONS_BOTH);hr = SimConnect_TransmitClientEvent(hSimConnect,0,EVENT_COM_RECEIVE_ALL_TOGGLE, 1 ,SIMCONNECT_GROUP_PRIORITY_STANDARD,SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY);printf("\n%s BOTH pressed.", Format_SOL(M_IN));}if (rbi(lastButtons, BUTTONS_BOTH) && rbi(buttons, BUTTONS_BOTH) == 0x00) {cbi(lastButtons, BUTTONS_BOTH);printf("\n%s BOTH released.", Format_SOL(M_IN));}if (rbi(buttons, BUTTONS_NAV1) && rbi(lastButtons, BUTTONS_NAV1) == 0) {sbi(lastButtons, BUTTONS_NAV1);hr = SimConnect_TransmitClientEvent(hSimConnect,0,EVENT_BRAKES, 1 ,SIMCONNECT_GROUP_PRIORITY_STANDARD,SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY);printf("\n%s Buttons brakes engaged.", Format_SOL(M_IN));}if (rbi(lastButtons, BUTTONS_NAV1) && rbi(buttons, BUTTONS_NAV1) == 0x00) {cbi(lastButtons, BUTTONS_NAV1);printf("\n%s Button brakes released.", Format_SOL(M_IN));}SimConnect_CallDispatch(hSimConnect, dispatchProc, NULL);Sleep(1);}Disconnect();} else {// Implement retrying}// Keeps the window open. Uses old test code// so state of CommSelector can be tested//testCode(handle);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) {case EVENT_BRAKES:printf("\nEvent brakes: %d", evt->dwData);break;case EVENT_COM1_TRANSMIT_SELECT:printf("\nEvent com1 select: %d", evt->dwData);break;case EVENT_COM2_TRANSMIT_SELECT:printf("\nEvent com1 select: %d", evt->dwData);break;case EVENT_COM_RECEIVE_ALL_TOGGLE:printf("\nEvent com1 select: %d", evt->dwData);break;default: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;Struct1 *pS = (Struct1*)&pObjData->dwData;if (pS->comm_1)sbi(ledStatus, BUTTONS_COM1);elsecbi(ledStatus, BUTTONS_COM1);if (pS->comm_2)sbi(ledStatus, BUTTONS_COM2);elsecbi(ledStatus, BUTTONS_COM2);if (pS->comm_both)sbi(ledStatus, BUTTONS_BOTH);elsecbi(ledStatus, BUTTONS_BOTH);updateLeds = true;//printf("\nTransmit Both: %f", pS->comm_both );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_SIMOBJECT_DATA: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 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_BRAKES, "brakes");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_AddClientEventToNotificationGroup(hSimConnect, GROUP0, EVENT_BRAKES);hr = SimConnect_AddClientEventToNotificationGroup(hSimConnect, GROUP0, EVENT_COM1_TRANSMIT_SELECT);hr = SimConnect_AddClientEventToNotificationGroup(hSimConnect, GROUP0, EVENT_COM2_TRANSMIT_SELECT);hr = SimConnect_AddClientEventToNotificationGroup(hSimConnect, GROUP0, EVENT_COM_RECEIVE_ALL_TOGGLE);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_MapInputEventToClientEvent(hSimConnect, INPUT0, "shift+ctrl+u", EVENT_BRAKES);//hr = SimConnect_SetInputGroupState(hSimConnect, INPUT0, SIMCONNECT_STATE_ON);}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);}}