gwinstek-gpd: Support auto-baud detection

If the user does not specify a serialcomm configuration,
try all three options from the manual.
This commit is contained in:
Richard Allen 2021-01-16 13:47:38 -06:00 committed by Soeren Apel
parent c329b788d2
commit c93c014f47
1 changed files with 144 additions and 131 deletions

View File

@ -51,6 +51,12 @@ static const char *channel_modes[] = {
"Independent", "Independent",
}; };
static const char *gpd_serialcomms[] = {
"9600/8n1",
"57600/8n1",
"115200/8n1"
};
static const struct gpd_model models[] = { static const struct gpd_model models[] = {
{ GPD_2303S, "GPD-2303S", { GPD_2303S, "GPD-2303S",
CHANMODE_INDEPENDENT, CHANMODE_INDEPENDENT,
@ -76,7 +82,7 @@ static const struct gpd_model models[] = {
static GSList *scan(struct sr_dev_driver *di, GSList *options) static GSList *scan(struct sr_dev_driver *di, GSList *options)
{ {
const char *conn, *serialcomm; const char *conn, *serialcomm, **serialcomms;
const struct gpd_model *model; const struct gpd_model *model;
const struct sr_config *src; const struct sr_config *src;
struct sr_channel *ch; struct sr_channel *ch;
@ -85,7 +91,7 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
struct sr_serial_dev_inst *serial; struct sr_serial_dev_inst *serial;
struct sr_dev_inst *sdi; struct sr_dev_inst *sdi;
char reply[100]; char reply[100];
unsigned int i; unsigned int i, b, serialcomms_count;
struct dev_context *devc; struct dev_context *devc;
char channel[10]; char channel[10];
GRegex *regex; GRegex *regex;
@ -112,12 +118,20 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
if (!conn) if (!conn)
return NULL; return NULL;
if (!serialcomm) if (serialcomm) {
serialcomm = "115200/8n1"; serialcomms = &serialcomm;
serialcomms_count = 1;
} else {
serialcomms = gpd_serialcomms;
serialcomms_count = sizeof(gpd_serialcomms) / sizeof(gpd_serialcomms[0]);
}
for( b = 0; b < serialcomms_count; b++) {
serialcomm = serialcomms[b];
sr_info("Probing serial port %s @ %s", conn, serialcomm); sr_info("Probing serial port %s @ %s", conn, serialcomm);
serial = sr_serial_dev_inst_new(conn, serialcomm); serial = sr_serial_dev_inst_new(conn, serialcomm);
if (serial_open(serial, SERIAL_RDWR) != SR_OK) if (serial_open(serial, SERIAL_RDWR) != SR_OK)
return NULL; continue;
/* /*
* Problem: we need to clear the GPD receive buffer before we * Problem: we need to clear the GPD receive buffer before we
@ -129,13 +143,13 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
* Solution: Send identification request a few times. * Solution: Send identification request a few times.
* The first should corrupt any previous buffered command if present * The first should corrupt any previous buffered command if present
* and respond with "Invalid Character." or respond directly with * and respond with "Invalid Character." or respond directly with
* an identification string starting with "GW INSTEK" * an identification string.
*/ */
for (i = 0; i<IDN_RETRIES; ++i) { for (i = 0; i < IDN_RETRIES; i++) {
/* Request the GPD to identify itself */ /* Request the GPD to identify itself */
gpd_send_cmd(serial, "*IDN?\n"); gpd_send_cmd(serial, "*IDN?\n");
if (gpd_receive_reply(serial, reply, sizeof(reply)) == SR_OK) { if (gpd_receive_reply(serial, reply, sizeof(reply)) == SR_OK) {
if (0 == strncmp(reply, "GW INSTEK", 9 )) { if (0 == strncmp(reply, "GW INSTEK", 9)) {
break; break;
} }
} }
@ -213,7 +227,7 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
gpd_receive_reply(serial, reply, sizeof(reply)); gpd_receive_reply(serial, reply, sizeof(reply));
} }
for (i = 0; i < model->num_channels; ++i) { for (i = 0; i < model->num_channels; i++) {
gpd_send_cmd(serial, "ISET%d?\n", i + 1); gpd_send_cmd(serial, "ISET%d?\n", i + 1);
gpd_receive_reply(serial, reply, sizeof(reply)); gpd_receive_reply(serial, reply, sizeof(reply));
if (sscanf(reply, "%f", &devc->config[i].output_current_max) != 1) { if (sscanf(reply, "%f", &devc->config[i].output_current_max) != 1) {
@ -241,17 +255,16 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
} }
} }
serial_close(serial);
return std_scan_complete(di, g_slist_append(NULL, sdi)); return std_scan_complete(di, g_slist_append(NULL, sdi));
error: error:
if (match_info) if (match_info)
g_match_info_free(match_info); g_match_info_free(match_info);
if (regex) if (regex)
g_regex_unref(regex); g_regex_unref(regex);
if (serial) if (serial)
serial_close(serial); serial_close(serial);
}
return NULL; return NULL;
} }