Ubuntu18.04でgpg3100のビルド

### これは何?

Ubuntu18.04で[PEX-361316](http://www.interface.co.jp/catalog/prdc.asp?name=PEX-361316)を利用したい。
いくつかモジュールを組み込む必要があるが、カーネルが新しいため、ビルドが必要。ビルドを通す際の記録。
いくつかビルドを通す必要があるが、長くなるため、`gpg3100`のみを取り上げます。

### ビルドを通すまで

```
$ cd ~/work/PEX-361316/gpg3100/x86_64/linux/drivers/src
```

`Makefile`を編集。

```Makefile
CFLAGS += -I$(INCLUDEDIR)
CFLAGS += -fno-pie // 追加
```

`ad_entry.c`を編集。

```ad_entry.c
#include <linux/kconfig.h> // 追加
#include <linux/kernel.h>

//return(MINOR(((struct file *)file)->f_dentry->d_inode->i_rdev));
return(MINOR(((struct file *)file)->f_path.dentry->d_inode->i_rdev));

/* 
ret = get_user_pages(
        current, 
        current->mm, 
        (Buffer & PAGE_MASK),
        mdl->NumberOfPages, 
        Direction, 
        1,
        (struct page **)mdl->PageList, 
        NULL);
*/
if(Direction == WRITE) {
        ret = get_user_pages((Buffer & PAGE_MASK), mdl->NumberOfPages,
                        FOLL_FORCE | FOLL_WRITE, (struct page **)mdl->PageList, NULL);
} else {
        ret = get_user_pages((Buffer & PAGE_MASK), mdl->NumberOfPages,
                        FOLL_FORCE, (struct page **)mdl->PageList, NULL);
}

//page_cache_release((struct page *)mdl->PageList[i]);
put_page((struct page *)mdl->PageList[i]);
// もう1箇所同様に修正

void gpg_ad_add_timer(void *ext, void *function, unsigned long data, unsigned long expires)
{
        PAD_EXTERNAL_STRUCT pExt;

        pExt = (PAD_EXTERNAL_STRUCT)ext;

        /*
        pExt->ad_timer.function = function;
        pExt->ad_timer.data = data;
        */
        timer_setup(&(pExt->ad_timer), function, data); // 追加
        pExt->ad_timer.expires = expires;

        add_timer(&(pExt->ad_timer));
}
```

`make`すると`cp3100.mod.c`が生成され、ビルドエラーで止まる。

```cp3100.mod.c
#include <linux/kconfig.h> // 追加
#include <linux/build-salt.h>
```

ビルドが通る。

```
$ make
...
ld -m elf_x86_64 -r -o cp3100.ko cp3100.o cp3100.mod.o
$ sudo make install
...
mkdir -p /lib/modules/5.0.0-37-generic/misc
cp -f cp3100.ko /lib/modules/5.0.0-37-generic/misc
$
```

### カーネル 5.0.37 から 5.3.26 への対応

カーネルの変化でビルドの通し方がちょっと変わった。
以下以外は5.0.37と同じです。

```ad_entry.c
#include <linux/kconfig.h>
typedef long long __kernel_time64_t; // 追加
```

```cp3100.mod.c
#include <linux/kconfig.h> // 追加( 5.0.37の時も )
typedef long long __kernel_time64_t; // 追加
```

### ロード
```
$ sudo depmod -a
$ sudo modprobe cp3100 
modprobe: ERROR: could not insert 'cp3100': Unknown symbol in module, or unknown parameter (see dmesg)
$ dmesg
...
[ 1026.613494] cp3100: Unknown symbol gpg_outl (err -2)
[ 1026.613506] cp3100: Unknown symbol gpg_iounmap (err -2)
[ 1026.613517] cp3100: Unknown symbol gpg_vfree (err -2)
[ 1026.613528] cp3100: Unknown symbol gpg_copy_from_user (err -2)
[ 1026.613539] cp3100: Unknown symbol gpg_udelay (err -2)
[ 1026.613551] cp3100: Unknown symbol gpg_writew (err -2)
[ 1026.613562] cp3100: Unknown symbol gpg_writel (err -2)
[ 1026.613573] cp3100: Unknown symbol gpg_interruptible_sleep_on (err -2)
[ 1026.613584] cp3100: Unknown symbol gpg_readw (err -2)
[ 1026.613598] cp3100: Unknown symbol signal_pending (err -2)
[ 1026.613609] cp3100: Unknown symbol gpg_get_file_f_version (err -2)
[ 1026.613620] cp3100: Unknown symbol interruptible_sleep_on_timeout (err -2)
[ 1026.613631] cp3100: Unknown symbol gpg_free_irq (err -2)
[ 1026.613644] cp3100: Unknown symbol gpg_inw (err -2)
[ 1026.613657] cp3100: Unknown symbol init_timer (err -2)
[ 1026.613668] cp3100: Unknown symbol gpg_release_region (err -2)
[ 1026.613679] cp3100: Unknown symbol gpg_request_mem_region (err -2)
[ 1026.613690] cp3100: Unknown symbol gpg_read_pcidevice_data (err -2)
[ 1026.613701] cp3100: Unknown symbol gpg_outb (err -2)
[ 1026.613713] cp3100: Unknown symbol gpg_writeb (err -2)
[ 1026.613724] cp3100: Unknown symbol gpg_MINOR (err -2)
[ 1026.613737] cp3100: Unknown symbol gpg_request_region (err -2)
[ 1026.613748] cp3100: Unknown symbol gpg_pci_find_subsys (err -2)
[ 1026.613759] cp3100: Unknown symbol gpg_pci_find_device (err -2)
[ 1026.613770] cp3100: Unknown symbol gpg_set_file_private_data (err -2)
[ 1026.613781] cp3100: Unknown symbol gpg_insw (err -2)
[ 1026.613792] cp3100: Unknown symbol gpg_inb (err -2)
[ 1026.613804] cp3100: Unknown symbol gpg_ioremap (err -2)
[ 1026.613816] cp3100: Unknown symbol gpg_memcpy (err -2)
[ 1026.613827] cp3100: Unknown symbol gpg_version_disp_load (err -2)
[ 1026.613838] cp3100: Unknown symbol gpg_pci_set_master (err -2)
[ 1026.613850] cp3100: Unknown symbol gpg_copy_to_user (err -2)
[ 1026.613861] cp3100: Unknown symbol gpg_vmalloc (err -2)
[ 1026.613874] cp3100: Unknown symbol gpg_version_disp_unload (err -2)
[ 1026.613886] cp3100: Unknown symbol gpg_inl (err -2)
[ 1026.613897] cp3100: Unknown symbol gpg_readb (err -2)
[ 1026.613907] cp3100: Unknown symbol gpg_outw (err -2)
[ 1026.613919] cp3100: Unknown symbol gpg_printk (err -2)
[ 1026.613930] cp3100: Unknown symbol gpg_readl (err -2)
[ 1026.613941] cp3100: Unknown symbol gpg_memset (err -2)
```

失敗する。`gpg_XXX`は[dpg0100のビルドの問題](https://qiita.com/ProjectM_TACCMI/items/7360b26d70cc2c866efb#cp3100%E3%83%AD%E3%83%BC%E3%83%89%E6%99%82%E3%81%AE%E5%95%8F%E9%A1%8C%E5%AF%BE%E5%87%A6)。
ほかは、以下で対応。

```ad_entry.c
...
#include <linux/sched/signal.h> // 追加( signal_pending の対応 )
...
/* interruptible_sleep_on_timeoutの対応。dpg0100.cを参照し、gpg_interruptible_sleep_on_timeoutを */
/* 呼び出せば、同じことがやれると判断。 */
/* 以下のように interruptible_sleep_on_timeout を gpg_interruptible_sleep_on_timeout に名称変更(4箇所) */
        case SMPL:
                lret = gpg_interruptible_sleep_on_timeout(&(pExt->smpl_wait), timeout);
                break;
...
/* コールバック関数追加。タイマーが切れたときに呼ばれる。 */
static void gpg_timer_fn(struct timer_list *t)
{
    return;
}
void gpg_ad_init_timer(void *ext)
{
        PAD_EXTERNAL_STRUCT pExt;

        pExt = (PAD_EXTERNAL_STRUCT)ext;

        //init_timer(&(pExt->ad_timer));
        timer_setup((struct timer_list *)(&(pExt->ad_timer)), gpg_timer_fn, 0); // 追加
}
...
```

```Makefile:Makefile
CFILES = ad_entry.c
obj-m += cp3100.o
cp3100-objs := $(CFILES:.c=.o) ../ver26/bocp3100noreg.o
VERBOSE = 0
KBUILD_EXTRA_SYMBOLS = .../PEX-361316/common/dpg0100/src/Module.symvers

all:
        make -C /lib/modules/$(shell uname -r)/build M=$(PWD) KBUILD_VERBOSE=$(VERBOSE) CONFIG_DEBUG_INFO=y modules
clean:
        make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
install:
        cp -f cp3100.ko /lib/modules/$(shell uname -r)/misc
```

```
$ ln ../../../../../common/dpg0100/src/dpg0100.h .
$ make
$ sudo make install
$ sudo depmod -a
$ sudo modprobe cp3100
$ dmesg
...
[13190.651470] pci 0000:05:0c.0: enabling device (0000 -> 0002)
[13190.651627] cp3100:Interface Analog Input Device Driver (Ver5.01.38.00) loaded.
```

### 参考ページ

- [linuxカーネル内部インターフェースの変更例 - Qiita](https://qiita.com/satoru_takeuchi/items/84ce3f86920a327b5128)
 - `struct timer_list ad_timer`の変更について
- [Ubuntu18.04でdpg0100のビルド - Qiita](https://qiita.com/ProjectM_TACCMI/items/7360b26d70cc2c866efb)
- [ソースファイルの分割 | Linuxデバイスドライバ開発入門](http://linux-dvr.biz/archives/60)
- [Linux source code: signal_pending identifier (v5.0.21) - Bootlin](https://elixir.bootlin.com/linux/v5.0.21/ident/signal_pending)
- [ART-Linux on Ubuntu 10.04](https://www.rbt.his.u-fukui.ac.jp/~naniwa/comp/art-linux.html)
 - `interruptible_sleep_on_timeout`の参考
- [c++ - linux kernel module linker warnings: &quot;*** Warning: &lt;function&gt; [&lt;module&gt;] undefined!&quot; - any way to get rid of them? - Stack Overflow](https://stackoverflow.com/questions/625685/linux-kernel-module-linker-warnings-warning-function-module-undefin)