/* example1_lid.c */

#include <stdio.h>
#include "erl_driver.h"

typedef struct {
    ErlDrvPort port;
} example_data;

static ErlDrvData example_drv_start(ErlDrvPort port, char *buff)
{
    example_data* d = (example_data*)driver_alloc(sizeof(example_data));
    d->port = port;
    return (ErlDrvData)d;
}

static void example_drv_stop(ErlDrvData handle)
{
    driver_free((char*)handle);
}

static void example_drv_output(ErlDrvData handle, char *buff, int bufflen)
{
    example_data* d = (example_data*)handle;
    char fn = buff[0], arg = buff[1], res;
    if (fn == 1) {
      res = twice(arg);
    } else if (fn == 2) {
      res = sum(buff[1], buff[2]);
    }
    driver_output(d->port, &res, 1);
}

ErlDrvEntry example_driver_entry = {
    NULL,               /* F_PTR init, 未使用 */
    example_drv_start,  /* L_PTR start, ポートのオープン時に呼び出される */
    example_drv_stop,   /* F_PTR stop, ポートのクローズ時に呼び出される */
    example_drv_output, /* F_PTR output, Erlangがポートにデータを送ったときに
			   呼び出される */
    NULL,               /* F_PTR ready_input, 入力ディスクリプタの読み出し
                           準備が整ったときに呼び出される */
    NULL,               /* F_PTR ready_output, 出力ディスクリプタの書き込み
                           準備が整ったときに呼び出される */
    "example1_drv",     /* char *driver_name, open_portの引数 */
    NULL,               /* F_PTR finish, アンロード時に呼び出される */
    NULL,               /* F_PTR control, port_commandコールバック */
    NULL,               /* F_PTR timeout, 予約 */
    NULL                /* F_PTR outputv, 予約 */
};

DRIVER_INIT(example_drv) /* driver_entryで指定した名前と一致しなければならない */
{
    return &example_driver_entry;
}

