dcttech-usbrelay: rework scan (enumeration) and probe (identification)

Move all of the sdi creation into the probe routine which communicates
to the relay card. Extend diagnostics in that code path. Which leaves
pure USB enumeration in the scan routine.
This commit is contained in:
Gerhard Sittig 2021-07-22 07:59:34 +02:00
parent e333a40c1c
commit 996331ce9b
1 changed files with 26 additions and 19 deletions

View File

@ -43,7 +43,8 @@ static const uint32_t devopts_cg[] = {
static struct sr_dev_driver dcttech_usbrelay_driver_info; static struct sr_dev_driver dcttech_usbrelay_driver_info;
static struct sr_dev_inst *probe_device(const char *path, size_t relay_count) static struct sr_dev_inst *probe_device(struct hid_device_info *dev,
size_t relay_count)
{ {
hid_device *hid; hid_device *hid;
int ret; int ret;
@ -60,9 +61,11 @@ static struct sr_dev_inst *probe_device(const char *path, size_t relay_count)
struct sr_channel_group *cg; struct sr_channel_group *cg;
/* Open device, need to communicate to identify. */ /* Open device, need to communicate to identify. */
hid = hid_open_path(path); hid = hid_open_path(dev->path);
if (!hid) if (!hid) {
sr_err("Cannot open %s: %ls.", dev->path, hid_error(NULL));
return NULL; return NULL;
}
/* Get an HID report. */ /* Get an HID report. */
hid_set_nonblocking(hid, 0); hid_set_nonblocking(hid, 0);
@ -75,8 +78,14 @@ static struct sr_dev_inst *probe_device(const char *path, size_t relay_count)
sr_spew("raw report, rc %d, bytes %s", ret, txt->str); sr_spew("raw report, rc %d, bytes %s", ret, txt->str);
sr_hexdump_free(txt); sr_hexdump_free(txt);
} }
if (ret != sizeof(report)) if (ret < 0) {
sr_err("Cannot read %s: %ls.", dev->path, hid_error(NULL));
return NULL; return NULL;
}
if (ret != sizeof(report)) {
sr_err("Unexpected HID report length: %s.", dev->path);
return NULL;
}
/* /*
* Serial number must be all printable characters. Relay state * Serial number must be all printable characters. Relay state
@ -87,22 +96,27 @@ static struct sr_dev_inst *probe_device(const char *path, size_t relay_count)
for (snr_pos = 0; snr_pos < SERNO_LENGTH; snr_pos++) { for (snr_pos = 0; snr_pos < SERNO_LENGTH; snr_pos++) {
c = report[1 + snr_pos]; c = report[1 + snr_pos];
serno[snr_pos] = c; serno[snr_pos] = c;
if (c < 0x20 || c > 0x7e) if (c < 0x20 || c > 0x7e) {
sr_dbg("non-printable serno");
return NULL; return NULL;
} }
}
curr_state = report[1 + STATE_INDEX]; curr_state = report[1 + STATE_INDEX];
sr_spew("report data, serno[%s], relays 0x%02x.", serno, curr_state); sr_spew("report data, serno[%s], relays 0x%02x.", serno, curr_state);
/* /* Create a device instance. */
* Create a device instance, create channels (groups). The
* caller fills in vendor, model, conn from USB enum details.
*/
sdi = g_malloc0(sizeof(*sdi)); sdi = g_malloc0(sizeof(*sdi));
sdi->vendor = g_strdup_printf("%ls", dev->manufacturer_string);
sdi->model = g_strdup_printf("%ls", dev->product_string);
sdi->serial_num = g_strdup(serno); sdi->serial_num = g_strdup(serno);
sdi->connection_id = g_strdup(path); sdi->connection_id = g_strdup(dev->path);
sdi->driver = &dcttech_usbrelay_driver_info;
sdi->inst_type = SR_INST_USB;
/* Create channels (groups). */
devc = g_malloc0(sizeof(*devc)); devc = g_malloc0(sizeof(*devc));
sdi->priv = devc; sdi->priv = devc;
devc->hid_path = g_strdup(path); devc->hid_path = g_strdup(dev->path);
devc->relay_count = relay_count; devc->relay_count = relay_count;
devc->relay_mask = (1U << relay_count) - 1; devc->relay_mask = (1U << relay_count) - 1;
for (idx = 0; idx < devc->relay_count; idx++) { for (idx = 0; idx < devc->relay_count; idx++) {
@ -195,18 +209,11 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
curdev->path, relay_count); curdev->path, relay_count);
/* Identify device by communicating to it. */ /* Identify device by communicating to it. */
sdi = probe_device(curdev->path, relay_count); sdi = probe_device(curdev, relay_count);
if (!sdi) { if (!sdi) {
sr_warn("Failed to communicate to %s.", curdev->path); sr_warn("Failed to communicate to %s.", curdev->path);
continue; continue;
} }
/* Amend driver instance from USB enumeration details. */
sdi->vendor = g_strdup_printf("%ls", curdev->manufacturer_string);
sdi->model = g_strdup_printf("%ls", curdev->product_string);
sdi->driver = &dcttech_usbrelay_driver_info;
sdi->inst_type = SR_INST_USB;
devices = g_slist_append(devices, sdi); devices = g_slist_append(devices, sdi);
} }
hid_free_enumeration(devs); hid_free_enumeration(devs);