- Fixed automatic detection of the control serial port.
- Fixed segmentation fault when an invalid network interface was given. - More helpful message in case of wrong PIN number. Submitted by: Fredrik Lindberg
This commit is contained in:
parent
fac99fc079
commit
ba0349b2b7
@ -66,6 +66,7 @@
|
|||||||
|
|
||||||
#define TTY_NAME "/dev/%s"
|
#define TTY_NAME "/dev/%s"
|
||||||
#define SYSCTL_TEST "dev.uhso.%d.%%driver"
|
#define SYSCTL_TEST "dev.uhso.%d.%%driver"
|
||||||
|
#define SYSCTL_LOCATION "dev.uhso.%d.%%location"
|
||||||
#define SYSCTL_PORTS "dev.uhso.%d.ports"
|
#define SYSCTL_PORTS "dev.uhso.%d.ports"
|
||||||
#define SYSCTL_NETIF "dev.uhso.%d.netif"
|
#define SYSCTL_NETIF "dev.uhso.%d.netif"
|
||||||
#define SYSCTL_NAME_TTY "dev.uhso.%d.port.%s.tty"
|
#define SYSCTL_NAME_TTY "dev.uhso.%d.port.%s.tty"
|
||||||
@ -207,9 +208,6 @@ tmr_run(struct timers *tmrs)
|
|||||||
while (te->timeout <= 0) {
|
while (te->timeout <= 0) {
|
||||||
te2 = TAILQ_NEXT(te, next);
|
te2 = TAILQ_NEXT(te, next);
|
||||||
TAILQ_REMOVE(&tmrs->head, te, next);
|
TAILQ_REMOVE(&tmrs->head, te, next);
|
||||||
if (te2 != NULL)
|
|
||||||
te2->timeout -= tmrs->res;
|
|
||||||
|
|
||||||
te->func(te->id, te->arg);
|
te->func(te->id, te->arg);
|
||||||
free(te);
|
free(te);
|
||||||
te = te2;
|
te = te2;
|
||||||
@ -579,12 +577,13 @@ readline(int fd, char *buf, size_t bufsz)
|
|||||||
static int
|
static int
|
||||||
at_cmd(struct ctx *ctx, const char *resp, resp_cb cb, resp_arg *ra, const char *cf, ...)
|
at_cmd(struct ctx *ctx, const char *resp, resp_cb cb, resp_arg *ra, const char *cf, ...)
|
||||||
{
|
{
|
||||||
|
char buf[512];
|
||||||
|
char cmd[64];
|
||||||
size_t l;
|
size_t l;
|
||||||
int n, error, retval = 0;
|
int n, error, retval = 0;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
fd_set set;
|
fd_set set;
|
||||||
char buf[512];
|
char *p;
|
||||||
char cmd[64];
|
|
||||||
|
|
||||||
va_start(ap, cf);
|
va_start(ap, cf);
|
||||||
vsnprintf(cmd, sizeof(cmd), cf, ap);
|
vsnprintf(cmd, sizeof(cmd), cf, ap);
|
||||||
@ -614,12 +613,12 @@ at_cmd(struct ctx *ctx, const char *resp, resp_cb cb, resp_arg *ra, const char *
|
|||||||
do {
|
do {
|
||||||
FD_SET(ctx->fd, &set);
|
FD_SET(ctx->fd, &set);
|
||||||
error = select(ctx->fd + 1, &set, NULL, NULL, NULL);
|
error = select(ctx->fd + 1, &set, NULL, NULL, NULL);
|
||||||
if (error < 0 && errno == EINTR && ctx->flags & FLG_WDEXP) {
|
if (ctx->flags & FLG_WDEXP) {
|
||||||
watchdog_disable(ctx);
|
watchdog_disable(ctx);
|
||||||
retval = -2;
|
return (-2);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
} while (error <= 0 && errno == EINTR);
|
} while (error <= 0 && errno == EINTR);
|
||||||
|
watchdog_disable(ctx);
|
||||||
|
|
||||||
if (error <= 0) {
|
if (error <= 0) {
|
||||||
retval = -2;
|
retval = -2;
|
||||||
@ -635,24 +634,30 @@ at_cmd(struct ctx *ctx, const char *resp, resp_cb cb, resp_arg *ra, const char *
|
|||||||
if (strcmp(buf, "\r\n") == 0 || strcmp(buf, "\n") == 0)
|
if (strcmp(buf, "\r\n") == 0 || strcmp(buf, "\n") == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if ((p = strchr(buf, '\r')) != NULL)
|
||||||
|
*p = '\0';
|
||||||
|
else if ((p = strchr(buf, '\n')) != NULL)
|
||||||
|
*p = '\0';
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
fprintf(stderr, "SYNC_RESP: %s", buf);
|
fprintf(stderr, "SYNC_RESP: %s\n", buf);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Skip local echo */
|
||||||
|
if (strncasecmp(cmd, buf, strlen(buf)) == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (cb != NULL)
|
||||||
|
cb(ra, cmd, buf);
|
||||||
|
|
||||||
if (strncmp(buf, "OK", 2) == 0) {
|
if (strncmp(buf, "OK", 2) == 0) {
|
||||||
|
retval = retval ? retval : 0;
|
||||||
break;
|
break;
|
||||||
}
|
} else if (strstr(buf, "ERROR") != NULL) {
|
||||||
else if (strncmp(buf, "ERROR", 5) == 0) {
|
|
||||||
retval = -1;
|
retval = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (resp != NULL)
|
||||||
if (resp != NULL) {
|
retval = strncmp(buf, resp, l);
|
||||||
retval = strncmp(resp, buf, l);
|
|
||||||
if (retval == 0 && cb != NULL) {
|
|
||||||
cb(ra, cmd, buf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
fprintf(stderr, "SYNC_RETVAL=%d\n", retval);
|
fprintf(stderr, "SYNC_RETVAL=%d\n", retval);
|
||||||
@ -684,6 +689,10 @@ saveresp(resp_arg *ra, const char *cmd, const char *resp)
|
|||||||
char **buf;
|
char **buf;
|
||||||
int i = ra->val[1].int32;
|
int i = ra->val[1].int32;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
fprintf(stderr, "Save '%s'\n", resp);
|
||||||
|
#endif
|
||||||
|
|
||||||
buf = realloc(ra->val[0].ptr, sizeof(char *) * (i + 1));
|
buf = realloc(ra->val[0].ptr, sizeof(char *) * (i + 1));
|
||||||
if (buf == NULL)
|
if (buf == NULL)
|
||||||
return;
|
return;
|
||||||
@ -694,6 +703,19 @@ saveresp(resp_arg *ra, const char *cmd, const char *resp)
|
|||||||
ra->val[1].int32 = i + 1;
|
ra->val[1].int32 = i + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
freeresp(resp_arg *ra)
|
||||||
|
{
|
||||||
|
char **buf;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
buf = ra->val[0].ptr;
|
||||||
|
for (i = 0; i < ra->val[1].int32; i++) {
|
||||||
|
free(buf[i]);
|
||||||
|
}
|
||||||
|
free(buf);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
at_async_creg(void *arg, const char *resp)
|
at_async_creg(void *arg, const char *resp)
|
||||||
{
|
{
|
||||||
@ -992,129 +1014,119 @@ static const char *port_type_list[] = {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Attempts to find a list of control tty for the interface
|
* Attempts to find a list of control tty for the interface
|
||||||
* FreeBSD attaches USb devices per interface so we have to go through
|
* FreeBSD attaches USB devices per interface so we have to go through
|
||||||
* hoops to find which ttys that belong to our network interface.
|
* hoops to find which ttys that belong to our network interface.
|
||||||
*/
|
*/
|
||||||
static char **
|
static char **
|
||||||
get_tty(struct ctx *ctx)
|
get_tty(struct ctx *ctx)
|
||||||
{
|
{
|
||||||
char buf[64];
|
char buf[64], data[128];
|
||||||
char data[128];
|
int error, i, usbport, usbport0, list_size = 0;
|
||||||
size_t len;
|
|
||||||
int error;
|
|
||||||
unsigned int i;
|
|
||||||
char **list = NULL;
|
char **list = NULL;
|
||||||
int list_size = 0;
|
size_t len;
|
||||||
const char **p;
|
const char **p, *q;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Look for the network interface first
|
||||||
|
*/
|
||||||
for (i = 0; ; i++) {
|
for (i = 0; ; i++) {
|
||||||
/* Basic test to check if we're even in the right ballpark */
|
/* Check if we still have uhso nodes to check */
|
||||||
snprintf(buf, 64, SYSCTL_TEST, i);
|
snprintf(buf, 64, SYSCTL_TEST, i);
|
||||||
len = 127;
|
len = 127;
|
||||||
error = sysctlbyname(buf, data, &len, NULL, 0);
|
error = sysctlbyname(buf, data, &len, NULL, 0);
|
||||||
|
data[len] = '\0';
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
fprintf(stderr, "sysctl %s returned(%d): %s\n",
|
fprintf(stderr, "sysctl %s returned(%d): %s\n",
|
||||||
buf, error, error == 0 ? data : "FAILED");
|
buf, error, error == 0 ? data : "FAILED");
|
||||||
#endif
|
#endif
|
||||||
if (error < 0)
|
if (error < 0 || strcasecmp(data, "uhso") != 0)
|
||||||
return NULL;
|
|
||||||
if (strcasecmp(data, "uhso") != 0)
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* Check for interface */
|
/* Check if this node contains the network interface we want */
|
||||||
snprintf(buf, 64, SYSCTL_NETIF, i);
|
snprintf(buf, 64, SYSCTL_NETIF, i);
|
||||||
len = 127;
|
len = 127;
|
||||||
error = sysctlbyname(buf, data, &len, NULL, 0);
|
error = sysctlbyname(buf, data, &len, NULL, 0);
|
||||||
|
data[len] = '\0';
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
fprintf(stderr, "sysctl %s returned(%d): %s\n",
|
fprintf(stderr, "sysctl %s returned(%d): %s\n",
|
||||||
buf, error, error == 0 ? data : "FAILED");
|
buf, error, error == 0 ? data : "FAILED");
|
||||||
#endif
|
#endif
|
||||||
if (error < 0)
|
if (error == 0 && strcasecmp(data, ctx->ifnam) == 0)
|
||||||
continue;
|
break;
|
||||||
|
|
||||||
if (strcasecmp(data, ctx->ifnam) != 0)
|
|
||||||
continue;
|
|
||||||
#ifdef DEBUG
|
|
||||||
fprintf(stderr, "Found %s at %s\n", ctx->ifnam, buf);
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add multiplexed ports */
|
/* Figure out the USB port location */
|
||||||
for (p = port_type_list; *p != NULL; p++) {
|
snprintf(buf, 64, SYSCTL_LOCATION, i);
|
||||||
snprintf(buf, 64, SYSCTL_NAME_TTY, i, *p);
|
len = 127;
|
||||||
len = 127;
|
error = sysctlbyname(buf, data, &len, NULL, 0);
|
||||||
error = sysctlbyname(buf, data, &len, NULL, 0);
|
data[len] = '\0';
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
fprintf(stderr, "sysctl %s returned(%d): %s\n",
|
fprintf(stderr, "sysctl %s returned(%d): %s\n",
|
||||||
buf, error, error == 0 ? data : "FAILED");
|
buf, error, error == 0 ? data : "FAILED");
|
||||||
#endif
|
#endif
|
||||||
if (error == 0) {
|
if (error != 0)
|
||||||
list = realloc(list, (list_size + 1) * sizeof(char *));
|
return (NULL);
|
||||||
list[list_size] = malloc(strlen(data) + strlen(TTY_NAME));
|
|
||||||
sprintf(list[list_size], TTY_NAME, data);
|
q = strstr(data, "port=");
|
||||||
list_size++;
|
if (q != NULL) {
|
||||||
|
error = sscanf(q, " port=%d", &usbport);
|
||||||
|
if (error != 1) {
|
||||||
|
#ifdef DEBUG
|
||||||
|
fprintf(stderr, "failed to read usb port location from '%s'\n", data);
|
||||||
|
#endif
|
||||||
|
return (NULL);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
|
|
||||||
/*
|
|
||||||
* We can return directly if we found multiplexed serial ports because
|
|
||||||
* devices with these ports only have additional diagnostic ports (useless)
|
|
||||||
* and modem ports (for used with pppd).
|
|
||||||
*/
|
|
||||||
if (list_size > 0) {
|
|
||||||
list = realloc(list, (list_size + 1) * sizeof(char *));
|
|
||||||
list[list_size] = NULL;
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The network port is on a high numbered interface so we walk backwards until
|
|
||||||
* we hit anything other than application/control.
|
|
||||||
*/
|
|
||||||
|
|
||||||
for (--i; i >= 0; i--) {
|
|
||||||
/* Basic test to check if we're even in the right ballpark */
|
|
||||||
snprintf(buf, 64, SYSCTL_TEST, i);
|
|
||||||
len = 127;
|
|
||||||
error = sysctlbyname(buf, data, &len, NULL, 0);
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
fprintf(stderr, "sysctl %s returned(%d): %s\n",
|
fprintf(stderr, "failed to parse location '%s'\n", data);
|
||||||
buf, error, error == 0 ? data : "FAILED");
|
#endif
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
#ifdef DEBUG
|
||||||
|
fprintf(stderr, "USB port location=%d\n", usbport);
|
||||||
#endif
|
#endif
|
||||||
if (error < 0)
|
|
||||||
break;
|
|
||||||
if (strcasecmp(data, "uhso") != 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* Test for useable ports */
|
/*
|
||||||
|
* Now go through it all again but only look at those matching the
|
||||||
|
* usb port location we found.
|
||||||
|
*/
|
||||||
|
for (i = 0; ; i++) {
|
||||||
|
snprintf(buf, 64, SYSCTL_LOCATION, i);
|
||||||
|
len = 127;
|
||||||
|
memset(&data, 0, sizeof(data));
|
||||||
|
error = sysctlbyname(buf, data, &len, NULL, 0);
|
||||||
|
if (error != 0)
|
||||||
|
break;
|
||||||
|
data[len] = '\0';
|
||||||
|
q = strstr(data, "port=");
|
||||||
|
if (q == NULL)
|
||||||
|
continue;
|
||||||
|
sscanf(q, " port=%d", &usbport0);
|
||||||
|
if (usbport != usbport0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Try to add ports */
|
||||||
for (p = port_type_list; *p != NULL; p++) {
|
for (p = port_type_list; *p != NULL; p++) {
|
||||||
snprintf(buf, 64, SYSCTL_NAME_TTY, i, p);
|
snprintf(buf, 64, SYSCTL_NAME_TTY, i, *p);
|
||||||
len = 127;
|
len = 127;
|
||||||
|
memset(&data, 0, sizeof(data));
|
||||||
error = sysctlbyname(buf, data, &len, NULL, 0);
|
error = sysctlbyname(buf, data, &len, NULL, 0);
|
||||||
|
data[len] = '\0';
|
||||||
|
#ifdef DEBUG
|
||||||
|
fprintf(stderr, "sysctl %s returned(%d): %s\n",
|
||||||
|
buf, error, error == 0 ? data : "FAILED");
|
||||||
|
#endif
|
||||||
if (error == 0) {
|
if (error == 0) {
|
||||||
list = realloc(list, (list_size + 1) * sizeof(char *));
|
list = realloc(list, (list_size + 1) * sizeof(char *));
|
||||||
list[list_size] = malloc(strlen(data) + strlen(TTY_NAME));
|
list[list_size] = malloc(strlen(data) + strlen(TTY_NAME));
|
||||||
sprintf(list[list_size], TTY_NAME, data);
|
sprintf(list[list_size], TTY_NAME, data);
|
||||||
list_size++;
|
list_size++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* HACK! first port is a diagnostic port, we abort here */
|
|
||||||
snprintf(buf, 64, SYSCTL_NAME_TTY, i, "diagnostic");
|
|
||||||
len = 127;
|
|
||||||
error = sysctlbyname(buf, data, &len, NULL, 0);
|
|
||||||
#ifdef DEBUG
|
|
||||||
fprintf(stderr, "sysctl %s returned(%d): %s\n",
|
|
||||||
buf, error, error == 0 ? data : "FAILED");
|
|
||||||
#endif
|
|
||||||
if (error == 0)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
list = realloc(list, (list_size + 1) * sizeof(char *));
|
list = realloc(list, (list_size + 1) * sizeof(char *));
|
||||||
list[list_size] = NULL;
|
list[list_size] = NULL;
|
||||||
return list;
|
return (list);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -1146,13 +1158,28 @@ do_connect(struct ctx *ctx, const char *tty)
|
|||||||
|
|
||||||
error = at_cmd(ctx, NULL, NULL, NULL, "AT\r\n");
|
error = at_cmd(ctx, NULL, NULL, NULL, "AT\r\n");
|
||||||
if (error == -2) {
|
if (error == -2) {
|
||||||
warnx("failed to read from device");
|
warnx("failed to read from device %s", tty);
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for PIN */
|
/* Check for PIN */
|
||||||
error = at_cmd(ctx, "+CPIN: READY", NULL, NULL, "AT+CPIN?\r\n");
|
error = at_cmd(ctx, "+CPIN: READY", NULL, NULL, "AT+CPIN?\r\n");
|
||||||
if (error != 0) {
|
if (error != 0) {
|
||||||
|
ra.val[0].ptr = NULL;
|
||||||
|
ra.val[1].int32 = 0;
|
||||||
|
error = at_cmd(ctx, "+CME ERROR", saveresp, &ra, "AT+CPIN?\r\n");
|
||||||
|
if (ra.val[1].int32 > 0) {
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
buf = ra.val[0].ptr;
|
||||||
|
if (strstr(buf[0], "+CME ERROR:") != NULL) {
|
||||||
|
buf[0] += 12;
|
||||||
|
errx(1, buf[0]);
|
||||||
|
}
|
||||||
|
freeresp(&ra);
|
||||||
|
} else
|
||||||
|
freeresp(&ra);
|
||||||
|
|
||||||
if (ctx->pin == NULL) {
|
if (ctx->pin == NULL) {
|
||||||
errx(1, "device requires PIN");
|
errx(1, "device requires PIN");
|
||||||
}
|
}
|
||||||
@ -1445,6 +1472,8 @@ main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
tty_list = get_tty(&ctx);
|
tty_list = get_tty(&ctx);
|
||||||
|
if (tty_list == NULL)
|
||||||
|
errx(1, "%s does not appear to be a uhso device", ifnam);
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (tty_list == NULL) {
|
if (tty_list == NULL) {
|
||||||
fprintf(stderr, "get_tty returned empty list\n");
|
fprintf(stderr, "get_tty returned empty list\n");
|
||||||
@ -1507,7 +1536,7 @@ main(int argc, char *argv[])
|
|||||||
network_access_type[ctx.con_net_type]);
|
network_access_type[ctx.con_net_type]);
|
||||||
if (ctx.dbm < 0)
|
if (ctx.dbm < 0)
|
||||||
printf(", signal: %d dBm", ctx.dbm);
|
printf(", signal: %d dBm", ctx.dbm);
|
||||||
printf("\r");
|
printf("\t\t\t\r");
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user