Fixing solution file .
1 /*******************************************************
2 Demo Program for HIDAPI
9 Copyright 2010, All Rights Reserved
11 This contents of this file may be used by anyone
12 for any reason without any conditions and may be
13 used as a starting point for your own applications
15 ********************************************************/
21 #include "mac_support.h"
27 // Thanks Microsoft, but I know how to use strncpy().
28 #pragma warning(disable:4996)
31 class MainWindow : public FXMainWindow {
36 ID_FIRST = FXMainWindow::ID_LAST,
40 ID_SEND_OUTPUT_REPORT,
41 ID_SEND_FEATURE_REPORT,
42 ID_GET_FEATURE_REPORT,
51 FXButton *connect_button;
52 FXButton *disconnect_button;
53 FXButton *rescan_button;
54 FXButton *output_button;
55 FXLabel *connected_label;
56 FXTextField *output_text;
57 FXTextField *output_len;
58 FXButton *feature_button;
59 FXButton *get_feature_button;
60 FXTextField *feature_text;
61 FXTextField *feature_len;
62 FXTextField *get_feature_text;
66 struct hid_device_info *devices;
67 hid_device *connected_device;
68 size_t getDataFromTextField(FXTextField *tf, char *buf, size_t len);
69 int getLengthFromTextField(FXTextField *tf);
77 virtual void create();
79 long onConnect(FXObject *sender, FXSelector sel, void *ptr);
80 long onDisconnect(FXObject *sender, FXSelector sel, void *ptr);
81 long onRescan(FXObject *sender, FXSelector sel, void *ptr);
82 long onSendOutputReport(FXObject *sender, FXSelector sel, void *ptr);
83 long onSendFeatureReport(FXObject *sender, FXSelector sel, void *ptr);
84 long onGetFeatureReport(FXObject *sender, FXSelector sel, void *ptr);
85 long onClear(FXObject *sender, FXSelector sel, void *ptr);
86 long onTimeout(FXObject *sender, FXSelector sel, void *ptr);
87 long onMacTimeout(FXObject *sender, FXSelector sel, void *ptr);
90 // FOX 1.7 changes the timeouts to all be nanoseconds.
91 // Fox 1.6 had all timeouts as milliseconds.
93 const int timeout_scalar = 1000*1000;
95 const int timeout_scalar = 1;
98 FXMainWindow *g_main_window;
101 FXDEFMAP(MainWindow) MainWindowMap [] = {
102 FXMAPFUNC(SEL_COMMAND, MainWindow::ID_CONNECT, MainWindow::onConnect ),
103 FXMAPFUNC(SEL_COMMAND, MainWindow::ID_DISCONNECT, MainWindow::onDisconnect ),
104 FXMAPFUNC(SEL_COMMAND, MainWindow::ID_RESCAN, MainWindow::onRescan ),
105 FXMAPFUNC(SEL_COMMAND, MainWindow::ID_SEND_OUTPUT_REPORT, MainWindow::onSendOutputReport ),
106 FXMAPFUNC(SEL_COMMAND, MainWindow::ID_SEND_FEATURE_REPORT, MainWindow::onSendFeatureReport ),
107 FXMAPFUNC(SEL_COMMAND, MainWindow::ID_GET_FEATURE_REPORT, MainWindow::onGetFeatureReport ),
108 FXMAPFUNC(SEL_COMMAND, MainWindow::ID_CLEAR, MainWindow::onClear ),
109 FXMAPFUNC(SEL_TIMEOUT, MainWindow::ID_TIMER, MainWindow::onTimeout ),
110 FXMAPFUNC(SEL_TIMEOUT, MainWindow::ID_MAC_TIMER, MainWindow::onMacTimeout ),
113 FXIMPLEMENT(MainWindow, FXMainWindow, MainWindowMap, ARRAYNUMBER(MainWindowMap));
115 MainWindow::MainWindow(FXApp *app)
116 : FXMainWindow(app, "HIDAPI Test Application", NULL, NULL, DECOR_ALL, 200,100, 425,700)
119 connected_device = NULL;
121 FXVerticalFrame *vf = new FXVerticalFrame(this, LAYOUT_FILL_Y|LAYOUT_FILL_X);
123 FXLabel *label = new FXLabel(vf, "HIDAPI Test Tool");
124 title_font = new FXFont(getApp(), "Arial", 14, FXFont::Bold);
125 label->setFont(title_font);
128 "Select a device and press Connect.", NULL, JUSTIFY_LEFT);
130 "Output data bytes can be entered in the Output section, \n"
131 "separated by space, comma or brackets. Data starting with 0x\n"
132 "is treated as hex. Data beginning with a 0 is treated as \n"
133 "octal. All other data is treated as decimal.", NULL, JUSTIFY_LEFT);
135 "Data received from the device appears in the Input section.",
138 "Optionally, a report length may be specified. Extra bytes are\n"
139 "padded with zeros. If no length is specified, the length is \n"
140 "inferred from the data.",
144 // Device List and Connect/Disconnect buttons
145 FXHorizontalFrame *hf = new FXHorizontalFrame(vf, LAYOUT_FILL_X);
146 //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);
147 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);
148 FXVerticalFrame *buttonVF = new FXVerticalFrame(hf);
149 connect_button = new FXButton(buttonVF, "Connect", NULL, this, ID_CONNECT, BUTTON_NORMAL|LAYOUT_FILL_X);
150 disconnect_button = new FXButton(buttonVF, "Disconnect", NULL, this, ID_DISCONNECT, BUTTON_NORMAL|LAYOUT_FILL_X);
151 disconnect_button->disable();
152 rescan_button = new FXButton(buttonVF, "Re-Scan devices", NULL, this, ID_RESCAN, BUTTON_NORMAL|LAYOUT_FILL_X);
153 new FXHorizontalFrame(buttonVF, 0, 0,0,0,0, 0,0,50,0);
155 connected_label = new FXLabel(vf, "Disconnected");
157 new FXHorizontalFrame(vf);
160 FXGroupBox *gb = new FXGroupBox(vf, "Output", FRAME_GROOVE|LAYOUT_FILL_X);
161 FXMatrix *matrix = new FXMatrix(gb, 3, MATRIX_BY_COLUMNS|LAYOUT_FILL_X);
162 new FXLabel(matrix, "Data");
163 new FXLabel(matrix, "Length");
164 new FXLabel(matrix, "");
166 //hf = new FXHorizontalFrame(gb, LAYOUT_FILL_X);
167 output_text = new FXTextField(matrix, 30, NULL, 0, TEXTFIELD_NORMAL|LAYOUT_FILL_X|LAYOUT_FILL_COLUMN);
168 output_text->setText("1 0x81 0");
169 output_len = new FXTextField(matrix, 5, NULL, 0, TEXTFIELD_NORMAL|LAYOUT_FILL_X|LAYOUT_FILL_COLUMN);
170 output_button = new FXButton(matrix, "Send Output Report", NULL, this, ID_SEND_OUTPUT_REPORT, BUTTON_NORMAL|LAYOUT_FILL_X);
171 output_button->disable();
172 //new FXHorizontalFrame(matrix, LAYOUT_FILL_X);
174 //hf = new FXHorizontalFrame(gb, LAYOUT_FILL_X);
175 feature_text = new FXTextField(matrix, 30, NULL, 0, TEXTFIELD_NORMAL|LAYOUT_FILL_X|LAYOUT_FILL_COLUMN);
176 feature_len = new FXTextField(matrix, 5, NULL, 0, TEXTFIELD_NORMAL|LAYOUT_FILL_X|LAYOUT_FILL_COLUMN);
177 feature_button = new FXButton(matrix, "Send Feature Report", NULL, this, ID_SEND_FEATURE_REPORT, BUTTON_NORMAL|LAYOUT_FILL_X);
178 feature_button->disable();
180 get_feature_text = new FXTextField(matrix, 30, NULL, 0, TEXTFIELD_NORMAL|LAYOUT_FILL_X|LAYOUT_FILL_COLUMN);
181 new FXWindow(matrix);
182 get_feature_button = new FXButton(matrix, "Get Feature Report", NULL, this, ID_GET_FEATURE_REPORT, BUTTON_NORMAL|LAYOUT_FILL_X);
183 get_feature_button->disable();
187 gb = new FXGroupBox(vf, "Input", FRAME_GROOVE|LAYOUT_FILL_X|LAYOUT_FILL_Y);
188 FXVerticalFrame *innerVF = new FXVerticalFrame(gb, LAYOUT_FILL_X|LAYOUT_FILL_Y);
189 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);
190 input_text->setEditable(false);
191 new FXButton(innerVF, "Clear", NULL, this, ID_CLEAR, BUTTON_NORMAL|LAYOUT_RIGHT);
196 MainWindow::~MainWindow()
198 if (connected_device)
199 hid_close(connected_device);
207 FXMainWindow::create();
210 onRescan(NULL, 0, NULL);
214 init_apple_message_system();
217 getApp()->addTimeout(this, ID_MAC_TIMER,
218 50 * timeout_scalar /*50ms*/);
222 MainWindow::onConnect(FXObject *sender, FXSelector sel, void *ptr)
224 if (connected_device != NULL)
227 FXint cur_item = device_list->getCurrentItem();
230 FXListItem *item = device_list->getItem(cur_item);
233 struct hid_device_info *device_info = (struct hid_device_info*) item->getData();
237 connected_device = hid_open_path(device_info->path);
239 if (!connected_device) {
240 FXMessageBox::error(this, MBOX_OK, "Device Error", "Unable To Connect to Device");
244 hid_set_nonblocking(connected_device, 1);
246 getApp()->addTimeout(this, ID_TIMER,
247 5 * timeout_scalar /*5ms*/);
250 s.format("Connected to: %04hx:%04hx -", device_info->vendor_id, device_info->product_id);
251 s += FXString(" ") + device_info->manufacturer_string;
252 s += FXString(" ") + device_info->product_string;
253 connected_label->setText(s);
254 output_button->enable();
255 feature_button->enable();
256 get_feature_button->enable();
257 connect_button->disable();
258 disconnect_button->enable();
259 input_text->setText("");
266 MainWindow::onDisconnect(FXObject *sender, FXSelector sel, void *ptr)
268 hid_close(connected_device);
269 connected_device = NULL;
270 connected_label->setText("Disconnected");
271 output_button->disable();
272 feature_button->disable();
273 get_feature_button->disable();
274 connect_button->enable();
275 disconnect_button->disable();
277 getApp()->removeTimeout(this, ID_TIMER);
283 MainWindow::onRescan(FXObject *sender, FXSelector sel, void *ptr)
285 struct hid_device_info *cur_dev;
287 device_list->clearItems();
290 hid_free_enumeration(devices);
291 devices = hid_enumerate(0x0, 0x0);
294 // Add it to the List Box.
297 s.format("%04hx:%04hx -", cur_dev->vendor_id, cur_dev->product_id);
298 s += FXString(" ") + cur_dev->manufacturer_string;
299 s += FXString(" ") + cur_dev->product_string;
300 usage_str.format(" (usage: %04hx:%04hx) ", cur_dev->usage_page, cur_dev->usage);
302 FXListItem *li = new FXListItem(s, NULL, cur_dev);
303 device_list->appendItem(li);
305 cur_dev = cur_dev->next;
308 if (device_list->getNumItems() == 0)
309 device_list->appendItem("*** No Devices Connected ***");
311 device_list->selectItem(0);
318 MainWindow::getDataFromTextField(FXTextField *tf, char *buf, size_t len)
320 const char *delim = " ,{}\t\r\n";
321 FXString data = tf->getText();
322 const FXchar *d = data.text();
325 // Copy the string from the GUI.
326 size_t sz = strlen(d);
327 char *str = (char*) malloc(sz+1);
330 // For each token in the string, parse and store in buf[].
331 char *token = strtok(str, delim);
334 long int val = strtol(token, &endptr, 0);
336 token = strtok(NULL, delim);
343 /* getLengthFromTextField()
347 -1: invalid length */
349 MainWindow::getLengthFromTextField(FXTextField *tf)
352 FXString str = tf->getText();
353 size_t sz = str.length();
357 len = strtol(str.text(), &endptr, 0);
358 if (endptr != str.text() && *endptr == '\0') {
360 FXMessageBox::error(this, MBOX_OK, "Invalid length", "Enter a length greater than zero.");
373 MainWindow::onSendOutputReport(FXObject *sender, FXSelector sel, void *ptr)
376 size_t data_len, len;
379 memset(buf, 0x0, sizeof(buf));
380 textfield_len = getLengthFromTextField(output_len);
381 data_len = getDataFromTextField(output_text, buf, sizeof(buf));
383 if (textfield_len < 0) {
384 FXMessageBox::error(this, MBOX_OK, "Invalid length", "Length field is invalid. Please enter a number in hex, octal, or decimal.");
388 if (textfield_len > sizeof(buf)) {
389 FXMessageBox::error(this, MBOX_OK, "Invalid length", "Length field is too long.");
393 len = (textfield_len)? textfield_len: data_len;
395 int res = hid_write(connected_device, (const unsigned char*)buf, len);
397 FXMessageBox::error(this, MBOX_OK, "Error Writing", "Could not write to device. Error reported was: %ls", hid_error(connected_device));
404 MainWindow::onSendFeatureReport(FXObject *sender, FXSelector sel, void *ptr)
407 size_t data_len, len;
410 memset(buf, 0x0, sizeof(buf));
411 textfield_len = getLengthFromTextField(feature_len);
412 data_len = getDataFromTextField(feature_text, buf, sizeof(buf));
414 if (textfield_len < 0) {
415 FXMessageBox::error(this, MBOX_OK, "Invalid length", "Length field is invalid. Please enter a number in hex, octal, or decimal.");
419 if (textfield_len > sizeof(buf)) {
420 FXMessageBox::error(this, MBOX_OK, "Invalid length", "Length field is too long.");
424 len = (textfield_len)? textfield_len: data_len;
426 int res = hid_send_feature_report(connected_device, (const unsigned char*)buf, len);
428 FXMessageBox::error(this, MBOX_OK, "Error Writing", "Could not send feature report to device. Error reported was: %ls", hid_error(connected_device));
435 MainWindow::onGetFeatureReport(FXObject *sender, FXSelector sel, void *ptr)
440 memset(buf, 0x0, sizeof(buf));
441 len = getDataFromTextField(get_feature_text, buf, sizeof(buf));
444 FXMessageBox::error(this, MBOX_OK, "Too many numbers", "Enter only a single report number in the text field");
447 int res = hid_get_feature_report(connected_device, (unsigned char*)buf, sizeof(buf));
449 FXMessageBox::error(this, MBOX_OK, "Error Getting Report", "Could not get feature report from device. Error reported was: %ls", hid_error(connected_device));
454 s.format("Returned Feature Report. %d bytes:\n", res);
455 for (int i = 0; i < res; i++) {
457 t.format("%02hhx ", buf[i]);
465 input_text->appendText(s);
466 input_text->setBottomLine(INT_MAX);
473 MainWindow::onClear(FXObject *sender, FXSelector sel, void *ptr)
475 input_text->setText("");
480 MainWindow::onTimeout(FXObject *sender, FXSelector sel, void *ptr)
482 unsigned char buf[256];
483 int res = hid_read(connected_device, buf, sizeof(buf));
487 s.format("Received %d bytes:\n", res);
488 for (int i = 0; i < res; i++) {
490 t.format("%02hhx ", buf[i]);
498 input_text->appendText(s);
499 input_text->setBottomLine(INT_MAX);
502 input_text->appendText("hid_read() returned error\n");
503 input_text->setBottomLine(INT_MAX);
506 getApp()->addTimeout(this, ID_TIMER,
507 5 * timeout_scalar /*5ms*/);
512 MainWindow::onMacTimeout(FXObject *sender, FXSelector sel, void *ptr)
515 check_apple_events();
517 getApp()->addTimeout(this, ID_MAC_TIMER,
518 50 * timeout_scalar /*50ms*/);
524 int main(int argc, char **argv)
526 FXApp app("HIDAPI Test Application", "Signal 11 Software");
527 app.init(argc, argv);
528 g_main_window = new MainWindow(&app);