compat_ioctl和unlocked_ioctl的使用場景

背景

接上一篇《藍牙遙控器連接流程分析》,我們這次正式開始藍牙遙控器的調試。按理來說,有了上一篇文章的理論支撐,要調試一款藍牙遙控器應該就不難了,實際也是這樣。但是調試過程中,還是遇到了一些問題,在此記錄一下。

正文

在上一篇文章我們可以看到,以前在安卓平臺想要創建/dev/input/eventX和/dev/hidrawX節點,藍牙協議棧中一般有一下操作:

int fd = open(/dev/uhid);
write(fd, ...);

不過在我調試的這款cypress 20704藍牙芯片中,廠家提供的協議棧(協議棧名叫bsa,不是Linux官方的bluez)並不是通過uhid驅動去操作的,而是有他自己的bthid驅動。不過流程相似,只是名字不同而已。我們先簡單看一下bthid驅動中的流程。
 

static const struct file_operations bthid_fops =
{
    .owner = THIS_MODULE,
    .open = bthid_open,
    .release = bthid_release,
    .write = bthid_write,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
    .unlocked_ioctl = bthid_ioctl
#else
    .ioctl = bthid_ioctl
#endif
};

static struct miscdevice bthid_misc =
{
    .fops = &bthid_fops,
    .minor = BTHID_MINOR,
    .name = BTHID_NAME
};

static int __init bthid_init(void)
{
    int ret;
    ret = misc_register(&bthid_misc);
    if (ret)
    {
        BTHID_ERR("misc driver registration error\n");
    }
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
    ret = hid_register_driver(&bthid_driver);
    if (ret)
    {
        BTHID_ERR("hid driver registration error\n");
    }
#endif
    return ret;
}

流程和uhid驅動一樣,註冊一個misc設備,並且也掛載到hid總線。將編譯出來的bthid驅動註冊進系統後,就會多出一個/dev/bthid文件。這個就和/dev/uhid類似了。所以在協議棧中肯定有一個打開/dev/bthid文件的操作,現在我們搜索一下協議棧的代碼,果不其然,在某個源碼中有一下動作:

#define APP_HH_BTHID_PATH "/dev/bthid"
int app_bthid_open(void)
{
    int bthid_fd;

    /* Open bthid device.  Return if failed */
    bthid_fd = open(APP_HH_BTHID_PATH, O_RDWR);
    if (bthid_fd < 0)
    {
        APP_ERROR1("Failed to open %s : %d", APP_HH_BTHID_PATH, errno);
        return -1;
    }
    APP_DEBUG1("fd=%d", bthid_fd);

    return bthid_fd;
}

所以我們可以猜測,註冊完bthid驅動後,再調用協議棧中上面的這段代碼,就大功告成了?我也是這麼想的,但是做完這些工作,卻遲遲沒有看到創建/dev/input/eventX和/dev/hidrawX節點。加了很多打印也沒找到原因,只是知道在協議棧中調用ioctl時失敗了,卻沒找到爲什麼失敗,後來網上看到一位大神的文章,恍然大悟。在bthid驅動中,ioctl的接口用的是unlocked_ioctl,但在32位系統64位的內核上面會走compat_ioctl接口,這就是compat_ioctl存在的意義,由於我使用的Linux系統是32位,內核編譯的是Arm64,這應該就是這個Bug產生的原因,替換成compat_ioctl,問題就解決了,謝天謝地!
參考鏈接:https://blog.csdn.net/qq_25402181/article/details/77985143

static const struct file_operations bthid_fops =
{
    .owner = THIS_MODULE,
    .open = bthid_open,
    .release = bthid_release,
    .write = bthid_write,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
    .compat_ioctl = bthid_ioctl
#else
    .ioctl = bthid_ioctl
#endif
};

結束

這只是調試藍牙遙控器遇到的一個小問題,後續調試過程中如果遇到有價值的問題,會繼續寫文章總結。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章