feat: argument parsing with getopt
feat: enumerate usb interfaces and endpoints rather than hardcoding them
This commit is contained in:
parent
18f2d75d91
commit
447e1c29ab
4 changed files with 241 additions and 89 deletions
|
@ -1,2 +1,3 @@
|
||||||
SUBSYSTEM=="usb", ATTRS{idVendor}=="0c2e", ATTRS{idProduct}=="0b07", MODE="0666"
|
|
||||||
SUBSYSTEM=="usb", ATTRS{idVendor}=="0c2e", ATTRS{idProduct}=="0b01", MODE="0666"
|
SUBSYSTEM=="usb", ATTRS{idVendor}=="0c2e", ATTRS{idProduct}=="0b01", MODE="0666"
|
||||||
|
SUBSYSTEM=="usb", ATTRS{idVendor}=="0c2e", ATTRS{idProduct}=="0b02", MODE="0666"
|
||||||
|
SUBSYSTEM=="usb", ATTRS{idVendor}=="0c2e", ATTRS{idProduct}=="0b07", MODE="0666"
|
||||||
|
|
2
Makefile
2
Makefile
|
@ -2,7 +2,7 @@
|
||||||
.PHONY: honeywell-config clean
|
.PHONY: honeywell-config clean
|
||||||
|
|
||||||
honeywell-config:
|
honeywell-config:
|
||||||
gcc -lusb-1.0 -o honeywell-config honeywell-config.c
|
gcc -Wall -Werror -lusb-1.0 -o honeywell-config honeywell-config.c
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f honeywell-config
|
rm -f honeywell-config
|
||||||
|
|
87
README.md
87
README.md
|
@ -19,32 +19,30 @@ First of all, compile the program using `make`. It depends only on `libusb-1.0`
|
||||||
The configuration strings need to be provided as command line arguments. You can provide multiple:
|
The configuration strings need to be provided as command line arguments. You can provide multiple:
|
||||||
|
|
||||||
```
|
```
|
||||||
./honeywell-config <string1> [... <stringN>]
|
usage: ./honeywell-config [-v vendor] [-p product] [-o] [-r] [-d] command1 [command2 [... commandN]]
|
||||||
|
-v vendor USB vendor ID of the barcode scanner
|
||||||
|
-p product USB product ID of the barcode scanner
|
||||||
|
-o Print response on one line, rather than one token per line
|
||||||
|
-r Reset device after configuration
|
||||||
|
-d Debug mode (more verbose output)
|
||||||
```
|
```
|
||||||
|
|
||||||
The commands sent to the scanner are prefixed with `>`, the (tokenized) responses from the scanner with `<`.
|
If no vendor ID or product ID is provided, the following set of IDs is tried:
|
||||||
|
|
||||||
In general, please refer to your scanner's manual for configuration strings.
|
- `0c2e:0b01` (Honeywell 1300G, USB Kkeyboard mode PC)
|
||||||
|
- `0c2e:0b02` (Honeywell 1300G, USB Keyboard Apple)
|
||||||
|
- `0c2e:0b07` (Honeywell 1300G, USB HID POS mode)
|
||||||
|
|
||||||
Here are some examples.
|
USB serial mode (`0c2e:0b0a`) is skipped because USB configuration does not seem to work for it (and it isn't found by EZconfig either).
|
||||||
|
|
||||||
|
For the actual configuration commands, please refer to your scanner's manual. Here are some examples.
|
||||||
|
|
||||||
### Factory Reset
|
### Factory Reset
|
||||||
|
|
||||||
```
|
```
|
||||||
$ ./honeywell-config DEFOVR. DEFALT.
|
$ ./honeywell-config DEFOVR. DEFALT.
|
||||||
> DEFOVR.
|
DEFOVR.
|
||||||
< DEFOVR.
|
DEFALT.
|
||||||
> DEFALT.
|
|
||||||
< DEFALT.
|
|
||||||
```
|
|
||||||
|
|
||||||
### Factory Reset - In one command
|
|
||||||
|
|
||||||
```
|
|
||||||
$ ./honeywell-config "DEFOVR;DEFALT."
|
|
||||||
> DEFOVR;DEFALT.
|
|
||||||
< DEFOVR.
|
|
||||||
< DEFALT.
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Switch Operation Mode
|
### Switch Operation Mode
|
||||||
|
@ -53,38 +51,46 @@ USBHID:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ ./honeywell-config PAP131.
|
$ ./honeywell-config PAP131.
|
||||||
> PAP131.
|
PAP131.
|
||||||
< PAP131.
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Keyboard:
|
Keyboard (PC):
|
||||||
|
|
||||||
```
|
```
|
||||||
$ ./honeywell-config PAP124.
|
$ ./honeywell-config PAP124.
|
||||||
> PAP124.
|
PAP124.
|
||||||
< PAP124.
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Keyboard (Apple):
|
||||||
|
|
||||||
|
```
|
||||||
|
$ ./honeywell-config PAP125.
|
||||||
|
PAP124.
|
||||||
|
```
|
||||||
|
|
||||||
|
Please note that when switching modes, the scanner restarts on its own, so some error messages are to be expected.
|
||||||
|
|
||||||
### Add Prefix to Output
|
### Add Prefix to Output
|
||||||
|
|
||||||
The following adds the string `FCKAFD ` (ASCII hex `46 43 4B 41 46 44 20`) in front of every scanned barcode:
|
The following adds the string `FCKAFD ` (ASCII hex `46 43 4B 41 46 44 20`) in front of every scanned barcode:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ ./honeywell-config PREBK246434B41464420.
|
$ ./honeywell-config PREBK29946434B41464420.
|
||||||
> PREBK246434B41464420.
|
PREBK29946434B41464420.
|
||||||
< PREBK246434B41464420.
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Note how this behaves differently from if you were to configure the scanner in-band via scanning config barcodes.
|
Note how this behaves differently from if you were to configure the scanner in-band via scanning config barcodes.
|
||||||
There you would scan a lot of individual codes from the manual:
|
There you would scan a lot of individual codes from the manual:
|
||||||
|
|
||||||
1. `PREBK2.`
|
1. `PREBK2.` (command)
|
||||||
1. `K4K.`
|
1. `K9K.` (argument "99" = all code types)
|
||||||
|
1. `K9K.`
|
||||||
|
1. `K4K.` (ASCII hex 46)
|
||||||
1. `K6K.`
|
1. `K6K.`
|
||||||
1. ...
|
1. ...
|
||||||
1. `K2K.`
|
1. `K2K.` (ASCII hex 20)
|
||||||
1. `K0K.`
|
1. `K0K.`
|
||||||
1. `MNUSAV.`
|
1. `MNUSAV.` (finish and save)
|
||||||
|
|
||||||
On the USB config interface, all of that goes into a single string instead.
|
On the USB config interface, all of that goes into a single string instead.
|
||||||
|
|
||||||
|
@ -92,19 +98,17 @@ On the USB config interface, all of that goes into a single string instead.
|
||||||
|
|
||||||
```
|
```
|
||||||
$ ./honeywell-config 'BEP?.'
|
$ ./honeywell-config 'BEP?.'
|
||||||
> BEP?.
|
BEPFQ12550,FQ2100,RPT1,ERR1,BEP1,BIP0,LVL0,EXZ,GRX,EXE,DFT,LED1.
|
||||||
< BEPFQ12550,FQ2100,RPT1,ERR1,BEP1,BIP0,LVL0,EXZ,GRX,EXE,DFT,LED1.
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### List all Settings and Their Possible Values
|
### List all Settings and Their Possible Values
|
||||||
|
|
||||||
```
|
```
|
||||||
$ ./honeywell-config '*.'
|
$ ./honeywell-config '*.'
|
||||||
> *.
|
BEPFQ1100-5000.
|
||||||
< BEPFQ1100-5000.
|
BEPFQ2100-5000.
|
||||||
< BEPFQ2100-5000.
|
|
||||||
...
|
...
|
||||||
< AXXMOD0|1|2|3|4|5|6|7|8|9|10.
|
AXXMOD0|1|2|3|4|5|6|7|8|9|10.
|
||||||
```
|
```
|
||||||
|
|
||||||
## USB Device Access
|
## USB Device Access
|
||||||
|
@ -116,19 +120,6 @@ Put this file into `/etc/udev/rules.d`, and run `sudo udevadm control --reload`
|
||||||
|
|
||||||
Once you replug the scanner, you should have access to it as a regular user.
|
Once you replug the scanner, you should have access to it as a regular user.
|
||||||
|
|
||||||
## Adapting for Other Scanners
|
|
||||||
|
|
||||||
The tool currently has hardcoded USB vendor/product IDs for a Honeywell Hyperion 1300G in Keyboard or USBHID modes.
|
|
||||||
|
|
||||||
If you have a different Honeywell scanner, and the tool doesn't find it, you can try making this tool work for it:
|
|
||||||
1. Obtain the USB vendor and product IDs for your scanner, e.g. through `lsusb`.
|
|
||||||
1. Replace the VID/PID in the following line of code in `honeywell-config.c`:
|
|
||||||
|
|
||||||
```c
|
|
||||||
libusb_device_handle *devh = libusb_open_device_with_vid_pid(ctx, 0x0c2e, 0x0b07);
|
|
||||||
```
|
|
||||||
1. Recompile the tool with `make`
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
MIT License
|
MIT License
|
||||||
|
|
|
@ -1,75 +1,169 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <libusb-1.0/libusb.h>
|
#include <libusb-1.0/libusb.h>
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
uint16_t vendor_id = 0;
|
||||||
uint8_t cmd[64];
|
uint16_t product_id = 0;
|
||||||
char tokbuf[1024];
|
uint8_t reset = 0;
|
||||||
|
uint8_t oneline = 0;
|
||||||
|
uint8_t debug = 0;
|
||||||
|
|
||||||
|
#define USBERR(msg, rc) { dprintf(2, "%s: %s\n", msg, libusb_strerror(rc)); }
|
||||||
|
#define DEBUG(...) { if (debug) { dprintf(2, __VA_ARGS__); } }
|
||||||
|
|
||||||
|
uint32_t vidpid[] = {
|
||||||
|
0x0c2e0b01,
|
||||||
|
0x0c2e0b02,
|
||||||
|
0x0c2e0b07,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int config(int argc, char **args) {
|
||||||
|
uint8_t cmd[64] = { 0 };
|
||||||
|
char tokbuf[1024] = { 0 };
|
||||||
libusb_context *ctx = NULL;
|
libusb_context *ctx = NULL;
|
||||||
|
libusb_device *dev = NULL;
|
||||||
|
libusb_device_handle *devh = NULL;
|
||||||
|
struct libusb_device_descriptor devd = { 0 };
|
||||||
|
struct libusb_config_descriptor *devc = NULL;
|
||||||
|
const struct libusb_interface *devi = NULL;
|
||||||
|
const struct libusb_interface_descriptor *devid = NULL;
|
||||||
|
const struct libusb_endpoint_descriptor *deved = NULL;
|
||||||
|
char devdesc[256] = { 0 };
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
uint8_t ints[32] = { 0 };
|
||||||
|
uint8_t inti = 0;
|
||||||
|
uint8_t endpoint = 0;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Find and open the device
|
// Find and open the device
|
||||||
//
|
//
|
||||||
libusb_init(&ctx);
|
rc = libusb_init(&ctx);
|
||||||
if (!ctx) {
|
if (!ctx) {
|
||||||
perror("failed to initialize libusb");
|
USBERR("failed to initialize libusb", rc);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
libusb_device_handle *devh = libusb_open_device_with_vid_pid(ctx, 0x0c2e, 0x0b07);
|
if (vendor_id || product_id) {
|
||||||
if (!devh) {
|
devh = libusb_open_device_with_vid_pid(ctx, vendor_id, product_id);
|
||||||
devh = libusb_open_device_with_vid_pid(ctx, 0x0c2e, 0x0b01);
|
|
||||||
if (!devh) {
|
if (!devh) {
|
||||||
perror("failed to open device");
|
dprintf(2, "device %04x:%04x not found\n", vendor_id, product_id);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
devh = NULL;
|
||||||
|
for (uint8_t i = 0; i < sizeof(vidpid)/sizeof(vidpid[0]) && !devh; ++i) {
|
||||||
|
devh = libusb_open_device_with_vid_pid(ctx, vidpid[i] >> 16, vidpid[i] & 0xffff);
|
||||||
|
}
|
||||||
|
if (!devh) {
|
||||||
|
dprintf(2, "default devices not found, please provide vendor and product id\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get endpoint infos
|
||||||
|
dev = libusb_get_device(devh);
|
||||||
|
rc = libusb_get_device_descriptor(dev, &devd);
|
||||||
|
if (rc) {
|
||||||
|
USBERR("failed to get device descriptor", rc);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
for (uint8_t c = 0; c < devd.bNumConfigurations; ++c) {
|
||||||
|
libusb_free_config_descriptor(devc);
|
||||||
|
rc = libusb_get_config_descriptor(dev, c, &devc);
|
||||||
|
if (rc) {
|
||||||
|
USBERR("failed to get config descriptor", rc);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
rc = libusb_get_string_descriptor_ascii(devh, devc->iConfiguration, (uint8_t *) devdesc, 256);
|
||||||
|
if (rc < 0) {
|
||||||
|
USBERR("failed to get config string descriptor", rc);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
DEBUG("- configuration %d: %s\n", c, devdesc);
|
||||||
|
for (uint8_t i = 0; i < devc->bNumInterfaces; ++i) {
|
||||||
|
DEBUG(" - interface %d\n", i);
|
||||||
|
devi = &(devc->interface[i]);
|
||||||
|
for (uint8_t a = 0; a < devi->num_altsetting; ++a) {
|
||||||
|
devid = &(devi->altsetting[a]);
|
||||||
|
rc = libusb_get_string_descriptor_ascii(devh, devid->iInterface, (uint8_t *) devdesc, 256);
|
||||||
|
if (rc < 0) {
|
||||||
|
USBERR("failed to get interface string descriptor", rc);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
DEBUG(" - altsetting %d: interface=%d, desc=%s class=%d subclass=%d protocol=%d\n",
|
||||||
|
devid->bAlternateSetting, devid->bInterfaceNumber, devdesc,
|
||||||
|
devid->bInterfaceClass, devid->bInterfaceSubClass, devid->bInterfaceProtocol);
|
||||||
|
for (uint8_t e = 0; e < devid->bNumEndpoints; ++e) {
|
||||||
|
deved = &(devid->endpoint[e]);
|
||||||
|
char type = "csbi"[deved->bmAttributes & 0b00000011];
|
||||||
|
DEBUG(" - endpoint %x: t=%c\n", deved->bEndpointAddress, type);
|
||||||
|
// build a list of interfaces so that we can claim all of them
|
||||||
|
ints[inti++] = devid->bInterfaceNumber;
|
||||||
|
// endpoint selection:
|
||||||
|
if ((deved->bmAttributes & 0b11) == LIBUSB_ENDPOINT_TRANSFER_TYPE_INTERRUPT // must be an interrupt endpoint
|
||||||
|
&& ((deved->bEndpointAddress & 0x80) == LIBUSB_ENDPOINT_IN) // must be a device to host endpoint
|
||||||
|
&& !strncmp("REM", devdesc, 3) // human readable description of the interface must be "REM" (Honeywell "Remote MasterMind" control interface)
|
||||||
|
) {
|
||||||
|
endpoint = deved->bEndpointAddress;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG("chose endpoint %x\n", endpoint);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Disconnect usbhid driver from both device interfaces
|
// Disconnect usbhid driver from both device interfaces
|
||||||
//
|
//
|
||||||
if (libusb_set_auto_detach_kernel_driver(devh, 1)) {
|
rc = libusb_set_auto_detach_kernel_driver(devh, 1);
|
||||||
perror("auto-attaching kernel driver not possible; please replug USB when done");
|
if (rc) {
|
||||||
for (uint8_t i = 0; i < 2; ++i) {
|
USBERR("auto-attaching kernel driver not possible; please replug USB when done", rc);
|
||||||
int ret = libusb_kernel_driver_active(devh, i);
|
for (uint8_t i = 0; i < inti; ++i) {
|
||||||
if (ret < 0) {
|
rc = libusb_kernel_driver_active(devh, ints[i]);
|
||||||
perror("failed to query kernel driver state");
|
if (rc < 0) {
|
||||||
|
USBERR("failed to query kernel driver state", rc);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (ret > 0) {
|
if (rc > 0) {
|
||||||
ret = libusb_detach_kernel_driver(devh, i);
|
rc = libusb_detach_kernel_driver(devh, ints[i]);
|
||||||
if (ret) {
|
if (rc) {
|
||||||
perror("failed to detach kernel driver");
|
USBERR("failed to detach kernel driver", rc);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (uint8_t i = 0; i < 2; ++i) {
|
|
||||||
if (libusb_claim_interface(devh, i)) {
|
for (uint8_t i = 0; i < inti; ++i) {
|
||||||
perror("failed to claim interface");
|
rc = libusb_claim_interface(devh, ints[i]);
|
||||||
|
if (rc) {
|
||||||
|
USBERR("failed to claim interface", rc);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Prepare and send a message on the control channel for each config argument
|
// Prepare and send a message on the control channel for each config argument
|
||||||
//
|
//
|
||||||
for (int i = 1; i < argc; ++i) {
|
for (int i = 0; i < argc; ++i) {
|
||||||
memset(cmd+5, 0, 59);
|
memset(cmd+5, 0, 59);
|
||||||
cmd[0] = 0xfd;
|
cmd[0] = 0xfd;
|
||||||
cmd[1] = strlen(argv[i])+3;
|
cmd[1] = strlen(args[i])+3;
|
||||||
cmd[2] = 0x16;
|
cmd[2] = 0x16;
|
||||||
cmd[3] = 0x4d;
|
cmd[3] = 0x4d;
|
||||||
cmd[4] = 0x0d;
|
cmd[4] = 0x0d;
|
||||||
memcpy(cmd+5, argv[i], strlen(argv[i]));
|
memcpy(cmd+5, args[i], strlen(args[i]));
|
||||||
int ret = libusb_control_transfer(devh, 0x21, 0x09, 0x02fd, 1, cmd, 64, 0);
|
rc = libusb_control_transfer(devh, 0x21, 0x09, 0x02fd, 1, cmd, 64, 0);
|
||||||
if (ret < 0) {
|
if (rc < 0) {
|
||||||
perror("failed to send control message");
|
USBERR("failed to send control message", rc);
|
||||||
} else {
|
} else {
|
||||||
printf("> %s\n", argv[i]);
|
DEBUG("> %s\n", args[i]);
|
||||||
}
|
}
|
||||||
int tx;
|
int tx;
|
||||||
tokbuf[64] = 0;
|
tokbuf[64] = 0;
|
||||||
|
@ -77,13 +171,14 @@ int main(int argc, char **argv) {
|
||||||
uint8_t eot = 0;
|
uint8_t eot = 0;
|
||||||
// Repeat until a "." (EOT) is encountered in the response.
|
// Repeat until a "." (EOT) is encountered in the response.
|
||||||
while (!eot) {
|
while (!eot) {
|
||||||
ret = libusb_interrupt_transfer(devh, 0x83, cmd, 64, &tx, 0);
|
rc = libusb_interrupt_transfer(devh, endpoint, cmd, 64, &tx, 1000);
|
||||||
if (ret) {
|
if (rc) {
|
||||||
perror("failed to receive response");
|
USBERR("failed to receive response from device", rc);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// strip 2-byte header and AIMID
|
// strip 2-byte header and AIMID
|
||||||
start = cmd+5;
|
start = (char *) cmd+5;
|
||||||
|
DEBUG("< %s\n", start);
|
||||||
while (1) {
|
while (1) {
|
||||||
// non-final tokens: terminated by ;
|
// non-final tokens: terminated by ;
|
||||||
end = strchr(start, ';');
|
end = strchr(start, ';');
|
||||||
|
@ -93,7 +188,11 @@ int main(int argc, char **argv) {
|
||||||
tok += end-start-1;
|
tok += end-start-1;
|
||||||
}
|
}
|
||||||
*tok = 0;
|
*tok = 0;
|
||||||
printf("< %s.\n", tokbuf);
|
if (oneline) {
|
||||||
|
printf("%s;", tokbuf);
|
||||||
|
} else {
|
||||||
|
printf("%s.\n", tokbuf);
|
||||||
|
}
|
||||||
tok = tokbuf;
|
tok = tokbuf;
|
||||||
*tok = 0;
|
*tok = 0;
|
||||||
start = end + 1;
|
start = end + 1;
|
||||||
|
@ -108,7 +207,7 @@ int main(int argc, char **argv) {
|
||||||
tok += end-start-1;
|
tok += end-start-1;
|
||||||
}
|
}
|
||||||
*tok = 0;
|
*tok = 0;
|
||||||
printf("< %s.\n", tokbuf);
|
printf("%s.\n", tokbuf);
|
||||||
tok = tokbuf;
|
tok = tokbuf;
|
||||||
*tok = 0;
|
*tok = 0;
|
||||||
break;
|
break;
|
||||||
|
@ -128,11 +227,72 @@ int main(int argc, char **argv) {
|
||||||
//
|
//
|
||||||
// Cleanup
|
// Cleanup
|
||||||
//
|
//
|
||||||
for (uint8_t i = 0; i < 2; ++i) {
|
for (uint8_t i = 0; i < inti; ++i) {
|
||||||
if (libusb_release_interface(devh, i)) {
|
rc = libusb_release_interface(devh, ints[i]);
|
||||||
perror("failed to release interface");
|
if (rc) {
|
||||||
|
USBERR("failed to release interface", rc);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (reset) {
|
||||||
|
libusb_reset_device(devh);
|
||||||
|
}
|
||||||
libusb_close(devh);
|
libusb_close(devh);
|
||||||
libusb_exit(ctx);
|
libusb_exit(ctx);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
int opt;
|
||||||
|
char *end;
|
||||||
|
long parsed;
|
||||||
|
while ((opt = getopt(argc, argv, "v:p:ord")) != -1) {
|
||||||
|
switch (opt) {
|
||||||
|
case 'v':
|
||||||
|
end = optarg;
|
||||||
|
parsed = strtol(optarg, &end, 16);
|
||||||
|
if (*end != 0) {
|
||||||
|
perror("failed to parse vendor id");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (parsed <= 0 || parsed > 0xffff) {
|
||||||
|
puts("invalid vendor id");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
vendor_id = (uint16_t) parsed;
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
end = optarg;
|
||||||
|
parsed = strtol(optarg, &end, 16);
|
||||||
|
if (*end != 0) {
|
||||||
|
perror("failed to parse product id");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (parsed <= 0 || parsed > 0xffff) {
|
||||||
|
puts("invalid product id");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
product_id = (uint16_t) parsed;
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
reset = 1;
|
||||||
|
break;
|
||||||
|
case 'o':
|
||||||
|
oneline = 1;
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
debug = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("usage: %s [-v vendor] [-p product] [-o] [-r] [-d] command1 [command2 [... commandN]]\n", argv[0]);
|
||||||
|
puts(" -v vendor\tUSB vendor ID of the barcode scanner");
|
||||||
|
puts(" -p product\tUSB product ID of the barcode scanner");
|
||||||
|
puts(" -o\t\tPrint response on one line, rather than one token per line");
|
||||||
|
puts(" -r\t\tReset device after configuration");
|
||||||
|
puts(" -d\t\tDebug mode (more verbose output)");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return config(argc-optind, argv+optind);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue