$OpenBSD: patch-src_wmtune_c,v 1.5 2003/03/28 22:39:10 david Exp $ --- src/wmtune.c.orig Sat Sep 11 11:49:24 1999 +++ src/wmtune.c Fri Sep 27 21:22:11 2002 @@ -18,102 +18,74 @@ **************************************************************** */ -#if !defined Linux -# if (defined NetBSD || defined OpenBSD) -# warning Compiling for NetBSD/OpenBSD using /dev/io style IO. -# include -# else -# if defined FreeBSD -# warning Compiling for FreeBSD using /dev/io style IO. -# include -# endif -# endif -#else -# warning Compiling for Linux using ioperm/iopl style IO. -# include -#endif - -#include +#include +#include #include +#include #include +#include #include -#include -#include +#ifdef ZOLTRIX +#include +#include +#include +#else +#include +#include +#endif /* ZOLTRIX */ -#include +#include #include "wmgeneral/wmgeneral.h" #include "wmtune-master.xpm" #include "wmtune-mask.xbm" -// Defines -#define VERSION "1.0" -#define RCFILE "wmtunerc" -#define LIMBO 3 -#define ON 1 -#define OFF 0 -#define TRUE 1 -#define FALSE 0 -#define FCODE(f) ((int)(((float)(f)-88.0)*40)+0xf6c) - -/* #define RADIOTRACK */ -/* #define KERNEL */ -/* #define ZOLTRIX */ - -#ifdef KERNEL - /* Kernel driver support */ - #include - #include - #include +/* Defines */ +const char *VERSION = "1.2-OpenBSD" +#ifdef ZOLTRIX + "-zoltrix" #endif +; +const char *RCFILE = "wmtunerc"; +#define TMPBUFLEN 128 +#define LIMBO 3 +#define ON 1 +#define OFF 0 +#define TRUE 1 +#define FALSE 0 + +/* Data Types */ +unsigned int max_presets; +unsigned int hour, minute; +struct tm *time_struct; +long current_time; + +int preset_count = 1; +int cmdline_preset = OFF; +int radio_status = OFF; +int auto_radio_on = OFF; +int auto_alarm_start = OFF; + +int volume = 0; + +struct presets_t { + double freq; +} *presets; -#if (defined FreeBSD || defined NetBSD || defined OpenBSD) - #define OUTW(word,port) outw(port,word) - #define OUTB(byte,port) outb(port,byte) +#ifdef ZOLTRIX +unsigned long iomap[32]; +struct i386_set_ioperm_args ioperms; +unsigned int rport = 0x000; #else - #define OUTW(word,port) outw(word,port) - #define OUTB(byte,port) outb(byte,port) -#endif - -// Data Types -#if (defined FreeBSD || defined NetBSD || defined OpenBSD) - int fpiopl; -#endif - - unsigned int max_presets; - unsigned int hour=0,minute=0; - - struct tm *time_struct; - long current_time; - - unsigned int rport=0x000; - double freqf=0.0; - int volume = 0; - - char *myname; - char temp[128]; - - int i; +int VOLUME_STEP; +static struct radio_info ri; +char *radiodevice = NULL; +#endif /* ZOLTRIX */ - XEvent Event; - - int but_stat=-1; - int but_timer=0; - - int auto_radio_on = OFF; - int auto_alarm_start = OFF; - int cmdline_preset = OFF; - int preset_count=1; - int radio_status=OFF; - int alarm_state=0; - -struct { double freq; } *presets; - -// Functions -void ParseCMDLine(int argc, char *argv[]); +/* Functions */ +void ParseCMDLine(int, char **); int ParseRCFile(char *); -void CheckIOPerms(void); void RadioOff(void); void RadioOn(void); void DrawDigitalFreq(void); @@ -127,7 +99,6 @@ void VolumeUp(void); void VolumeDown(void); void TuneUp(void); void TuneDown(void); -void RadioOut(int, int); void PresetHandler(int); void ScanUp(void); void ScanDown(void); @@ -137,333 +108,262 @@ void FastFreqUpdate(void); void TuneRadio(void); int TestTune(void); void TestFreq(void); +void usage(void); + #ifdef ZOLTRIX -void tuneFreq(double freq,int fast); +void tuneFreq(double, int); +void CheckIOPerms(void); +void goroot(void); +void gouser(void); +inline int cardRead(int); +inline void cardWrite(int); +#else +int SetGetRadioInfo(int); +void GetVolumeStep(void); #endif -// Main -void main(int argc,char *argv[]) -{ - myname = argv[0]; - ParseCMDLine(argc,argv); +int main(int argc,char **argv) { + char temp[TMPBUFLEN]; + char *home; + XEvent Event; + int but_stat = -1; + int but_timer = 0; + int alarm_state = 0; + int i = 0; - strcpy(temp,(char*)getenv("HOME")); - strcat(temp,"/."); - strcat(temp,RCFILE); - if (ParseRCFile(temp) == 1) - { - strcpy(temp, "/etc/"); - strcat(temp, RCFILE); +#ifdef ZOLTRIX + /* Drop privileges */ + gouser(); +#endif /* ZOLTRIX */ + + ParseCMDLine(argc, argv); + + home = getenv("HOME"); + if (home == NULL) + home = "."; + strlcpy(temp, home, TMPBUFLEN); + strlcat(temp, "/.", TMPBUFLEN); + strlcat(temp, RCFILE, TMPBUFLEN); + + if (ParseRCFile(temp) == 1) { + strlcpy(temp, "/etc/", TMPBUFLEN); + strlcat(temp, RCFILE, TMPBUFLEN); if (ParseRCFile(temp) == 1) - { - fprintf(stderr,"User(~/.%s) or global(/etc/%s) configuration files not found.\n",RCFILE,RCFILE); - exit(1); - } + errx(1, "~/.%s or /etc/%s configuration files not found", RCFILE, RCFILE); } -#ifndef KERNEL +#ifdef ZOLTRIX CheckIOPerms(); +#else + if (SetGetRadioInfo(RIOCGINFO) < 0) + errx(1, "Cannot manage the FM tuner"); + GetVolumeStep(); #endif + if (cmdline_preset == ON) - { - if (!(preset_count <= max_presets && preset_count >= 1)) - { - fprintf(stderr,"Selected preset number is not valid in your %s file.\n",RCFILE); - exit(1); - } - } + if (preset_count > max_presets || preset_count < 1) + errx(1, "Selected preset number is not valid in your %s file", RCFILE); - freqf = presets[preset_count].freq; + presets[0].freq = presets[preset_count].freq; openXwindow(argc,argv,wmtune_master_xpm,wmtune_mask_bits, wmtune_mask_width,wmtune_mask_height); - AddMouseRegion(0,47,48,59,59); // ON/OFF BUTTON - AddMouseRegion(1,5,35,16,44); // FINE TUNE UP (+) - AddMouseRegion(2,16,35,27,44); // FINE TUNE DOWN (-) - AddMouseRegion(3,27,35,38,44); // SCAN UP - AddMouseRegion(4,38,35,49,44); // SCAN DOWN - AddMouseRegion(5,49,35,59,44); // ALARM BUTTON - AddMouseRegion(6,23,48,35,59); // LEFT PRESET SCAN BUTTON - AddMouseRegion(7,35,48,47,59); // RIGHT PRESET SCAN BUTTON + AddMouseRegion(0, 47, 48, 59, 59); /* ON/OFF BUTTON */ + AddMouseRegion(1, 5, 35, 16, 44); /* FINE TUNE UP (+) */ + AddMouseRegion(2, 16, 35, 27, 44); /* FINE TUNE DOWN (-) */ + AddMouseRegion(3, 27, 35, 38, 44); /* SCAN UP */ + AddMouseRegion(4, 38, 35, 49, 44); /* SCAN DOWN */ + AddMouseRegion(5, 49, 35, 59, 44); /* ALARM BUTTON */ + AddMouseRegion(6, 23, 48, 35, 59); /* LEFT PRESET SCAN BUTTON */ + AddMouseRegion(7, 35, 48, 47, 59); /* RIGHT PRESET SCAN BUTTON */ - if (auto_alarm_start == ON) - { + if (auto_alarm_start == ON) { alarm_state = ON; DrawDigitalTime(hour,minute); - copyXPMArea(117, 70, 5, 6, 6, 23); // Light On + copyXPMArea(117, 70, 5, 6, 6, 23); /* Light On */ usleep(300000L); RedrawWindow(); } - if (auto_radio_on == ON) - { + if (auto_radio_on == ON) { RadioOn(); RedrawWindow(); } -while (1) -{ - while (XPending(display)) - { - XNextEvent(display, &Event); - switch (Event.type) - { + while (1) { + while (XPending(display)) { + XNextEvent(display, &Event); + switch (Event.type) { case Expose: RedrawWindow(); - break; + break; case DestroyNotify: XCloseDisplay(display); - #if (defined FreeBSD || defined NetBSD || defined OpenBSD) - close(fpiopl); - #else - #ifdef RADIOTRACK - ioperm(rport,2,0); - #elif defined ZOLTRIX - ioperm(rport,4,0); - #endif - #endif +#ifdef ZOLTRIX + goroot(); + + memset(iomap, 0xFFFF, sizeof(iomap)); + ioperms.iomap = iomap; + sysarch(I386_SET_IOPERM, (char *)&ioperms); + + gouser(); +#endif /* NATIVE */ exit(0); - break; + break; case ButtonPress: i = CheckMouseRegion(Event.xbutton.x, Event.xbutton.y); - switch (i) - { - case 0: // ON/OFF BUTTON - ButtonDown(0); - break; - case 1: // FINE TUNE UP (+) - ButtonDown(1); - but_timer = 0; - break; - case 2: // FINE TUNE DOWN (-) - ButtonDown(2); - but_timer = 0; - break; - case 3: // SCAN UP - ButtonDown(3); - but_timer = 0; - break; - case 4: // SCAN DOWN - ButtonDown(4); - but_timer = 0; - break; - case 5: // ALARM BUTTON - ButtonDown(5); - break; - case 6: // LEFT PRESET SCAN BUTTON - ButtonDown(6); - break; - case 7: // RIGHT PRESET SCAN BUTTON - ButtonDown(7); - break; - } + ButtonDown(i); + if (i > 0 && i < 5) + but_timer = 0; but_stat = i; - break; + break; case ButtonRelease: - switch (but_stat) - { - case 0: // ON/OFF BUTTON - ButtonUp(0); - break; - case 1: // FINE TUNE UP (+) - ButtonUp(1); - break; - case 2: // FINE TUNE DOWN (-) - ButtonUp(2); - break; - case 3: // SCAN UP - ButtonUp(3); - break; - case 4: // SCAN DOWN - ButtonUp(4); - break; - case 5: // ALARM BUTTON - ButtonUp(5); - break; - case 6: // LEFT PRESET SCAN BUTTON - ButtonUp(6); - break; - case 7: // RIGHT PRESET SCAN BUTTON - ButtonUp(7); - break; - } - if (i == but_stat && but_stat >= 0) - { - if (radio_status == OFF || alarm_state == LIMBO) - { - if (alarm_state == LIMBO) - { - switch (i) - { - case 3: // TIME UP - if (!(but_timer >= 5)) - { - TimeUp(); - } - break; - case 4: // TIME DOWN - if (!(but_timer >= 5)) - { - TimeDown(); + ButtonUp(but_stat); + if (i == but_stat && but_stat >= 0) { + if (radio_status == OFF || + alarm_state == LIMBO) { + if (alarm_state == LIMBO) { + switch (i) { + case 3: // TIME UP + if (!(but_timer >= 5)) + TimeUp(); + break; + case 4: // TIME DOWN + if (!(but_timer >= 5)) + TimeDown(); + break; + case 5: // ALARM BUTTON SET + alarm_state = ON; + copyXPMArea(117, 70, 5, 6, 6, 23); // Light On + RedrawWindowXYWH(6, 23, 5, 6); + break; } - break; - case 5: // ALARM BUTTON SET - alarm_state = ON; - copyXPMArea(117, 70, 5, 6, 6, 23); // Light On - RedrawWindowXYWH(6, 23, 5, 6); - break; - } - } - else - { - switch (i) - { - case 0: - RadioOn(); - break; - } - } - but_stat = -1; - } - else - { - switch (i) - { - case 0: // ON/OFF BUTTON - RadioOff(); - break; - case 1: // FINE TUNE UP (+) + } else { + if (i == 0) + RadioOn(); + } + but_stat = -1; + } else { + switch (i) { + case 0: // ON/OFF BUTTON + RadioOff(); + break; + case 1: // FINE TUNE UP (+) if (!(but_timer >= 5)) - { TuneUp(); - } OnPreset(); FastFreqUpdate(); TestFreq(); - break; - case 2: // FINE TUNE DOWN (-) + break; + case 2: // FINE TUNE DOWN (-) if (!(but_timer >= 5)) - { TuneDown(); - } OnPreset(); FastFreqUpdate(); TestFreq(); - break; - case 3: // SCAN UP - switch (Event.xbutton.button) - { - case 1: - ScanUp(); - OnPreset(); + break; + case 3: // SCAN UP + switch (Event.xbutton.button) { + case 1: + ScanUp(); + OnPreset(); break; - case 3: - VolumeUp(); + case 3: + VolumeUp(); break; } - break; - case 4: // SCAN DOWN - switch (Event.xbutton.button) - { - case 1: - ScanDown(); - OnPreset(); + break; + case 4: // SCAN DOWN + switch (Event.xbutton.button) { + case 1: + ScanDown(); + OnPreset(); break; - case 3: - VolumeDown(); + case 3: + VolumeDown(); break; } - break; - case 5: // ALARM BUTTON - if (alarm_state == ON) - { + break; + case 5: // ALARM BUTTON + if (alarm_state == ON) { alarm_state = OFF; copyXPMArea(76, 55, 34, 7, 6, 22); RedrawWindowXYWH(6, 22, 34, 7); - } - else - { + } else { alarm_state = LIMBO; DrawDigitalTime(hour,minute); } - break; - case 6: // LEFT PRESET SCAN BUTTON + break; + case 6: // LEFT PRESET SCAN BUTTON PresetHandler(-1); - break; - case 7: // RIGHT PRESET SCAN BUTTON + break; + case 7: // RIGHT PRESET SCAN BUTTON PresetHandler(1); - break; + break; } } - but_stat = -1; + but_stat = -1; + } } - } - } - if (((i == but_stat && but_stat >= 0)) && (radio_status == ON)) - { - but_timer++; - if(but_timer >= 5) - { - if (alarm_state == LIMBO) - { - switch (i) - { - case 3: // TIME UP, AUTO-REPEAT + } + if (((i == but_stat && but_stat >= 0)) && (radio_status == ON)) { + but_timer++; + if(but_timer >= 5) { + if (alarm_state == LIMBO) { + switch (i) { + case 3: // TIME UP, AUTO-REPEAT TimeUp(); - break; - case 4: // TIME DOWN, AUTO-REPEAT + break; + case 4: // TIME DOWN, AUTO-REPEAT TimeDown(); - break; - } - } - else - { - switch (i) - { - case 1: // FINE TUNE UP (+) AUTO-REPEAT + break; + } + } else { + switch (i) { + case 1: // FINE TUNE UP (+) AUTO-REPEAT TuneUp(); - break; - case 2: // FINE TUNE DOWN (-) AUTO-REPEAT + break; + case 2: // FINE TUNE DOWN (-) AUTO-REPEAT TuneDown(); - break; - } - } - } - } - usleep(5000); - if (alarm_state == ON) - { - current_time = time(0); - time_struct = localtime(¤t_time); - if(hour == time_struct->tm_hour); - { - if (minute == time_struct->tm_min) - { - alarm_state = OFF; - copyXPMArea(76, 55, 34, 7, 6, 22); - RedrawWindowXYWH(6, 22, 34, 7); - if (radio_status == ON) - { - RadioOff(); + break; + } } - else - { - RadioOn(); + } + } + usleep(5000); + if (alarm_state == ON) { + current_time = time(NULL); + time_struct = localtime((time_t *)¤t_time); + if(hour == time_struct->tm_hour) { + if (minute == time_struct->tm_min) { + alarm_state = OFF; + copyXPMArea(76, 55, 34, 7, 6, 22); + RedrawWindowXYWH(6, 22, 34, 7); + if (radio_status == ON) + RadioOff(); + else + RadioOn(); } - } - } - } -} // while -} // main + } + } + } /* while */ + + return 0; +} /* main */ void RadioOn(void) { radio_status = ON; + + if (volume == 0) + volume = 1; + copyXPMArea(93, 90, 13, 5, 44, 9); - RedrawWindowXYWH(44, 9, 13, 5); // Mhz/Khz + RedrawWindowXYWH(44, 9, 13, 5); /* MHz/KHz */ copyXPMArea(96, 79, 11, 7, 45, 22); - RedrawWindowXYWH(45, 22, 11, 7); // FM/AM + RedrawWindowXYWH(45, 22, 11, 7); /* FM/AM */ + GeneralFreqUpdate(); } @@ -475,110 +375,65 @@ void GeneralFreqUpdate(void) DrawDigitalFreq(); } -#ifdef KERNEL -/* Determine and return the appropriate frequency multiplier for - the first tuner on the open video device with handle FD. */ - -static double -get_freq_fact (int fd) -{ - struct video_tuner tuner; - tuner.tuner = 0; - if (-1 == ioctl (fd, VIDIOCGTUNER, &tuner) - || (tuner.flags & VIDEO_TUNER_LOW) == 0) - return .16; - return 160.; -} -#endif - -void FastFreqUpdate(void) -{ -#ifdef RADIOTRACK - RadioOut(FCODE(freqf),16); - RadioOut(0xa0,8); -#elif defined ZOLTRIX - tuneFreq(freqf,1); -#elif defined KERNEL - int fd = open ("/dev/radio", O_RDONLY); - unsigned long xl_freq = (unsigned long)(freqf*100*get_freq_fact(fd)); - ioctl (fd, VIDIOCSFREQ, &xl_freq); - close (fd); -#endif -} - void DrawDigitalTime(int hr, int min) { - char temp[10]; - char *p = temp; - int i,j,k=13; - - sprintf(temp, "%02d:%02d", hr, min); - - for (i=0; i<2; i++) - { - for (j=0; j<2; j++) - { - copyXPMArea((*p-'0')*6 + 1, 79, 6, 7, k, 22); - k += 6; - p++; - } - if (*p == ':') - { - copyXPMArea(61, 79, 2, 7, k, 22); - k += 4; - p++; - } - } + char temp[TMPBUFLEN + 1]; + char *p = temp; + int i, j, k = 13; + + snprintf(temp, TMPBUFLEN, "%02d:%02d", hr, min); + temp[TMPBUFLEN] = '\0'; + + for (i = 0; i < 2; i++) { + for (j = 0; j < 2; j++) { + copyXPMArea((*p-'0')*6 + 1, 79, 6, 7, k, 22); + k += 6; + p++; + } + if (*p == ':') { + copyXPMArea(61, 79, 2, 7, k, 22); + k += 4; + p++; + } + } RedrawWindowXYWH(13, 22, 27, 7); } void PresetHandler(int preset_hint) { - if (preset_hint < 0) - { + if (preset_hint < 0) { if (preset_count == 1) - { preset_count = max_presets; - } else - { preset_count--; - } - } - else - { + } else { if (preset_count == max_presets) - { preset_count = 1; - } else - { preset_count++; - } } - freqf = presets[preset_count].freq; + presets[0].freq = presets[preset_count].freq; GeneralFreqUpdate(); } void DrawDigitalPreset(void) { - char temp[10]; - char *p = temp; - int j=0,k=6; + char temp[TMPBUFLEN + 1]; + char *p = temp; + int j = 0, k = 6; - sprintf(temp,"%02d",preset_count); + snprintf(temp, TMPBUFLEN, "%02d", preset_count); + temp[TMPBUFLEN] = '\0'; - if (*p == '0') - { + if (*p == '0') { copyXPMArea(66, 79, 5, 7, k, 50); k += 6; j++; p++; } - while (j<2) - { + while (j < 2) { copyXPMArea((*p-'0')*6 + 1, 79, 5, 7, k, 50); k += 6; p++; @@ -589,16 +444,15 @@ void DrawDigitalPreset(void) void DrawDigitalFreq(void) { - char temp[10]; - char *p = temp; - int i=5,j=0,k=6; - - sprintf(temp,"%0f",freqf); - - while (j= 0 && hour <= 23) - && (minute >= 0 && minute <= 59))) - { - fprintf(stderr,"Invalid timer setting, valid is ##:@@ where ## is 0-23 and @@ is 0-59.\n"); - exit(1); - } + case 't': + auto_alarm_start = ON; + hour = strtol(optarg, (char **)NULL, 10); + if ((optarg = strchr(optarg, ':')) != NULL) + minute = strtol(optarg + 1, (char **)NULL, 10); + if (hour < 0 || hour > 23 || minute < 0 || minute > 59) + errx(1, "Invalid timer setting, valid is ##:@@ where ## is 0-23 and @@ is 0-59."); break; - case 'p': - sscanf(cmdline+3,"%d",&preset_count); - cmdline_preset = ON; + case 'p': + preset_count = strtol(optarg, (char **)NULL, 10); + cmdline_preset = ON; break; - case 'd': +#ifndef ZOLTRIX + case 'f': + radiodevice = optarg; break; - default: - printf("\nwmtune v%s, by soren@leiden.org, design & art by warp@xs4all.nl\n",VERSION); - printf("http://soren.org/linux/wmtune & http://windowmaker.mezaway.org\n\n"); - printf("usage:\n"); - printf("\t-n\t\tturn radio on initially on startup\n"); - printf("\t-t <##:##>\tset timer on startup, military time\n"); - printf("\t-p <##>\t\tset startup preset # listed in %s file\n",RCFILE); - printf("\t-d \tselects target display\n"); - printf("\t-h\t\tdisplay this screen\n"); - printf("\n"); - printf("examples:\n"); - printf("\t\tturn on radio on startup using preset 5\n"); - printf("\twmtune -n -p 5\n"); - printf("\t\tturn radio on at 2:35pm using preset 2\n"); - printf("\twmtune -p 2 -t 14:35\n"); - printf("\t\tturn on radio on startup and turn radio off at midnight\n"); - printf("\twmtune -n -t 0:0\n"); - printf("\n"); - exit(0); - } +#endif /* !ZOLTRIX */ + case 'h': + default: + usage(); + exit(0); } } } -#ifdef ZOLTRIX -inline void cardWrite(int k) -{ - usleep(0); - OUTB(k,rport); -} - -inline int cardRead(int offset) -{ - return inb(rport+offset); -} - -void tuneFreq(double freq, int fast) -{ - /* tunes the radio to the desired frequency */ - unsigned long long bitmask, f; - int i; - - f = (unsigned long long)(((float)(freq-88.0))*200.0)+0x4d1c; - bitmask = 0xc480402c10080000ull; - i = 45; - if (!fast) - { - cardWrite (0x00); - cardWrite (0x00); - cardRead(3); - } - cardWrite (0x40); - cardWrite (0xc0); - bitmask = (bitmask ^ ((f & 0xff) << 47) ^ ((f & 0xff00) << 30) ^ (/*stereo*/ 0 << 31)); - while (i--) - { - if ((bitmask & 0x8000000000000000ull) != 0) - { - cardWrite (0x80); - cardWrite (0x00); - cardWrite (0x80); - } - else - { - cardWrite (0xc0); - cardWrite (0x40); - cardWrite (0xc0); - } - bitmask *= 2; - } - /* termination sequence */ - cardWrite (0x80); - cardWrite (0xc0); - cardWrite (0x40); - usleep (20000); - cardWrite (volume); - usleep (10000); - cardRead(2); -} -#endif - -void RadioOff(void) -{ -#ifdef RADIOTRACK - OUTB(0,rport); - OUTB(0xc0,rport); -#elif defined ZOLTRIX - cardWrite(0); - cardWrite(0); - cardRead(3); -#elif defined KERNEL - struct video_audio va; - int fd = open ("/dev/radio", O_RDONLY); - va.flags = VIDEO_AUDIO_MUTE; - va.audio = 0; - ioctl (fd, VIDIOCSAUDIO, &va); - close (fd); -#endif - radio_status = OFF; - copyXPMArea(76, 40, 51, 13, 6, 7); - copyXPMArea(115, 55, 11, 7, 45, 22); - copyXPMArea(83, 55, 11, 7, 6, 50); - RedrawWindowXYWH(6, 50, 11, 7); // Full Preset Field - RedrawWindowXYWH(6, 7, 51, 22); // Full Upper Field -} - -void TuneRadio(void) -{ -#ifdef RADIOTRACK - RadioOut(FCODE(freqf),16); - RadioOut(0xa0,8); - usleep(1000); - OUTB(0,rport); - usleep(50000); - OUTB(0xc8,rport); -#elif defined ZOLTRIX - tuneFreq(freqf,0); -#elif defined KERNEL - int fd = open ("/dev/radio", O_RDONLY); - unsigned long xl_freq = (unsigned long)(freqf*100*get_freq_fact(fd)); - ioctl (fd, VIDIOCSFREQ, &xl_freq); - close (fd); -#endif -} - -void RadioOut(int v,int n) -{ - while (n--) - { - if (v&1) - { - OUTW (5,rport); - OUTW (5,rport); - OUTW (7,rport); - OUTW (7,rport); - } - else - { - OUTW (1,rport); - OUTW (1,rport); - OUTW (3,rport); - OUTW (3,rport); - } - v>>=1; - } -} - void ButtonDown(int button) { - switch (button) - { - case 0: // ON/OFF BUTTON - copyXPMArea(79, 100, 12, 11, 47, 48); - RedrawWindowXYWH(47, 48, 12, 11); - break; - case 1: // FINE TUNE UP (+) - copyXPMArea(0, 98, 11, 9, 5, 35); - RedrawWindowXYWH(5, 35, 11, 9); - break; - case 2: // FINE TUNE DOWN (-) - copyXPMArea(11, 98, 11, 9, 16, 35); - RedrawWindowXYWH(16, 35, 11, 9); - break; - case 3: // SCAN UP & TIME UP - copyXPMArea(22, 98, 11, 9, 27, 35); - RedrawWindowXYWH(27, 35, 11, 9); - break; - case 4: // SCAN DOWN & TIME DOWN - copyXPMArea(33, 98, 11, 9, 38, 35); - RedrawWindowXYWH(38, 35, 11, 9); - break; - case 5: // ALARM BUTTON - copyXPMArea(44, 98, 10, 9, 49, 35); - RedrawWindowXYWH(49, 35, 10, 9); - break; - case 6: // LEFT PRESET SCAN BUTTON - copyXPMArea(55, 100, 12, 11, 23, 48); - RedrawWindowXYWH(23, 48, 12, 11); - break; - case 7: // RIGHT PRESET SCAN BUTTON - copyXPMArea(67, 100, 12, 11, 35, 48); - RedrawWindowXYWH(35, 48, 12, 11); + switch (button) { + case 0: // ON/OFF BUTTON + copyXPMArea(79, 100, 12, 11, 47, 48); + RedrawWindowXYWH(47, 48, 12, 11); + break; + case 1: // FINE TUNE UP (+) + copyXPMArea(0, 98, 11, 9, 5, 35); + RedrawWindowXYWH(5, 35, 11, 9); + break; + case 2: // FINE TUNE DOWN (-) + copyXPMArea(11, 98, 11, 9, 16, 35); + RedrawWindowXYWH(16, 35, 11, 9); + break; + case 3: // SCAN UP & TIME UP + copyXPMArea(22, 98, 11, 9, 27, 35); + RedrawWindowXYWH(27, 35, 11, 9); + break; + case 4: // SCAN DOWN & TIME DOWN + copyXPMArea(33, 98, 11, 9, 38, 35); + RedrawWindowXYWH(38, 35, 11, 9); + break; + case 5: // ALARM BUTTON + copyXPMArea(44, 98, 10, 9, 49, 35); + RedrawWindowXYWH(49, 35, 10, 9); + break; + case 6: // LEFT PRESET SCAN BUTTON + copyXPMArea(55, 100, 12, 11, 23, 48); + RedrawWindowXYWH(23, 48, 12, 11); + break; + case 7: // RIGHT PRESET SCAN BUTTON + copyXPMArea(67, 100, 12, 11, 35, 48); + RedrawWindowXYWH(35, 48, 12, 11); break; } } void ButtonUp(int button) { - switch (button) - { - case 0: // ON/OFF BUTTON - copyXPMArea(79, 88, 12, 11, 47, 48); - RedrawWindowXYWH(47, 48, 12, 11); - break; - case 1: // FINE TUNE UP (+) - copyXPMArea(0, 88, 11, 9, 5, 35); - RedrawWindowXYWH(5, 35, 11, 9); - break; - case 2: // FINE TUNE DOWN (-) - copyXPMArea(11, 88, 11, 9, 16, 35); - RedrawWindowXYWH(16, 35, 11, 9); - break; - case 3: // SCAN UP - copyXPMArea(22, 88, 11, 9, 27, 35); - RedrawWindowXYWH(27, 35, 11, 9); - break; - case 4: // SCAN DOWN - copyXPMArea(33, 88, 11, 9, 38, 35); - RedrawWindowXYWH(38, 35, 11, 9); - break; - case 5: // ALARM BUTTON - copyXPMArea(44, 88, 10, 9, 49, 35); - RedrawWindowXYWH(49, 35, 10, 9); - break; - case 6: // LEFT PRESET SCAN BUTTON - copyXPMArea(55, 88, 12, 11, 23, 48); - RedrawWindowXYWH(23, 48, 12, 11); - break; - case 7: // RIGHT PRESET SCAN BUTTON - copyXPMArea(67, 88, 12, 11, 35, 48); - RedrawWindowXYWH(35, 48, 12, 11); + switch (button) { + case 0: // ON/OFF BUTTON + copyXPMArea(79, 88, 12, 11, 47, 48); + RedrawWindowXYWH(47, 48, 12, 11); + break; + case 1: // FINE TUNE UP (+) + copyXPMArea(0, 88, 11, 9, 5, 35); + RedrawWindowXYWH(5, 35, 11, 9); + break; + case 2: // FINE TUNE DOWN (-) + copyXPMArea(11, 88, 11, 9, 16, 35); + RedrawWindowXYWH(16, 35, 11, 9); + break; + case 3: // SCAN UP + copyXPMArea(22, 88, 11, 9, 27, 35); + RedrawWindowXYWH(27, 35, 11, 9); + break; + case 4: // SCAN DOWN + copyXPMArea(33, 88, 11, 9, 38, 35); + RedrawWindowXYWH(38, 35, 11, 9); + break; + case 5: // ALARM BUTTON + copyXPMArea(44, 88, 10, 9, 49, 35); + RedrawWindowXYWH(49, 35, 10, 9); + break; + case 6: // LEFT PRESET SCAN BUTTON + copyXPMArea(55, 88, 12, 11, 23, 48); + RedrawWindowXYWH(23, 48, 12, 11); + break; + case 7: // RIGHT PRESET SCAN BUTTON + copyXPMArea(67, 88, 12, 11, 35, 48); + RedrawWindowXYWH(35, 48, 12, 11); break; } } void TimeUp(void) { - if (minute == 59) - { + if (minute == 59) { if (hour == 23) - { hour = 0; - } else - { hour++; - } minute = 0; - } - else - { + } else { minute++; } DrawDigitalTime(hour,minute); @@ -985,113 +652,48 @@ void TimeUp(void) void TimeDown(void) { - if (minute == 0) - { + if (minute == 0) { if (hour == 0) - { hour = 23; - } else - { hour--; - } minute = 59; - } - else - { + } else { minute--; } DrawDigitalTime(hour,minute); } -void VolumeUp(void) -{ -#ifdef RADIOTRACK - OUTB(0x88,rport); - usleep(200000); - OUTB(0xc8,rport); -#elif defined ZOLTRIX - if (volume < 16) - volume++; - cardWrite(volume); - usleep(10000); - cardRead(2); -#elif defined KERNEL - if (volume < 10) { - struct video_audio va; - int fd = open ("/dev/radio", O_RDONLY); - va.flags = VIDEO_AUDIO_VOLUME; - va.audio = 0; - va.volume = (++volume) * (65535/10); - ioctl (fd, VIDIOCSAUDIO, &va); - close (fd); - } -#endif -} - -void VolumeDown(void) -{ -#ifdef RADIOTRACK - OUTB(0x48,rport); - usleep(200000); - OUTB(0xc8,rport); -#elif defined ZOLTRIX - if (volume > 0) - volume--; - cardWrite(volume); - usleep(10000); - cardRead(2); -#elif defined KERNEL - if (volume > 0) { - struct video_audio va; - int fd = open ("/dev/radio", O_RDONLY); - va.flags = VIDEO_AUDIO_VOLUME; - va.audio = 0; - va.volume = (--volume) * (65535/10); - ioctl (fd, VIDIOCSAUDIO, &va); - close (fd); - } -#endif -} void TuneUp(void) { - if ((float)freqf != 108.0) - { - freqf += .01; - } + if (presets[0].freq != 108.0) + presets[0].freq += .01; else - { - freqf = 88.0; - } + presets[0].freq = 88.0; DrawDigitalFreq(); } void TuneDown(void) { - if ((float)freqf != 88.0) - { - freqf -= .01; - } + if (presets[0].freq != 88.0) + presets[0].freq -= .01; else - { - freqf = 108.0; - } + presets[0].freq = 108.0; DrawDigitalFreq(); } void TestFreq(void) { - switch (TestTune()) - { - case 0: - copyXPMArea(114, 49, 13, 4, 44, 16); // POSSIBLE SIGNAL LOSS (0) + switch (TestTune()) { + case 0: /* POSSIBLE SIGNAL LOSS (0) */ + copyXPMArea(114, 49, 13, 4, 44, 16); break; - case 1: - copyXPMArea(92, 100, 13, 4, 44, 16); // SIGNAL & STEREO (1) + case 1: /* SIGNAL & STEREO (1) */ + copyXPMArea(92, 100, 13, 4, 44, 16); break; - case 2: - copyXPMArea(92, 105, 13, 4, 44, 16); // POSSIBLY MONO :) (2) + case 2: /* POSSIBLY MONO :) (2) */ + copyXPMArea(92, 105, 13, 4, 44, 16); break; } RedrawWindowXYWH(44, 16, 13, 4); @@ -1099,12 +701,10 @@ void TestFreq(void) void OnPreset(void) { - int count=1; + int count = 1; - while (count < max_presets+1) - { - if ((float)freqf == (float)presets[count].freq) - { + while (count < (max_presets + 1)) { + if (presets[0].freq == presets[count].freq) { preset_count = count; DrawDigitalPreset(); return; @@ -1113,28 +713,129 @@ void OnPreset(void) } } -int TestTune(void) +int ParseRCFile(char *filename) { -#ifdef RADIOTRACK - int res; + char temp[TMPBUFLEN + 1], *p; + FILE *fp; + int ln = 1, count = -1; + char *tokens = " \t\n"; + + presets = malloc(sizeof(struct presets_t)); + if (presets == NULL) + err(1, "memory allocation error"); - OUTB(0xf8,rport); - usleep(150000); - res = (int)inb(rport); - if (res == 0x0fd) - { - return 1; // SIGNAL & STEREO (1) - } - else if (res != 0xff) - { - return 2; // POSSIBLY MONO :) (2) + if ((fp = fopen(filename, "r")) == NULL) + return 1; + + while (fgets(temp, TMPBUFLEN, fp)) { + if ((p = strtok(temp, tokens)) != NULL) { + if ((p = strchr(temp, '#')) != NULL) + *p = '\0'; + + if ((strlen(temp)) != 0) { +#ifdef ZOLTRIX + if (count == -1) + rport = strtol(temp, (char **)NULL, 10); +#endif /* ZOLTRIX */ + if (count > 0) { + max_presets++; + + presets = realloc(presets, (count + 1) * sizeof(struct presets_t)); + if (presets == NULL) + err(1, "memory reallocation error"); + + presets[count].freq = atof(temp); + if (presets[count].freq < 88.0 || presets[count].freq > 108.0) + errx(1, "Invalid preset in %s line %d.", filename, ln); + } + count++; + } + } + ln++; } - return 0; // POSSIBLE SIGNAL LOSS (0) -#elif defined ZOLTRIX + + fclose(fp); + return 0; +} + +void +usage(void) { + const char usagestr[] = + "\nwmtune v%s, by soren@leiden.org, design & art by warp@xs4all.nl\n" + "http://soren.org/linux/wmtune & http://windowmaker.mezaway.org\n\n" + "usage:\n" + "\t-n\t\tturn radio on initially on startup\n" + "\t-t <##:##>\tset timer on startup, military time\n" + "\t-p <##>\t\tset startup preset # listed in %s file\n" +#ifndef ZOLTRIX + "\t-f \tuse filename as a radio device file\n" +#endif + "\t-h\t\tdisplay this screen\n\n" + "examples:\n" + "\t\tturn on radio on startup using preset 5\n" + "\twmtune -n -p 5\n" + "\t\tturn radio on at 2:35pm using preset 2\n" + "\twmtune -p 2 -t 14:35\n" + "\t\tturn on radio on startup and turn radio off at midnight\n" + "\twmtune -n -t 0:0\n\n"; + + printf(usagestr, VERSION, RCFILE); +} + +/* CARD MANAGEMENT ROUTINES */ +void RadioOff(void) +{ +#ifdef ZOLTRIX + cardWrite(0); + cardWrite(0); + cardRead(3); +#else + ri.mute = 1; + SetGetRadioInfo(RIOCSINFO); +#endif /* ZOLTRIX */ + radio_status = OFF; + copyXPMArea(76, 40, 51, 13, 6, 7); + copyXPMArea(115, 55, 11, 7, 45, 22); + copyXPMArea(83, 55, 11, 7, 6, 50); + RedrawWindowXYWH(6, 50, 11, 7); /* Full Preset Field */ + RedrawWindowXYWH(6, 7, 51, 22); /* Full Upper Field */ +} + +void FastFreqUpdate(void) +{ +#ifdef ZOLTRIX + tuneFreq(presets[0].freq, 1); +#else + ri.freq = presets[0].freq * 1000; + SetGetRadioInfo(RIOCSINFO); + usleep(50000); + SetGetRadioInfo(RIOCGINFO); + presets[0].freq = (float)ri.freq / 1000.; +#endif +} + +void TuneRadio(void) +{ +#ifdef ZOLTRIX + tuneFreq(presets[0].freq, 0); +#else + ri.freq = presets[0].freq * 1000; + ri.volume = volume * VOLUME_STEP; + ri.mute = 0; + SetGetRadioInfo(RIOCSINFO); + usleep(200000); + SetGetRadioInfo(RIOCGINFO); + presets[0].freq = (float)ri.freq / 1000.; +#endif /* ZOLTRIX */ +} + +int TestTune(void) +{ +#ifdef ZOLTRIX int x1,x2; - OUTB(0x00, rport); // This stuff I found to do nothing - OUTB(volume, rport); + outb(rport, 0x00); /* This stuff I found to do nothing */ + outb(rport, volume); usleep(10000); x1 = inb(rport); @@ -1143,73 +844,181 @@ int TestTune(void) if ((x1 == x2) && (x1 == 0xdf)) return 1; - else return 0; -#elif defined KERNEL - struct video_tuner v; - int fd = open ("/dev/radio", O_RDONLY); - v.tuner = 0; - ioctl (fd, VIDIOCGTUNER, &v); - close (fd); - return (v.signal != 0)?1:0; -#endif +#else + int ret = 0; + + SetGetRadioInfo(RIOCGINFO); + if (ri.info & RADIO_INFO_SIGNAL) + ret = 1; + if (ri.info & RADIO_INFO_STEREO) + ret |= 2; + switch (ret) { + case 0: return 0; + case 1: return 2; + default: + return 1; + } +#endif /* ZOLTRIX */ return 0; } -int ParseRCFile(char *filename) +void VolumeUp(void) { - char temp[128]; - char *p; - FILE *fp; - int ln=1; - int count=-1; - char *tokens = " \t\n"; +#ifdef ZOLTRIX + if (volume < 16) + volume++; + cardWrite(volume); + usleep(10000); + cardRead(2); +#else + if (volume < 255 / VOLUME_STEP) + volume++; - if ((fp = fopen(filename,"r")) == NULL) - { - return 1; + ri.volume = volume * VOLUME_STEP; + SetGetRadioInfo(RIOCSINFO); +#endif +} + +void VolumeDown(void) +{ + if (volume > 0) + volume--; + +#ifdef ZOLTRIX + cardWrite(volume); + usleep(10000); + cardRead(2); +#else + ri.volume = volume * VOLUME_STEP; + SetGetRadioInfo(RIOCSINFO); +#endif +} + +/* ZOLTRIX & NATIVE STUFF */ +#ifdef ZOLTRIX +void +goroot(void) { + if (seteuid(0) < 0) + err(1, "failed to restore saved root id"); +} + +void +gouser(void) { + if (seteuid(getuid()) < 0) + err(1, "failed to get effective user id"); +} + +inline void cardWrite(int k) +{ + usleep(0); + outb(rport, k); +} + +inline int cardRead(int offset) +{ + return inb(rport + offset); +} + +void tuneFreq(double freq, int fast) +{ +/* tunes the radio to the desired frequency */ + unsigned long long bitmask, f; + int i; + + f = (unsigned long long)(((float)(freq - 88.0)) * 200.0) + 0x4d1c; + bitmask = 0xc480402c10080000ull; + i = 45; + if (!fast) { + cardWrite(0x00); + cardWrite(0x00); + cardRead(3); + } + cardWrite(0x40); + cardWrite(0xc0); + bitmask = (bitmask ^ ((f & 0xff) << 47) ^ ((f & 0xff00) << 30) ^ (/*stereo*/ 0 << 31)); + while (i--) { + if ((bitmask & 0x8000000000000000ull) != 0) { + cardWrite(0x80); + cardWrite(0x00); + cardWrite(0x80); + } else { + cardWrite(0xc0); + cardWrite(0x40); + cardWrite(0xc0); + } + bitmask *= 2; + } + /* termination sequence */ + cardWrite(0x80); + cardWrite(0xc0); + cardWrite(0x40); + usleep (20000); + cardWrite(volume); + usleep (10000); + cardRead(2); +} + +void CheckIOPerms(void) +{ + int offset; + unsigned long mask = 0; + offset = rport / 32; + + goroot(); + + mask = 0x0F << rport % 32; + memset(iomap, 0xFFFF, sizeof(iomap)); + iomap[offset] ^= mask; + ioperms.iomap = iomap; + if (sysarch(I386_SET_IOPERM, (char *)&ioperms) < 0) + err(1, "Unsufficient IO privileges"); + + gouser(); +} +#else /* !ZOLTRIX */ +int +SetGetRadioInfo(int setinfo) { + int rd; + + rd = open(radiodevice, setinfo == RIOCSINFO ? O_RDWR : O_RDONLY); + if (rd < 0) { + warn("%s open error", radiodevice); + return -1; } - while(fgets(temp, 128, fp)) - { - if ((p = strtok(temp,tokens)) != NULL) - { - if ((p = strchr(temp,'#')) != NULL) - { - *p = '\0'; - } - if ((strlen(temp)) != 0) - { - if (count == -1) - { - sscanf(temp,"%x",&rport); - } - if (count == 0) - { - sscanf(temp,"%d",&max_presets); - presets = malloc(sizeof(*presets) * (max_presets+1)); - if (!(max_presets >= 1 && max_presets <= 99)) - { - fprintf(stderr,"Invalid number of presets (1-99) in %s line %d.\n",filename,ln); - exit(1); - } - } - else - { - if (!(count > max_presets)) - { - sscanf(temp,"%lf",&presets[count].freq); - if (!(presets[count].freq >= 88.0 - && presets[count].freq <= 108.0)) - { - fprintf(stderr,"Invalid preset in %s line %d.\n",filename,ln); - exit(1); - } - } - } - count++; - } - } - ln++; + + if (ioctl(rd, setinfo, &ri) < 0) { + warn("%s", setinfo == RIOCSINFO ? "RIOCSINFO" : "RIOCGINFO"); + return -1; } - fclose(fp); + + if (close(rd) < 0) { + warn("%s close error", radiodevice); + return -1; + } + return 0; } + +void +GetVolumeStep(void) { + int i; + int oldvol; + + oldvol = ri.volume; + + for (i = 0; i < 256; i++) { + ri.volume = i; + if (SetGetRadioInfo(RIOCSINFO) < 0) + break; + if (SetGetRadioInfo(RIOCGINFO) < 0) + break; + if (ri.volume) { + VOLUME_STEP = ri.volume; + break; + } + } + + ri.volume = oldvol; + SetGetRadioInfo(RIOCSINFO); +} +#endif