Updated SDL, Bullet and OpenAL soft libs

Fixed case sensitivity problem
Fixed clang compiler problem with having the class namespace used in an inline for the == operator
Tweaked some theme stuff to be more consistent.
Added initial test of no-pie for linux
test sidestep of getTexCoord in shadergen hlsl feature so we don't assert when getting the terrain's shaderstuffs(which uses float3 instead of normal float2)
This commit is contained in:
Areloch 2019-07-07 02:43:49 -05:00
parent a1ecc98c87
commit 370161cfb1
1102 changed files with 205083 additions and 62836 deletions

View file

@ -0,0 +1,26 @@
OS=$(shell uname)
ifeq ($(OS), Darwin)
FILE=Makefile.mac
endif
ifneq (,$(findstring MINGW,$(OS)))
FILE=Makefile.mingw
endif
ifeq ($(OS), Linux)
FILE=Makefile.linux
endif
ifeq ($(OS), FreeBSD)
FILE=Makefile.freebsd
endif
ifeq ($(FILE), )
all:
$(error Your platform ${OS} is not supported at this time.)
endif
include $(FILE)

View file

@ -0,0 +1,43 @@
AM_CPPFLAGS = -I$(top_srcdir)/hidapi/ $(CFLAGS_TESTGUI)
if OS_LINUX
## Linux
bin_PROGRAMS = hidapi-hidraw-testgui hidapi-libusb-testgui
hidapi_hidraw_testgui_SOURCES = test.cpp
hidapi_hidraw_testgui_LDADD = $(top_builddir)/linux/libhidapi-hidraw.la $(LIBS_TESTGUI)
hidapi_libusb_testgui_SOURCES = test.cpp
hidapi_libusb_testgui_LDADD = $(top_builddir)/libusb/libhidapi-libusb.la $(LIBS_TESTGUI)
else
## Other OS's
bin_PROGRAMS = hidapi-testgui
hidapi_testgui_SOURCES = test.cpp
hidapi_testgui_LDADD = $(top_builddir)/$(backend)/libhidapi.la $(LIBS_TESTGUI)
endif
if OS_DARWIN
hidapi_testgui_SOURCES = test.cpp mac_support_cocoa.m mac_support.h
# Rules for copying the binary and its dependencies into the app bundle.
TestGUI.app/Contents/MacOS/hidapi-testgui$(EXEEXT): hidapi-testgui$(EXEEXT)
$(srcdir)/copy_to_bundle.sh
all: all-am TestGUI.app/Contents/MacOS/hidapi-testgui$(EXEEXT)
endif
EXTRA_DIST = \
copy_to_bundle.sh \
Makefile-manual \
Makefile.freebsd \
Makefile.linux \
Makefile.mac \
Makefile.mingw \
TestGUI.app.in \
testgui.sln \
testgui.vcproj
distclean-local:
rm -rf TestGUI.app

View file

@ -0,0 +1,33 @@
###########################################
# Simple Makefile for HIDAPI test program
#
# Alan Ott
# Signal 11 Software
# 2010-06-01
###########################################
all: testgui
CC=cc
CXX=c++
COBJS=../libusb/hid.o
CPPOBJS=test.o
OBJS=$(COBJS) $(CPPOBJS)
CFLAGS=-I../hidapi -I/usr/local/include `fox-config --cflags` -Wall -g -c
LDFLAGS= -L/usr/local/lib
LIBS= -lusb -liconv `fox-config --libs` -pthread
testgui: $(OBJS)
$(CXX) -Wall -g $^ $(LDFLAGS) -o $@ $(LIBS)
$(COBJS): %.o: %.c
$(CC) $(CFLAGS) $< -o $@
$(CPPOBJS): %.o: %.cpp
$(CXX) $(CFLAGS) $< -o $@
clean:
rm *.o testgui
.PHONY: clean

View file

@ -0,0 +1,32 @@
###########################################
# Simple Makefile for HIDAPI test program
#
# Alan Ott
# Signal 11 Software
# 2010-06-01
###########################################
all: testgui
CC=gcc
CXX=g++
COBJS=../libusb/hid.o
CPPOBJS=test.o
OBJS=$(COBJS) $(CPPOBJS)
CFLAGS=-I../hidapi -Wall -g -c `fox-config --cflags` `pkg-config libusb-1.0 --cflags`
LIBS=-ludev -lrt -lpthread `fox-config --libs` `pkg-config libusb-1.0 --libs`
testgui: $(OBJS)
g++ -Wall -g $^ $(LIBS) -o testgui
$(COBJS): %.o: %.c
$(CC) $(CFLAGS) $< -o $@
$(CPPOBJS): %.o: %.cpp
$(CXX) $(CFLAGS) $< -o $@
clean:
rm *.o testgui
.PHONY: clean

View file

@ -0,0 +1,46 @@
###########################################
# Simple Makefile for HIDAPI test program
#
# Alan Ott
# Signal 11 Software
# 2010-07-03
###########################################
all: hidapi-testgui
CC=gcc
CXX=g++
COBJS=../mac/hid.o
CPPOBJS=test.o
OBJCOBJS=mac_support_cocoa.o
OBJS=$(COBJS) $(CPPOBJS) $(OBJCOBJS)
CFLAGS=-I../hidapi -Wall -g -c `fox-config --cflags`
LDFLAGS=-L/usr/X11R6/lib
LIBS=`fox-config --libs` -framework IOKit -framework CoreFoundation -framework Cocoa
hidapi-testgui: $(OBJS) TestGUI.app
g++ -Wall -g $(OBJS) $(LIBS) $(LDFLAGS) -o hidapi-testgui
./copy_to_bundle.sh
#cp TestGUI.app/Contents/MacOS/hidapi-testgui TestGUI.app/Contents/MacOS/tg
#cp start.sh TestGUI.app/Contents/MacOS/hidapi-testgui
$(COBJS): %.o: %.c
$(CC) $(CFLAGS) $< -o $@
$(CPPOBJS): %.o: %.cpp
$(CXX) $(CFLAGS) $< -o $@
$(OBJCOBJS): %.o: %.m
$(CXX) $(CFLAGS) -x objective-c++ $< -o $@
TestGUI.app: TestGUI.app.in
rm -Rf TestGUI.app
mkdir -p TestGUI.app
cp -R TestGUI.app.in/ TestGUI.app
clean:
rm -f $(OBJS) hidapi-testgui
rm -Rf TestGUI.app
.PHONY: clean

View file

@ -0,0 +1,32 @@
###########################################
# Simple Makefile for HIDAPI test program
#
# Alan Ott
# Signal 11 Software
# 2010-06-01
###########################################
all: hidapi-testgui
CC=gcc
CXX=g++
COBJS=../windows/hid.o
CPPOBJS=test.o
OBJS=$(COBJS) $(CPPOBJS)
CFLAGS=-I../hidapi -I../../hidapi-externals/fox/include -g -c
LIBS= -mwindows -lsetupapi -L../../hidapi-externals/fox/lib -Wl,-Bstatic -lFOX-1.6 -Wl,-Bdynamic -lgdi32 -Wl,--enable-auto-import -static-libgcc -static-libstdc++ -lkernel32
hidapi-testgui: $(OBJS)
g++ -g $^ $(LIBS) -o hidapi-testgui
$(COBJS): %.o: %.c
$(CC) $(CFLAGS) $< -o $@
$(CPPOBJS): %.o: %.cpp
$(CXX) $(CFLAGS) $< -o $@
clean:
rm -f *.o hidapi-testgui.exe
.PHONY: clean

View file

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleDisplayName</key>
<string></string>
<key>CFBundleExecutable</key>
<string>hidapi-testgui</string>
<key>CFBundleIconFile</key>
<string>Signal11.icns</string>
<key>CFBundleIdentifier</key>
<string>us.signal11.hidtestgui</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>testgui</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>CSResourcesFileMapped</key>
<true/>
</dict>
</plist>

View file

@ -0,0 +1 @@
APPL????

View file

@ -0,0 +1,97 @@
#!/bin/bash
#### Configuration:
# The name of the executable. It is assumed
# that it is in the current working directory.
EXE_NAME=hidapi-testgui
# Path to the executable directory inside the bundle.
# This must be an absolute path, so use $PWD.
EXEPATH=$PWD/TestGUI.app/Contents/MacOS
# Libraries to explicitly bundle, even though they
# may not be in /opt/local. One per line. These
# are used with grep, so only a portion of the name
# is required. eg: libFOX, libz, etc.
LIBS_TO_BUNDLE=libFOX
function copydeps {
local file=$1
# echo "Copying deps for $file...."
local BASE_OF_EXE=`basename $file`
# A will contain the dependencies of this library
local A=`otool -LX $file |cut -f 1 -d " "`
local i
for i in $A; do
local BASE=`basename $i`
# See if it's a lib we specifically want to bundle
local bundle_this_lib=0
local j
for j in $LIBS_TO_BUNDLE; do
echo $i |grep -q $j
if [ $? -eq 0 ]; then
bundle_this_lib=1
echo "bundling $i because it's in the list."
break;
fi
done
# See if it's in /opt/local. Bundle all in /opt/local
local isOptLocal=0
echo $i |grep -q /opt/local
if [ $? -eq 0 ]; then
isOptLocal=1
echo "bundling $i because it's in /opt/local."
fi
# Bundle the library
if [ $isOptLocal -ne 0 ] || [ $bundle_this_lib -ne 0 ]; then
# Copy the file into the bundle if it exists.
if [ -f $EXEPATH/$BASE ]; then
z=0
else
cp $i $EXEPATH
chmod 755 $EXEPATH/$BASE
fi
# echo "$BASE_OF_EXE depends on $BASE"
# Fix the paths using install_name_tool and then
# call this function recursively for each dependency
# of this library.
if [ $BASE_OF_EXE != $BASE ]; then
# Fix the paths
install_name_tool -id @executable_path/$BASE $EXEPATH/$BASE
install_name_tool -change $i @executable_path/$BASE $EXEPATH/$BASE_OF_EXE
# Call this function (recursive) on
# on each dependency of this library.
copydeps $EXEPATH/$BASE
fi
fi
done
}
rm -f $EXEPATH/*
# Copy the binary into the bundle. Use ../libtool to do this if it's
# available beacuse if $EXE_NAME was built with autotools, it will be
# necessary. If ../libtool not available, just use cp to do the copy, but
# only if $EXE_NAME is a binary.
if [ -x ../libtool ]; then
../libtool --mode=install cp $EXE_NAME $EXEPATH
else
file -bI $EXE_NAME |grep binary
if [ $? -ne 0 ]; then
echo "There is no ../libtool and $EXE_NAME is not a binary."
echo "I'm not sure what to do."
exit 1
else
cp $EXE_NAME $EXEPATH
fi
fi
copydeps $EXEPATH/$EXE_NAME

View file

@ -0,0 +1,134 @@
/*******************************
Mac support for HID Test GUI
Alan Ott
Signal 11 Software
Some of this code is from Apple Documentation, most notably
http://developer.apple.com/legacy/mac/library/documentation/AppleScript/Conceptual/AppleEvents/AppleEvents.pdf
*******************************/
#include <Carbon/Carbon.h>
#include <fx.h>
extern FXMainWindow *g_main_window;
static pascal OSErr HandleQuitMessage(const AppleEvent *theAppleEvent, AppleEvent
*reply, long handlerRefcon)
{
puts("Quitting\n");
FXApp::instance()->exit();
return 0;
}
static pascal OSErr HandleReopenMessage(const AppleEvent *theAppleEvent, AppleEvent
*reply, long handlerRefcon)
{
puts("Showing");
g_main_window->show();
return 0;
}
static pascal OSErr HandleWildCardMessage(const AppleEvent *theAppleEvent, AppleEvent
*reply, long handlerRefcon)
{
puts("WildCard\n");
return 0;
}
OSStatus AEHandler(EventHandlerCallRef inCaller, EventRef inEvent, void* inRefcon)
{
Boolean release = false;
EventRecord eventRecord;
OSErr ignoreErrForThisSample;
// Events of type kEventAppleEvent must be removed from the queue
// before being passed to AEProcessAppleEvent.
if (IsEventInQueue(GetMainEventQueue(), inEvent))
{
// RemoveEventFromQueue will release the event, which will
// destroy it if we don't retain it first.
RetainEvent(inEvent);
release = true;
RemoveEventFromQueue(GetMainEventQueue(), inEvent);
}
// Convert the event ref to the type AEProcessAppleEvent expects.
ConvertEventRefToEventRecord(inEvent, &eventRecord);
ignoreErrForThisSample = AEProcessAppleEvent(&eventRecord);
if (release)
ReleaseEvent(inEvent);
// This Carbon event has been handled, even if no AppleEvent handlers
// were installed for the Apple event.
return noErr;
}
static void HandleEvent(EventRecord *event)
{
//printf("What: %d message %x\n", event->what, event->message);
if (event->what == osEvt) {
if (((event->message >> 24) & 0xff) == suspendResumeMessage) {
if (event->message & resumeFlag) {
g_main_window->show();
}
}
}
#if 0
switch (event->what)
{
case mouseDown:
//HandleMouseDown(event);
break;
case keyDown:
case autoKey:
//HandleKeyPress(event);
break;
case kHighLevelEvent:
puts("Calling ProcessAppleEvent\n");
AEProcessAppleEvent(event);
break;
}
#endif
}
void
init_apple_message_system()
{
OSErr err;
static const EventTypeSpec appleEvents[] =
{
{ kEventClassAppleEvent, kEventAppleEvent }
};
/* Install the handler for Apple Events */
InstallApplicationEventHandler(NewEventHandlerUPP(AEHandler),
GetEventTypeCount(appleEvents), appleEvents, 0, NULL);
/* Install handlers for the individual Apple Events that come
from the Dock icon: the Reopen (click), and the Quit messages. */
err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
NewAEEventHandlerUPP(HandleQuitMessage), 0, false);
err = AEInstallEventHandler(kCoreEventClass, kAEReopenApplication,
NewAEEventHandlerUPP(HandleReopenMessage), 0, false);
#if 0
// Left as an example of a wild card match.
err = AEInstallEventHandler(kCoreEventClass, typeWildCard,
NewAEEventHandlerUPP(HandleWildMessage), 0, false);
#endif
}
void
check_apple_events()
{
RgnHandle cursorRgn = NULL;
Boolean gotEvent=TRUE;
EventRecord event;
while (gotEvent) {
gotEvent = WaitNextEvent(everyEvent, &event, 0L/*timeout*/, cursorRgn);
if (gotEvent) {
HandleEvent(&event);
}
}
}

View file

@ -0,0 +1,17 @@
/*******************************
Mac support for HID Test GUI
Alan Ott
Signal 11 Software
*******************************/
#ifndef MAC_SUPPORT_H__
#define MAC_SUPPORT_H__
extern "C" {
void init_apple_message_system();
void check_apple_events();
}
#endif

View file

@ -0,0 +1,94 @@
/*******************************
Mac support for HID Test GUI
Alan Ott
Signal 11 Software
*******************************/
#include <fx.h>
#import <Cocoa/Cocoa.h>
extern FXMainWindow *g_main_window;
@interface MyAppDelegate : NSObject
{
}
@end
@implementation MyAppDelegate
- (void) applicationWillBecomeActive:(NSNotification*)notif
{
printf("WillBecomeActive\n");
g_main_window->show();
}
- (void) applicationWillTerminate:(NSNotification*)notif
{
/* Doesn't get called. Not sure why */
printf("WillTerminate\n");
FXApp::instance()->exit();
}
- (NSApplicationTerminateReply) applicationShouldTerminate:(NSApplication*)sender
{
/* Doesn't get called. Not sure why */
printf("ShouldTerminate\n");
return YES;
}
- (void) applicationWillHide:(NSNotification*)notif
{
printf("WillHide\n");
g_main_window->hide();
}
- (void) handleQuitEvent:(NSAppleEventDescriptor*)event withReplyEvent:(NSAppleEventDescriptor*)replyEvent
{
printf("QuitEvent\n");
FXApp::instance()->exit();
}
@end
extern "C" {
void
init_apple_message_system()
{
static MyAppDelegate *d = [MyAppDelegate new];
[[NSApplication sharedApplication] setDelegate:d];
/* Register for Apple Events. */
/* This is from
http://stackoverflow.com/questions/1768497/application-exit-event */
NSAppleEventManager *aem = [NSAppleEventManager sharedAppleEventManager];
[aem setEventHandler:d
andSelector:@selector(handleQuitEvent:withReplyEvent:)
forEventClass:kCoreEventClass andEventID:kAEQuitApplication];
}
void
check_apple_events()
{
NSApplication *app = [NSApplication sharedApplication];
NSAutoreleasePool *pool = [NSAutoreleasePool new];
while (1) {
NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask
untilDate:nil
inMode:NSDefaultRunLoopMode
dequeue:YES];
if (event == NULL)
break;
else {
//printf("Event happened: Type: %d\n", event->_type);
[app sendEvent: event];
}
}
[pool release];
}
} /* extern "C" */

View file

@ -0,0 +1,2 @@
#!/bin/bash
xterm -e /Users/alan/work/hidapi/testgui/TestGUI.app/Contents/MacOS/tg

View file

@ -0,0 +1,532 @@
/*******************************************************
Demo Program for HIDAPI
Alan Ott
Signal 11 Software
2010-07-20
Copyright 2010, All Rights Reserved
This contents of this file may be used by anyone
for any reason without any conditions and may be
used as a starting point for your own applications
which use HIDAPI.
********************************************************/
#include <fx.h>
#include "hidapi.h"
#include "mac_support.h"
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#ifdef _WIN32
// Thanks Microsoft, but I know how to use strncpy().
#pragma warning(disable:4996)
#endif
class MainWindow : public FXMainWindow {
FXDECLARE(MainWindow)
public:
enum {
ID_FIRST = FXMainWindow::ID_LAST,
ID_CONNECT,
ID_DISCONNECT,
ID_RESCAN,
ID_SEND_OUTPUT_REPORT,
ID_SEND_FEATURE_REPORT,
ID_GET_FEATURE_REPORT,
ID_CLEAR,
ID_TIMER,
ID_MAC_TIMER,
ID_LAST,
};
private:
FXList *device_list;
FXButton *connect_button;
FXButton *disconnect_button;
FXButton *rescan_button;
FXButton *output_button;
FXLabel *connected_label;
FXTextField *output_text;
FXTextField *output_len;
FXButton *feature_button;
FXButton *get_feature_button;
FXTextField *feature_text;
FXTextField *feature_len;
FXTextField *get_feature_text;
FXText *input_text;
FXFont *title_font;
struct hid_device_info *devices;
hid_device *connected_device;
size_t getDataFromTextField(FXTextField *tf, char *buf, size_t len);
int getLengthFromTextField(FXTextField *tf);
protected:
MainWindow() {};
public:
MainWindow(FXApp *a);
~MainWindow();
virtual void create();
long onConnect(FXObject *sender, FXSelector sel, void *ptr);
long onDisconnect(FXObject *sender, FXSelector sel, void *ptr);
long onRescan(FXObject *sender, FXSelector sel, void *ptr);
long onSendOutputReport(FXObject *sender, FXSelector sel, void *ptr);
long onSendFeatureReport(FXObject *sender, FXSelector sel, void *ptr);
long onGetFeatureReport(FXObject *sender, FXSelector sel, void *ptr);
long onClear(FXObject *sender, FXSelector sel, void *ptr);
long onTimeout(FXObject *sender, FXSelector sel, void *ptr);
long onMacTimeout(FXObject *sender, FXSelector sel, void *ptr);
};
// FOX 1.7 changes the timeouts to all be nanoseconds.
// Fox 1.6 had all timeouts as milliseconds.
#if (FOX_MINOR >= 7)
const int timeout_scalar = 1000*1000;
#else
const int timeout_scalar = 1;
#endif
FXMainWindow *g_main_window;
FXDEFMAP(MainWindow) MainWindowMap [] = {
FXMAPFUNC(SEL_COMMAND, MainWindow::ID_CONNECT, MainWindow::onConnect ),
FXMAPFUNC(SEL_COMMAND, MainWindow::ID_DISCONNECT, MainWindow::onDisconnect ),
FXMAPFUNC(SEL_COMMAND, MainWindow::ID_RESCAN, MainWindow::onRescan ),
FXMAPFUNC(SEL_COMMAND, MainWindow::ID_SEND_OUTPUT_REPORT, MainWindow::onSendOutputReport ),
FXMAPFUNC(SEL_COMMAND, MainWindow::ID_SEND_FEATURE_REPORT, MainWindow::onSendFeatureReport ),
FXMAPFUNC(SEL_COMMAND, MainWindow::ID_GET_FEATURE_REPORT, MainWindow::onGetFeatureReport ),
FXMAPFUNC(SEL_COMMAND, MainWindow::ID_CLEAR, MainWindow::onClear ),
FXMAPFUNC(SEL_TIMEOUT, MainWindow::ID_TIMER, MainWindow::onTimeout ),
FXMAPFUNC(SEL_TIMEOUT, MainWindow::ID_MAC_TIMER, MainWindow::onMacTimeout ),
};
FXIMPLEMENT(MainWindow, FXMainWindow, MainWindowMap, ARRAYNUMBER(MainWindowMap));
MainWindow::MainWindow(FXApp *app)
: FXMainWindow(app, "HIDAPI Test Application", NULL, NULL, DECOR_ALL, 200,100, 425,700)
{
devices = NULL;
connected_device = NULL;
FXVerticalFrame *vf = new FXVerticalFrame(this, LAYOUT_FILL_Y|LAYOUT_FILL_X);
FXLabel *label = new FXLabel(vf, "HIDAPI Test Tool");
title_font = new FXFont(getApp(), "Arial", 14, FXFont::Bold);
label->setFont(title_font);
new FXLabel(vf,
"Select a device and press Connect.", NULL, JUSTIFY_LEFT);
new FXLabel(vf,
"Output data bytes can be entered in the Output section, \n"
"separated by space, comma or brackets. Data starting with 0x\n"
"is treated as hex. Data beginning with a 0 is treated as \n"
"octal. All other data is treated as decimal.", NULL, JUSTIFY_LEFT);
new FXLabel(vf,
"Data received from the device appears in the Input section.",
NULL, JUSTIFY_LEFT);
new FXLabel(vf,
"Optionally, a report length may be specified. Extra bytes are\n"
"padded with zeros. If no length is specified, the length is \n"
"inferred from the data.",
NULL, JUSTIFY_LEFT);
new FXLabel(vf, "");
// Device List and Connect/Disconnect buttons
FXHorizontalFrame *hf = new FXHorizontalFrame(vf, LAYOUT_FILL_X);
//device_list = new FXList(new FXHorizontalFrame(hf,FRAME_SUNKEN|FRAME_THICK, 0,0,0,0, 0,0,0,0), NULL, 0, LISTBOX_NORMAL|LAYOUT_FILL_X|LAYOUT_FILL_Y|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT, 0,0,300,200);
device_list = new FXList(new FXHorizontalFrame(hf,FRAME_SUNKEN|FRAME_THICK|LAYOUT_FILL_X|LAYOUT_FILL_Y, 0,0,0,0, 0,0,0,0), NULL, 0, LISTBOX_NORMAL|LAYOUT_FILL_X|LAYOUT_FILL_Y, 0,0,300,200);
FXVerticalFrame *buttonVF = new FXVerticalFrame(hf);
connect_button = new FXButton(buttonVF, "Connect", NULL, this, ID_CONNECT, BUTTON_NORMAL|LAYOUT_FILL_X);
disconnect_button = new FXButton(buttonVF, "Disconnect", NULL, this, ID_DISCONNECT, BUTTON_NORMAL|LAYOUT_FILL_X);
disconnect_button->disable();
rescan_button = new FXButton(buttonVF, "Re-Scan devices", NULL, this, ID_RESCAN, BUTTON_NORMAL|LAYOUT_FILL_X);
new FXHorizontalFrame(buttonVF, 0, 0,0,0,0, 0,0,50,0);
connected_label = new FXLabel(vf, "Disconnected");
new FXHorizontalFrame(vf);
// Output Group Box
FXGroupBox *gb = new FXGroupBox(vf, "Output", FRAME_GROOVE|LAYOUT_FILL_X);
FXMatrix *matrix = new FXMatrix(gb, 3, MATRIX_BY_COLUMNS|LAYOUT_FILL_X);
new FXLabel(matrix, "Data");
new FXLabel(matrix, "Length");
new FXLabel(matrix, "");
//hf = new FXHorizontalFrame(gb, LAYOUT_FILL_X);
output_text = new FXTextField(matrix, 30, NULL, 0, TEXTFIELD_NORMAL|LAYOUT_FILL_X|LAYOUT_FILL_COLUMN);
output_text->setText("1 0x81 0");
output_len = new FXTextField(matrix, 5, NULL, 0, TEXTFIELD_NORMAL|LAYOUT_FILL_X|LAYOUT_FILL_COLUMN);
output_button = new FXButton(matrix, "Send Output Report", NULL, this, ID_SEND_OUTPUT_REPORT, BUTTON_NORMAL|LAYOUT_FILL_X);
output_button->disable();
//new FXHorizontalFrame(matrix, LAYOUT_FILL_X);
//hf = new FXHorizontalFrame(gb, LAYOUT_FILL_X);
feature_text = new FXTextField(matrix, 30, NULL, 0, TEXTFIELD_NORMAL|LAYOUT_FILL_X|LAYOUT_FILL_COLUMN);
feature_len = new FXTextField(matrix, 5, NULL, 0, TEXTFIELD_NORMAL|LAYOUT_FILL_X|LAYOUT_FILL_COLUMN);
feature_button = new FXButton(matrix, "Send Feature Report", NULL, this, ID_SEND_FEATURE_REPORT, BUTTON_NORMAL|LAYOUT_FILL_X);
feature_button->disable();
get_feature_text = new FXTextField(matrix, 30, NULL, 0, TEXTFIELD_NORMAL|LAYOUT_FILL_X|LAYOUT_FILL_COLUMN);
new FXWindow(matrix);
get_feature_button = new FXButton(matrix, "Get Feature Report", NULL, this, ID_GET_FEATURE_REPORT, BUTTON_NORMAL|LAYOUT_FILL_X);
get_feature_button->disable();
// Input Group Box
gb = new FXGroupBox(vf, "Input", FRAME_GROOVE|LAYOUT_FILL_X|LAYOUT_FILL_Y);
FXVerticalFrame *innerVF = new FXVerticalFrame(gb, LAYOUT_FILL_X|LAYOUT_FILL_Y);
input_text = new FXText(new FXHorizontalFrame(innerVF,LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_SUNKEN|FRAME_THICK, 0,0,0,0, 0,0,0,0), NULL, 0, LAYOUT_FILL_X|LAYOUT_FILL_Y);
input_text->setEditable(false);
new FXButton(innerVF, "Clear", NULL, this, ID_CLEAR, BUTTON_NORMAL|LAYOUT_RIGHT);
}
MainWindow::~MainWindow()
{
if (connected_device)
hid_close(connected_device);
hid_exit();
delete title_font;
}
void
MainWindow::create()
{
FXMainWindow::create();
show();
onRescan(NULL, 0, NULL);
#ifdef __APPLE__
init_apple_message_system();
#endif
getApp()->addTimeout(this, ID_MAC_TIMER,
50 * timeout_scalar /*50ms*/);
}
long
MainWindow::onConnect(FXObject *sender, FXSelector sel, void *ptr)
{
if (connected_device != NULL)
return 1;
FXint cur_item = device_list->getCurrentItem();
if (cur_item < 0)
return -1;
FXListItem *item = device_list->getItem(cur_item);
if (!item)
return -1;
struct hid_device_info *device_info = (struct hid_device_info*) item->getData();
if (!device_info)
return -1;
connected_device = hid_open_path(device_info->path);
if (!connected_device) {
FXMessageBox::error(this, MBOX_OK, "Device Error", "Unable To Connect to Device");
return -1;
}
hid_set_nonblocking(connected_device, 1);
getApp()->addTimeout(this, ID_TIMER,
5 * timeout_scalar /*5ms*/);
FXString s;
s.format("Connected to: %04hx:%04hx -", device_info->vendor_id, device_info->product_id);
s += FXString(" ") + device_info->manufacturer_string;
s += FXString(" ") + device_info->product_string;
connected_label->setText(s);
output_button->enable();
feature_button->enable();
get_feature_button->enable();
connect_button->disable();
disconnect_button->enable();
input_text->setText("");
return 1;
}
long
MainWindow::onDisconnect(FXObject *sender, FXSelector sel, void *ptr)
{
hid_close(connected_device);
connected_device = NULL;
connected_label->setText("Disconnected");
output_button->disable();
feature_button->disable();
get_feature_button->disable();
connect_button->enable();
disconnect_button->disable();
getApp()->removeTimeout(this, ID_TIMER);
return 1;
}
long
MainWindow::onRescan(FXObject *sender, FXSelector sel, void *ptr)
{
struct hid_device_info *cur_dev;
device_list->clearItems();
// List the Devices
hid_free_enumeration(devices);
devices = hid_enumerate(0x0, 0x0);
cur_dev = devices;
while (cur_dev) {
// Add it to the List Box.
FXString s;
FXString usage_str;
s.format("%04hx:%04hx -", cur_dev->vendor_id, cur_dev->product_id);
s += FXString(" ") + cur_dev->manufacturer_string;
s += FXString(" ") + cur_dev->product_string;
usage_str.format(" (usage: %04hx:%04hx) ", cur_dev->usage_page, cur_dev->usage);
s += usage_str;
FXListItem *li = new FXListItem(s, NULL, cur_dev);
device_list->appendItem(li);
cur_dev = cur_dev->next;
}
if (device_list->getNumItems() == 0)
device_list->appendItem("*** No Devices Connected ***");
else {
device_list->selectItem(0);
}
return 1;
}
size_t
MainWindow::getDataFromTextField(FXTextField *tf, char *buf, size_t len)
{
const char *delim = " ,{}\t\r\n";
FXString data = tf->getText();
const FXchar *d = data.text();
size_t i = 0;
// Copy the string from the GUI.
size_t sz = strlen(d);
char *str = (char*) malloc(sz+1);
strcpy(str, d);
// For each token in the string, parse and store in buf[].
char *token = strtok(str, delim);
while (token) {
char *endptr;
long int val = strtol(token, &endptr, 0);
buf[i++] = val;
token = strtok(NULL, delim);
}
free(str);
return i;
}
/* getLengthFromTextField()
Returns length:
0: empty text field
>0: valid length
-1: invalid length */
int
MainWindow::getLengthFromTextField(FXTextField *tf)
{
long int len;
FXString str = tf->getText();
size_t sz = str.length();
if (sz > 0) {
char *endptr;
len = strtol(str.text(), &endptr, 0);
if (endptr != str.text() && *endptr == '\0') {
if (len <= 0) {
FXMessageBox::error(this, MBOX_OK, "Invalid length", "Enter a length greater than zero.");
return -1;
}
return len;
}
else
return -1;
}
return 0;
}
long
MainWindow::onSendOutputReport(FXObject *sender, FXSelector sel, void *ptr)
{
char buf[256];
size_t data_len, len;
int textfield_len;
memset(buf, 0x0, sizeof(buf));
textfield_len = getLengthFromTextField(output_len);
data_len = getDataFromTextField(output_text, buf, sizeof(buf));
if (textfield_len < 0) {
FXMessageBox::error(this, MBOX_OK, "Invalid length", "Length field is invalid. Please enter a number in hex, octal, or decimal.");
return 1;
}
if (textfield_len > sizeof(buf)) {
FXMessageBox::error(this, MBOX_OK, "Invalid length", "Length field is too long.");
return 1;
}
len = (textfield_len)? textfield_len: data_len;
int res = hid_write(connected_device, (const unsigned char*)buf, len);
if (res < 0) {
FXMessageBox::error(this, MBOX_OK, "Error Writing", "Could not write to device. Error reported was: %ls", hid_error(connected_device));
}
return 1;
}
long
MainWindow::onSendFeatureReport(FXObject *sender, FXSelector sel, void *ptr)
{
char buf[256];
size_t data_len, len;
int textfield_len;
memset(buf, 0x0, sizeof(buf));
textfield_len = getLengthFromTextField(feature_len);
data_len = getDataFromTextField(feature_text, buf, sizeof(buf));
if (textfield_len < 0) {
FXMessageBox::error(this, MBOX_OK, "Invalid length", "Length field is invalid. Please enter a number in hex, octal, or decimal.");
return 1;
}
if (textfield_len > sizeof(buf)) {
FXMessageBox::error(this, MBOX_OK, "Invalid length", "Length field is too long.");
return 1;
}
len = (textfield_len)? textfield_len: data_len;
int res = hid_send_feature_report(connected_device, (const unsigned char*)buf, len);
if (res < 0) {
FXMessageBox::error(this, MBOX_OK, "Error Writing", "Could not send feature report to device. Error reported was: %ls", hid_error(connected_device));
}
return 1;
}
long
MainWindow::onGetFeatureReport(FXObject *sender, FXSelector sel, void *ptr)
{
char buf[256];
size_t len;
memset(buf, 0x0, sizeof(buf));
len = getDataFromTextField(get_feature_text, buf, sizeof(buf));
if (len != 1) {
FXMessageBox::error(this, MBOX_OK, "Too many numbers", "Enter only a single report number in the text field");
}
int res = hid_get_feature_report(connected_device, (unsigned char*)buf, sizeof(buf));
if (res < 0) {
FXMessageBox::error(this, MBOX_OK, "Error Getting Report", "Could not get feature report from device. Error reported was: %ls", hid_error(connected_device));
}
if (res > 0) {
FXString s;
s.format("Returned Feature Report. %d bytes:\n", res);
for (int i = 0; i < res; i++) {
FXString t;
t.format("%02hhx ", buf[i]);
s += t;
if ((i+1) % 4 == 0)
s += " ";
if ((i+1) % 16 == 0)
s += "\n";
}
s += "\n";
input_text->appendText(s);
input_text->setBottomLine(INT_MAX);
}
return 1;
}
long
MainWindow::onClear(FXObject *sender, FXSelector sel, void *ptr)
{
input_text->setText("");
return 1;
}
long
MainWindow::onTimeout(FXObject *sender, FXSelector sel, void *ptr)
{
unsigned char buf[256];
int res = hid_read(connected_device, buf, sizeof(buf));
if (res > 0) {
FXString s;
s.format("Received %d bytes:\n", res);
for (int i = 0; i < res; i++) {
FXString t;
t.format("%02hhx ", buf[i]);
s += t;
if ((i+1) % 4 == 0)
s += " ";
if ((i+1) % 16 == 0)
s += "\n";
}
s += "\n";
input_text->appendText(s);
input_text->setBottomLine(INT_MAX);
}
if (res < 0) {
input_text->appendText("hid_read() returned error\n");
input_text->setBottomLine(INT_MAX);
}
getApp()->addTimeout(this, ID_TIMER,
5 * timeout_scalar /*5ms*/);
return 1;
}
long
MainWindow::onMacTimeout(FXObject *sender, FXSelector sel, void *ptr)
{
#ifdef __APPLE__
check_apple_events();
getApp()->addTimeout(this, ID_MAC_TIMER,
50 * timeout_scalar /*50ms*/);
#endif
return 1;
}
int main(int argc, char **argv)
{
FXApp app("HIDAPI Test Application", "Signal 11 Software");
app.init(argc, argv);
g_main_window = new MainWindow(&app);
app.create();
app.run();
return 0;
}