Linux ioctl
определения и уровни совместимости - увлекательная тема, против которой я только что разбил голову.
Как правило, ioctl
определения используют семейство макросов _IOW / _IOR и др., Которые принимают имя типа аргумента в качестве ссылки, вместе с магическим числом и порядковым значением, которые подставляются для получения значения аргумента ioctl (например, HIDIOCGRAWINFO
). Имя типа используется для кодирования sizeof(arg_type)
в определении. Это означает, что тип, используемый в user space, определяет значение , сгенерированное макросом ioctl
- т.е. HIDIOCGRAWINFO может варьироваться в зависимости от условий включения.
Здесь первая точка, в которой 32- и 64-разрядные различия отличаются, sizeof
может отличаться в зависимости от упаковки, использования нечетких размеров данных (например, длинных), но особенно (и неизбежно), если вы используете указатель аргумент. Таким образом, в этом случае 64-битный модуль ядра, который требуется для поддержки 32-битных клиентов, должен определить тип аргумента совместимости, чтобы он соответствовал макету 32-битного эквивалента типа аргумента и, следовательно, 32-битного совместимого ioctl. В этих 32-битных эквивалентных определениях используется ядро / слой, называемый compat
.
В вашем случае sizeof()
- это то же самое, так что это не тот путь, по которому вы идете, но важно понимать все, что может происходить.
Кроме того, конфигурация ядра может определять CONFIG_COMPAT
, который изменяет оболочки системного вызова (особенно код, окружающий интерфейс пользователя / ядра по отношению к ioctl
), чтобы облегчить бремя поддержки 32- и 64-битных систем. Часть этого включает в себя ioctl
обратный вызов совместимости под названием ioctl_compat
.
То, что я видел, с CONFIG_COMPAT
определено, что 32-битные программы будут генерировать код, который доставляет ioctl
s для обратного вызова ioctl_compat
, даже если может генерировать то же самое ioctl
значение как 64-битное (например, в вашем случае). Поэтому пишущий драйвер должен убедиться, что ioctl_compat
обрабатывает и специальные (разные) 32-битные совместимые ioctl
ТИПЫ и обычные "64-битные - или неизмененные 32-битные" типы.
Таким образом, модуль ядра, разработанный и протестированный только в 32-разрядных и 64-разрядных системах (без CONFIG_COMPAT), может работать для 32- и 64-разрядных программ, но не для той, которая поддерживает оба.
Итак, глядя в HID, я вижу, что это было добавлено в 2.6.38:
http://lxr.linux.no/#linux+v2.6.38/drivers/hid/hidraw.c#L347