dpdk: Add support for Mellanox ConnectX-4 devices
[vpp.git] / g2 / pointsel.c
1 /* 
2  *------------------------------------------------------------------
3  * Copyright (c) 2005-2016 Cisco and/or its affiliates.
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <strings.h>
20 #include <ctype.h>
21 #include <string.h>
22 #include <gtk/gtk.h>
23 #include "g2.h"
24
25 /*
26  * globals
27  */
28 event_def_t g_eventdefs[NEVENTS];
29
30 /*
31  * locals
32  */
33 static GtkWidget *s_pointselbox;
34 static FILE *s_hfp;
35 static FILE *s_elog_hfp;
36 static int s_basenum;
37 static GtkWidget *s_event_buttons[NEVENTS];
38 static int s_min_shown_pointsel;
39 static int s_max_shown_pointsel;
40 static GtkWidget *s_allbutton;
41 static GtkWidget *s_nonebutton;
42 static GtkWidget *s_pointselbuttons;
43 static GtkWidget *s_ps_vscroll;
44 static GtkObject *s_ps_vsadj;
45 static int g_neventdefs;
46
47 enum button_click {
48     ALL_BUTTON=1,
49     NONE_BUTTON,
50 };
51
52 /*
53  * config params
54  */
55 int c_maxpointsel;
56
57 /****************************************************************************
58 * recompute_vscrollbar
59 ****************************************************************************/
60
61 static void recompute_ps_vscrollbar (void)
62 {
63     GtkAdjustment *adj;
64     ulong limit;
65
66     adj = GTK_ADJUSTMENT(s_ps_vsadj);
67
68 #ifdef NOTDEF
69     /* This seems like the right calculation, but seems not to work */
70     if (g_neventdefs > c_maxpointsel)
71         limit = g_neventdefs - c_maxpointsel;
72     else
73         limit = g_neventdefs;
74 #else
75     limit = g_neventdefs-1;
76 #endif
77
78     adj->lower = (gfloat)0.00;
79     adj->upper = (gfloat)limit;
80     adj->value = (gfloat)0.00;
81     adj->step_increment = (gfloat)1.00;
82     adj->page_increment = (gfloat)(c_maxpointsel / 3);
83     adj->page_size = (gfloat)c_maxpointsel;
84     gtk_adjustment_changed(adj);
85     gtk_adjustment_value_changed(adj);
86     gtk_widget_show(s_ps_vscroll);
87 }
88
89 /****************************************************************************
90 * point_select_callback
91 ****************************************************************************/
92
93 static void point_select_callback(GtkToggleButton *item, gpointer data)
94 {
95     int i = (int) (unsigned long long) data;
96
97     g_eventdefs[i].selected = gtk_toggle_button_get_active(
98         GTK_TOGGLE_BUTTON(s_event_buttons[i]));
99     view1_display_when_idle();
100 }
101
102 /****************************************************************************
103 * up_button
104 ****************************************************************************/
105
106 static void up_button(void)
107 {
108     int i;
109     int increment = c_maxpointsel/4;
110
111     if (s_min_shown_pointsel == 0)
112         return;
113
114     s_min_shown_pointsel -= increment;
115
116     if (s_min_shown_pointsel < 0)
117         s_min_shown_pointsel = 0;
118
119     s_max_shown_pointsel = s_min_shown_pointsel + c_maxpointsel;
120
121     for (i = 0; i < g_neventdefs; i++) {
122         if (i >= s_min_shown_pointsel &&
123             i <= s_max_shown_pointsel)
124             gtk_widget_show(s_event_buttons[i]);
125         else
126             gtk_widget_hide(s_event_buttons[i]);
127     }
128
129 }
130
131 #ifdef NOTDEF
132 /****************************************************************************
133 * down_button
134 ****************************************************************************/
135
136 static void down_button(void)
137 {
138     int i;
139     int increment = c_maxpointsel/4;
140
141     if (s_max_shown_pointsel == g_neventdefs)
142         return;
143
144     s_max_shown_pointsel += increment;
145
146     if (s_max_shown_pointsel >= g_neventdefs)
147         s_max_shown_pointsel = (g_neventdefs-1);
148
149     s_min_shown_pointsel = s_max_shown_pointsel - c_maxpointsel;
150
151     if (s_min_shown_pointsel < 0)
152         s_min_shown_pointsel = 0;
153
154     for (i = 0; i < g_neventdefs; i++) {
155         if (i >= s_min_shown_pointsel &&
156             i <= s_max_shown_pointsel)
157             gtk_widget_show(s_event_buttons[i]);
158         else
159             gtk_widget_hide(s_event_buttons[i]);
160     }
161
162 }
163 #endif
164
165 /****************************************************************************
166 * button_click_callback
167 ****************************************************************************/
168
169 static void button_click_callback(GtkButton *item, gpointer data)
170 {
171     int i;
172     enum button_click click = (enum button_click)data;
173
174     switch (click) {
175     case ALL_BUTTON:
176         for (i = 0; i < g_neventdefs; i++) {
177             gtk_toggle_button_set_active (
178                 GTK_TOGGLE_BUTTON(s_event_buttons[i]), TRUE);
179             g_eventdefs[i].selected = TRUE;
180         }
181         break;
182
183     case NONE_BUTTON:
184         for (i = 0; i < g_neventdefs; i++) {
185             gtk_toggle_button_set_active (
186                 GTK_TOGGLE_BUTTON(s_event_buttons[i]), FALSE);
187             g_eventdefs[i].selected = FALSE;
188         }
189         break;
190     }
191 }
192
193 /****************************************************************************
194 * scroll_callback
195 ****************************************************************************/
196
197 static void scroll_callback (GtkAdjustment *adj, GtkWidget *notused)
198 {
199     int i;
200
201     s_min_shown_pointsel = (int)adj->value;
202     s_max_shown_pointsel = s_min_shown_pointsel + c_maxpointsel;
203
204     for (i = 0; i < g_neventdefs; i++) {
205         if (i >= s_min_shown_pointsel &&
206             i <= s_max_shown_pointsel)
207             gtk_widget_show(s_event_buttons[i]);
208         else
209             gtk_widget_hide(s_event_buttons[i]);
210     }
211 }
212
213 /****************************************************************************
214 * point_selector_init
215 ****************************************************************************/
216
217 void point_selector_init(void)
218 {
219
220     c_maxpointsel = atol(getprop_default("event_selector_lines", "20"));
221
222     s_pointselbox = gtk_vbox_new(FALSE,5);
223
224     s_pointselbuttons = gtk_hbox_new(FALSE,5);
225
226     s_allbutton = gtk_button_new_with_label("ALL");
227     gtk_widget_show(s_allbutton);
228     s_nonebutton = gtk_button_new_with_label("NONE");
229     gtk_widget_show(s_nonebutton);
230
231     gtk_signal_connect (GTK_OBJECT(s_allbutton), "clicked",
232                         GTK_SIGNAL_FUNC(button_click_callback), 
233                         (gpointer) ALL_BUTTON);
234
235     gtk_signal_connect (GTK_OBJECT(s_nonebutton), "clicked",
236                         GTK_SIGNAL_FUNC(button_click_callback), 
237                         (gpointer) NONE_BUTTON);
238
239     gtk_box_pack_start(GTK_BOX(s_pointselbuttons), s_allbutton, FALSE, 
240                        FALSE, 0);
241     gtk_box_pack_start(GTK_BOX(s_pointselbuttons), s_nonebutton, FALSE, 
242                        FALSE, 0);
243     
244     gtk_widget_show(s_pointselbuttons);
245     gtk_widget_ref(s_pointselbuttons); 
246
247     gtk_box_pack_start(GTK_BOX(s_pointselbox), s_pointselbuttons, FALSE, 
248                        FALSE, 0);
249
250     gtk_box_pack_end (GTK_BOX(g_mainhbox), s_pointselbox, 
251                        FALSE, FALSE, 0);
252
253     s_ps_vsadj = gtk_adjustment_new(0.0 /* initial value */, 
254                                     0.0 /* minimum value */,
255                                     2000.0 /* maximum value */,
256                                     0.1 /* step increment */, 
257                                     10.0/* page increment */, 
258                                     10.0/* page size */);
259     
260     s_ps_vscroll = gtk_vscrollbar_new (GTK_ADJUSTMENT(s_ps_vsadj));
261     gtk_signal_connect (GTK_OBJECT (s_ps_vsadj), "value-changed",
262                         GTK_SIGNAL_FUNC (scroll_callback), 
263                         (gpointer)s_ps_vscroll);
264     gtk_box_pack_end(GTK_BOX(g_mainhbox), s_ps_vscroll, FALSE, FALSE, 0);
265 }
266
267 /****************************************************************************
268 * sxerox
269 ****************************************************************************/
270
271 char *sxerox (char *s)
272 {
273     char *rv;
274
275     /* Note: g_malloc does or dies... */
276     rv = (char *)g_malloc(strlen(s)+1);
277     strcpy (rv, s);
278     return (rv);
279 }
280
281 /****************************************************************************
282 * reset_point_selector
283 ****************************************************************************/
284
285 static void reset_point_selector(void)
286 {
287     int i;
288
289     gtk_widget_hide(s_pointselbox);
290     gtk_widget_hide(s_pointselbuttons);
291     gtk_widget_hide(s_ps_vscroll);
292     gtk_container_remove(GTK_CONTAINER(s_pointselbox), 
293                          s_pointselbuttons);
294     
295     for (i = 0; i < g_neventdefs; i++) {
296         if (s_event_buttons[i]) {
297             gtk_container_remove(GTK_CONTAINER(s_pointselbox), 
298                                  s_event_buttons[i]);
299             s_event_buttons[i] = 0;
300         }
301     }
302 }
303
304 /****************************************************************************
305 * create_point_selector
306 ****************************************************************************/
307
308 static void create_point_selector(void)
309 {
310     int i;
311     char tmpbuf [1024];
312     event_def_t *ep;
313     GtkWidget *wp;
314
315     for (i = 0; i < g_neventdefs; i++) {
316         ep = &g_eventdefs[i];
317         sprintf(tmpbuf, "[%lu] %s", ep->event, 
318                 ep->name ? ep->name : "(none)");
319         /* Hack to reduce width of point selectors */
320         if (strlen(tmpbuf) > 50) {
321             tmpbuf[50] = 0;
322         }
323
324         wp = gtk_check_button_new_with_label (tmpbuf);
325         s_event_buttons[i] = wp;
326         gtk_signal_connect (GTK_OBJECT(wp), "toggled",
327                             GTK_SIGNAL_FUNC(point_select_callback), 
328                             (gpointer) (unsigned long long) i);
329         gtk_toggle_button_set_active (
330             GTK_TOGGLE_BUTTON(wp), TRUE);
331         gtk_box_pack_start(GTK_BOX(s_pointselbox), wp, FALSE, FALSE, 0);
332     }
333
334     /* set up scroll parameters by faking an up-button */
335     s_min_shown_pointsel = 1;
336     up_button();
337
338     gtk_box_pack_start(GTK_BOX(s_pointselbox), s_pointselbuttons, FALSE, 
339                        FALSE, 0);
340     gtk_widget_show(s_pointselbuttons);
341     gtk_widget_show(s_pointselbox);
342     gtk_widget_show(s_ps_vscroll);
343 }
344
345 /****************************************************************************
346 * remove_all_events
347 ****************************************************************************/
348
349 static void remove_all_events(void)
350 {
351     event_def_t *ep;
352     int i;
353
354     for (i = 0; i < g_neventdefs; i++) {
355         ep = &g_eventdefs[i];
356         if (!ep->is_clib) {
357             if (ep->name)
358                 g_free(ep->name);
359             if(ep->format)
360                 g_free(ep->format);
361         }
362     }
363     g_neventdefs = 0;
364 }
365
366 /****************************************************************************
367 * add_event
368 ****************************************************************************/
369
370 static void add_event(ulong event, char *name, char *format)
371 {
372     int i;
373     event_def_t *ep;
374
375     if (g_neventdefs >= NEVENTS) {
376         g_error("Too many event definitions, increase NEVENTS!");
377         /*NOTREACHED*/
378     }
379         
380     /* Simple dup check, probably not needed very often */
381     for (i = 0; i < g_neventdefs; i++) {
382         if (g_eventdefs[i].event == event) {
383             g_warning("Duplicate def event %lu: first definition retained\n",
384                       event);
385             return;
386         }
387     }
388
389     ep = &g_eventdefs[g_neventdefs++];
390
391     ep->event = event;
392     ep->name = sxerox(name);
393     ep->format = sxerox(format);
394     ep->selected = TRUE;
395 }
396
397 /****************************************************************************
398 * add_event_from_cpel_file
399 ****************************************************************************/
400
401 void add_event_from_cpel_file(ulong event, char *event_format, 
402                               char *datum_format)
403 {
404     event_def_t *ep;
405
406     if (g_neventdefs >= NEVENTS) {
407         g_error("Too many event definitions, increase NEVENTS!");
408         /*NOTREACHED*/
409     }
410
411     ep = &g_eventdefs[g_neventdefs++];
412
413     ep->event = event;
414     /*
415      * Duplicate the strings for backward compatibility. Otherwise,
416      * the g_free above will barf because the name/format strings are
417      * actually in mmap'ed memory 
418      */
419     ep->name = sxerox(event_format);
420     ep->format = sxerox(datum_format);
421     ep->selected = TRUE;
422 }
423
424 /****************************************************************************
425 * add_event_from_clib_file
426 ****************************************************************************/
427
428 void add_event_from_clib_file(unsigned int event, char *name, 
429                               unsigned int vec_index)
430 {
431     event_def_t *ep;
432
433     if (g_neventdefs >= NEVENTS) {
434         g_error("Too many event definitions, increase NEVENTS!");
435         /*NOTREACHED*/
436     }
437
438     ep = &g_eventdefs[g_neventdefs++];
439
440     ep->event = event;
441
442     ep->name = sxerox(name);
443     ep->format = (void *)(unsigned long long) vec_index;
444     ep->selected = TRUE;
445     ep->is_clib = TRUE;
446 }
447
448 /****************************************************************************
449 * read_header_file - eats header file lines of the form
450 *
451 *     #define EVENT_FOO  123    / * name: %d * /
452 *
453 ****************************************************************************/
454
455 static void read_header_file (void)
456 {
457     char tmpbuf [1024];
458     char *name, *format;
459     char *cp;
460     unsigned long event;
461     int ev_num_flag;
462
463     while (fgets (tmpbuf, sizeof (tmpbuf), s_hfp))
464     {
465         cp = tmpbuf;
466         ev_num_flag = 0;
467
468         if (strncmp (cp, "#define", 7))
469             continue;
470
471         /* skip #define */
472         while (*cp && !(isspace ((int)*cp)))
473             cp++;
474
475         if (*cp == 0)
476             continue;
477
478         /* skip ws after #define */
479         while (*cp && isspace ((int)*cp))
480             cp++;
481             
482         if (*cp == 0)
483             continue;
484
485         /* skip symbolic name */
486         while (*cp && !(isspace ((int)*cp)))
487             cp++;
488
489         if (*cp == 0)
490             continue;
491
492         /* skip ws after symbolic name */
493         while (*cp && isspace ((int)*cp))
494             cp++;
495             
496         if (*cp == 0)
497             continue;
498
499         event = 0;
500
501         if (!strncmp(cp, "EV_NUM", 6)) {
502             cp += 6;
503             ev_num_flag = 1;
504
505             while (*cp && *cp != '(')
506                 cp++;
507             
508             if (*cp == 0)
509                 continue;
510
511             cp++; 
512
513             while (*cp && isspace ((int)*cp))
514                 cp++;
515             
516         } 
517
518         /* eat event code. */
519         while (*cp && isdigit ((int)*cp))
520         {
521             event = event * 10 + (*cp - '0');
522             cp++;
523         }
524
525         if (*cp == 0)
526             continue;
527
528         if (ev_num_flag) {
529             while (*cp && *cp != ')')
530                 cp++;
531             if (*cp == 0)
532                 continue;
533             cp++;
534             event += s_basenum;
535         }
536
537         /* skip ws after event code */
538         while (*cp && isspace ((int)*cp))
539             cp++;
540             
541         if (*cp != '/')
542             continue;
543
544         cp++;
545
546         if (*cp != '*')
547             continue;
548
549         cp++;
550
551         /* skip ws after comment start */
552         while (*cp && isspace ((int)*cp))
553             cp++;
554
555         if (*cp == 0)
556             continue;
557
558         name = cp;
559
560         /* accumulate name */
561         while (*cp && *cp != ':' && *cp != '*')
562             cp++;
563
564         if (*cp == 0)
565             continue;
566
567         *cp++ = 0;
568         
569         /* skip ws after name: */
570         while (*cp && isspace ((int)*cp))
571             cp++;
572         
573         if (*cp == 0 || *cp == '/')
574         {
575             format = " ";
576             goto write_it;
577         }
578
579         format = cp;
580         
581         /* accumulate format string */
582         while (*cp && !isspace ((int)*cp))
583             cp++;
584
585         *cp = 0;
586
587     write_it:
588
589         add_event (event, name, format);
590     }
591 }
592
593 /****************************************************************************
594 * read_header_files - eats header file lines of the form
595 *
596 *     #define FILE1_BASE  100   / * pointdefs: ../vpn/vpn_points.h * /
597 *
598 ****************************************************************************/
599
600 static boolean read_header_files (void)
601 {
602     char *cp, *name;
603     char tmpbuf [1024];
604     int basenum;
605     boolean rv=FALSE;
606
607     while (fgets (tmpbuf, sizeof (tmpbuf), s_elog_hfp))
608     {
609         cp = tmpbuf;
610
611         if (strncmp (cp, "#define", 7))
612             continue;
613
614         cp += 7;
615
616         /* skip ws after #define */
617         while (*cp && isspace ((int)*cp))
618             cp++;
619
620         if (*cp == 0)
621             continue;
622
623         /* skip EV_COMPxxx_START */
624         while (*cp && !isspace((int)*cp))
625             cp++;
626
627         if (*cp == 0)
628             continue;
629
630         /* skip ws after EV_COMPxxx_START */
631         while (*cp && isspace ((int)*cp))
632             cp++;
633         
634         if (*cp == 0)
635             continue;
636         
637         basenum = atol (cp);
638         
639         /* skip #define */
640         while (*cp && (*cp != '/'))
641             cp++;
642
643         if (*cp == 0)
644             continue;
645
646         cp++;
647         if (*cp != '*')
648             continue;
649
650         cp++;
651
652         /* skip ws after comment start */
653         while (*cp && isspace ((int)*cp))
654             cp++;
655
656         if (*cp == 0)
657             continue;
658
659         if (strncmp (cp, "pointdefs:", 10))
660             continue;
661
662         cp += 10;
663
664         /* skip ws after comment start */
665         while (*cp && isspace ((int)*cp))
666             cp++;
667
668         name = cp;
669
670         while (*cp && !isspace ((int)*cp))
671             cp++;
672        
673         *cp = 0;
674
675         s_hfp = fopen (name, "rt");
676
677         if (s_hfp == NULL) {
678             g_warning ("Couldn't open header file %s\n", name);
679             continue;
680         }
681         rv = TRUE;
682
683         s_basenum = basenum;
684
685         read_header_file();
686
687         fclose (s_hfp);
688     }
689     return(rv);
690 }
691
692 /****************************************************************************
693 * event_def_cmp
694 ****************************************************************************/
695
696 int event_def_cmp(const void *a1, const void *a2)
697 {
698     event_def_t *e1 = (event_def_t *)a1;
699     event_def_t *e2 = (event_def_t *)a2;
700
701     if (e1->event < e2->event)
702         return(-1);
703     else if (e1->event == e2->event)
704         return(0);
705     else
706         return(1);
707 }
708
709 /****************************************************************************
710 * sort_event_definitions
711 ****************************************************************************/
712
713 void sort_event_definitions(void)
714 {
715     qsort(&g_eventdefs[0], g_neventdefs, sizeof(event_def_t), event_def_cmp);
716 }
717
718 static boolean remove_needed=TRUE;
719
720 void finalize_events(void)
721 {
722     sort_event_definitions();
723     create_point_selector();
724     recompute_ps_vscrollbar();
725     view1_display_when_idle();
726     remove_needed = TRUE;
727 }
728
729 void initialize_events(void)
730 {
731     if (remove_needed) {
732         reset_point_selector();
733         remove_all_events();
734         remove_needed = FALSE;
735     }
736 }
737
738 /****************************************************************************
739 * read_event_definitions
740 ****************************************************************************/
741
742 boolean read_event_definitions (char *filename)
743 {
744     char tmpbuf [128];
745
746     initialize_events();
747
748     s_elog_hfp = fopen (filename, "rt");
749     if (s_elog_hfp == NULL) {
750         sprintf (tmpbuf, "Couldn't open %s\n", filename);
751         infobox ("Open Failed", tmpbuf);
752         return(FALSE);
753     }
754     /* Presume "elog.h".  Note fallthrough... */
755     if (read_header_files()) {
756         sort_event_definitions();
757         create_point_selector();
758         recompute_ps_vscrollbar();
759         fclose(s_elog_hfp);
760         view1_display_when_idle();
761         remove_needed = TRUE;
762         return(TRUE);
763     }
764     fclose(s_elog_hfp);
765
766     s_hfp = fopen (filename, "rt");
767     if (s_hfp == NULL) {
768         sprintf (tmpbuf, "Couldn't open %s\n", filename);
769         infobox ("Read Event Definition Failure", tmpbuf);
770         return(FALSE);
771     }
772
773     read_header_file();
774
775     /* Happens if the user feeds us the wrong file, for example */
776     if (g_neventdefs == 0) {
777         sprintf (tmpbuf, "No event definitions found in %s\n", filename);
778         infobox ("No Event Definitions?", tmpbuf);
779         return(FALSE);
780     }
781     finalize_events();
782     return(TRUE);
783 }
784
785 static event_def_t dummy_event;
786 static char dummy_string[32];
787
788 /****************************************************************************
789 * find_event_definition
790 * Binary search for first event whose time is >= t
791 ****************************************************************************/
792
793 event_def_t *find_event_definition (ulong code)
794 {
795     int index, bottom, top;
796     event_def_t *edp;
797
798     if (g_neventdefs == 0)
799         goto use_dummy;
800
801     bottom = g_neventdefs-1;
802     top = 0;
803
804     while (1) {
805         index = (bottom + top) / 2;
806
807         edp = (g_eventdefs + index);
808         
809         if (edp->event == code)
810             return(edp);
811
812         if (top >= bottom) {
813         use_dummy:
814             edp = &dummy_event;
815             edp->selected = TRUE;
816             edp->event = code;
817             edp->format = "0x%x";
818             sprintf (dummy_string, "E%lu", code);
819             edp->name = &dummy_string[0];
820             return(edp);
821         }
822
823         if (edp->event < code)
824             top = index + 1;
825         else 
826             bottom = index - 1;
827     }
828 }
829
830 /****************************************************************************
831 * pointsel_next_snapshot
832 * Set dialog buttons from snapshot
833 ****************************************************************************/
834
835 void pointsel_next_snapshot(void)
836 {
837     int i;
838     
839     for (i = 0; i < g_neventdefs; i++) {
840         gtk_toggle_button_set_active (
841             GTK_TOGGLE_BUTTON(s_event_buttons[i]), 
842             g_eventdefs[i].selected);
843     }
844 }
845
846 /****************************************************************************
847 * pointsel_about
848 ****************************************************************************/
849
850 void pointsel_about (char *tmpbuf)
851 {
852     sprintf (tmpbuf+strlen(tmpbuf), "%d event definitions\n", 
853              g_neventdefs);
854 }