From b20777fc0c6552bec63ce4197410a55ea563c4ee Mon Sep 17 00:00:00 2001 From: Alan Ott Date: Mon, 26 Nov 2012 22:24:42 -0500 Subject: [PATCH] testgui: more robust handling of report length fields Improve logic of report length field handling for empty fields. Add column headers for data and length fields. Add documentation statement about length fields. Increase window size. Add message boxes when invalid values are entered. memset() buffers to zero. --- testgui/test.cpp | 123 +++++++++++++++++++++++++++++++---------------- 1 file changed, 81 insertions(+), 42 deletions(-) diff --git a/testgui/test.cpp b/testgui/test.cpp index 3e88d4d..538db79 100644 --- a/testgui/test.cpp +++ b/testgui/test.cpp @@ -60,14 +60,13 @@ private: FXTextField *feature_text; FXTextField *feature_len; FXTextField *get_feature_text; - FXTextField *get_feature_len; 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); - size_t getLengthFromTextField(FXTextField *tf, size_t len); + int getLengthFromTextField(FXTextField *tf); protected: @@ -114,7 +113,7 @@ FXDEFMAP(MainWindow) MainWindowMap [] = { FXIMPLEMENT(MainWindow, FXMainWindow, MainWindowMap, ARRAYNUMBER(MainWindowMap)); MainWindow::MainWindow(FXApp *app) - : FXMainWindow(app, "HIDAPI Test Application", NULL, NULL, DECOR_ALL, 200,100, 425,600) + : FXMainWindow(app, "HIDAPI Test Application", NULL, NULL, DECOR_ALL, 200,100, 425,700) { devices = NULL; connected_device = NULL; @@ -135,6 +134,11 @@ MainWindow::MainWindow(FXApp *app) 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 @@ -155,22 +159,26 @@ MainWindow::MainWindow(FXApp *app) // 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, 40, NULL, 0, TEXTFIELD_NORMAL|LAYOUT_FILL_X|LAYOUT_FILL_COLUMN); + 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, 10, NULL, 0, TEXTFIELD_NORMAL|LAYOUT_FILL_X|LAYOUT_FILL_COLUMN); + 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, 40, NULL, 0, TEXTFIELD_NORMAL|LAYOUT_FILL_X|LAYOUT_FILL_COLUMN); - feature_len = new FXTextField(matrix, 10, NULL, 0, TEXTFIELD_NORMAL|LAYOUT_FILL_X|LAYOUT_FILL_COLUMN); + 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, 40, NULL, 0, TEXTFIELD_NORMAL|LAYOUT_FILL_X|LAYOUT_FILL_COLUMN); - get_feature_len = new FXTextField(matrix, 10, NULL, 0, TEXTFIELD_NORMAL|LAYOUT_FILL_X|LAYOUT_FILL_COLUMN); + 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(); @@ -332,41 +340,57 @@ MainWindow::getDataFromTextField(FXTextField *tf, char *buf, size_t len) return i; } -size_t -MainWindow::getLengthFromTextField(FXTextField *tf, size_t len) +/* getLengthFromTextField() + Returns length: + 0: empty text field + >0: valid length + -1: invalid length */ +int +MainWindow::getLengthFromTextField(FXTextField *tf) { - // must be called after getDataFromTextField()... - // on Windows the exact expected length is required... - FXString data = tf->getText(); - const FXchar *d = data.text(); - size_t i = 0; - - // Copy the string from the GUI. - size_t sz = strlen(d); + long int len; + FXString str = tf->getText(); + size_t sz = str.length(); + if (sz > 0) { - char *str = (char*) malloc(sz+1); - strcpy(str, d); - char *endptr; - i = (size_t)strtol(str, &endptr, 0); + 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; + } - free(str); - return i; - } - else { - // if length is not passed in use the data length determined by getDataFromTextField - return len; - } + return 0; } long MainWindow::onSendOutputReport(FXObject *sender, FXSelector sel, void *ptr) { char buf[256]; - size_t len; - len = getDataFromTextField(output_text, buf, sizeof(buf)); - // for Windows we need to send the exact buffer size. - len = getLengthFromTextField(output_len, len); + 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) { @@ -380,16 +404,30 @@ long MainWindow::onSendFeatureReport(FXObject *sender, FXSelector sel, void *ptr) { char buf[256]; - size_t len; - len = getDataFromTextField(feature_text, buf, sizeof(buf)); - // for Windows we need to send the exact buffer size. - len = getLengthFromTextField(feature_len, len); + 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; } @@ -398,13 +436,15 @@ 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"); } - len = getLengthFromTextField(get_feature_len, len); - int res = hid_get_feature_report(connected_device, (unsigned char*)buf, len); + 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)); } @@ -425,7 +465,6 @@ MainWindow::onGetFeatureReport(FXObject *sender, FXSelector sel, void *ptr) input_text->appendText(s); input_text->setBottomLine(INT_MAX); } - return 1; }