test.cpp
author sl
Wed, 21 May 2014 22:43:19 +0200
changeset 10 4c3d32f38c09
parent 9 e6c42e1e2a96
child 11 11a0e8a2346e
permissions -rw-r--r--
Working on our architecture. Adding a bunch of HID and Futaba classes.
     1 /*******************************************************
     2  Demo Program for HIDAPI
     3 
     4  Alan Ott
     5  Signal 11 Software
     6 
     7  2010-07-20
     8 
     9  Copyright 2010, All Rights Reserved
    10 
    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
    14  which use HIDAPI.
    15 ********************************************************/
    16 
    17 #include "MainWindow.h"
    18 
    19 
    20 // FOX 1.7 changes the timeouts to all be nanoseconds.
    21 // Fox 1.6 had all timeouts as milliseconds.
    22 #if (FOX_MINOR >= 7)
    23 	const int timeout_scalar = 1000*1000;
    24 #else
    25 	const int timeout_scalar = 1;
    26 #endif
    27 
    28 
    29 FXDEFMAP(MainWindow) MainWindowMap [] = {
    30 	FXMAPFUNC(SEL_COMMAND, MainWindow::ID_CONNECT, MainWindow::onConnect ),
    31 	FXMAPFUNC(SEL_COMMAND, MainWindow::ID_DISCONNECT, MainWindow::onDisconnect ),
    32 	FXMAPFUNC(SEL_COMMAND, MainWindow::ID_RESCAN, MainWindow::onRescan ),
    33 	FXMAPFUNC(SEL_COMMAND, MainWindow::ID_SEND_OUTPUT_REPORT, MainWindow::onSendOutputReport ),
    34 	FXMAPFUNC(SEL_COMMAND, MainWindow::ID_SEND_FEATURE_REPORT, MainWindow::onSendFeatureReport ),
    35 	FXMAPFUNC(SEL_COMMAND, MainWindow::ID_GET_FEATURE_REPORT, MainWindow::onGetFeatureReport ),
    36 	FXMAPFUNC(SEL_COMMAND, MainWindow::ID_CLEAR, MainWindow::onClear ),
    37 	FXMAPFUNC(SEL_COMMAND, MainWindow::ID_FUTABA_CLEAR_DISPLAY, MainWindow::onFutabaClearDisplay ),
    38 	FXMAPFUNC(SEL_COMMAND, MainWindow::ID_FUTABA_DIMMING, MainWindow::onFutabaDimming ),
    39 	FXMAPFUNC(SEL_COMMAND, MainWindow::ID_FUTABA_DISPLAY_DATA_INPUT, MainWindow::onFutabaDisplayDataInput ),
    40 	FXMAPFUNC(SEL_COMMAND, MainWindow::ID_FUTABA_READ_ID, MainWindow::onFutabaReadId ),
    41 	FXMAPFUNC(SEL_COMMAND, MainWindow::ID_FUTABA_READ_FIRMWARE_REVISION, MainWindow::onFutabaReadFirmwareRevision ),
    42 	FXMAPFUNC(SEL_COMMAND, MainWindow::ID_FUTABA_POWER_SUPPLY_MONITOR, MainWindow::onFutabaPowerSupplyMonitor ),
    43     FXMAPFUNC(SEL_COMMAND, MainWindow::ID_FUTABA_SET_PIXEL, MainWindow::onFutabaSetPixel ),
    44 	FXMAPFUNC(SEL_COMMAND, MainWindow::ID_FUTABA_RESET_PIXEL, MainWindow::onFutabaResetPixel ),
    45     FXMAPFUNC(SEL_COMMAND, MainWindow::ID_FUTABA_SET_ALL_PIXELS, MainWindow::onFutabaSetAllPixels ),
    46     FXMAPFUNC(SEL_COMMAND, MainWindow::ID_SELECT_FONT, MainWindow::onSelectFont ),
    47 	FXMAPFUNC(SEL_TIMEOUT, MainWindow::ID_TIMER, MainWindow::onTimeout ),
    48 	FXMAPFUNC(SEL_TIMEOUT, MainWindow::ID_MAC_TIMER, MainWindow::onMacTimeout ),
    49 };
    50 
    51 FXIMPLEMENT(MainWindow, FXMainWindow, MainWindowMap, ARRAYNUMBER(MainWindowMap));
    52 
    53 MainWindow::MainWindow(FXApp *app)
    54 	: FXMainWindow(app, "HIDAPI Test Application", NULL, NULL, DECOR_ALL, 200,100, 600,900),
    55     iCurrentFont(NULL),
    56     iFontImage(NULL)
    57 {
    58 	iDimming=0x35;
    59 	devices = NULL;
    60 	connected_device = NULL;
    61 
    62 	FXVerticalFrame *vf = new FXVerticalFrame(this, LAYOUT_FILL_Y|LAYOUT_FILL_X);
    63 
    64 	FXLabel *label = new FXLabel(vf, "HIDAPI Test Tool");
    65 	title_font = new FXFont(getApp(), "Arial", 14, FXFont::Bold);
    66 	label->setFont(title_font);
    67 
    68 	new FXLabel(vf,
    69 		"Select a device and press Connect.", NULL, JUSTIFY_LEFT);
    70 	new FXLabel(vf,
    71 		"Output data bytes can be entered in the Output section, \n"
    72 		"separated by space, comma or brackets. Data starting with 0x\n"
    73 		"is treated as hex. Data beginning with a 0 is treated as \n"
    74 		"octal. All other data is treated as decimal.", NULL, JUSTIFY_LEFT);
    75 	new FXLabel(vf,
    76 		"Data received from the device appears in the Input section.",
    77 		NULL, JUSTIFY_LEFT);
    78 	new FXLabel(vf,
    79 		"Optionally, a report length may be specified. Extra bytes are\n"
    80 		"padded with zeros. If no length is specified, the length is \n"
    81 		"inferred from the data.",
    82 		NULL, JUSTIFY_LEFT);
    83 	new FXLabel(vf, "");
    84 
    85 	// Device List and Connect/Disconnect buttons
    86 	FXHorizontalFrame *hf = new FXHorizontalFrame(vf, LAYOUT_FILL_X);
    87 	//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);
    88 	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);
    89 	FXVerticalFrame *buttonVF = new FXVerticalFrame(hf);
    90 	connect_button = new FXButton(buttonVF, "Connect", NULL, this, ID_CONNECT, BUTTON_NORMAL|LAYOUT_FILL_X);
    91 	disconnect_button = new FXButton(buttonVF, "Disconnect", NULL, this, ID_DISCONNECT, BUTTON_NORMAL|LAYOUT_FILL_X);
    92 	disconnect_button->disable();
    93 	rescan_button = new FXButton(buttonVF, "Re-Scan devices", NULL, this, ID_RESCAN, BUTTON_NORMAL|LAYOUT_FILL_X);
    94 	new FXHorizontalFrame(buttonVF, 0, 0,0,0,0, 0,0,50,0);
    95 
    96 	connected_label = new FXLabel(vf, "Disconnected");
    97 
    98     //Font group
    99     new FXHorizontalFrame(vf);
   100     FXGroupBox *gb = new FXGroupBox(vf, "Fonts", FRAME_GROOVE|LAYOUT_FILL_X);
   101     FXMatrix *matrix = new FXMatrix(gb, 3, MATRIX_BY_COLUMNS|LAYOUT_FILL_X);
   102     iButtonSelectFont = new FXButton(matrix, "Select Font", NULL, this, ID_SELECT_FONT, BUTTON_NORMAL|LAYOUT_FILL_X);
   103 
   104 	//Futaba VFD commands
   105 	new FXHorizontalFrame(vf);
   106 	gb = new FXGroupBox(vf, "Futaba GP1212A01A", FRAME_GROOVE|LAYOUT_FILL_X);
   107 	matrix = new FXMatrix(gb, 3, MATRIX_BY_COLUMNS|LAYOUT_FILL_X);
   108 	iButtonClearDisplay = new FXButton(matrix, "Clear Display", NULL, this, ID_FUTABA_CLEAR_DISPLAY, BUTTON_NORMAL|LAYOUT_FILL_X);
   109 	iButtonDimming = new FXButton(matrix, "Dimming", NULL, this, ID_FUTABA_DIMMING, BUTTON_NORMAL|LAYOUT_FILL_X);
   110 	iButtonDisplayDataInput = new FXButton(matrix, "Display Data Input", NULL, this, ID_FUTABA_DISPLAY_DATA_INPUT, BUTTON_NORMAL|LAYOUT_FILL_X);
   111 	iButtonReadId = new FXButton(matrix, "Read Id", NULL, this, ID_FUTABA_READ_ID, BUTTON_NORMAL|LAYOUT_FILL_X);
   112 	iButtonReadFirmwareRevision =  new FXButton(matrix, "Read Firmware Revision", NULL, this, ID_FUTABA_READ_FIRMWARE_REVISION, BUTTON_NORMAL|LAYOUT_FILL_X);
   113 	iButtonPowerSupplyMonitor = new FXButton(matrix, "Power Supply Monitor", NULL, this, ID_FUTABA_POWER_SUPPLY_MONITOR, BUTTON_NORMAL|LAYOUT_FILL_X);
   114     new FXLabel(matrix, "X",NULL,LABEL_NORMAL|LAYOUT_FILL_X);
   115     new FXLabel(matrix, "Y",NULL,LABEL_NORMAL|LAYOUT_FILL_X);
   116     new FXLabel(matrix, "",NULL,LABEL_NORMAL|LAYOUT_FILL_X);
   117     iTextFieldX = new FXTextField(matrix, 3, NULL, 0, TEXTFIELD_NORMAL|TEXTFIELD_INTEGER|LAYOUT_FILL_X);
   118     iTextFieldY = new FXTextField(matrix, 3, NULL, 0, TEXTFIELD_NORMAL|TEXTFIELD_INTEGER|LAYOUT_FILL_X);
   119     iButtonSetPixel = new FXButton(matrix, "Set Pixel", NULL, this, ID_FUTABA_SET_PIXEL, BUTTON_NORMAL|LAYOUT_FILL_X);
   120 	iButtonResetPixel = new FXButton(matrix, "Reset Pixel", NULL, this, ID_FUTABA_RESET_PIXEL, BUTTON_NORMAL|LAYOUT_FILL_X);
   121     //
   122     iButtonSetAllPixels = new FXButton(matrix, "Set All Pixels", NULL, this, ID_FUTABA_SET_ALL_PIXELS, BUTTON_NORMAL|LAYOUT_FILL_X);
   123     //
   124 
   125 	//
   126 	iButtonClearDisplay->disable();
   127 	iButtonDimming->disable();
   128 	iButtonDisplayDataInput->disable();
   129 	iButtonReadId->disable();
   130 	iButtonReadFirmwareRevision->disable();
   131 	iButtonPowerSupplyMonitor->disable();
   132     iTextFieldX->disable();
   133     iTextFieldY->disable();
   134     iButtonSetPixel->disable();
   135 	iButtonResetPixel->disable();
   136     iButtonSetAllPixels->disable();
   137 	//
   138 
   139 	// Output Group Box
   140 	new FXHorizontalFrame(vf);
   141 	gb = new FXGroupBox(vf, "Output", FRAME_GROOVE|LAYOUT_FILL_X);
   142 	matrix = new FXMatrix(gb, 3, MATRIX_BY_COLUMNS|LAYOUT_FILL_X);
   143 	new FXLabel(matrix, "Data");
   144 	new FXLabel(matrix, "Length");
   145 	new FXLabel(matrix, "");
   146 
   147 	//hf = new FXHorizontalFrame(gb, LAYOUT_FILL_X);
   148 	output_text = new FXTextField(matrix, 30, NULL, 0, TEXTFIELD_NORMAL|LAYOUT_FILL_X|LAYOUT_FILL_COLUMN);
   149 	output_text->setText("1 0x81 0");
   150 	output_len = new FXTextField(matrix, 5, NULL, 0, TEXTFIELD_NORMAL|LAYOUT_FILL_X|LAYOUT_FILL_COLUMN);
   151 	output_button = new FXButton(matrix, "Send Output Report", NULL, this, ID_SEND_OUTPUT_REPORT, BUTTON_NORMAL|LAYOUT_FILL_X);
   152 	output_button->disable();
   153 	//new FXHorizontalFrame(matrix, LAYOUT_FILL_X);
   154 
   155 	//hf = new FXHorizontalFrame(gb, LAYOUT_FILL_X);
   156 	feature_text = new FXTextField(matrix, 30, NULL, 0, TEXTFIELD_NORMAL|LAYOUT_FILL_X|LAYOUT_FILL_COLUMN);
   157 	feature_len = new FXTextField(matrix, 5, NULL, 0, TEXTFIELD_NORMAL|LAYOUT_FILL_X|LAYOUT_FILL_COLUMN);
   158 	feature_button = new FXButton(matrix, "Send Feature Report", NULL, this, ID_SEND_FEATURE_REPORT, BUTTON_NORMAL|LAYOUT_FILL_X);
   159 	feature_button->disable();
   160 
   161 	get_feature_text = new FXTextField(matrix, 30, NULL, 0, TEXTFIELD_NORMAL|LAYOUT_FILL_X|LAYOUT_FILL_COLUMN);
   162 	new FXWindow(matrix);
   163 	get_feature_button = new FXButton(matrix, "Get Feature Report", NULL, this, ID_GET_FEATURE_REPORT, BUTTON_NORMAL|LAYOUT_FILL_X);
   164 	get_feature_button->disable();
   165 
   166 
   167 	// Input Group Box
   168 	gb = new FXGroupBox(vf, "Input", FRAME_GROOVE|LAYOUT_FILL_X|LAYOUT_FILL_Y);
   169 	FXVerticalFrame *innerVF = new FXVerticalFrame(gb, LAYOUT_FILL_X|LAYOUT_FILL_Y);
   170 	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);
   171 	input_text->setEditable(false);
   172 	new FXButton(innerVF, "Clear", NULL, this, ID_CLEAR, BUTTON_NORMAL|LAYOUT_RIGHT);
   173 
   174 
   175 }
   176 
   177 MainWindow::~MainWindow()
   178 {
   179     delete iCurrentFont;
   180     iCurrentFont = NULL;
   181 
   182     delete iFontImage;
   183     iFontImage = NULL;
   184 
   185 	if (connected_device)
   186 		hid_close(connected_device);
   187 	hid_exit();
   188 	delete title_font;
   189 }
   190 
   191 void
   192 MainWindow::create()
   193 {
   194 	FXMainWindow::create();
   195 	show();
   196 
   197 	onRescan(NULL, 0, NULL);
   198 
   199 
   200 #ifdef __APPLE__
   201 	init_apple_message_system();
   202 #endif
   203 
   204 	getApp()->addTimeout(this, ID_MAC_TIMER,
   205 		50 * timeout_scalar /*50ms*/);
   206 }
   207 
   208 long
   209 MainWindow::onConnect(FXObject *sender, FXSelector sel, void *ptr)
   210 {
   211 	if (connected_device != NULL)
   212 		return 1;
   213 
   214 	FXint cur_item = device_list->getCurrentItem();
   215 	if (cur_item < 0)
   216 		return -1;
   217 	FXListItem *item = device_list->getItem(cur_item);
   218 	if (!item)
   219 		return -1;
   220 	struct hid_device_info *device_info = (struct hid_device_info*) item->getData();
   221 	if (!device_info)
   222 		return -1;
   223 
   224 	connected_device =  hid_open_path(device_info->path);
   225 
   226 	if (!connected_device) {
   227 		FXMessageBox::error(this, MBOX_OK, "Device Error", "Unable To Connect to Device");
   228 		return -1;
   229 	}
   230 
   231 	hid_set_nonblocking(connected_device, 1);
   232 
   233 	getApp()->addTimeout(this, ID_TIMER,
   234 		5 * timeout_scalar /*5ms*/);
   235 
   236 	FXString s;
   237 	s.format("Connected to: %04hx:%04hx -", device_info->vendor_id, device_info->product_id);
   238 	s += FXString(" ") + device_info->manufacturer_string;
   239 	s += FXString(" ") + device_info->product_string;
   240 	connected_label->setText(s);
   241 	output_button->enable();
   242 	feature_button->enable();
   243 	get_feature_button->enable();
   244 	connect_button->disable();
   245 	disconnect_button->enable();
   246 	input_text->setText("");
   247 	//
   248 	iButtonClearDisplay->enable();
   249 	iButtonDimming->enable();
   250 	iButtonDisplayDataInput->enable();
   251 	iButtonReadId->enable();
   252 	iButtonReadFirmwareRevision->enable();
   253 	iButtonPowerSupplyMonitor->enable();
   254     iTextFieldX->enable();
   255     iTextFieldY->enable();
   256     iButtonSetPixel->enable();
   257 	iButtonResetPixel->enable();
   258     iButtonSetAllPixels->enable();
   259 
   260 	//
   261 	iOutputReportBuffer=new unsigned char[KFutabaMaxHidReportSize]; //TODO: use connected_device->output_report_length
   262 
   263 	return 1;
   264 }
   265 
   266 long
   267 MainWindow::onDisconnect(FXObject *sender, FXSelector sel, void *ptr)
   268 {
   269 	hid_close(connected_device);
   270 	connected_device = NULL;
   271 	connected_label->setText("Disconnected");
   272 	output_button->disable();
   273 	feature_button->disable();
   274 	get_feature_button->disable();
   275 	connect_button->enable();
   276 	disconnect_button->disable();
   277 
   278 	getApp()->removeTimeout(this, ID_TIMER);
   279 
   280 	//
   281 	iButtonClearDisplay->disable();
   282 	iButtonDimming->disable();
   283 	iButtonDisplayDataInput->disable();
   284 	iButtonReadId->disable();
   285 	iButtonReadFirmwareRevision->disable();
   286 	iButtonPowerSupplyMonitor->disable();
   287     iTextFieldX->disable();
   288     iTextFieldY->disable();
   289     iButtonSetPixel->disable();
   290 	iButtonResetPixel->disable();
   291     iButtonSetAllPixels->disable();
   292 	//
   293 
   294 
   295 	delete iOutputReportBuffer;
   296 	iOutputReportBuffer=NULL;
   297 
   298 	return 1;
   299 }
   300 
   301 long
   302 MainWindow::onRescan(FXObject *sender, FXSelector sel, void *ptr)
   303 {
   304 	struct hid_device_info *cur_dev;
   305 
   306 	device_list->clearItems();
   307 
   308 	// List the Devices
   309 	hid_free_enumeration(devices);
   310 	devices = hid_enumerate(0x0, 0x0);
   311 	cur_dev = devices;
   312 	while (cur_dev) {
   313 		// Add it to the List Box only if it is a Futaba device
   314 		if (cur_dev->vendor_id == KFutabaVendorId)
   315 			{
   316 			FXString s;
   317 			FXString usage_str;
   318 			s.format("%04hx:%04hx -", cur_dev->vendor_id, cur_dev->product_id);
   319 			s += FXString(" ") + cur_dev->manufacturer_string;
   320 			s += FXString(" ") + cur_dev->product_string;
   321 			usage_str.format(" (usage: %04hx:%04hx) ", cur_dev->usage_page, cur_dev->usage);
   322 			s += usage_str;
   323 			FXListItem *li = new FXListItem(s, NULL, cur_dev);
   324 			device_list->appendItem(li);
   325 			}
   326 
   327 		cur_dev = cur_dev->next;
   328 	}
   329 
   330 	if (device_list->getNumItems() == 0)
   331 		device_list->appendItem("*** No Devices Connected ***");
   332 	else {
   333 		device_list->selectItem(0);
   334 	}
   335 
   336 	return 1;
   337 }
   338 
   339 size_t
   340 MainWindow::getDataFromTextField(FXTextField *tf, char *buf, size_t len)
   341 {
   342 	const char *delim = " ,{}\t\r\n";
   343 	FXString data = tf->getText();
   344 	const FXchar *d = data.text();
   345 	size_t i = 0;
   346 
   347 	// Copy the string from the GUI.
   348 	size_t sz = strlen(d);
   349 	char *str = (char*) malloc(sz+1);
   350 	strcpy(str, d);
   351 
   352 	// For each token in the string, parse and store in buf[].
   353 	char *token = strtok(str, delim);
   354 	while (token) {
   355 		char *endptr;
   356 		long int val = strtol(token, &endptr, 0);
   357 		buf[i++] = val;
   358 		token = strtok(NULL, delim);
   359 	}
   360 
   361 	free(str);
   362 	return i;
   363 }
   364 
   365 /* getLengthFromTextField()
   366    Returns length:
   367 	 0: empty text field
   368 	>0: valid length
   369 	-1: invalid length */
   370 int
   371 MainWindow::getLengthFromTextField(FXTextField *tf)
   372 {
   373 	long int len;
   374 	FXString str = tf->getText();
   375 	size_t sz = str.length();
   376 
   377 	if (sz > 0) {
   378 		char *endptr;
   379 		len = strtol(str.text(), &endptr, 0);
   380 		if (endptr != str.text() && *endptr == '\0') {
   381 			if (len <= 0) {
   382 				FXMessageBox::error(this, MBOX_OK, "Invalid length", "Enter a length greater than zero.");
   383 				return -1;
   384 			}
   385 			return len;
   386 		}
   387 		else
   388 			return -1;
   389 	}
   390 
   391 	return 0;
   392 }
   393 
   394 long
   395 MainWindow::onSendOutputReport(FXObject *sender, FXSelector sel, void *ptr)
   396 {
   397 	char buf[256];
   398 	size_t data_len, len;
   399 	int textfield_len;
   400 
   401 	memset(buf, 0x0, sizeof(buf));
   402 	textfield_len = getLengthFromTextField(output_len);
   403 	data_len = getDataFromTextField(output_text, buf, sizeof(buf));
   404 
   405 	if (textfield_len < 0) {
   406 		FXMessageBox::error(this, MBOX_OK, "Invalid length", "Length field is invalid. Please enter a number in hex, octal, or decimal.");
   407 		return 1;
   408 	}
   409 
   410 	if (textfield_len > sizeof(buf)) {
   411 		FXMessageBox::error(this, MBOX_OK, "Invalid length", "Length field is too long.");
   412 		return 1;
   413 	}
   414 
   415 	len = (textfield_len)? textfield_len: data_len;
   416 
   417 	int res = hid_write(connected_device, (const unsigned char*)buf, len);
   418 	if (res < 0) {
   419 		FXMessageBox::error(this, MBOX_OK, "Error Writing", "Could not write to device. Error reported was: %ls", hid_error(connected_device));
   420 	}
   421 
   422 	return 1;
   423 }
   424 
   425 long
   426 MainWindow::onSendFeatureReport(FXObject *sender, FXSelector sel, void *ptr)
   427 {
   428 	char buf[256];
   429 	size_t data_len, len;
   430 	int textfield_len;
   431 
   432 	memset(buf, 0x0, sizeof(buf));
   433 	textfield_len = getLengthFromTextField(feature_len);
   434 	data_len = getDataFromTextField(feature_text, buf, sizeof(buf));
   435 
   436 	if (textfield_len < 0) {
   437 		FXMessageBox::error(this, MBOX_OK, "Invalid length", "Length field is invalid. Please enter a number in hex, octal, or decimal.");
   438 		return 1;
   439 	}
   440 
   441 	if (textfield_len > sizeof(buf)) {
   442 		FXMessageBox::error(this, MBOX_OK, "Invalid length", "Length field is too long.");
   443 		return 1;
   444 	}
   445 
   446 	len = (textfield_len)? textfield_len: data_len;
   447 
   448 	int res = hid_send_feature_report(connected_device, (const unsigned char*)buf, len);
   449 	if (res < 0) {
   450 		FXMessageBox::error(this, MBOX_OK, "Error Writing", "Could not send feature report to device. Error reported was: %ls", hid_error(connected_device));
   451 	}
   452 
   453 	return 1;
   454 }
   455 
   456 long
   457 MainWindow::onGetFeatureReport(FXObject *sender, FXSelector sel, void *ptr)
   458 {
   459 	char buf[256];
   460 	size_t len;
   461 
   462 	memset(buf, 0x0, sizeof(buf));
   463 	len = getDataFromTextField(get_feature_text, buf, sizeof(buf));
   464 
   465 	if (len != 1) {
   466 		FXMessageBox::error(this, MBOX_OK, "Too many numbers", "Enter only a single report number in the text field");
   467 	}
   468 
   469 	int res = hid_get_feature_report(connected_device, (unsigned char*)buf, sizeof(buf));
   470 	if (res < 0) {
   471 		FXMessageBox::error(this, MBOX_OK, "Error Getting Report", "Could not get feature report from device. Error reported was: %ls", hid_error(connected_device));
   472 	}
   473 
   474 	if (res > 0) {
   475 		FXString s;
   476 		s.format("Returned Feature Report. %d bytes:\n", res);
   477 		for (int i = 0; i < res; i++) {
   478 			FXString t;
   479 			t.format("%02hhx ", buf[i]);
   480 			s += t;
   481 			if ((i+1) % 4 == 0)
   482 				s += " ";
   483 			if ((i+1) % 16 == 0)
   484 				s += "\n";
   485 		}
   486 		s += "\n";
   487 		input_text->appendText(s);
   488 		input_text->setBottomLine(INT_MAX);
   489 	}
   490 
   491 	return 1;
   492 }
   493 
   494 long
   495 MainWindow::onClear(FXObject *sender, FXSelector sel, void *ptr)
   496 {
   497 	input_text->setText("");
   498 	return 1;
   499 }
   500 
   501 
   502 long
   503 MainWindow::onFutabaClearDisplay(FXObject *sender, FXSelector sel, void *ptr)
   504 {
   505 	memset(iOutputReportBuffer, 0x0, KFutabaMaxHidReportSize);
   506 	iOutputReportBuffer[0]=0x00; //Report ID
   507 	iOutputReportBuffer[1]=0x04; //Report length
   508 	iOutputReportBuffer[2]=0x1B; //
   509 	iOutputReportBuffer[3]=0x5B; //
   510 	iOutputReportBuffer[4]=0x32; //
   511 	iOutputReportBuffer[5]=0x4A; //
   512 	int res = hid_write(connected_device, iOutputReportBuffer, KFutabaMaxHidReportSize);
   513 
   514 	return 1;
   515 }
   516 
   517 long
   518 MainWindow::onFutabaDimming(FXObject *sender, FXSelector sel, void *ptr)
   519 {
   520 	memset(iOutputReportBuffer, 0x0, KFutabaMaxHidReportSize);
   521 	iOutputReportBuffer[0]=0x00; //Report ID
   522 	iOutputReportBuffer[1]=0x06; //Report length
   523 	iOutputReportBuffer[2]=0x1B; //
   524 	iOutputReportBuffer[3]=0x5C; //
   525 	iOutputReportBuffer[4]=0x3F; //
   526 	iOutputReportBuffer[5]=0x4C; //
   527 	iOutputReportBuffer[6]=0x44; //
   528 	iDimming = (iDimming==0x35?0x30:++iDimming);
   529 	iOutputReportBuffer[7]=iDimming;
   530 	int res = hid_write(connected_device, iOutputReportBuffer, KFutabaMaxHidReportSize);
   531 
   532 	return 1;
   533 }
   534 
   535 long
   536 MainWindow::onFutabaDisplayDataInput(FXObject *sender, FXSelector sel, void *ptr)
   537 {
   538 	//@1B 5B F0 00 00 07 00 01 FF
   539 
   540 	memset(iOutputReportBuffer, 0x0, KFutabaMaxHidReportSize);
   541 	iOutputReportBuffer[0]=0x00; //Report ID
   542 	iOutputReportBuffer[1]=0x09; //Report length
   543 	iOutputReportBuffer[2]=0x1B; //
   544 	iOutputReportBuffer[3]=0x5B; //
   545 	iOutputReportBuffer[4]=0xF0; //
   546 	iOutputReportBuffer[5]=0x00; //X
   547 	iOutputReportBuffer[6]=0x00; //Y
   548 	iOutputReportBuffer[7]=0x07; //
   549 	iOutputReportBuffer[8]=0x00; //
   550 	iOutputReportBuffer[9]=0x01; //
   551 	iOutputReportBuffer[10]=0xFF; //
   552 	int res = hid_write(connected_device, iOutputReportBuffer, KFutabaMaxHidReportSize);
   553 
   554 
   555 	return 1;
   556 }
   557 
   558 
   559 
   560 
   561 /**
   562 Set a single pixel to the specified value.
   563 @param X coordinate of our pixel.
   564 @param Y coordinate of our pixel.
   565 @param The LSB defines our pixel value.
   566 */
   567 void MainWindow::SetPixel(int aX, int aY, unsigned char aValue)
   568 	{
   569 	//Just specify a one pixel block
   570 	SetPixelBlock(aX,aY,0x00,0x01,aValue);
   571 	}
   572 
   573 /**
   574 Set the defined pixel block to the given value.
   575 @param X coordinate of our pixel block starting point.
   576 @param Y coordinate of our pixel block starting point.
   577 @param The height of our pixel block.
   578 @param The size of our pixel data. Number of pixels divided by 8.
   579 @param The value set to 8 pixels.
   580 */
   581 void MainWindow::SetPixelBlock(int aX, int aY, int aHeight, int aSize, unsigned char aValue)
   582 	{
   583 	//Size must be 63 or below
   584 	memset(iOutputReportBuffer, 0x0, KFutabaMaxHidReportSize);
   585 	iOutputReportBuffer[0]=0x00; //Report ID
   586 	iOutputReportBuffer[1]=0x08+aSize; //Report length
   587 	iOutputReportBuffer[2]=0x1B; //
   588 	iOutputReportBuffer[3]=0x5B; //
   589 	iOutputReportBuffer[4]=0xF0; //
   590 	iOutputReportBuffer[5]=aX; //X
   591 	iOutputReportBuffer[6]=aY; //Y
   592 	iOutputReportBuffer[7]=aHeight; //Y length before return. Though outside the specs, setting this to zero apparently allows us to modify a single pixel without touching any other.
   593 	iOutputReportBuffer[8]=0x00; //Size of pixel data in bytes (MSB)
   594 	iOutputReportBuffer[9]=aSize; //Size of pixel data in bytes (LSB)
   595 	memset(iOutputReportBuffer+10, aValue, KFutabaMaxHidReportSize);
   596 	//iOutputReportBuffer[10]=aValue; //Pixel data
   597 	int res = hid_write(connected_device, iOutputReportBuffer, KFutabaMaxHidReportSize);
   598 	}
   599 
   600 /**
   601 Send an output report to a Futaba VFD device.
   602 */
   603 /*
   604 void MainWindow::SendFutabaOutputReport(unsigned char* aReportData, unsigned char aSize)
   605     {
   606     //
   607     memset(iOutputReportBuffer, 0x0, KFutabaMaxHidReportSize);
   608     iOutputReportBuffer[0]=0x00; //Report ID is always null
   609     iOutputReportBuffer[1]=0x08+aSize; //Report length
   610     iOutputReportBuffer[2]=0x1B; //
   611     iOutputReportBuffer[3]=0x5B; //
   612     iOutputReportBuffer[4]=0xF0; //
   613     iOutputReportBuffer[5]=aX; //X
   614     iOutputReportBuffer[6]=aY; //Y
   615     iOutputReportBuffer[7]=aHeight; //Y length before return. Though outside the specs, setting this to zero apparently allows us to modify a single pixel without touching any other.
   616     iOutputReportBuffer[8]=0x00; //Size of pixel data in bytes (MSB)
   617     iOutputReportBuffer[9]=aSize; //Size of pixel data in bytes (LSB)
   618     memset(iOutputReportBuffer+10, aValue, KFutabaMaxHidReportSize);
   619     //iOutputReportBuffer[10]=aValue; //Pixel data
   620     int res = hid_write(connected_device, iOutputReportBuffer, KFutabaMaxHidReportSize);
   621     }
   622 */
   623 
   624 
   625 /**
   626 */
   627 long MainWindow::onFutabaSetPixel(FXObject *sender, FXSelector sel, void *ptr)
   628 {
   629 	int x=0;
   630 	int y=0;
   631 	iTextFieldX->getText().scan("%d",&x);
   632 	iTextFieldY->getText().scan("%d",&y);
   633     SetPixel(x,y,0x01);
   634 	return 1;
   635 }
   636 
   637 /**
   638 */
   639 long MainWindow::onFutabaResetPixel(FXObject *sender, FXSelector sel, void *ptr)
   640 {
   641 	int x=0;
   642 	int y=0;
   643 	iTextFieldX->getText().scan("%d",&x);
   644 	iTextFieldY->getText().scan("%d",&y);
   645     SetPixel(x,y,0x00);
   646     return 1;
   647 }
   648 
   649 long MainWindow::onFutabaSetAllPixels(FXObject *sender, FXSelector sel, void *ptr)
   650 	{
   651 	//One pixel at a time
   652 	/*
   653 	for (int i=0;i<256;i++)
   654 		{
   655 		for (int j=0;j<64;j++)
   656 			{
   657 			SetPixel(i,j,0x01);
   658 			}
   659 		}
   660 	*/
   661 	//16x16=256 pixels at a time goes much faster
   662 	for (int i=0;i<256;i+=16)
   663 		{
   664 		for (int j=0;j<64;j+=16)
   665 			{
   666 			SetPixelBlock(i,j,15,32,0xFF);
   667 			//FXThread::sleep(1000000000);
   668 			}
   669 		}
   670 
   671     return 1;
   672 	}
   673 
   674 long
   675 MainWindow::onFutabaReadId(FXObject *sender, FXSelector sel, void *ptr)
   676 {
   677 	//1BH,5BH,63H,49H,44H
   678 	memset(iOutputReportBuffer, 0x0, KFutabaMaxHidReportSize);
   679 	iOutputReportBuffer[0]=0x00; //Report ID
   680 	iOutputReportBuffer[1]=0x05; //Report length
   681 	iOutputReportBuffer[2]=0x1B; //
   682 	iOutputReportBuffer[3]=0x5B; //
   683 	iOutputReportBuffer[4]=0x63; //
   684 	iOutputReportBuffer[5]=0x49; //
   685 	iOutputReportBuffer[6]=0x44; //
   686 	int res = hid_write(connected_device, iOutputReportBuffer, KFutabaMaxHidReportSize);
   687 
   688 	return 1;
   689 }
   690 
   691 long
   692 MainWindow::onFutabaReadFirmwareRevision(FXObject *sender, FXSelector sel, void *ptr)
   693 {
   694 	//1BH,5BH,63H,46H,52H
   695 	memset(iOutputReportBuffer, 0x0, KFutabaMaxHidReportSize);
   696 	iOutputReportBuffer[0]=0x00; //Report ID
   697 	iOutputReportBuffer[1]=0x05; //Report length
   698 	iOutputReportBuffer[2]=0x1B; //
   699 	iOutputReportBuffer[3]=0x5B; //
   700 	iOutputReportBuffer[4]=0x63; //
   701 	iOutputReportBuffer[5]=0x46; //
   702 	iOutputReportBuffer[6]=0x52; //
   703 	int res = hid_write(connected_device, iOutputReportBuffer, KFutabaMaxHidReportSize);
   704 
   705 	return 1;
   706 }
   707 
   708 long
   709 MainWindow::onFutabaPowerSupplyMonitor(FXObject *sender, FXSelector sel, void *ptr)
   710 {
   711 	//1BH,5BH,63H,50H,4DH
   712 	memset(iOutputReportBuffer, 0x0, KFutabaMaxHidReportSize);
   713 	iOutputReportBuffer[0]=0x00; //Report ID
   714 	iOutputReportBuffer[1]=0x05; //Report length
   715 	iOutputReportBuffer[2]=0x1B; //
   716 	iOutputReportBuffer[3]=0x5B; //
   717 	iOutputReportBuffer[4]=0x63; //
   718 	iOutputReportBuffer[5]=0x50; //
   719 	iOutputReportBuffer[6]=0x4D; //
   720 	int res = hid_write(connected_device, iOutputReportBuffer, KFutabaMaxHidReportSize);
   721 
   722 	return 1;
   723 }
   724 
   725 
   726 
   727 long
   728 MainWindow::onTimeout(FXObject *sender, FXSelector sel, void *ptr)
   729 {
   730 	unsigned char buf[256];
   731 	int res = hid_read(connected_device, buf, sizeof(buf));
   732 
   733 	if (res > 0) {
   734 		FXString s;
   735 		s.format("Received %d bytes:\n", res);
   736 		for (int i = 0; i < res; i++) {
   737 			FXString t;
   738 			t.format("%02hhx ", buf[i]);
   739 			s += t;
   740 			if ((i+1) % 4 == 0)
   741 				s += " ";
   742 			if ((i+1) % 16 == 0)
   743 				s += "\n";
   744 		}
   745 		s += "\n";
   746 		input_text->appendText(s);
   747 		input_text->setBottomLine(INT_MAX);
   748 	}
   749 	if (res < 0) {
   750 		input_text->appendText("hid_read() returned error\n");
   751 		input_text->setBottomLine(INT_MAX);
   752 	}
   753 
   754 	getApp()->addTimeout(this, ID_TIMER,
   755 		5 * timeout_scalar /*5ms*/);
   756 	return 1;
   757 }
   758 
   759 long
   760 MainWindow::onMacTimeout(FXObject *sender, FXSelector sel, void *ptr)
   761 {
   762 #ifdef __APPLE__
   763 	check_apple_events();
   764 
   765 	getApp()->addTimeout(this, ID_MAC_TIMER,
   766 		50 * timeout_scalar /*50ms*/);
   767 #endif
   768 
   769 	return 1;
   770 }
   771 
   772 /**
   773 
   774 */
   775 long MainWindow::onSelectFont(FXObject *sender, FXSelector sel, void *ptr)
   776     {
   777     FXFontDialog* dlg=new FXFontDialog(this,"Pick a font");
   778     if (dlg->execute())
   779         {
   780         dlg->getFontSelection(iCurrentFontDesc);
   781         delete iCurrentFont;
   782         iCurrentFont = NULL;
   783         iCurrentFont = new FXFont(getApp(),iCurrentFontDesc);
   784         iCurrentFont->create();
   785         //
   786         delete iFontImage;
   787         iFontImage = NULL;
   788         //
   789         FXString text="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-[]{}();%$£&~#|_";
   790         //Create an image the proper size for our text
   791         iFontImage = new FXTGAImage(getApp(),NULL,IMAGE_SHMI|IMAGE_SHMP,iCurrentFont->getTextWidth(text),iCurrentFont->getFontHeight());
   792         iFontImage->create();
   793         //Perform our drawing
   794             {
   795             FXDCWindow dc(iFontImage);
   796             //dc.begin(iFontImage);
   797             dc.setFont(iCurrentFont);
   798             dc.setForeground(0xFFFFFFFF);
   799             //dc.setBackground(0xFF000000);
   800             //dc.setFillStyle(FILL_SOLID);
   801             dc.fillRectangle(0,0,iFontImage->getWidth(),iFontImage->getHeight());
   802             dc.setForeground(0xFF000000);
   803             dc.drawText(0,iCurrentFont->getFontAscent(),text);
   804             //dc.end();
   805             }
   806         FXFileStream file;
   807         file.open("fonttest.tga",FXStreamSave);
   808         iFontImage->restore();
   809         iFontImage->savePixels(file);
   810         file.close();
   811 
   812         //
   813 
   814         }
   815 
   816     delete dlg;
   817     return 1;
   818     }
   819 
   820 
   821