275 lines
5.4 KiB
C
275 lines
5.4 KiB
C
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <stdio.h>
|
|
#include <dirent.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
|
|
#include <asterisk.h>
|
|
#include <asterisk/linkedlists.h> /* AST_LIST_ENTRY() */
|
|
|
|
#include "mutils.h"
|
|
#include "tty.h"
|
|
|
|
struct dev_descr {
|
|
AST_LIST_ENTRY (dev_descr) entry;
|
|
|
|
int busnum;
|
|
char devpath[40];
|
|
int configuration;
|
|
int interfaceno;
|
|
char port[80];
|
|
};
|
|
|
|
typedef AST_LIST_HEAD_NOLOCK(, dev_descr) dev_list_t;
|
|
|
|
static const char sys_driver[] = "/sys/bus/usb/drivers";
|
|
static const char port_number[] = "port_number";
|
|
|
|
#/* */
|
|
char * read_result(int fd)
|
|
{
|
|
unsigned total = 0;
|
|
char buf[4096];
|
|
char * found;
|
|
int read_bytes;
|
|
|
|
while(1) {
|
|
read_bytes = read(fd, buf + total, sizeof(buf) - total);
|
|
if(read_bytes <= 0)
|
|
return NULL;
|
|
total += read_bytes;
|
|
// fprintf(stdout, "%*s", read_bytes, buf);
|
|
if((found = memmem(buf, total, "\r\nOK\r\n", 6)) != NULL) {
|
|
found[0] = 0;
|
|
return strdup(buf);
|
|
} else if((found = memmem(buf, total, "\r\nERROR\r\n", 9)) != NULL) {
|
|
return NULL;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
#/* */
|
|
unsigned count_lines(const char * lines)
|
|
{
|
|
unsigned lno = 1;
|
|
const char * str = lines;
|
|
|
|
while(1) {
|
|
const char * x = strstr(str, "\r\n");
|
|
if(x == NULL)
|
|
break;
|
|
str = x + 2;
|
|
lno++;
|
|
}
|
|
|
|
return lno;
|
|
}
|
|
|
|
#/* */
|
|
char ** read_results(int fd, int * argc)
|
|
{
|
|
int arg;
|
|
char * str;
|
|
char * x;
|
|
char ** argv;
|
|
int lno;
|
|
|
|
char * lines = read_result(fd);
|
|
|
|
if(!lines) {
|
|
argc = 0;
|
|
return NULL;
|
|
}
|
|
|
|
lno = count_lines(lines);
|
|
argv = malloc((lno + 1) * sizeof(lines));
|
|
|
|
for(arg = 0, str = lines; arg < lno; ) {
|
|
x = strstr(str, "\r\n");
|
|
if(x == NULL)
|
|
break;
|
|
x[0] = 0;
|
|
if(str[0] != 0)
|
|
argv[arg++] = strdup(str);
|
|
str = x + 2;
|
|
}
|
|
free(lines);
|
|
argv[arg] = NULL;
|
|
|
|
*argc = arg;
|
|
return argv;
|
|
}
|
|
|
|
#/* */
|
|
void free_results(char ** argv)
|
|
{
|
|
if(argv) {
|
|
unsigned idx;
|
|
for(idx = 0; argv[idx]; idx++) {
|
|
free(argv[idx]);
|
|
}
|
|
free(argv);
|
|
}
|
|
}
|
|
|
|
#/* */
|
|
int discovery_port(struct dev_descr * descr, const char * name)
|
|
{
|
|
char pname[PATH_MAX];
|
|
struct dirent * entry;
|
|
struct stat statb;
|
|
|
|
DIR * dir = opendir(name);
|
|
if(dir) {
|
|
while((entry = readdir(dir)) != NULL) {
|
|
snprintf(pname, sizeof(pname), "%s/%s/%s", name, entry->d_name, port_number);
|
|
if(stat(pname, &statb) == 0) {
|
|
snprintf(descr->port, sizeof(descr->port), "/dev/%s", entry->d_name);
|
|
return 1;
|
|
}
|
|
}
|
|
closedir(dir);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#/* */
|
|
char * get_info_item(char ** argv, const char * name, unsigned len)
|
|
{
|
|
for(; argv[0]; argv++) {
|
|
if(strncmp(argv[0], name, len) == 0) {
|
|
char * found = argv[0] + len;
|
|
while(found[0] == ' ')
|
|
found++;
|
|
return strdup(found);
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
#/* */
|
|
int get_info(const char * port, char ** manu, char ** model, char ** imei, char ** imsi)
|
|
{
|
|
int fd = opentty(port);
|
|
*manu = *model = *imei = *imsi = 0;
|
|
if(fd >= 0) {
|
|
static const char ati[] = "ATI\r";
|
|
static const char cimi[] = "AT+CIMI\r";
|
|
char **argv;
|
|
int argc;
|
|
|
|
write_all(fd, ati, STRLEN(ati));
|
|
argv = read_results(fd, &argc);
|
|
if(argv) {
|
|
static const char s_manufactorer[] = "Manufacturer:";
|
|
static const char s_model[] = "Model:";
|
|
static const char s_imei[] = "IMEI:";
|
|
|
|
|
|
*manu = get_info_item(argv, s_manufactorer, STRLEN(s_manufactorer));
|
|
*model = get_info_item(argv, s_model, STRLEN(s_model));
|
|
*imei = get_info_item(argv, s_imei, STRLEN(s_imei));
|
|
|
|
free_results(argv);
|
|
}
|
|
|
|
write_all(fd, cimi, STRLEN(cimi));
|
|
argv = read_results(fd, &argc);
|
|
if(argv) {
|
|
int x = 0;
|
|
if(strncmp(argv[x], cimi, STRLEN(cimi)) == 0)
|
|
x++;
|
|
*imsi = strdup(argv[x]);
|
|
free_results(argv);
|
|
}
|
|
closetty(port, fd);
|
|
}
|
|
|
|
return *manu || *model || *imei || *imsi;
|
|
}
|
|
|
|
#/* */
|
|
int discovery_all(dev_list_t * devs)
|
|
{
|
|
struct dev_descr * dev;
|
|
|
|
AST_LIST_TRAVERSE(devs, dev, entry) {
|
|
if(dev->interfaceno == 0) {
|
|
char * manu, * model, * imei, * imsi;
|
|
fprintf(stdout, "Bus: %d Dev: %s Conf: %d\n", dev->busnum, dev->devpath, dev->configuration);
|
|
if(get_info(dev->port, &manu, &model, &imei, &imsi)) {
|
|
fprintf(stdout, "Manufacturer: %s Model: %s IMEI: %s IMSI: %s\n", manu, model, imei, imsi);
|
|
free(manu);
|
|
free(model);
|
|
free(imei);
|
|
free(imsi);
|
|
}
|
|
}
|
|
fprintf(stdout, "\tInterface: %d Port: %s\n", dev->interfaceno, dev->port);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* /sys/bus/usb/drivers/option
|
|
* 1-1:1.0
|
|
* 1-1:1.1
|
|
* 1-1:1.2
|
|
*
|
|
*/
|
|
|
|
#/* */
|
|
void discovery_driver(const char * driver)
|
|
{
|
|
char realname[PATH_MAX];
|
|
char name[PATH_MAX];
|
|
char * name2;
|
|
DIR * dir;
|
|
struct dirent * entry;
|
|
int len;
|
|
dev_list_t devs;
|
|
|
|
len = snprintf(name, sizeof(name), "%s/%s", sys_driver, driver);
|
|
dir = opendir(name);
|
|
if(dir) {
|
|
while((entry = readdir(dir)) != NULL) {
|
|
struct dev_descr * descr = malloc(sizeof(*descr));
|
|
/* check numbers */
|
|
// if(entry->d_type == && sscanf(entry->d_name, "%u:%u-%u:%u", &id1, &id2, &id3, &id4) == 4)
|
|
if(sscanf(entry->d_name, "%d-%39[^:]:%d.%d", &descr->busnum, descr->devpath, &descr->configuration, &descr->interfaceno) == 4)
|
|
{
|
|
// fprintf(stdout, "device %s\n", entry->d_name);
|
|
snprintf(name + len, sizeof(name) - len, "/%s", entry->d_name);
|
|
|
|
if(realpath(name, realname) != NULL)
|
|
name2 = realname;
|
|
else {
|
|
name2 = name;
|
|
}
|
|
|
|
if(discovery_port(descr, name2)) {
|
|
AST_LIST_INSERT_TAIL(&devs, descr, entry);
|
|
continue;
|
|
}
|
|
}
|
|
free(descr);
|
|
}
|
|
closedir(dir);
|
|
}
|
|
|
|
discovery_all(&devs);
|
|
}
|
|
|
|
#/* */
|
|
int main(int argc, char * argv[])
|
|
{
|
|
int arg;
|
|
|
|
discovery_driver("option");
|
|
for(arg = 1; arg < argc; ++arg)
|
|
discovery_driver(argv[arg]);
|
|
return 0;
|
|
}
|