#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#ifdef HPI_OS_LINUX
#include <unistd.h>
#endif
#include <getopt.h>
#ifdef __APPLE__
#include <hpi/hpidebug.h>
#else
#include <hpidebug.h>
#endif
#define verbose_printf if (opt_verbose) printf
#define nanosec 1000000
static void HandleErrorComment(
const char *comment,
hpi_err_t err);
static void HandleErrorCommentContinue(
const char *comment,
hpi_err_t err);
static int getch(void);
static void asi_sleep(unsigned int milliseconds);
"invalid",
"AM",
"FM",
"NTSC_M",
"FM2",
"Aux",
"PAL_BG",
"PAL_I",
"PAL_DK",
"Secam_L",
"DAB"
};
static int keep_looping = 1;
static uint16_t opt_adapter_index = 0;
static uint16_t opt_tuner_index = 0;
static uint16_t opt_band = 0;
static uint32_t opt_tuner_frequency = 0;
static uint32_t opt_dab_poll = 0;
static short opt_rss_mode = -1;
static short opt_rds_mode = -1;
static int opt_query_tuner_caps = 0;
static int opt_query_tuner_settings = 0;
static int opt_verbose = 0;
static int opt_rds_poll_ms = 1000;
static int opt_rds_poll_loops = 0;
static short opt_mux_index = -1;
static uint32_t opt_serv = 0;
static uint16_t opt_comp = 0;
static struct option long_options[] = {
{"adapter", required_argument, 0, 'a'},
{"band", required_argument, 0, 'b'},
{"query-caps", no_argument, 0, 'c'},
{"frequency", required_argument, 0, 'f'},
{"rss-mode", required_argument, 0, 'm'},
{"rds-mode", required_argument, 0, 'n'},
{"rds-poll-ms", required_argument, 0, 'p'},
{"rds", optional_argument, 0, 'r'},
{"settings", no_argument, 0, 's'},
{"tuner", required_argument, 0, 't'},
{"verbose", no_argument, 0, 'v'},
{"mux", required_argument, 0, 'x'},
{"audio-service", no_argument, 0, 'y'},
{"help", no_argument, 0, 'h'},
{0, 0, 0, 0}
};
static const char *short_options = "a:b:cf:m:n:p:r::t:st:vx:y:h";
static const char *option_help[] = {
"<adapter number> to test, default is 0.",
"<band> see below for valid options",
"Query tuner capabilities.",
"<freq in kHz> tuner frequency",
"<mode> Set tuner RSS mode.",
"<mode> Set tuner RDS mode.",
"<milliseconds> Set RDS polling interval. Default 1000",
"[optional loop count] Reads RDS data from the tuner. Default 100 loops",
"Read back tuner settings.",
"<tuner index> to query or set, default is 0.",
"Enable verbose output.",
"<n> Set audio out mux to tuner",
"set DAB or HD audio service channel #",
"Show this text."
};
static void help(
void
)
{
int i = 0;
printf("\nUsage - asihpitune [options]\n");
while (long_options[i].name != 0) {
printf("--%s -%c %s\n",
long_options[i].name,
(char)(long_options[i].val), option_help[i]);
i++;
}
printf("Valid values for -b option are ");
printf("%s, ", band_names[i]);
printf("\n");
exit(0);
}
static void parse_options(
int argc,
char *argv[]
)
{
int c;
while (1) {
int option_index = 0;
c = getopt_long(argc, argv, short_options,
long_options, &option_index);
if (c == -1)
break;
switch (c) {
case 0:
printf("option %s", long_options[option_index].name);
if (optarg)
printf(" with arg %s", optarg);
printf("\n");
break;
case 'a':
opt_adapter_index = atoi(optarg);
break;
case 'b':
{
int i;
if (strcmp(band_names[i], optarg) ==
0)
opt_band = i;
if (!opt_band) {
printf("\n****** Invalid band: %s ******\n", optarg);
help();
}
opt_query_tuner_settings = 1;
}
break;
case 'c':
opt_query_tuner_caps = 1;
break;
case 'f':
opt_tuner_frequency = atoi(optarg);
opt_query_tuner_settings = 1;
break;
case 'm':
opt_rss_mode = atoi(optarg);
opt_query_tuner_settings = 1;
break;
case 'n':
opt_rds_mode = atoi(optarg);
opt_query_tuner_settings = 1;
break;
case 'p':
opt_rds_poll_ms = atoi(optarg);
if (!opt_rds_poll_loops)
opt_rds_poll_loops = 100;
break;
case 'r':
if (optarg)
opt_rds_poll_loops = atoi(optarg);
else
opt_rds_poll_loops = 100;
break;
case 's':
opt_query_tuner_settings = 1;
break;
case 't':
opt_tuner_index = atoi(optarg);
break;
case 'v':
opt_verbose = 1;
break;
case 'x':
opt_mux_index = atoi(optarg);
break;
case 'y':
opt_dab_poll = atoi(optarg);
break;
case '?':
case 'h':
help();
break;
default:
printf("?? getopt returned character code 0%o ??\n",
c);
}
}
if (optind < argc) {
char *endptr;
while ((optind < argc)) {
opt_serv = strtoll(argv[optind], &endptr, 0);
opt_comp = strtol(endptr+1, NULL, 0);
optind++;
}
}
}
uint32_t service_id,
uint16_t component_id,
)
{
int i;
int t = 20;
for (i = 0; i < 20; i++) {
service_id, component_id, component_info);
asi_sleep(t);
t += 20;
} else {
break;
}
}
return err;
}
uint32_t service_id,
uint16_t component_id,
int start
)
{
int i;
int t = 20;
service_id, component_id, start);
return err;
asi_sleep(t);
for (i = 0; i < 10; i++) {
service_id, component_id, start);
asi_sleep(t);
t += 20;
} else
break;
}
return err;
}
{
int c;
uint32_t sid;
char label[DAB_LABEL_LEN + 1];
if (err)
return err;
sid = dsi.id;
memcpy(label, dsi.label, DAB_LABEL_LEN);
label[DAB_LABEL_LEN] = 0;
printf("Service ID 0x%08X, name %s\n", sid, label);
for (c = 0; c < dsi.num_components; c++) {
uint16_t cid;
cid = dsi.components[c].id;
err = Tuner_GetDabComponentInfo(hTuner,
sid, cid, &dci);
if (err)
break;
memcpy(label, dci.label, DAB_LABEL_LEN);
label[DAB_LABEL_LEN] = 0;
printf("\tComponent ID 0x%04X, name '%s'\n", cid, label);
}
return err;
}
static void ProcessPacket(void* buffer, size_t data_len)
{
uint32_t sid, cid;
uint16_t packet_size;
printf("Received %4d byte packet from 0x%08X:0x%04X\n", packet_size, sid, cid);
}
{
char buffer[8192];
size_t packet_len;
int next_poll_ms;
while (keep_looping && opt_dab_poll) {
buffer, sizeof(buffer), &packet_len, &next_poll_ms);
if (!err) {
ProcessPacket(buffer, packet_len);
continue;
break;
}
asi_sleep(next_poll_ms);
opt_dab_poll--;
}
}
{
hpi_hsubsys_t *hSubSys = NULL;
uint32_t dwIndex;
uint16_t wSetting;
uint32_t dwStart, dwEnd, dwStep;
printf("\nTuner %d supports\n", opt_tuner_index);
for (dwIndex = 0; dwIndex < 100; dwIndex++) {
if (err)
break;
printf("Unknown band type %d\n", wSetting);
continue;
}
printf("%i %s : ", dwIndex, band_names[wSetting]);
(hSubSys, hTuner, 0, wSetting,
&dwStart);
(hSubSys, hTuner, 1, wSetting,
&dwEnd);
(hSubSys, hTuner, 2, wSetting,
&dwStep);
printf("from %ikHz to %ikHz step %ikHz\n", dwStart, dwEnd, dwStep);
}
}
{
hpi_hsubsys_t *hSubSys = NULL;
uint16_t nTunerBand = 0;
short int nRfLevel = 0;
uint32_t opt_tuner_frequency = 0;
uint32_t wMode = 0;
uint16_t wMuxIndex = 0;
uint16_t wStatus = 0;
uint16_t wStatusMask = 0;
uint32_t nAudioServices = 0;
uint32_t nCurrentService = 0;
uint32_t sid;
uint16_t cid;
int i = 0;
HandleErrorComment("Get Mux", err);
HandleErrorComment("HPI_Tuner_GetBand", err);
HandleErrorComment("HPI_Tuner_GetFrequency", err);
HandleErrorComment("HPI_Tuner_GetRFLevel", err);
HandleErrorComment("HPI_Multiplexer_GetSource", err);
HandleErrorComment("HPI_Tuner_GetStatus", err);
printf("Tuner %d:\nBand=%s band, frequency=%i. Mode=%d. RF level=%3.2fdBuV. Mux=%d\n",
opt_tuner_index, band_names[nTunerBand],
opt_tuner_frequency, wMode, nRfLevel / 100.0, wMuxIndex);
printf("Status mask=%08X, value=%08X\n", wStatusMask, wStatus);
if (nTunerBand == HPI_TUNER_BAND_DAB) {
char multiplex_name[20];
char audio_info[80];
printf("\nDAB info:\n");
for (i = 0; i < 20; i++) {
&nCurrentService, &nAudioServices);
if (err)
break;
if (nAudioServices)
break;
asi_sleep(1000);
}
multiplex_name, sizeof(multiplex_name));
printf("Multiplex name: %s\n", multiplex_name );
printf("Number of Services=%d\n", nAudioServices);
if (opt_verbose)
for (i = 0 ; i < nAudioServices ; i++)
PrintDabServiceInfo(hTuner, i);
printf("Current Audio Service=0x%08X:0x%04X - %s\n", sid, cid, audio_info);
printf("\n");
}
verbose_printf("Tuner does not have MODEs.\n");
wMode = 0;
verbose_printf("TUNER_MODE_RSS not supported\n");
wMode = 0;
} else {
HandleErrorComment("HPI_Tuner_GetMode", err);
printf("TUNER_MODE_RSS %d\n", wMode);
}
verbose_printf("TUNER_MODE_RDS not supported\n");
wMode = 0;
} else {
HandleErrorComment("HPI_Tuner_GetMode", err);
printf("TUNER_MODE_RDS %d\n", wMode);
}
}
}
{
hpi_hsubsys_t *hSubSys = NULL;
unsigned int nRDSloopcount = opt_rds_poll_loops;
uint32_t dwPTY = 0, dwPI = 0;
HandleErrorComment("Get Tuner Control", err);
HandleErrorComment("HPI_MixerGetControl (HPI_CONTROL_PAD)", err);
if (err)
return;
while (--nRDSloopcount) {
printf("\nLoop - %d\n", nRDSloopcount);
if (opt_verbose) {
unsigned char aRDS[12];
if (!err) {
int i;
printf("RDS block data ");
for (i = 0; i < 12; i++)
printf("%u ", aRDS[i]);
printf("\n");
printf("PI from ^---^ = 0x%X\n",
aRDS[1] << 8 | aRDS[0]);
} else {
HandleErrorCommentContinue("HPI_Tuner_GetRDS", err);
}
}
if (!ecn) {
szPAD, sizeof(szPAD));
HandleErrorCommentContinue
("HPI_PAD_GetChannelName", ecn);
if (!ecn)
printf("ChannelName : %s\n", szPAD);
}
szPAD, sizeof(szPAD));
HandleErrorComment("HPI_PAD_GetArtist", err);
if (!err)
printf("Artist/RT : %s\n", szPAD);
szPAD, sizeof(szPAD));
HandleErrorComment("HPI_PAD_GetTitle", err);
if (!err)
printf("Title/PS : %s\n", szPAD);
if (!ec) {
szPAD, sizeof(szPAD));
HandleErrorCommentContinue
("HPI_PAD_GetComment", ec);
if (!ec)
printf("Comment/PS : %s\n", szPAD);
}
HandleErrorComment("HPI_PAD_GetProgramType", err);
if (!err) {
szPAD, sizeof(szPAD));
if (!err)
printf("PTY : %d, %s\n", dwPTY,
szPAD);
}
if (!epi) {
HandleErrorCommentContinue("HPI_PAD_GetRdsPI",
epi);
if (!epi)
printf("PI : 0x%X\n", dwPI);
}
asi_sleep(opt_rds_poll_ms);
}
}
static void sigHandler(int sig)
{
if (keep_looping)
keep_looping = 0;
else
exit(0);
}
int main(
int argc,
char *argv[]
)
{
hpi_hsubsys_t *hSubSys;
uint32_t dwVersion = 0;
int numAdapters = 0;
uint16_t wVersion;
uint32_t dwSerialNumber;
uint16_t wType;
uint16_t wNumOutStreams;
uint16_t wNumInStreams;
int i;
parse_options(argc, argv);
signal(SIGINT, sigHandler);
verbose_printf
("********************************************************************\n");
verbose_printf
("** asihpitune **\n");
verbose_printf("** HPI test code for tuners **\n");
verbose_printf
("********************************************************************\n");
printf("HPI_SubSysCreate\n");
if (hSubSys == NULL) {
printf("hSubSys==NULL\n");
exit(1);
}
HandleError(err);
verbose_printf("HPI_SubSysGetVersionEx=%d.%02d.%02d\n",
dwVersion >> 16, (dwVersion >> 8) & 0xff, dwVersion & 0xff);
HandleError(err);
verbose_printf("HPI_SubSysGetNumAdapters NumberAdapters=%d\n", numAdapters);
for (i = 0; i < numAdapters; i++) {
uint32_t dwAdapterIndex;
uint16_t wAdapterType;
i, &dwAdapterIndex, &wAdapterType);
verbose_printf("%d=ASI%4X\n", dwAdapterIndex, wAdapterType);
}
HandleError(err);
verbose_printf("HPI_AdapterClose \n");
HandleError(err);
verbose_printf("HPI_AdapterOpen \n");
&wNumOutStreams, &wNumInStreams, &wVersion, &dwSerialNumber, &wType);
HandleError(err);
verbose_printf("HPI_AdapterGetInfo\n");
verbose_printf("Adapter=ASI%4X Index=%d NumOutStreams=%d NumInStreams=%d S/N=%d Hw Version %c%d ",
wType, opt_adapter_index, wNumOutStreams, wNumInStreams,
dwSerialNumber, ((wVersion >> 3) & 0xf) + 'A',
wVersion & 0x7
);
if (opt_verbose) {
uint16_t major, minor;
&major, &minor);
HandleError(err);
verbose_printf("DSP code version %d.%02d.%02d\n", major >> 8,
major & 0xff, minor);
}
verbose_printf("HPI_MixerOpen: handle=%X\n", hMixer);
HandleError(err);
printf("\n");
if ((wType & 0xF000) != 0x8000) {
printf("Only ASI87xx, ASI8821 and ASI89xx adapters are supported/n");
goto close;
}
HandleErrorComment("Get Tuner Control", err);
if (err)
goto close;
HandleErrorComment("Get Mux", err);
if (opt_rss_mode >= 0) {
HandleErrorComment("SetMode RSS", err);
}
if (opt_rds_mode >= 0) {
HandleErrorComment("SetMode RDS", err);
}
if (hMux && (opt_mux_index >= 0) && (opt_mux_index < 8)) {
HandleErrorComment("Get mux ctrl", err);
HandleErrorComment("SetMuxSource", err);
}
if (opt_band) {
HandleErrorComment("SetBand", err);
}
if (opt_tuner_frequency) {
opt_tuner_frequency);
HandleErrorComment("SetFrequency", err);
}
asi_sleep(nanosec / 1000000);
if (opt_query_tuner_caps)
query_tuner_caps(hMixer, hTuner, opt_tuner_index);
if (opt_query_tuner_settings)
query_tuner_settings(hMixer, hTuner, opt_tuner_index);
if (opt_rds_poll_loops)
poll_rds(hMixer, hTuner, opt_tuner_index);
if (opt_band == HPI_TUNER_BAND_DAB) {
if (opt_serv && opt_comp) {
printf("Start DAB service 0x%X:0x%X\n", opt_serv, opt_comp);
err = Tuner_SetDabService(hTuner, opt_serv, opt_comp,
HPI_SWITCH_ON);
HandleError(err);
}
if (opt_dab_poll)
poll_dab(hTuner);
if (opt_serv && opt_comp) {
printf("Stop DAB service 0x%X:0x%X\n", opt_serv, opt_comp);
err = Tuner_SetDabService(hTuner, opt_serv, opt_comp,
HPI_SWITCH_OFF);
HandleError(err);
}
}
close:
verbose_printf("\nHPI_MixerClose\n");
HandleError(err);
verbose_printf("HPI_AdapterClose\n");
HandleError(err);
printf("\nNormal exit\n");
return 0;
}
static void HandleErrorCommentContinue(
const char *comment,
hpi_err_t err)
{
char szError[256];
if (err) {
printf("\t\t%s\n", comment);
HPI_GetErrorText(err, szError);
printf("\t\tERROR %s\n", szError);
}
}
{
char szError[256];
char nK = 0;
if (err) {
HPI_GetErrorText(err, szError);
printf("ERROR %d %s\n", err, szError);
printf("\tpress Enter to continue, (q,Enter) to exit...\n");
nK = getch();
if (nK == 'q')
exit(0);
}
}
static void HandleErrorComment(
const char *comment,
hpi_err_t err)
{
if (err)
printf("%s ", comment);
HandleError(err);
}
static int getch(void)
{
return getchar();
}
static void asi_sleep(unsigned int milliseconds)
{
#if defined(HPI_OS_LINUX) || defined(__APPLE__)
struct timespec req =
{ milliseconds / 1000, (milliseconds % 1000) * 1000000 };
nanosleep(&req, 0);
#else
Sleep(milliseconds);
#endif
}