1 // Copyright (c) <2012> <Leif Asbrink>
2 //
3 // Permission is hereby granted, free of charge, to any person
4 // obtaining a copy of this software and associated documentation
5 // files (the "Software"), to deal in the Software without restriction,
6 // including without limitation the rights to use, copy, modify,
7 // merge, publish, distribute, sublicense, and/or sell copies of
8 // the Software, and to permit persons to whom the Software is
9 // furnished to do so, subject to the following conditions:
10 //
11 // The above copyright notice and this permission notice shall be
12 // included in all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
16 // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
18 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19 // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
21 // OR OTHER DEALINGS IN THE SOFTWARE.
22 
23 #if DARWIN == 1
24 // include something here.......
25 #else
26 #if (defined(__unix__) || defined(unix)) && !defined(USG)
27 #include <sys/param.h>
28 #endif
29 #ifdef BSD
30 #include <sys/cdefs.h>
31 #include <sys/types.h>
32 #include <sys/sysctl.h>
33 #include <machine/cpufunc.h>
34 #include <machine/sysarch.h>
35 #else
36 #include <sys/io.h>
37 #endif
38 #endif
39 
40 
41 #include <unistd.h>
42 #include <sys/mman.h>
43 #include <sys/resource.h>
44 #include <pthread.h>
45 #include <sched.h>
46 #include <sys/time.h>
47 #include <fcntl.h>
48 #include <termios.h>
49 #include <string.h>
50 #include "globdef.h"
51 #include "rusage.h"
52 #include "thrdef.h"
53 #include "uidef.h"
54 #include "lconf.h"
55 #include "xdef.h"
56 #include "ldef.h"
57 #include "hwaredef.h"
58 #include "options.h"
59 #include "sdrdef.h"
60 
61 
62 int open_USB2LPT(void);
63 
64 struct termios old_options;
65 #ifdef BSD
66 char serport_name[]="/dev/ttyu....";
67 #else
68 char serport_name[]="/dev/ttyS....?";
69 #endif
70 
print_procerr(int xxprint)71 void print_procerr(int xxprint)
72 {
73 int i;
74 if( (xxprint&1) != 0)
75   {
76   i=0;
77   if( (xxprint&2)==0)
78     {
79     i=1;
80     printf("\nMMX supported by hardware");
81     }
82   if( (xxprint&4)==0 && simd_present != 0)
83     {
84     i=1;
85     printf("\nSIMD (=sse) supported by hardware");
86     }
87   if(i!=0)
88     {
89     printf("\n/proc/cpuinfo says LINUX core is not compatible.");
90     printf("\n\nLinrad will allow you to select routines that may be illegal");
91     printf("\non your system.");
92     printf("\nAny illegal instruction will cause a program crasch!!");
93     printf("\nSeems just the sse flag in /proc/cpuinfo is missing.");
94     printf("\nTo use fast routines with an older core, recompile LINUX");
95     printf("\nwith appropriate patches.\n\n");
96     }
97   }
98 }
99 
mmxerr(void)100 void mmxerr(void)
101 {
102 printf("\n\nCould not read file /proc/cpuinfo (flags:)");
103 printf("\nSetting MMX and SIMD flags from hardware");
104 printf("\nProgram may fail if kernel support is missing and modes");
105 printf("\nneeding MMX or SIMD are selected.");
106 printf("\n\n%s",press_enter);
107 fflush(stdout);
108 getchar();
109 }
110 
investigate_cpu(void)111 int investigate_cpu(void)
112 {
113 int i;
114 #ifndef BSD
115 int k, maxproc, maxproc_flag;
116 FILE *file;
117 char s[256];
118 char *flags="flags";
119 char *fmmx=" mmx";
120 char *fsse=" sse";
121 char *fht=" ht";
122 char *fprocessor="processor";
123 #endif
124 int xxprint;
125 // If there is no mmx, do not use simd either.
126 tickspersec = sysconf(_SC_CLK_TCK);
127 xxprint=0;
128 #if CPU == CPU_INTEL
129 #if IA64 == 0
130 i=check_mmx();
131 #else
132 // We do not use assembly on 64 bit systems (yet??)
133 i=0;
134 i=2; // simd is OK, but not MMX.
135 #endif
136 mmx_present=i&1;
137 simd_present=i>>1;
138 #else
139 mmx_present=0;
140 simd_present=0;
141 #endif
142 #ifdef BSD
143 size_t len=sizeof(no_of_processors);
144 int err;
145 if((err=sysctlbyname("hw.ncpu", &no_of_processors,
146                                &len, NULL, 0)) < 0)no_of_processors=1;
147 #else
148 no_of_processors=1;
149 no_of_ht=0;
150 maxproc=0;
151 maxproc_flag=0;
152 file = fopen("/proc/cpuinfo", "r");
153 if (file == NULL)
154   {
155   mmxerr();
156   return 0;
157   }
158 else
159   {
160   no_of_processors=0;
161 nxline:;
162   if(fgets(s,256,file)==NULL)
163     {
164     if(no_of_processors>0)goto cpuinfo_ok;
165     fclose(file);
166 #if CPU == CPU_INTEL
167     mmxerr();
168 #endif
169     no_of_processors=1;
170     return 0;
171     }
172   else
173     {
174     for(i=0; i<9; i++) if(s[i]!=fprocessor[i])goto nxt;
175     k=8;
176     while(s[k+1] == ' ' || s[k+1] == ':' || s[k+1] == 9)k++;
177     i=atoi(&s[k]);
178     if(i != no_of_processors)maxproc_flag++;
179     no_of_processors++;
180     if(i > maxproc)maxproc=i;
181 nxt:;
182     k=0;
183     while(s[k] != flags[0] && k < 10)k++;
184     for(i=0; i<5; i++) if(s[i+k]!=flags[i])goto nxline;
185     k+=5;
186 nxbln:
187     while(s[k]!=0 && s[k]!=' ')k++;
188     while(s[k]!=0 && s[k]==' ')k++;
189     if(s[k]!=0)
190       {
191       k--;
192       for(i=0; i<4; i++)if(s[i+k]!=fmmx[i])goto notmmx;
193       if(s[k+4] != ' ' && s[k+4] != 10)goto notmmx;
194       xxprint|=2;
195 notmmx:;
196       for(i=0; i<4; i++)if(s[i+k]!=fsse[i])goto notsse;
197       if(s[k+4] != ' ' && s[k+4] != 10)goto notsse;
198       xxprint|=4;
199 notsse:;
200       for(i=0; i<3; i++)if(s[i+k]!=fht[i])goto notht;
201       if(s[k+3] != ' ' && s[k+3] != 10)goto notht;
202       no_of_ht++;
203 notht:;
204       k++;
205       goto nxbln;
206       }
207     xxprint|=1;
208     }
209   goto nxline;
210 cpuinfo_ok:;
211   fclose(file);
212   }
213 if(maxproc_flag != 0)
214   {
215 // If something went wrong, better underestimate the number of CPUs.
216   maxproc++;
217   if(no_of_processors > maxproc)no_of_processors=maxproc;
218   }
219 if(no_of_processors == no_of_ht)
220   {
221 // This is incorrect. In e.g. Ubuntu Studio 13.10 the hyperthreaded
222 // cores are not listed, but nevertheless the ht flag is set.
223 // In case it turns out to be interesting to control cpu affinities
224 // it will be necessary do something else here.
225 // Look for 'core id' and 'cpu cores'
226   hyperthread_flag=TRUE;
227   }
228 else
229   {
230   hyperthread_flag=FALSE;
231   }
232 #endif
233 return xxprint;
234 }
235 
236 
237 
238 // Old versions of Linux have a special implementation of getrusage
239 // that returns the timing for the calling thread and not the timing for
240 // the process as prescribed by POSIX
241 // The configure script will set RESAGE_OLD=TRUE for those old linux
242 // kernels.
243 #if RUSAGE_OLD != TRUE
244 #include <sys/syscall.h>
245 
lir_system_times(double * cpu_time,double * total_time)246 void lir_system_times(double *cpu_time, double *total_time)
247 {
248 cpu_time[0]=lir_get_cpu_time();
249 total_time[0]=current_time();
250 }
251 
clear_thread_times(int no)252 void clear_thread_times(int no)
253 {
254 #ifdef BSD
255 thread_pid[no]=no;
256 #else
257 thread_pid[no]=syscall(SYS_gettid);
258 #endif
259 thread_tottim1[no]=current_time();
260 thread_cputim1[no]=lir_get_cpu_time();
261 thread_workload[no]=0;
262 }
263 
make_thread_times(int no)264 void make_thread_times(int no)
265 {
266 float t1,t2;
267 thread_tottim2[no]=current_time();
268 thread_cputim2[no]=lir_get_thread_time(no);
269 t1=100*(thread_cputim2[no]-thread_cputim1[no]);
270 t2=thread_tottim2[no]-thread_tottim1[no];
271 if(t1>0 && t2>0)
272   {
273   thread_workload[no]=t1/t2;
274   }
275 else
276   {
277   thread_workload[no]=0;
278   }
279 }
280 
lir_get_cpu_time(void)281 double lir_get_cpu_time(void)
282 {
283 double tm;
284 struct rusage rudat;
285 getrusage(RUSAGE_SELF,&rudat);
286 tm=0.000001*(rudat.ru_utime.tv_usec + rudat.ru_stime.tv_usec)+
287                     rudat.ru_utime.tv_sec + rudat.ru_stime.tv_sec;
288 return tm;
289 }
290 
lir_get_thread_time(int no)291 double lir_get_thread_time(int no)
292 {
293 #ifdef BSD
294 return 0*no;
295 #else
296 char fnam[80], info[512];
297 FILE *pidstat;
298 int j,k,m;
299 long long int ii1, ii2;
300 sprintf(fnam,"/proc/%d/task/%d/stat",thread_pid[no],thread_pid[no]);
301 pidstat=fopen(fnam,"r");
302 if(pidstat==NULL)return 0;
303 #if VALGRIND == TRUE
304 memset(info, 0, 512);
305 #endif
306 m=fread(info,1,512,pidstat);
307 fclose(pidstat);
308 j=0;
309 k=0;
310 while(k<13)
311   {
312   while(info[j]!= ' ' && j<m)j++;
313   while(info[j]== ' ' && j<m)j++;
314   k++;
315   }
316 if(j>=m)return 0;
317 sscanf(&info[j], "%lld %lld", &ii1, &ii2);
318 return (double)(ii1+ii2)/tickspersec;
319 #endif
320 }
321 #endif
322 
323 // Old versions of Linux have a special implementation of getrusage
324 // that returns the timing for the calling thread and not the timing for
325 // the process as prescribed by POSIX
326 // The configure script will set RESAGE_OLD=TRUE for those old linux
327 // kernels.
328 #if RUSAGE_OLD == TRUE
329 
make_thread_times(int no)330 void make_thread_times(int no)
331 {
332 float t1,t2;
333 thread_tottim2[no]=current_time();
334 thread_cputim2[no]=lir_get_thread_time();
335 t1=100*(thread_cputim2[no]-thread_cputim1[no]);
336 t2=thread_tottim2[no]-thread_tottim1[no];
337 if(t1>0 && t2>0)
338   {
339   thread_workload[no]=t1/t2;
340   }
341 else
342   {
343   thread_workload[no]=0;
344   }
345 }
346 
clear_thread_times(int no)347 void clear_thread_times(int no)
348 {
349 thread_tottim1[no]=current_time();
350 thread_cputim1[no]=lir_get_cpu_time();
351 thread_workload[no]=0;
352 }
353 
lir_get_cpu_time(void)354 double lir_get_cpu_time(void)
355 {
356 int i;
357 float t1;
358 t1=0;
359 for(i=0; i<THREAD_MAX; i++)
360   {
361   if(thread_command_flag[i]!=THRFLAG_NOT_ACTIVE)
362     {
363     t1+=thread_workload[i];
364     }
365   }
366 return t1;
367 }
368 
lir_get_thread_time(void)369 double lir_get_thread_time(void)
370 {
371 double tm;
372 struct rusage rudat;
373 getrusage(RUSAGE_SELF,&rudat);
374 tm=0.000001*(rudat.ru_utime.tv_usec + rudat.ru_stime.tv_usec)+
375                     rudat.ru_utime.tv_sec + rudat.ru_stime.tv_sec;
376 return tm;
377 }
378 
379 #endif
380 
381 
lir_init_event(int i)382 void lir_init_event(int i)
383 {
384 pthread_mutex_init(&lir_event_mutex[i],NULL);
385 lir_event_flag[i]=FALSE;
386 pthread_cond_init(&lir_event_cond[i], NULL);
387 }
388 
lir_close_event(int i)389 void lir_close_event(int i)
390 {
391 pthread_mutex_destroy(&lir_event_mutex[i]);
392 pthread_cond_destroy(&lir_event_cond[i]);
393 }
394 
395 
lir_set_event(int no)396 void lir_set_event(int no)
397 {
398 while(pthread_mutex_lock(&lir_event_mutex[no]) != 0)lir_sleep(10);
399 lir_event_flag[no]=TRUE;
400 pthread_cond_signal(&lir_event_cond[no]);
401 pthread_mutex_unlock(&lir_event_mutex[no]);
402 }
403 
lir_await_event(int no)404 void lir_await_event(int no)
405 {
406 while(pthread_mutex_lock(&lir_event_mutex[no]) != 0)lir_sleep(10);
407 if(lir_event_flag[no] != TRUE)
408   {
409   pthread_cond_wait(&lir_event_cond[no], &lir_event_mutex[no]);
410   }
411 lir_event_flag[no]=FALSE;
412 while(pthread_mutex_unlock(&lir_event_mutex[no]) != 0)lir_sleep(10);
413 }
414 
415 
416 
417 
418 
lir_noisegen(int level)419 float lir_noisegen(int level)
420 {
421 // Return a number distributed following a gaussian
422 // Mean value is 0 and sigma pow(2,level)
423 float x, y, z;
424 y = (float)(random()+0.5)/(float)RAND_MAX;
425 z = (float)(random()+0.5)/(float)RAND_MAX;
426 x = z * 2*PI_L;
427 return sin(x)*sqrt(-2*log(y))*pow(2.,level);
428 }
429 
lir_mutex_init(void)430 void lir_mutex_init(void)
431 {
432 int i;
433 for(i=0; i<MAX_LIRMUTEX; i++)
434   {
435   pthread_mutex_init(&linux_mutex[i],NULL);
436   }
437 }
438 
lir_mutex_destroy(void)439 void lir_mutex_destroy(void)
440 {
441 int i;
442 for(i=0; i<MAX_LIRMUTEX; i++)
443   {
444   pthread_mutex_destroy(&linux_mutex[i]);
445   }
446 }
447 
lir_mutex_lock(int no)448 void lir_mutex_lock(int no)
449 {
450 pthread_mutex_lock(&linux_mutex[no]);
451 }
452 
lir_mutex_unlock(int no)453 void lir_mutex_unlock(int no)
454 {
455 pthread_mutex_unlock(&linux_mutex[no]);
456 }
457 
lirerr(int errcod)458 void lirerr(int errcod)
459 {
460 fprintf(STDERR,"\nlir error %d",errcod);
461 if(kill_all_flag) return;
462 DEB"\nlirerr(%d)",errcod);
463 if(dmp != 0)fflush(dmp);
464 lir_errcod=errcod;
465 lir_set_event(EVENT_KILL_ALL);
466 while(!kill_all_flag)lir_sleep(10000);
467 }
468 
lir_open_serport(int serport_number,int baudrate,int stopbit_flag,int rts_mode)469 int lir_open_serport(int serport_number, int baudrate,int stopbit_flag, int rts_mode)
470 {
471 int rte;
472 int rc;
473 struct termios options;
474 rc=0;
475 if(serport != -1)return rc ;
476 if(serport_number < 1 || serport_number > 8)
477   {
478   rc=1279;
479   return rc;
480   }
481 if(serport_number <= 4)
482   {
483   sprintf(&serport_name[0],"%s","/dev/ttyS");
484   sprintf(&serport_name[9],"%d",serport_number-1);
485   }
486 else
487   {
488   sprintf(&serport_name[0],"%s","/dev/ttyUSB");
489   sprintf(&serport_name[11],"%d",serport_number-5);
490   }
491 serport=open(serport_name,O_RDWR  | O_NOCTTY | O_NDELAY);
492 if (serport == -1)
493   {
494   rc=1244;
495   return rc;
496   }
497 fcntl(serport,F_SETFL,0);           //blocking I/O
498 //fcntl(serport, F_SETFL, FNDELAY);     //non blocking I/O
499 if(tcgetattr(serport,&options) != 0)
500   {
501   rc=1277;
502   goto close_x;
503   }
504 switch ( baudrate )
505   {
506   case 110:
507   rte=B110;
508   break;
509 
510   case 300:
511   rte=B300;
512   break;
513 
514   case 600:
515   rte=B600;
516   break;
517 
518   case 1200:
519   rte=B1200;
520   break;
521 
522   case 2400:
523   rte=B2400;
524   break;
525 
526   case 4800:
527   rte=B4800;
528   break;
529 
530   case 9600:
531   rte=B9600;
532   break;
533 
534   case 19200:
535   rte=B19200;
536   break;
537 
538   case 38400:
539   rte=B38400;
540   break;
541 
542   case 57600:
543   rte=B57600;
544   break;
545 
546   default:
547   rc=1280;
548   goto close_x;
549   }
550 old_options=options;
551 cfsetispeed(&options,rte);
552 cfsetospeed(&options,rte);
553 //CLOCAL means don’t allow
554 //control of the port to be changed
555 //CREAD says to enable the receiver
556 options.c_cflag|= (CLOCAL | CREAD);
557 // no parity, 2 or 1 stopbits, 8 bits per word
558 options.c_cflag&= ~PARENB; //  no parity=>disable the "enable parity bit" PARENB
559 if(stopbit_flag)
560   {
561   options.c_cflag|= CSTOPB;// =>2 stopbits
562   }
563 else
564   {
565   options.c_cflag&= ~CSTOPB;//=> 1 stopbit
566   }
567 options.c_cflag&= ~CSIZE;   // clear size-bit by anding with negation
568 options.c_cflag|= CS8;      // =>set size to 8 bits per word
569 // raw input /output
570 options.c_oflag &= ~OPOST;
571 options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
572 //Set the timeouts:
573 //VMIN is the minimum amount characters to read
574 options.c_cc[VMIN]=0;
575 //The amount of time to wait
576 //for the amount of data
577 //specified by VMIN in tenths
578 //of a second.
579 options.c_cc[VTIME] = 1;
580 //  Select  flow control  mode
581 switch (rts_mode)
582   {
583   case 0:
584   options.c_cflag &= ~CRTSCTS;       // no handshaking
585   options.c_iflag &= ~IXON;
586   break;
587 
588   case 1:
589   options.c_cflag &= ~CRTSCTS;       // Enable Xon/Xoff software handshaking
590   options.c_iflag |= IXON;
591   break;
592 
593   case 2:
594   options.c_cflag |= CRTSCTS;        // Enable Hardware RTS handshaking
595   options.c_iflag &= ~IXON;
596   break;
597   }
598 //flush I/O  buffers and apply the settings
599 if(tcsetattr(serport, TCSAFLUSH,&options) != 0)
600   {
601   rc=1278;
602 close_x:
603   close(serport);
604   serport=-1;
605   }
606 return rc;
607 }
608 
lir_close_serport(void)609 void lir_close_serport(void)
610 {
611 if(serport == -1)return;
612 if(tcsetattr(serport, TCSAFLUSH,&old_options) != 0)lirerr(1278);
613 close(serport);
614 serport=-1;
615 }
616 
lir_write_serport(void * s,int bytes)617 int lir_write_serport(void *s, int bytes)
618 {
619 return write(serport,s,bytes);
620 }
621 
lir_read_serport(void * s,int bytes)622 int lir_read_serport(void *s, int bytes)
623 {
624 int retnum, nread = 0;
625 while (bytes > 0) {
626 	retnum = read (serport, (char *)(s + nread), bytes);
627 	if (retnum <= 0) return -1;
628 	nread += retnum;
629 	bytes -= retnum;
630 	}
631 return nread;
632 }
633 
lir_parport_permission(int portno)634 int lir_parport_permission(int portno)
635 {
636 int i;
637 // If the user selected USB2LPT16_PORT_NUMBER we will use USB for
638 // the 25 pin parallel port. It may not be permitted in case
639 // the user does not have privileges.
640 // verify that we can open the device.
641 if (wse.parport == USB2LPT16_PORT_NUMBER)
642   {
643   if(!usb2lpt_flag)usb2lpt_flag=open_USB2LPT();
644   return usb2lpt_flag;
645   }
646 #if DARWIN == 0
647 // Get permission to write to the parallel port
648 #ifdef BSD
649 #ifdef i386_set_ioperm
650 i=i386_set_ioperm(portno,4,1);
651 #else
652 i=portno;
653 return FALSE;
654 #endif
655 #else
656 if(portno < 0x400-4)
657   {
658   i=ioperm(portno,4,1);
659   }
660 else
661   {
662   i=iopl(3);
663   }
664 #endif
665 if(i != 0)
666   {
667   lir_text(2,2,"Access to parallel port denied.");
668   lir_text(2,4,"Use sudo or run as root");
669   lir_text(2,6,press_any_key);
670   await_keyboard();
671   clear_screen();
672   return FALSE;
673   }
674 return TRUE;
675 #else
676 i=portno;
677 i=FALSE;
678 return i;
679 #endif
680 }
681 
lir_sched_yield(void)682 void lir_sched_yield(void)
683 {
684 sched_yield();
685 }
686 
win_global_uiparms(int n)687 void win_global_uiparms(int n)
688 {
689 (void) n;
690 // Dummy routine. Not used under Linux.
691 }
692 
linrad_thread_create(int no)693 void linrad_thread_create(int no)
694 {
695 thread_status_flag[no]=THRFLAG_INIT;
696 thread_command_flag[no]=THRFLAG_ACTIVE;
697 pthread_create(&thread_identifier[no],NULL,(void*)thread_routine[no], NULL);
698 threads_running=TRUE;
699 }
700 
fix_prio(int thread)701 void fix_prio(int thread)
702 {
703 #if OSNUM == OSNUM_LINUX
704 int policy;
705 int i, k;
706 if(ui.process_priority != 0)
707   {
708   struct sched_param parms;
709   pthread_getschedparam(thread_identifier[thread],&policy,&parms);
710   policy=SCHED_FIFO;
711   i=sched_get_priority_max(policy);
712   switch (ui.process_priority)
713     {
714     case 3:
715     k=i-1;
716     break;
717 
718     case 2:
719     k=(i+parms.sched_priority)/2;
720     break;
721 
722     default:
723     k=parms.sched_priority+1;
724     if(k > i) k=i;
725     }
726   parms.sched_priority=k;
727   pthread_setschedparam(thread_identifier[thread],policy,&parms);
728   }
729 #endif
730 }
731 
732 
thread_rx_output(void)733 void thread_rx_output(void)
734 {
735 fix_prio(THREAD_RX_OUTPUT);
736 rx_output();
737 thread_status_flag[THREAD_RX_OUTPUT]=THRFLAG_RETURNED;
738 }
739 
thread_kill_all(void)740 void thread_kill_all(void)
741 {
742 // Wait until the event is set.
743 // Then stop all processing threads so main can write any
744 // error code/message and exit.
745 lir_await_event(EVENT_KILL_ALL);
746 kill_all();
747 }
748 
current_time(void)749 double current_time(void)
750 {
751 struct timeval t;
752 gettimeofday(&t,NULL);
753 recent_time=0.000001*t.tv_usec+t.tv_sec;
754 return recent_time;
755 }
756 
ms_since_midnight(int set)757 int ms_since_midnight(int set)
758 {
759 int i;
760 double dt1;
761 dt1=current_time();
762 if(set)netstart_time=dt1;
763 i=dt1/(24*3600);
764 dt1-=24*3600*i;
765 i=1000*dt1;
766 return i%(24*3600000);
767 }
768 
lir_sync(void)769 void lir_sync(void)
770 {
771 // This routine is called to force a write to the hard disk
772 sync();
773 }
774 
775 
lir_get_epoch_seconds(void)776 int lir_get_epoch_seconds(void)
777 {
778 struct timeval tim;
779 gettimeofday(&tim,NULL);
780 return tim.tv_sec;
781 }
782 
lir_join(int no)783 void lir_join(int no)
784 {
785 lir_sched_yield();
786 if(thread_command_flag[no]==THRFLAG_NOT_ACTIVE)return;
787 pthread_join(thread_identifier[no],0);
788 thread_status_flag[no]=THRFLAG_NOT_ACTIVE;
789 }
790 
lir_sleep(int us)791 void lir_sleep(int us)
792 {
793 usleep(us);
794 }
795 
lir_outb(char byte,int port)796 void lir_outb(char byte, int port)
797 {
798 int i;
799 if(libusb1_library_flag == TRUE || libusb0_library_flag == TRUE)
800   {
801   if(wse.parport==USB2LPT16_PORT_NUMBER)
802     {
803     out_USB2LPT(byte,(port-wse.parport));
804     }
805   }
806 else
807   {
808 #if DARWIN == 0
809 #ifdef BSD
810 #ifdef i386_set_ioperm
811   i=i386_set_ioperm(port,4,1);
812 #else
813   return;
814 #endif
815 #else
816   if(port < 0x400-4)
817     {
818     i=ioperm(port,4,1);
819     }
820   else
821     {
822     i=iopl(3);
823     }
824   #endif
825   if(i!=0)lirerr(764921);
826 #ifdef BSD
827     {
828     int k;
829     k=byte;
830     outb(k,port);
831     }
832 #else
833   outb(byte,port);
834 #endif
835 #else
836 i=byte+port;
837 #endif
838   }
839 i=1000;
840 while(i>0)i--;
841 }
842 
lir_inb(int port)843 char lir_inb(int port)
844 {
845 #if DARWIN == 0
846 int i;
847 #endif
848 if(wse.parport==USB2LPT16_PORT_NUMBER)
849   {
850   if(libusb1_library_flag == TRUE || libusb0_library_flag == TRUE)
851     {
852     return in_USB2LPT((port-wse.parport));
853     }
854   else
855     {
856     lirerr(7211332);
857     return 0;
858     }
859   }
860 else
861   {
862 #ifdef BSD
863 #ifdef i386_set_ioperm
864   i=i386_set_ioperm(port,4,1);
865 #else
866   return 0;
867 #endif
868 #else
869 #if DARWIN == 0
870   if(port < 0x400-4)
871     {
872     i=ioperm(port,4,1);
873     }
874   else
875     {
876     i=iopl(3);
877     }
878 #endif
879 #endif
880 #if DARWIN == 0
881 if(i!=0)lirerr(764921);
882 return inb(port);
883 #endif
884   }
885 return port;
886 }
887 
lir_random(void)888 float lir_random(void)
889 {
890 return (float)(random())/(float)RAND_MAX;
891 }
892 
lir_srandom(void)893 void lir_srandom(void)
894 {
895 unsigned int seed;
896 seed=current_time();
897 srandom(seed);
898 }
899 
900 // *********************************************************************
901 // Thread entries for Linux
902 // *********************************************************************
903 
thread_main_menu(void)904 void thread_main_menu(void)
905 {
906 main_menu();
907 }
908 
thread_tune(void)909 void thread_tune(void)
910 {
911 tune();
912 }
913 
thread_sdr14_input(void)914 void thread_sdr14_input(void)
915 {
916 fix_prio(THREAD_SDR14_INPUT);
917 sdr14_input();
918 }
919 
thread_radar(void)920 void thread_radar(void)
921 {
922 fix_prio(THREAD_RADAR);
923 run_radar();
924 }
925 
thread_blocking_rxout(void)926 void thread_blocking_rxout(void)
927 {
928 fix_prio(THREAD_BLOCKING_RXOUT);
929 blocking_rxout();
930 }
931 
thread_write_raw_file(void)932 void thread_write_raw_file(void)
933 {
934 write_raw_file();
935 }
936 
thread_perseus_input(void)937 void thread_perseus_input(void)
938 {
939 fix_prio(THREAD_PERSEUS_INPUT);
940 perseus_input();
941 }
942 
thread_rtl2832_input(void)943 void thread_rtl2832_input(void)
944 {
945 fix_prio(THREAD_RTL2832_INPUT);
946 rtl2832_input();
947 }
948 
thread_mirics_input(void)949 void thread_mirics_input(void)
950 {
951 fix_prio(THREAD_MIRISDR_INPUT);
952 mirics_input();
953 }
954 
thread_bladerf_input(void)955 void thread_bladerf_input(void)
956 {
957 fix_prio(THREAD_BLADERF_INPUT);
958 bladerf_input();
959 }
960 
thread_pcie9842_input(void)961 void thread_pcie9842_input(void)
962 {
963 fix_prio(THREAD_PCIE9842_INPUT);
964 pcie9842_input();
965 }
966 
thread_openhpsdr_input(void)967 void thread_openhpsdr_input(void)
968 {
969 fix_prio(THREAD_OPENHPSDR_INPUT);
970 openhpsdr_input();
971 }
972 
thread_hware_command(void)973 void thread_hware_command(void)
974 {
975 hware_command();
976 }
977 
thread_sdrip_input(void)978 void thread_sdrip_input(void)
979 {
980 fix_prio(THREAD_SDRIP_INPUT);
981 sdrip_input();
982 }
983 
thread_netafedri_input(void)984 void thread_netafedri_input(void)
985 {
986 fix_prio(THREAD_NETAFEDRI_INPUT);
987 netafedri_input();
988 }
989 
thread_excalibur_input(void)990 void thread_excalibur_input(void)
991 {
992 fix_prio(THREAD_EXCALIBUR_INPUT);
993 excalibur_input();
994 }
995 
thread_cal_filtercorr(void)996 void thread_cal_filtercorr(void)
997 {
998 cal_filtercorr();
999 }
1000 
thread_cal_interval(void)1001 void thread_cal_interval(void)
1002 {
1003 do_cal_interval();
1004 }
1005 
thread_user_command(void)1006 void thread_user_command(void)
1007 {
1008 user_command();
1009 }
1010 
thread_narrowband_dsp(void)1011 void thread_narrowband_dsp(void)
1012 {
1013 fix_prio(THREAD_NARROWBAND_DSP);
1014 narrowband_dsp();
1015 }
1016 
thread_do_fft1c(void)1017 void thread_do_fft1c(void)
1018 {
1019 fix_prio(THREAD_DO_FFT1C);
1020 do_fft1c();
1021 }
1022 
thread_fft1b(void)1023 void thread_fft1b(void)
1024 {
1025 do_fft1b();
1026 }
1027 
thread_wideband_dsp(void)1028 void thread_wideband_dsp(void)
1029 {
1030 fix_prio(THREAD_WIDEBAND_DSP);
1031 wideband_dsp();
1032 }
1033 
thread_second_fft(void)1034 void thread_second_fft(void)
1035 {
1036 fix_prio(THREAD_SECOND_FFT);
1037 second_fft();
1038 }
1039 
thread_timf2(void)1040 void thread_timf2(void)
1041 {
1042 fix_prio(THREAD_TIMF2);
1043 timf2_routine();
1044 }
1045 
thread_tx_input(void)1046 void thread_tx_input(void)
1047 {
1048 fix_prio(THREAD_TX_INPUT);
1049 tx_input();
1050 }
1051 
thread_tx_output(void)1052 void thread_tx_output(void)
1053 {
1054 fix_prio(THREAD_TX_OUTPUT);
1055 run_tx_output();
1056 }
1057 
thread_screen(void)1058 void thread_screen(void)
1059 {
1060 screen_routine();
1061 }
1062 
thread_rx_file_input(void)1063 void thread_rx_file_input(void)
1064 {
1065 fix_prio(THREAD_RX_FILE_INPUT);
1066 rx_file_input();
1067 }
1068 
thread_cal_iqbalance(void)1069 void thread_cal_iqbalance(void)
1070 {
1071 cal_iqbalance();
1072 }
1073 
thread_rx_adtest(void)1074 void thread_rx_adtest(void)
1075 {
1076 rx_adtest();
1077 }
1078 
thread_powtim(void)1079 void thread_powtim(void)
1080 {
1081 powtim();
1082 }
1083 
thread_txtest(void)1084 void thread_txtest(void)
1085 {
1086 txtest();
1087 }
1088 
thread_syscall(void)1089 void thread_syscall(void)
1090 {
1091 do_syscall();
1092 }
1093 
thread_extio_input(void)1094 void thread_extio_input(void)
1095 {
1096 fix_prio(THREAD_EXTIO_INPUT);
1097 extio_input();
1098 }
1099 
thread_rtl_starter(void)1100 void thread_rtl_starter(void)
1101 {
1102 rtl_starter();
1103 }
1104 
thread_mirisdr_starter(void)1105 void thread_mirisdr_starter(void)
1106 {
1107 mirisdr_starter();
1108 }
1109 
thread_bladerf_starter(void)1110 void thread_bladerf_starter(void)
1111 {
1112 bladerf_starter();
1113 }
1114 
thread_html_server(void)1115 void thread_html_server(void)
1116 {
1117 #if SERVER == 1
1118 html_server();
1119 #endif
1120 }
1121 
1122