Keep device status compatible with Pro.
[fcdcontrol:fcdcontrol-proplus.git] / main.c
1 /* 
2  * FunCube Dongle command line interface
3  * David Pello EA1IDZ 2011
4  * Pieter-Tjerk de Boer PA3FWM Sept. 2011: added LNA gain setting, auto-detect 
5  * of units for frequency, reading current settings from dongle, 
6  * (non-elegant) support for multiple dongles
7  *
8  * This code is licensed under a GNU GPL licensed
9  * See LICENSE for information
10  *
11  */
12 #ifdef FCDPP
13 #define PROGRAM_VERSION "0.4.1-fcdpp"
14 #else
15 #define PROGRAM_VERSION "0.4.1"
16 #endif
17
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <unistd.h>
21 #include <getopt.h>
22 #include <stdint.h>
23 #include "fcd.h"
24 #include "fcdhidcmd.h"
25
26 // based on the #defines for TLGE_P10_0DB etc. from fcdhidcmd.h :
27 double lnagainvalues[]={-5.0,-2.5,-999,-999,0,2.5,5,7.5,10,12.5,15,17.5,20,25,30};
28
29 #include "hidapi.h"
30 extern const unsigned short _usVID;
31 extern const unsigned short _usPID;
32 extern int whichdongle;
33
34 void print_list(void)
35 {
36     // based on code from fcd.c
37     struct hid_device_info *phdi=NULL;
38     //hid_device *phd=NULL;
39     //char *pszPath=NULL;
40
41     // look for all FCDs
42     phdi=hid_enumerate(_usVID,_usPID);
43     if (phdi==NULL)
44     {
45         puts("No FCD found.\n");
46         return;
47     }
48
49     puts("  nr   USB path       firmware   frequency         LNA gain   audio device");
50     //      0    0004:0006:02   18.09      1234.567890 MHz   +20 dB     card2
51
52     // iterate over all FCDs found
53     int idx=0;
54     while (phdi) {
55         whichdongle=idx;
56         printf("  %-3i  %-12s  ",idx, phdi->path);
57         int stat = fcdGetMode();
58         if (stat == FCD_MODE_NONE) printf("No FCD Detected.\n");
59         else if (stat == FCD_MODE_BL) printf("In bootloader mode.\n");
60         else {
61             uint8_t lnagain;
62             uint8_t freq[4];
63             char version[20];
64
65             // read version, frequency, gain
66             fcdGetFwVerStr(version);
67             fcdAppGetParam(FCD_CMD_APP_GET_FREQ_HZ,freq,4);
68             fcdAppGetParam(FCD_CMD_APP_GET_LNA_GAIN,&lnagain,1);
69
70             // try to find the corresponding audio device, by comparing the USB path to USB paths found under /proc/asound
71             char audiopath[16]="(not found)";
72             int usb1=-1,usb2=-1;
73             sscanf(phdi->path,"%i:%i",&usb1,&usb2);
74
75             int i;
76             for (i=0;i<16;i++) {
77                 char s[32];        
78                 sprintf(s,"/proc/asound/card%i/usbbus",i);
79                 FILE *f;
80                 f=fopen(s,"r");
81                 if (f) {
82                     fgets(s,32,f);
83                     int u1=0,u2=0;
84                     sscanf(s,"%i/%i",&u1,&u2);
85                     fclose(f);
86                     if (u1==usb1 && u2==usb2) { sprintf(audiopath,"card%i",i); break; }
87                 }
88             }
89
90             // print our findings
91 #ifdef FCDPP
92             printf(" %-8s   %11.6f MHz   %s    %s\n", version, (*(int *)freq)/1e6, lnagain ? "enabled" : "disabled", audiopath);
93 #else
94             printf(" %-8s   %11.6f MHz   %4g dB     %s\n", version, (*(int *)freq)/1e6, lnagainvalues[lnagain], audiopath);
95 #endif
96         }
97         idx++;
98         phdi = phdi->next;
99     }
100     hid_free_enumeration(phdi);
101 }
102
103
104 const char* program_name;
105
106 void print_help()
107 {
108     printf("FCDcontrol V %s\n", PROGRAM_VERSION);
109     printf("USAGE: %s options [arguments]\n", program_name);
110     printf("     -l   --list                    List all FCDs in the system\n");
111     printf("     -s   --status                  Gets FCD current status\n");
112     printf("     -f   --frequency <frequency>   Sets FCD frequency in MHz\n");
113 #ifdef FCDPP
114     printf("     -g   --gain <gain>                     Enable/disable LNA gain (0 or 1)\n");
115 #else
116     printf("     -g   --gain <gain>                     Sets LNA gain in dB\n");
117     printf("     -c   --correction <correction> Sets frequency correction in ppm\n");
118 #endif
119     printf("     -i   --index <index>           Which dongle to show/set (default: 0, i.e. first)\n");
120     printf("     -h   --help                            Shows this help\n");
121 }
122
123 void print_status()
124 {
125     int stat;
126     char version[20];
127
128     stat = fcdGetMode();
129
130     if (stat == FCD_MODE_NONE)
131     {
132         printf("No FCD Detected.\n");
133         return;
134     }
135     else if (stat == FCD_MODE_BL)
136     {
137         printf("FCD present in bootloader mode.\n");
138         return;
139     }
140     else        
141     {
142         printf("FCD present in application mode.\n");
143         stat = fcdGetFwVerStr(version);
144         printf("FCD firmware version: %s.\n", version);
145         unsigned char b[8];
146         stat = fcdAppGetParam(FCD_CMD_APP_GET_FREQ_HZ,b,8);
147         printf("FCD frequency: %.6f MHz.\n", (*(int *)b)/1e6);
148         stat = fcdAppGetParam(FCD_CMD_APP_GET_LNA_GAIN,b,1);
149 #ifdef FCDPP
150         printf("FCD LNA gain: %s.\n", b[0] == 1 ? "enabled" : "disabled");
151 #else
152                 printf("FCD LNA gain: %g dB.\n", lnagainvalues[b[0]]);
153 #endif
154         return;
155     }
156 }
157
158 int main(int argc, char* argv[])
159 {
160     int stat;
161     int freq = 0;
162     double freqf = 0;
163     int gain = -999;
164     int corr = 0;
165     int dolist = 0;
166     int dostatus = 0;
167
168     /* getopt infrastructure */
169     int next_option;
170     const char* const short_options = "slg:f:c:i:h";
171     const struct option long_options[] =
172     {
173         { "status", 0, NULL, 's' },
174         { "list", 0, NULL, 'l' },
175         { "frequency", 1, NULL, 'f' },
176         { "index", 1, NULL, 'i' },
177         { "gain", 1, NULL, 'g' },
178         { "correction", 1, NULL, 'c' },
179         { "help", 0, NULL, 'h' }
180     };
181
182
183     /* save program name */
184     program_name = argv[0];
185
186     if (argc == 1)
187     {
188         print_help();
189         exit(EXIT_SUCCESS);
190     }
191
192     while(1)
193     {
194         /* call getopt */
195         next_option = getopt_long(argc, argv, short_options, long_options, NULL);
196
197         /* end of the options */
198         if (next_option == -1)
199             break;
200
201         switch (next_option)
202         {
203             case 'h' :
204                 print_help();
205                 exit(EXIT_SUCCESS);
206             case 's' :
207                 dostatus=1;
208                 break;
209             case 'l' :
210                 dolist=1;
211                 break;
212             case 'f' :
213                 freqf = atof(optarg);
214                 break;
215             case 'g' :
216                 gain = atoi(optarg);
217                 break;
218             case 'i' :
219                 whichdongle = atoi(optarg);
220                 break;
221             case 'c' :
222                 corr = atoi(optarg);
223                 break;
224             case '?' :
225                 print_help();
226                 exit(1);
227             default :
228                 abort();
229         }       
230     }
231
232     if (freqf>0) {
233         /* MHz -> Hz */
234         freq = (int)(freqf * 1.0e6f);
235
236         /* calculate frequency */
237         freq *= 1.0 + corr / 1000000.0;
238
239         /* set it */
240         stat = fcdAppSetFreq(freq);
241         if (stat == FCD_MODE_NONE)
242         {
243             printf("No FCD Detected.\n");
244             return 1;
245         }
246         else if (stat == FCD_MODE_BL)
247         {
248             printf("FCD in bootloader mode.\n");
249             return 1;
250         }
251         else    
252         {
253             printf("Freq set to %.6f MHz.\n", freq/1e6);
254         }
255     }
256
257     if (gain>-999) {
258         unsigned char b=0;
259 #ifdef FCDPP
260         b = gain ? 1 : 0;
261 #else
262         while (b<sizeof(lnagainvalues)/sizeof(lnagainvalues[0]) && gain>lnagainvalues[b]+1) b++;
263 #endif
264         stat = fcdAppSetParam(FCD_CMD_APP_SET_LNA_GAIN,&b,1);
265         if (stat == FCD_MODE_NONE) { printf("No FCD Detected.\n"); return 1; }
266         else if (stat == FCD_MODE_BL) { printf("FCD in bootloader mode.\n"); return 1; }
267 #ifdef FCDPP
268         else printf("LNA gain %s.\n", b ? "enabled" : "disabled");
269 #else
270         else printf("LNA gain set to %g dB.\n",lnagainvalues[b]);
271 #endif
272
273     }
274
275     if (dolist) print_list();
276
277     if (dostatus) print_status();
278
279     return EXIT_SUCCESS;
280
281
282 }