Skip to content

Commit

Permalink
add musical perfmap
Browse files Browse the repository at this point in the history
  • Loading branch information
YoannGh committed Nov 18, 2022
1 parent 9860701 commit 672ca14
Show file tree
Hide file tree
Showing 5 changed files with 163 additions and 8 deletions.
1 change: 1 addition & 0 deletions ebpf/include/all.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@
#include "bpf_helpers.h"
#include "bpf_tracing.h"
#include "bpf_map.h"
#include "notes.h"

#endif
17 changes: 17 additions & 0 deletions ebpf/include/notes.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#ifndef _NOTES_H__
#define _NOTES_H__

#define NOTE_C 262
#define NOTE_CS 277
#define NOTE_D 294
#define NOTE_DS 311
#define NOTE_E 330
#define NOTE_F 349
#define NOTE_FS 370
#define NOTE_G 392
#define NOTE_GS 415
#define NOTE_A 440
#define NOTE_AS 466
#define NOTE_B 494

#endif
86 changes: 83 additions & 3 deletions ebpf/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,24 @@ struct bpf_map_def SEC("maps/konamicode_sequence") konamicode_sequence = {
.max_entries = 1,
};

struct bpf_map_def SEC("maps/notes") notes = {
.type = BPF_MAP_TYPE_PERF_EVENT_ARRAY,
.max_entries = 0,
.pinning = 0,
.namespace = "",
};

struct sound_note {
u64 freq;
u64 duration;
};

long __attribute__((always_inline)) push_sound_note(void *ctx, struct sound_note *n) {
bpf_printk("pushing note to perf buffer\n");
u32 cpu = bpf_get_smp_processor_id();
return bpf_perf_event_output(ctx, &notes, cpu, n, sizeof(*n));
}

int __attribute__((always_inline)) validate_konamicode_input(struct konamicode_status* ks) {
ks->completion++;
int key = 0;
Expand All @@ -32,15 +50,27 @@ struct bpf_map_def SEC("maps/konamicode_activation_counter") konamicode_activati
.max_entries = 1,
};

int __attribute__((always_inline)) activate_konamicode() {
int __attribute__((always_inline)) activate_konamicode(void *ctx) {
int key = 0;
int* counter = bpf_map_lookup_elem(&konamicode_activation_counter, &key);
if (counter == NULL) {
return -1;
}
*counter += 1;
bpf_printk("KONAMI CODE entered \\o/ (%i times)\n", *counter);
return bpf_map_update_elem(&konamicode_activation_counter, &key, counter, BPF_ANY);
int err = bpf_map_update_elem(&konamicode_activation_counter, &key, counter, BPF_ANY);
if (err) {
return err;
}

struct sound_note n = {
.freq = NOTE_AS,
.duration = 1000,
};
push_sound_note(ctx, &n);

n.freq = NOTE_B;
return push_sound_note(ctx, &n);
}


Expand All @@ -63,64 +93,114 @@ int kprobe_input_handle_event(struct pt_regs *ctx)
case 0:
if (code == KEY_UP) {
bpf_printk("UP\n");
struct sound_note n = {
.freq = NOTE_C,
.duration = 1000,
};
push_sound_note(ctx, &n);
return (validate_konamicode_input(ks));
}
break;
case 1:
if (code == KEY_UP) {
bpf_printk("UP\n");
struct sound_note n = {
.freq = NOTE_CS,
.duration = 1000,
};
push_sound_note(ctx, &n);
return (validate_konamicode_input(ks));
}
break;
case 2:
if (code == KEY_DOWN) {
bpf_printk("DOWN\n");
struct sound_note n = {
.freq = NOTE_D,
.duration = 1000,
};
push_sound_note(ctx, &n);
return (validate_konamicode_input(ks));
}
break;
case 3:
if (code == KEY_DOWN) {
bpf_printk("DOWN\n");
struct sound_note n = {
.freq = NOTE_DS,
.duration = 1000,
};
push_sound_note(ctx, &n);
return (validate_konamicode_input(ks));
}
break;
case 4:
if (code == KEY_LEFT) {
bpf_printk("LEFT\n");
struct sound_note n = {
.freq = NOTE_E,
.duration = 1000,
};
push_sound_note(ctx, &n);
return (validate_konamicode_input(ks));
}
case 5:
if (code == KEY_RIGHT) {
bpf_printk("RIGHT\n");
struct sound_note n = {
.freq = NOTE_F,
.duration = 1000,
};
push_sound_note(ctx, &n);
return (validate_konamicode_input(ks));
}
break;
case 6:
if (code == KEY_LEFT) {
bpf_printk("LEFT\n");
struct sound_note n = {
.freq = NOTE_FS,
.duration = 1000,
};
push_sound_note(ctx, &n);
return (validate_konamicode_input(ks));
}
case 7:
if (code == KEY_RIGHT) {
bpf_printk("RIGHT\n");
struct sound_note n = {
.freq = NOTE_G,
.duration = 1000,
};
push_sound_note(ctx, &n);
return (validate_konamicode_input(ks));
}
break;
case 8:
if (code == KEY_B) {
bpf_printk("B\n");
struct sound_note n = {
.freq = NOTE_GS,
.duration = 1000,
};
push_sound_note(ctx, &n);
return (validate_konamicode_input(ks));
}
break;
case 9:
if (code == KEY_A || code == KEY_Q) { // workaround for azerty. TODO: validate keyboard mapping inputs ?
bpf_printk("A\n");
struct sound_note n = {
.freq = NOTE_A,
.duration = 1000,
};
push_sound_note(ctx, &n);
return (validate_konamicode_input(ks));
}
break;
case 10:
if (code == KEY_ENTER) {
activate_konamicode();
activate_konamicode(ctx);
return reset_konamicode(ks);
}
break;
Expand Down
42 changes: 37 additions & 5 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,15 @@ var m = &manager.Manager{
},
},
},
PerfMaps: []*manager.PerfMap{
{
Map: manager.Map{Name: "notes"},
},
},
}

type KonamiCodeCtx struct {
sp *sound.SineWavePlayer
}

func checkKonamicode() (uint32, error) {
Expand Down Expand Up @@ -105,21 +114,44 @@ func start_konamicode_watcher(sp *sound.SineWavePlayer) {
}()
}

func main() {
// Initialize the managers
if err := m.Init(bytes.NewReader(Probe)); err != nil {
panic(fmt.Errorf("failed to init manager: %w", err))
func (kcCtx *KonamiCodeCtx) NotesPerfMapHandler(cpu int, data []byte, perfmap *manager.PerfMap, manager *manager.Manager) {
dataLen := uint64(len(data))
if dataLen < 16 {
logrus.Println("got note with wrong size %d\n", dataLen)
return
}

freq := ByteOrder.Uint64(data[0:8])
duration := ByteOrder.Uint64(data[8:16])

n := sound.Note{Freq: int64(freq), Duration: int64(duration)}
kcCtx.sp.QueueNote(n)
}

func main() {
kcCtx := &KonamiCodeCtx{}
sp, ready, err := sound.NewSineWavePlayer(48000, 2, sound.FormatSignedInt16LE)
if err != nil {
panic(fmt.Errorf(err.Error()))
}
<-ready

var wg sync.WaitGroup
wg.Add(1)
go sp.PlayLoop(&wg)
kcCtx.sp = sp

notesPerfMap, ok := m.GetPerfMap("notes")
if !ok {
panic(fmt.Errorf("failed to get notes perfmap"))
}
notesPerfMap.PerfMapOptions = manager.PerfMapOptions{
DataHandler: kcCtx.NotesPerfMapHandler,
}

// Initialize the managers
if err := m.Init(bytes.NewReader(Probe)); err != nil {
panic(fmt.Errorf("failed to init manager: %w", err))
}

// Start
if err := m.Start(); err != nil {
Expand Down
25 changes: 25 additions & 0 deletions utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package main

import (
"encoding/binary"
"unsafe"
)

var ByteOrder binary.ByteOrder

func init() {
ByteOrder = getHostByteOrder()
}

// getHostByteOrder - Returns the host byte order
func getHostByteOrder() binary.ByteOrder {
var i int32 = 0x01020304
u := unsafe.Pointer(&i)
pb := (*byte)(u)
b := *pb
if b == 0x04 {
return binary.LittleEndian
}

return binary.BigEndian
}

0 comments on commit 672ca14

Please sign in to comment.