Saya sedang mengembangkan driver umpan balik kekuatan (linux) untuk gamepad yang belum didukung.

Setiap kali aplikasi di ruang pengguna meminta efek ff (mis. gemuruh), fungsi di driver saya dipanggil:

static int foo_ff_play(struct input_dev *dev, void *data, struct ff_effect *effect)

Ini diatur oleh kode berikut di dalam fungsi init saya:

input_set_capability(dev, EV_FF, FF_RUMBLE);
input_ff_create_memless(dev, NULL, foo_ff_play);

Saya mengakses struct ff_effect (yang diteruskan ke fungsi foo_ff_play saya) seperti ini:

static int foo_ff_play(struct input_dev *dev, void *data, struct ff_effect *effect)
{
    u16 length;
    length = effect->replay.length;
    printk(KERN_DEBUG "length: %i", length);

    return 0;
}

Masalahnya adalah, panjang yang dilaporkan (dalam ff_effect->replay) selalu nol.

Itu membingungkan, karena saya menjalankan fftest di perangkat saya, dan fftest pasti menyetel atribut length: https://github.com/flosse/linuxconsole/blob/master/utils/fftest.c (baris 308)

/* a strong rumbling effect */
effects[4].type = FF_RUMBLE;
effects[4].id = -1;
effects[4].u.rumble.strong_magnitude = 0x8000;
effects[4].u.rumble.weak_magnitude = 0;
effects[4].replay.length = 5000;
effects[4].replay.delay = 1000;

Apakah ini ada hubungannya dengan "tanpa anggota"? Mengapa data di ff_replay tampak nol jika tidak?

Terima kasih sebelumnya

1
ataraxis 30 Desember 2017, 15:49

1 menjawab

Jawaban Terbaik

Mengapa struct replay kosong?

Lihat https: //elixir.free-electrons.com/linux/v4.4/source/drivers/input/ff-memless.c#L406 kita menemukan:

static void ml_play_effects(struct ml_device *ml)
{
    struct ff_effect effect;
    DECLARE_BITMAP(handled_bm, FF_MEMLESS_EFFECTS);

    memset(handled_bm, 0, sizeof(handled_bm));

    while (ml_get_combo_effect(ml, handled_bm, &effect))
        ml->play_effect(ml->dev, ml->private, &effect);

    ml_schedule_timer(ml);
}

ml_get_combo_effect menyetel efek dengan memanggil ml_combine_effects., tetapi ml_combine_effects sama sekali tidak menyalin replay.length ke ff_effect struct yang diteruskan ke foo_play_effect kami (setidaknya tidak jika tipe efeknya adalah FF_RUMBLE): https://elixir.free-electrons.com/linux/v4.4/source/drivers/input/ff-memless.c#L286

Itu sebabnya kami tidak dapat membaca ff_replay-data dalam fungsi foo_play_effect kami.

Oke, replay kosong - bagaimana kita bisa menentukan berapa lama kita harus memainkan efeknya (mis. FF_RUMBLE)?

Sepertinya struktur replay adalah sesuatu yang bahkan tidak perlu kita bawa. Ya, fftest menyetel panjangnya dan kemudian mengunggah efeknya ke driver, tetapi jika kita lihat ml_ff_upload (https://elixir.free-electrons.com/linux/v4.4/source/drivers /input/ff-memless.c#L481), kita dapat melihat berikut ini:

if (test_bit(FF_EFFECT_STARTED, &state->flags)) {
    __clear_bit(FF_EFFECT_PLAYING, &state->flags);
    state->play_at = jiffies +
             msecs_to_jiffies(state->effect->replay.delay);
    state->stop_at = state->play_at +
             msecs_to_jiffies(state->effect->replay.length);
    state->adj_at = state->play_at;
    ml_schedule_timer(ml);
}

Artinya, durasi sudah ditangani oleh subsistem input. Ini memulai efek dan juga menghentikannya sesuai kebutuhan.

Selanjutnya bisa kita lihat di https ://elixir.free-electrons.com/linux/v4.4/source/include/uapi/linux/input.h#L279 itu

/*
 * All duration values are expressed in ms. Values above 32767 ms (0x7fff)
 * should not be used and have unspecified results.
 */

Itu berarti kita harus membuat efek kita bermain setidaknya 32767ms. Segala sesuatu yang lain (menghentikan efek sebelumnya) terserah penjadwal - yang bukan bagian kami :D

1
Community 20 Juni 2020, 09:12