試験運用中なLinux備忘録・旧記事

はてなダイアリーで公開していた2007年5月-2015年3月の記事を保存しています。

Linux上におけるフォースフィードバックの振動の低レベル制御に関するメモ(後半)

Linux上におけるフォースフィードバックの振動の低レベル制御に関するメモ(前半)」の続き。

振動の設定(effect)とその送信(upload)

振動の設定はstruct ff_effect型構造体(effect)を用いて行う。この型はフォースフィードバックにおける振動以外の種類にも共通しているが、メンバu.rumble以下を用いて振動固有のパラメータ(strong_magnitude,weak_magnitude)を設定することになる。uは共用体(union)で、振動以外の種類に固有のパラメータ(constant,ramp,periodic,conditionのいずれか)と同時には指定できない(する必要/意味もない)。種類を振動と指定するにはメンバtypeを「FF_RUMBLE」にする。また、replay.lengthで長さ,replay.delayで開始までの時間も設定できる。

struct ff_effect effect;
effect.type = FF_RUMBLE;
effect.id = -1;
effect.u.rumble.strong_magnitude = [強い作動装置の振動の規模 0-0xffff(65535)];
effect.u.rumble.weak_magnitude = [弱い作動装置の振動の規模 0-0xffff(65535)];
effect.replay.length = [長さ(ミリ秒)];
effect.replay.delay = [開始までの時間(ミリ秒)];

メンバidについてはまだ設定が送信(upload)されていなければ「-1」にする。送信後にこのメンバには固有のIDが入り、id以外のメンバの値(effect設定)を変更して再びこれを送信した場合、前の設定を上書きすることができる。
設定を送信するにはioctl()でEVIOCSFFというマクロと設定の構造体の場所を指定する。

if (ioctl (fd_eventdev, EVIOCSFF, &effect) == -1)
{
  /* 送信失敗した場合 */
}
/* ここでeffect.idには固有のIDが入っている */

...

/* パラメータを変更して同じIDで送信(前の設定を上書き) */
effect.u.rumble.strong_magnitude = [強い作動装置の振動の規模];
effect.u.rumble.weak_magnitude = [弱い作動装置の振動の規模];
effect.replay.length = [長さ(ミリ秒)];
effect.replay.delay = [開始までの時間(ミリ秒)];
if (ioctl (fd_eventdev, EVIOCSFF, &effect) == -1)
{
  /* 送信に失敗した場合の処理 */
}
同時に保持できる設定(effect)数

設定(effect)は複数個続けて(idを-1として)送信することで同時に保持できるが、その数には上限がある。この数はマクロEVIOCGEFFECTSを用いて下のようにして調べることができる。fftestでは「Number of simultaneous effects:」の右に表示される。

int num_of_effects;
if (ioctl(fd_eventdev, EVIOCGEFFECTS, &num_of_effects) == -1)
{
  /* 問い合わせに失敗したときの処理 */
}
/* ここでnum_of_effectsにはeffectの同時保持数の上限が入っている */
設定(effect)を削除する

送信済みの設定を削除するためにはマクロEVIOCRMFFとID番号を用いて以下のようにする。

if (ioctl(fd_eventdev, EVIOCRMFF, [ID番号]) == -1)
{
  /* 送信に失敗した場合の処理 */
}

effectの構造体を用いて指定する場合はそのメンバidを用いて

if (ioctl(fd_eventdev, EVIOCRMFF, effect.id) == -1)
{
  /* 送信に失敗した場合の処理 */
}

のようにする。

フォースフィードバックイベント(開始/停止)の送信

ここまでを行っても振動は行われないが、振動開始のイベントを送信すると、replay.delayの時間経過した後で振動が開始し、replay.lengthの時間振動が続く。
振動開始のイベントはstruct input_event型構造体を用いて下のようにして送信する。

struct input_event play;
play.type = EV_FF;
play.code = effect.id;
play.value = 1;
if (write (fd_eventdev, (const void *) &play, sizeof (play)) == -1)
{
  /* イベント送信に失敗したときの処理 */
}

途中で振動を止めたい場合はstruct input_event型構造体のメンバvalueを0にしたものを同様にして送信する。

struct input_event play;
play.type = EV_FF;
play.code = effect.id;
play.value = 0;
if (write (fd_eventdev, (const void *) &play, sizeof (play)) == -1)
{
  /* イベント送信に失敗したときの処理 */
}

ファイル記述子を閉じる

バイスをプログラムから用いなくなったら、イベントファイルのファイル記述子を閉じる。

close (fd_eventdev);

関連記事:

使用したバージョン: