int main(int argc, char *argv[]) { spectool_device_list list; int x = 0, r = 0; spectool_sample_sweep *sb; spectool_server sr; char errstr[SPECTOOL_ERROR_MAX]; int ret; spectool_phy *pi; static struct option long_options[] = { { "net", required_argument, 0, 'n' }, { "broadcast", no_argument, 0, 'b' }, { "list", no_argument, 0, 'l' }, { "range", required_argument, 0, 'r' }, { "help", no_argument, 0, 'h' }, { 0, 0, 0, 0 } }; int option_index; char *neturl = NULL; char bcasturl[SPECTOOL_NETCLI_URL_MAX]; int bcastlisten = 0; int bcastsock; int list_only = 0; ndev = spectool_device_scan(&list); int *rangeset = NULL; if (ndev > 0) { rangeset = (int *) malloc(sizeof(int) * ndev); memset(rangeset, 0, sizeof(int) * ndev); } while (1) { int o = getopt_long(argc, argv, "n:bhr:l", long_options, &option_index); if (o < 0) break; if (o == 'h') { Usage(); return; } else if (o == 'b') { bcastlisten = 1; } else if (o == 'n') { neturl = strdup(optarg); printf("debug - spectool_raw neturl %s\n", neturl); continue; } else if (o == 'l') { list_only = 1; } else if (o == 'r' && ndev > 0) { if (sscanf(optarg, "%d:%d", &x, &r) != 2) { if (sscanf(optarg, "%d", &r) != 1) { fprintf(stderr, "Invalid range, expected device#:range# " "or range#\n"); exit(-1); } else { rangeset[0] = r; } } else { if (x < 0 || x >= ndev) { fprintf(stderr, "Invalid range, no device %d\n", x); exit(-1); } else { rangeset[x] = r; } } } } signal(SIGINT, sighandle); if (list_only) { if (ndev <= 0) { printf("No spectool devices found, bailing\n"); exit(1); } printf("Found %d devices...\n", ndev); for (x = 0; x < ndev; x++) { printf("Device %d: %s id %u\n", x, list.list[x].name, list.list[x].device_id); for (r = 0; r < list.list[x].num_sweep_ranges; r++) { spectool_sample_sweep *ran = &(list.list[x].supported_ranges[r]); printf(" Range %d: \"%s\" %d%s-%d%s @ %0.2f%s, %d samples\n", r, ran->name, ran->start_khz > 1000 ? ran->start_khz / 1000 : ran->start_khz, ran->start_khz > 1000 ? "MHz" : "KHz", ran->end_khz > 1000 ? ran->end_khz / 1000 : ran->end_khz, ran->end_khz > 1000 ? "MHz" : "KHz", (ran->res_hz / 1000) > 1000 ? ((float) ran->res_hz / 1000) / 1000 : ran->res_hz / 1000, (ran->res_hz / 1000) > 1000 ? "MHz" : "KHz", ran->num_samples); } } exit(0); } if (bcastlisten) { printf("Initializing broadcast listen...\n"); if ((bcastsock = spectool_netcli_initbroadcast(SPECTOOL_NET_DEFAULT_PORT, errstr)) < 0) { printf("Error initializing bcast socket: %s\n", errstr); exit(1); } printf("Waiting for a broadcast server ID...\n"); } else if (neturl != NULL) { printf("Initializing network connection...\n"); if (spectool_netcli_init(&sr, neturl, errstr) < 0) { printf("Error initializing network connection: %s\n", errstr); exit(1); } if (spectool_netcli_connect(&sr, errstr) < 0) { printf("Error opening network connection: %s\n", errstr); exit(1); } printf("Connected to server, waiting for device list...\n"); } else if (neturl == NULL) { if (ndev <= 0) { printf("No spectool devices found, bailing\n"); exit(1); } printf("Found %d spectool devices...\n", ndev); for (x = 0; x < ndev; x++) { printf("Initializing WiSPY device %s id %u\n", list.list[x].name, list.list[x].device_id); pi = (spectool_phy *) malloc(SPECTOOL_PHY_SIZE); pi->next = devs; devs = pi; if (spectool_device_init(pi, &(list.list[x])) < 0) { printf("Error initializing WiSPY device %s id %u\n", list.list[x].name, list.list[x].device_id); printf("%s\n", spectool_get_error(pi)); exit(1); } if (spectool_phy_open(pi) < 0) { printf("Error opening WiSPY device %s id %u\n", list.list[x].name, list.list[x].device_id); printf("%s\n", spectool_get_error(pi)); exit(1); } spectool_phy_setcalibration(pi, 1); /* configure the default sweep block */ spectool_phy_setposition(pi, rangeset[x], 0, 0); } spectool_device_scan_free(&list); } /* Naive poll that doesn't use select() to find pending data */ while (1) { fd_set rfds; fd_set wfds; int maxfd = 0; struct timeval tm; FD_ZERO(&rfds); FD_ZERO(&wfds); pi = devs; while (pi != NULL) { if (spectool_phy_getpollfd(pi) >= 0) { FD_SET(spectool_phy_getpollfd(pi), &rfds); if (spectool_phy_getpollfd(pi) > maxfd) maxfd = spectool_phy_getpollfd(pi); } pi = pi->next; } if (neturl != NULL) { if (spectool_netcli_getpollfd(&sr) >= 0) { FD_SET(spectool_netcli_getpollfd(&sr), &rfds); if (spectool_netcli_getpollfd(&sr) > maxfd) maxfd = spectool_netcli_getpollfd(&sr); } if (spectool_netcli_getwritepend(&sr) > 0) { FD_SET(spectool_netcli_getwritefd(&sr), &wfds); if (spectool_netcli_getwritefd(&sr) > maxfd) maxfd = spectool_netcli_getwritefd(&sr); } } if (bcastlisten) { FD_SET(bcastsock, &rfds); if (bcastsock > maxfd) maxfd = bcastsock; } tm.tv_sec = 0; tm.tv_usec = 10000; if (select(maxfd + 1, &rfds, &wfds, NULL, &tm) < 0) { printf("spectool_raw select() error: %s\n", strerror(errno)); exit(1); } if (bcastlisten && FD_ISSET(bcastsock, &rfds)) { if (spectool_netcli_pollbroadcast(bcastsock, bcasturl, errstr) == 1) { printf("Saw broadcast for server %s\n", bcasturl); if (neturl == NULL) { neturl = strdup(bcasturl); if (spectool_netcli_init(&sr, neturl, errstr) < 0) { printf("Error initializing network connection: %s\n", errstr); exit(1); } if (spectool_netcli_connect(&sr, errstr) < 0) { printf("Error opening network connection: %s\n", errstr); exit(1); } } } } if (neturl != NULL && spectool_netcli_getwritefd(&sr) >= 0 && FD_ISSET(spectool_netcli_getwritefd(&sr), &wfds)) { if (spectool_netcli_writepoll(&sr, errstr) < 0) { printf("Error write-polling network server %s\n", errstr); exit(1); } } ret = SPECTOOL_NETCLI_POLL_ADDITIONAL; while (neturl != NULL && spectool_netcli_getpollfd(&sr) >= 0 && FD_ISSET(spectool_netcli_getpollfd(&sr), &rfds) && (ret & SPECTOOL_NETCLI_POLL_ADDITIONAL)) { if ((ret = spectool_netcli_poll(&sr, errstr)) < 0) { printf("Error polling network server %s\n", errstr); exit(1); } if ((ret & SPECTOOL_NETCLI_POLL_NEWDEVS)) { spectool_net_dev *ndi = sr.devlist; while (ndi != NULL) { printf("Enabling network device: %s (%u)\n", ndi->device_name, ndi->device_id); pi = spectool_netcli_enabledev(&sr, ndi->device_id, errstr); pi->next = devs; devs = pi; ndi = ndi->next; } } } pi = devs; while (pi != NULL) { spectool_phy *di = pi; pi = pi->next; if (spectool_phy_getpollfd(di) < 0) { if (spectool_get_state(di) == SPECTOOL_STATE_ERROR) { printf("Error polling spectool device %s\n", spectool_phy_getname(di)); printf("%s\n", spectool_get_error(di)); exit(1); } continue; } if (FD_ISSET(spectool_phy_getpollfd(di), &rfds) == 0) { continue; } do { r = spectool_phy_poll(di); if ((r & SPECTOOL_POLL_CONFIGURED)) { printf("Configured device %u (%s)\n", spectool_phy_getdevid(di), spectool_phy_getname(di), di->device_spec->num_sweep_ranges); spectool_sample_sweep *ran = spectool_phy_getcurprofile(di); if (ran == NULL) { printf("Error - no current profile?\n"); continue; } printf(" %d%s-%d%s @ %0.2f%s, %d samples\n", ran->start_khz > 1000 ? ran->start_khz / 1000 : ran->start_khz, ran->start_khz > 1000 ? "MHz" : "KHz", ran->end_khz > 1000 ? ran->end_khz / 1000 : ran->end_khz, ran->end_khz > 1000 ? "MHz" : "KHz", (ran->res_hz / 1000) > 1000 ? ((float) ran->res_hz / 1000) / 1000 : ran->res_hz / 1000, (ran->res_hz / 1000) > 1000 ? "MHz" : "KHz", ran->num_samples); continue; } else if ((r & SPECTOOL_POLL_ERROR)) { printf("Error polling spectool device %s\n", spectool_phy_getname(di)); printf("%s\n", spectool_get_error(di)); exit(1); } else if ((r & SPECTOOL_POLL_SWEEPCOMPLETE)) { sb = spectool_phy_getsweep(di); if (sb == NULL) continue; printf("%s: ", spectool_phy_getname(di)); for (r = 0; r < sb->num_samples; r++) { // printf("[%d %d %d %d] ", sb->sample_data[r], sb->amp_offset_mdbm, sb->amp_res_mdbm, sb->sample_data[r] * (sb->amp_res_mdbm / 1000) + (sb->amp_offset_mdbm / 1000)); printf("%d ", SPECTOOL_RSSI_CONVERT(sb->amp_offset_mdbm, sb->amp_res_mdbm, sb->sample_data[r])); } printf("\n"); } } while ((r & SPECTOOL_POLL_ADDITIONAL)); } } return 0; }
int main(int argc, char *argv[]) { wispy_device_list list; int x = 0, r = 0, y = 0, ndev = 0; wispy_sample_sweep *sb = NULL; wispy_sweep_cache *sweepcache = NULL; spectool_server sr; char errstr[WISPY_ERROR_MAX]; int ret; WINDOW *window; WINDOW *sigwin; WINDOW *chwin; int graph_bg = 0, graph_peak = 0, graph_avg = 0; int amp_offset_mdbm = 0, amp_res_mdbm = 0, base_db_offset = 0; int min_db_draw = 0, start_db = 0; int nuse = 0, mod, avg, avgc, pos, group; int range = 0; int device = -1; int list_only = 0; static struct option long_options[] = { { "net", required_argument, 0, 'n' }, { "list", no_argument, 0, 'l' }, { "device", required_argument, 0, 'd' }, { "range", required_argument, 0, 'r' }, { "help", no_argument, 0, 'h' }, { 0, 0, 0, 0 } }; int option_index; char *neturl = NULL; ndev = wispy_device_scan(&list); while (1) { int o = getopt_long(argc, argv, "n:ld:r:h", long_options, &option_index); if (o < 0) break; if (o == 'h') { Usage(); return; } else if (o == 'n') { neturl = strdup(optarg); continue; } else if (o == 'r') { if (sscanf(optarg, "%d", &range) != 1) { printf("Expected number for range, see listing for supported ranges\n"); Usage(); return; } continue; } else if (o == 'd') { if (sscanf(optarg, "%d", &device) != 1) { printf("Expected number for device, see listing for detected devices\n"); Usage(); return; } if (device < 0 || device >= ndev) { printf("Device number invalid, see listing for detected devices\n"); Usage(); return; } continue; } else if (o == 'l') { list_only = 1; } } if (list_only) { if (ndev <= 0) { printf("No wispy devices found, bailing\n"); exit(1); } printf("Found %d devices...\n", ndev); for (x = 0; x < ndev; x++) { printf("Device %d: %s id %u\n", x, list.list[x].name, list.list[x].device_id); for (r = 0; r < list.list[x].num_sweep_ranges; r++) { wispy_sample_sweep *ran = &(list.list[x].supported_ranges[r]); printf(" Range %d: \"%s\" %d%s-%d%s @ %0.2f%s, %d samples\n", r, ran->name, ran->start_khz > 1000 ? ran->start_khz / 1000 : ran->start_khz, ran->start_khz > 1000 ? "MHz" : "KHz", ran->end_khz > 1000 ? ran->end_khz / 1000 : ran->end_khz, ran->end_khz > 1000 ? "MHz" : "KHz", (ran->res_hz / 1000) > 1000 ? ((float) ran->res_hz / 1000) / 1000 : ran->res_hz / 1000, (ran->res_hz / 1000) > 1000 ? "MHz" : "KHz", ran->num_samples); } } exit(0); } signal(SIGINT, sighandle); if (neturl != NULL) { printf("Initializing network connection...\n"); if (spectool_netcli_init(&sr, neturl, errstr) < 0) { printf("Error initializing network connection: %s\n", errstr); exit(1); } if (spectool_netcli_connect(&sr, errstr) < 0) { printf("Error opening network connection: %s\n", errstr); exit(1); } printf("Connected to server, waiting for device list...\n"); } else if (neturl == NULL) { if (ndev <= 0) { printf("No wispy devices found, bailing\n"); exit(1); } printf("Found %d wispy devices...\n", ndev); if (ndev > 1 && device == -1) { printf("spectool-curses can only display one device, specify one with " "spectool-curses -d\n"); exit(1); } else if (device == -1) { device = 0; } if (range < 0 || range >= list.list[device].num_sweep_ranges) { printf("Invalid range for device %d, see listing for supported ranges\n", device); exit(1); } dev = (wispy_phy *) malloc(WISPY_PHY_SIZE); dev->next = NULL; if (wispy_device_init(dev, &(list.list[device])) < 0) { printf("Error initializing WiSPY device %s id %u\n", list.list[device].name, list.list[device].device_id); printf("%s\n", wispy_get_error(dev)); exit(1); } if (wispy_phy_open(dev) < 0) { printf("Error opening WiSPY device %s id %u\n", list.list[device].name, list.list[device].device_id); printf("%s\n", wispy_get_error(dev)); exit(1); } wispy_phy_setcalibration(dev, 1); /* Configure the range */ wispy_phy_setposition(dev, range, 0, 0); wispy_device_scan_free(&list); } sweepcache = wispy_cache_alloc(50, 1, 1); /* Fire up curses */ initscr(); start_color(); cbreak(); noecho(); init_pair(1, COLOR_BLACK, COLOR_BLACK); init_pair(2, COLOR_BLUE, COLOR_BLUE); init_pair(3, COLOR_GREEN, COLOR_GREEN); init_pair(4, COLOR_YELLOW, COLOR_BLACK); init_pair(5, COLOR_YELLOW, COLOR_BLUE); init_pair(6, COLOR_YELLOW, COLOR_GREEN); window = subwin(stdscr, LINES - 2, COLS - 5, 0, 5); sigwin = subwin(stdscr, LINES - 2, 5, 0, 0); box(window, 0, 0); mvwaddstr(sigwin, 0, 0, " dBm "); wrefresh(window); wrefresh(sigwin); refresh(); /* Naive poll that doesn't use select() to find pending data */ while (1) { fd_set rfds; fd_set wfds; int maxfd = 0; struct timeval tm; FD_ZERO(&rfds); FD_ZERO(&wfds); if (wispy_phy_getpollfd(dev) >= 0) { FD_SET(wispy_phy_getpollfd(dev), &rfds); if (wispy_phy_getpollfd(dev) > maxfd) maxfd = wispy_phy_getpollfd(dev); } if (neturl != NULL) { if (spectool_netcli_getpollfd(&sr) >= 0) { FD_SET(spectool_netcli_getpollfd(&sr), &rfds); if (spectool_netcli_getpollfd(&sr) > maxfd) maxfd = spectool_netcli_getpollfd(&sr); } if (spectool_netcli_getwritepend(&sr) > 0) { FD_SET(spectool_netcli_getwritefd(&sr), &wfds); if (spectool_netcli_getwritefd(&sr) > maxfd) maxfd = spectool_netcli_getwritefd(&sr); } } tm.tv_sec = 0; tm.tv_usec = 10000; if (select(maxfd + 1, &rfds, &wfds, NULL, &tm) < 0) { printf("wispy_raw select() error: %s\n", strerror(errno)); exit(1); } if (spectool_netcli_getwritefd(&sr) >= 0 && FD_ISSET(spectool_netcli_getwritefd(&sr), &wfds)) { if (spectool_netcli_writepoll(&sr, errstr) < 0) { printf("Error write-polling network server %s\n", errstr); exit(1); } } ret = SPECTOOL_NETCLI_POLL_ADDITIONAL; while (spectool_netcli_getpollfd(&sr) >= 0 && FD_ISSET(spectool_netcli_getpollfd(&sr), &rfds) && (ret & SPECTOOL_NETCLI_POLL_ADDITIONAL)) { if ((ret = spectool_netcli_poll(&sr, errstr)) < 0) { printf("Error polling network server %s\n", errstr); exit(1); } if ((ret & SPECTOOL_NETCLI_POLL_NEWDEVS)) { /* Only enable the first device */ spectool_net_dev *ndi = sr.devlist; dev = spectool_netcli_enabledev(&sr, ndi->device_id, errstr); } } if (wispy_phy_getpollfd(dev) < 0) { if (wispy_get_state(dev) == WISPY_STATE_ERROR) { printf("Error polling wispy device %s\n", wispy_phy_getname(dev)); printf("%s\n", wispy_get_error(dev)); exit(1); } } if (FD_ISSET(wispy_phy_getpollfd(dev), &rfds) == 0) { continue; } do { r = wispy_phy_poll(dev); if ((r & WISPY_POLL_CONFIGURED)) { wispy_sample_sweep *ran = &(dev->device_spec->supported_ranges[0]); amp_offset_mdbm = ran->amp_offset_mdbm; amp_res_mdbm = ran->amp_res_mdbm; base_db_offset = WISPY_RSSI_CONVERT(amp_offset_mdbm, amp_res_mdbm, ran->rssi_max); min_db_draw = WISPY_RSSI_CONVERT(amp_offset_mdbm, amp_res_mdbm, 0); continue; } else if ((r & WISPY_POLL_ERROR)) { printf("Error polling wispy device %s\n", wispy_phy_getname(dev)); printf("%s\n", wispy_get_error(dev)); exit(1); } else if ((r & WISPY_POLL_SWEEPCOMPLETE)) { sb = wispy_phy_getsweep(dev); if (sb == NULL) continue; wispy_cache_append(sweepcache, sb); min_db_draw = WISPY_RSSI_CONVERT(amp_offset_mdbm, amp_res_mdbm, sb->min_rssi_seen > 2 ? sb->min_rssi_seen - 1 : sb->min_rssi_seen); } } while ((r & WISPY_POLL_ADDITIONAL)); /* Redraw the windows */ werase(sigwin); mvwaddstr(sigwin, 0, 0, " dBm "); start_db = 0; for (x = base_db_offset - 1; x > min_db_draw; x--) { if (x % 10 == 0) { start_db = 0; break; } } if (start_db == 0) start_db = base_db_offset; for (x = start_db; x > min_db_draw; x -= 10) { int py; py = (float) (LINES - 4) * (float) ((float) (abs(x) + base_db_offset) / (float) (abs(min_db_draw) + base_db_offset)); snprintf(errstr, WISPY_ERROR_MAX, "%d", x); mvwaddstr(sigwin, py + 1, 0, errstr); } werase(window); if (sweepcache->latest == NULL) { wrefresh(window); wrefresh(sigwin); refresh(); continue; } /* Interpolate the data down into an appropriate graph */ mod = ceilf((float) sweepcache->avg->num_samples / (float) (COLS - 7)); group = mod * 2; r = 0; for (x = 0; x < (COLS - 7); x++) { int py, pyc; avg = 0; avgc = 0; nuse = 0; r = ((float) x / (float) (COLS - 7)) * (float) sweepcache->peak->num_samples; for (pos = -1 * (group / 2); pos < (group / 2); pos++) { if (r + pos >= sweepcache->peak->num_samples || r + pos < 0) continue; avg += sweepcache->peak->sample_data[r + pos]; avgc += sweepcache->latest->sample_data[r + pos]; nuse++; } if (nuse == 0) continue; avg = WISPY_RSSI_CONVERT(amp_offset_mdbm, amp_res_mdbm, (avg / nuse)); avgc = WISPY_RSSI_CONVERT(amp_offset_mdbm, amp_res_mdbm, (avgc / nuse)); py = (float) (LINES - 4) * (float) ((float) (abs(avg) + base_db_offset) / (float) (abs(min_db_draw) + base_db_offset)); pyc = (float) (LINES - 4) * (float) ((float) (abs(avgc) + base_db_offset) / (float) (abs(min_db_draw) + base_db_offset)); for (y = 0; y < (LINES - 4); y++) { if (pyc == y) { if (py > y) wcolor_set(window, 4, NULL); else wcolor_set(window, 5, NULL); mvwaddstr(window, y + 1, x + 1, "#"); continue; } if (py > y) continue; wcolor_set(window, 2, NULL); mvwaddstr(window, y + 1, x + 1, " "); } } r = 0; for (x = 0; x < (COLS - 7); x++) { int py, pyc; avg = 0; avgc = 0; nuse = 0; r = ((float) x / (float) (COLS - 7)) * (float) sweepcache->avg->num_samples; for (pos = -1 * (group / 2); pos < (group / 2); pos++) { if (r + pos >= sweepcache->avg->num_samples || r + pos < 0) continue; avg += sweepcache->avg->sample_data[r + pos]; avgc += sweepcache->latest->sample_data[r + pos]; nuse++; } if (nuse == 0) continue; avg = WISPY_RSSI_CONVERT(amp_offset_mdbm, amp_res_mdbm, (avg / nuse)); avgc = WISPY_RSSI_CONVERT(amp_offset_mdbm, amp_res_mdbm, (avgc / nuse)); py = (float) (LINES - 4) * (float) ((float) (abs(avg) + base_db_offset) / (float) (abs(min_db_draw) + base_db_offset)); pyc = (float) (LINES - 4) * (float) ((float) (abs(avgc) + base_db_offset) / (float) (abs(min_db_draw) + base_db_offset)); for (y = 0; y < (LINES - 4); y++) { if (pyc == y && y >= py) { wcolor_set(window, 6, NULL); mvwaddstr(window, y + 1, x + 1, "#"); continue; } if (py > y) continue; wcolor_set(window, 3, NULL); mvwaddstr(window, y + 1, x + 1, "m"); } } wcolor_set(window, 0, NULL); box(window, 0, 0); wrefresh(window); wrefresh(sigwin); refresh(); } endwin(); return 0; }