mirror of
https://github.com/CTCaer/hidapi.git
synced 2024-11-23 10:09:46 +00:00
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.
This commit is contained in:
parent
1fba3f98f0
commit
b20777fc0c
123
testgui/test.cpp
123
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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user