€•÷ƒŒsphinx.addnodes”Œdocument”“”)”}”(Œ rawsource”Œ”Œchildren”]”(Œ translations”Œ LanguagesNode”“”)”}”(hhh]”(hŒ pending_xref”“”)”}”(hhh]”Œdocutils.nodes”ŒText”“”ŒChinese (Simplified)”…””}”Œparent”hsbaŒ attributes”}”(Œids”]”Œclasses”]”Œnames”]”Œdupnames”]”Œbackrefs”]”Œ refdomain”Œstd”Œreftype”Œdoc”Œ reftarget”Œ"/translations/zh_CN/usb/functionfs”Œmodname”NŒ classname”NŒ refexplicit”ˆuŒtagname”hhh ubh)”}”(hhh]”hŒChinese (Traditional)”…””}”hh2sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ"/translations/zh_TW/usb/functionfs”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒItalian”…””}”hhFsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ"/translations/it_IT/usb/functionfs”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒJapanese”…””}”hhZsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ"/translations/ja_JP/usb/functionfs”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒKorean”…””}”hhnsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ"/translations/ko_KR/usb/functionfs”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒPortuguese (Brazilian)”…””}”hh‚sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ"/translations/pt_BR/usb/functionfs”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒSpanish”…””}”hh–sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ"/translations/sp_SP/usb/functionfs”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubeh}”(h]”h ]”h"]”h$]”h&]”Œcurrent_language”ŒEnglish”uh1h hhŒ _document”hŒsource”NŒline”NubhŒsection”“”)”}”(hhh]”(hŒtitle”“”)”}”(hŒHow FunctionFS works”h]”hŒHow FunctionFS works”…””}”(hh¼h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhh·h²hh³Œ iSerialNumber= functions=mtp,hid $ mkdir /dev/ffs-mtp && mount -t functionfs mtp /dev/ffs-mtp $ ( cd /dev/ffs-mtp && mtp-daemon ) & $ mkdir /dev/ffs-hid && mount -t functionfs hid /dev/ffs-hid $ ( cd /dev/ffs-hid && hid-daemon ) &”h]”hX$ insmod g_ffs.ko idVendor= iSerialNumber= functions=mtp,hid $ mkdir /dev/ffs-mtp && mount -t functionfs mtp /dev/ffs-mtp $ ( cd /dev/ffs-mtp && mtp-daemon ) & $ mkdir /dev/ffs-hid && mount -t functionfs hid /dev/ffs-hid $ ( cd /dev/ffs-hid && hid-daemon ) &”…””}”hjusbah}”(h]”h ]”h"]”h$]”h&]”Œ xml:space”Œpreserve”uh1jsh³hÊh´K2hhËh²hubhÝ)”}”(hŒƒOn kernel level the gadget checks ffs_data->dev_name to identify whether its FunctionFS is designed for MTP ("mtp") or HID ("hid").”h]”hŒ‹On kernel level the gadget checks ffs_data->dev_name to identify whether its FunctionFS is designed for MTP (“mtpâ€) or HID (“hidâ€).”…””}”(hj…h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´K8hhËh²hubhÝ)”}”(hŒdIf no "functions" module parameters is supplied, the driver accepts just one function with any name.”h]”hŒhIf no “functions†module parameters is supplied, the driver accepts just one function with any name.”…””}”(hj“h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´K;hhËh²hubhÝ)”}”(hX1When "functions" module parameter is supplied, only functions with listed names are accepted. In particular, if the "functions" parameter's value is just a one-element list, then the behaviour is similar to when there is no "functions" at all; however, only a function with the specified name is accepted.”h]”hX?When “functions†module parameter is supplied, only functions with listed names are accepted. In particular, if the “functions†parameter’s value is just a one-element list, then the behaviour is similar to when there is no “functions†at all; however, only a function with the specified name is accepted.”…””}”(hj¡h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´K>hhËh²hubhÝ)”}”(hŒ¢The gadget is registered only after all the declared function filesystems have been mounted and USB descriptors of all functions have been written to their ep0's.”h]”hŒ¤The gadget is registered only after all the declared function filesystems have been mounted and USB descriptors of all functions have been written to their ep0’s.”…””}”(hj¯h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´KDhhËh²hubhÝ)”}”(hŒYConversely, the gadget is unregistered after the first USB function closes its endpoints.”h]”hŒYConversely, the gadget is unregistered after the first USB function closes its endpoints.”…””}”(hj½h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´KHhhËh²hubeh}”(h]”Œoverview”ah ]”h"]”Œoverview”ah$]”h&]”uh1hµhh·h²hh³hÊh´Kubh¶)”}”(hhh]”(h»)”}”(hŒEndpoint IOCTLs”h]”hŒEndpoint IOCTLs”…””}”(hjÖh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhjÓh²hh³hÊh´KLubhÝ)”}”(hŒËFunctionFS supports additional IOCTLs that can be performed on data endpoints (ie. not ep0). For a full list of these IOCTLs, please refer to the documentation in ``include/uapi/linux/usb/functionfs.h``.”h]”(hŒ£FunctionFS supports additional IOCTLs that can be performed on data endpoints (ie. not ep0). For a full list of these IOCTLs, please refer to the documentation in ”…””}”(hjäh²hh³Nh´NubhŒliteral”“”)”}”(hŒ'``include/uapi/linux/usb/functionfs.h``”h]”hŒ#include/uapi/linux/usb/functionfs.h”…””}”(hjîh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jìhjäubhŒ.”…””}”(hjäh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´KNhjÓh²hubhÝ)”}”(hŒOne such IOCTL is:”h]”hŒOne such IOCTL is:”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´KRhjÓh²hubhŒ block_quote”“”)”}”(hXŽ``FUNCTIONFS_ENDPOINT_ENABLE_ZLP(__u32 *)`` Enable or disable automatic zero-length packet (ZLP) appending for the endpoint. The argument is a pointer to a __u32: 0 to disable, non-zero to enable. When enabled, the kernel will automatically append a ZLP at the end of a transfer if the payload length is an exact multiple of the endpoint's max packet size. This is useful for compatibility with legacy protocols which require automatic ZLP appending to data written from userspace. This IOCTL can only be used on IN endpoints. It can be called at any time after the FunctionFS instance is active, even before the host has connected or enabled the endpoint. Returns zero on success, or a negative errno value on error: * ``-ENODEV``: The FunctionFS instance is not active. * ``-EINVAL``: The endpoint is not an IN endpoint. * ``-EFAULT``: Invalid user space pointer for the argument. ”h]”hŒdefinition_list”“”)”}”(hhh]”hŒdefinition_list_item”“”)”}”(hXt``FUNCTIONFS_ENDPOINT_ENABLE_ZLP(__u32 *)`` Enable or disable automatic zero-length packet (ZLP) appending for the endpoint. The argument is a pointer to a __u32: 0 to disable, non-zero to enable. When enabled, the kernel will automatically append a ZLP at the end of a transfer if the payload length is an exact multiple of the endpoint's max packet size. This is useful for compatibility with legacy protocols which require automatic ZLP appending to data written from userspace. This IOCTL can only be used on IN endpoints. It can be called at any time after the FunctionFS instance is active, even before the host has connected or enabled the endpoint. Returns zero on success, or a negative errno value on error: * ``-ENODEV``: The FunctionFS instance is not active. * ``-EINVAL``: The endpoint is not an IN endpoint. * ``-EFAULT``: Invalid user space pointer for the argument. ”h]”(hŒterm”“”)”}”(hŒ+``FUNCTIONFS_ENDPOINT_ENABLE_ZLP(__u32 *)``”h]”jí)”}”(hj)h]”hŒ'FUNCTIONFS_ENDPOINT_ENABLE_ZLP(__u32 *)”…””}”(hj+h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jìhj'ubah}”(h]”h ]”h"]”h$]”h&]”uh1j%h³hÊh´Kbhj!ubhŒ definition”“”)”}”(hhh]”(hÝ)”}”(hX¡Enable or disable automatic zero-length packet (ZLP) appending for the endpoint. The argument is a pointer to a __u32: 0 to disable, non-zero to enable. When enabled, the kernel will automatically append a ZLP at the end of a transfer if the payload length is an exact multiple of the endpoint's max packet size. This is useful for compatibility with legacy protocols which require automatic ZLP appending to data written from userspace. This IOCTL can only be used on IN endpoints. It can be called at any time after the FunctionFS instance is active, even before the host has connected or enabled the endpoint. Returns zero on success, or a negative errno value on error:”h]”hX£Enable or disable automatic zero-length packet (ZLP) appending for the endpoint. The argument is a pointer to a __u32: 0 to disable, non-zero to enable. When enabled, the kernel will automatically append a ZLP at the end of a transfer if the payload length is an exact multiple of the endpoint’s max packet size. This is useful for compatibility with legacy protocols which require automatic ZLP appending to data written from userspace. This IOCTL can only be used on IN endpoints. It can be called at any time after the FunctionFS instance is active, even before the host has connected or enabled the endpoint. Returns zero on success, or a negative errno value on error:”…””}”(hjCh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´KUhj@ubhŒ bullet_list”“”)”}”(hhh]”(hŒ list_item”“”)”}”(hŒ3``-ENODEV``: The FunctionFS instance is not active.”h]”hÝ)”}”(hjZh]”(jí)”}”(hŒ ``-ENODEV``”h]”hŒ-ENODEV”…””}”(hj_h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jìhj\ubhŒ(: The FunctionFS instance is not active.”…””}”(hj\h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´K`hjXubah}”(h]”h ]”h"]”h$]”h&]”uh1jVhjSubjW)”}”(hŒ0``-EINVAL``: The endpoint is not an IN endpoint.”h]”hÝ)”}”(hjh]”(jí)”}”(hŒ ``-EINVAL``”h]”hŒ-EINVAL”…””}”(hj„h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jìhjubhŒ%: The endpoint is not an IN endpoint.”…””}”(hjh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´Kahj}ubah}”(h]”h ]”h"]”h$]”h&]”uh1jVhjSubjW)”}”(hŒ:``-EFAULT``: Invalid user space pointer for the argument. ”h]”hÝ)”}”(hŒ9``-EFAULT``: Invalid user space pointer for the argument.”h]”(jí)”}”(hŒ ``-EFAULT``”h]”hŒ-EFAULT”…””}”(hjªh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jìhj¦ubhŒ.: Invalid user space pointer for the argument.”…””}”(hj¦h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´Kbhj¢ubah}”(h]”h ]”h"]”h$]”h&]”uh1jVhjSubeh}”(h]”h ]”h"]”h$]”h&]”Œbullet”Œ*”uh1jQh³hÊh´K`hj@ubeh}”(h]”h ]”h"]”h$]”h&]”uh1j>hj!ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÊh´Kbhjubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÊh´KThjÓh²hubeh}”(h]”Œendpoint-ioctls”ah ]”h"]”Œendpoint ioctls”ah$]”h&]”uh1hµhh·h²hh³hÊh´KLubh¶)”}”(hhh]”(h»)”}”(hŒRW Proxy Endpoints”h]”hŒRW Proxy Endpoints”…””}”(hjóh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhjðh²hh³hÊh´KeubhÝ)”}”(hX”If the ``FUNCTIONFS_RW_PROXY_EPS`` flag is passed in the descriptor header (requires ``FUNCTIONFS_DESCRIPTORS_MAGIC_V2``), FunctionFS will provision a bidirectional rw_proxy file descriptor (e.g., "ep1_rw") alongside each pair of IN and OUT endpoints. The rw_proxy file aliases the underlying hardware endpoints, allowing userspace to use a single file descriptor for both reading (OUT) and writing (IN).”h]”(hŒIf the ”…””}”(hjh²hh³Nh´Nubjí)”}”(hŒ``FUNCTIONFS_RW_PROXY_EPS``”h]”hŒFUNCTIONFS_RW_PROXY_EPS”…””}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jìhjubhŒ3 flag is passed in the descriptor header (requires ”…””}”(hjh²hh³Nh´Nubjí)”}”(hŒ#``FUNCTIONFS_DESCRIPTORS_MAGIC_V2``”h]”hŒFUNCTIONFS_DESCRIPTORS_MAGIC_V2”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jìhjubhX ), FunctionFS will provision a bidirectional rw_proxy file descriptor (e.g., “ep1_rwâ€) alongside each pair of IN and OUT endpoints. The rw_proxy file aliases the underlying hardware endpoints, allowing userspace to use a single file descriptor for both reading (OUT) and writing (IN).”…””}”(hjh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´Kghjðh²hubhÝ)”}”(hX?This flag requires the total number of hardware endpoints to be an even number. FunctionFS will automatically walk the provided endpoints and group them into adjacent pairs (e.g., ep1 and ep2 form the first pair, ep3 and ep4 form the second pair). Each pair must consist of exactly one IN endpoint and one OUT endpoint.”h]”hX?This flag requires the total number of hardware endpoints to be an even number. FunctionFS will automatically walk the provided endpoints and group them into adjacent pairs (e.g., ep1 and ep2 form the first pair, ep3 and ep4 form the second pair). Each pair must consist of exactly one IN endpoint and one OUT endpoint.”…””}”(hj3h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´Knhjðh²hubhÝ)”}”(hŒöFor each valid pair, a rw_proxy file is created and named after the first endpoint in the pair with a "_rw" suffix. For example, if ep1 and ep2 are paired, a rw_proxy file named "ep1_rw" is created. If ep3 and ep4 are paired, "ep3_rw" is created.”h]”hXFor each valid pair, a rw_proxy file is created and named after the first endpoint in the pair with a “_rw†suffix. For example, if ep1 and ep2 are paired, a rw_proxy file named “ep1_rw†is created. If ep3 and ep4 are paired, “ep3_rw†is created.”…””}”(hjAh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´Kthjðh²hubhÝ)”}”(hXCIf the ``FUNCTIONFS_VIRTUAL_ADDR`` flag is also enabled, the endpoints will be named using their physical endpoint address in hexadecimal instead of their index. RW proxy files will inherit this naming convention. For example, if the first endpoint of a pair maps to address 0x02, the rw_proxy file will be named "ep02_rw".”h]”(hŒIf the ”…””}”(hjOh²hh³Nh´Nubjí)”}”(hŒ``FUNCTIONFS_VIRTUAL_ADDR``”h]”hŒFUNCTIONFS_VIRTUAL_ADDR”…””}”(hjWh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jìhjOubhX% flag is also enabled, the endpoints will be named using their physical endpoint address in hexadecimal instead of their index. RW proxy files will inherit this naming convention. For example, if the first endpoint of a pair maps to address 0x02, the rw_proxy file will be named “ep02_rwâ€.”…””}”(hjOh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´Kyhjðh²hubhÝ)”}”(hXWhen this flag is enabled, userspace has the choice of performing data transfers via the single rw_proxy file descriptor or the two base file descriptors. The rw_proxy file descriptor acts as a pure VFS alias that proxies all operations directly to the underlying base file descriptors.”h]”hXWhen this flag is enabled, userspace has the choice of performing data transfers via the single rw_proxy file descriptor or the two base file descriptors. The rw_proxy file descriptor acts as a pure VFS alias that proxies all operations directly to the underlying base file descriptors.”…””}”(hjoh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´Khjðh²hubhÝ)”}”(hXaBecause it is a pure proxy, there are no data races or buffer corruptions if userspace uses both the rw_proxy endpoint and the base endpoints concurrently. The native mutexes of the base endpoints perfectly serialize all concurrent transfers. However, userspace should generally pick one method and stick to it to avoid interleaving its own data stream.”h]”hXaBecause it is a pure proxy, there are no data races or buffer corruptions if userspace uses both the rw_proxy endpoint and the base endpoints concurrently. The native mutexes of the base endpoints perfectly serialize all concurrent transfers. However, userspace should generally pick one method and stick to it to avoid interleaving its own data stream.”…””}”(hj}h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´K„hjðh²hubjR)”}”(hhh]”(jW)”}”(hŒú**IOCTLs (Clear Halt, etc.):** RW proxy endpoints do not support IOCTLs and will return ``-ENOTTY``. To clear a host-initiated halt, userspace must issue the ``FUNCTIONFS_CLEAR_HALT`` ioctl directly on the corresponding base endpoint file descriptor.”h]”hÝ)”}”(hŒú**IOCTLs (Clear Halt, etc.):** RW proxy endpoints do not support IOCTLs and will return ``-ENOTTY``. To clear a host-initiated halt, userspace must issue the ``FUNCTIONFS_CLEAR_HALT`` ioctl directly on the corresponding base endpoint file descriptor.”h]”(hŒstrong”“”)”}”(hŒ**IOCTLs (Clear Halt, etc.):**”h]”hŒIOCTLs (Clear Halt, etc.):”…””}”(hj˜h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j–hj’ubhŒ: RW proxy endpoints do not support IOCTLs and will return ”…””}”(hj’h²hh³Nh´Nubjí)”}”(hŒ ``-ENOTTY``”h]”hŒ-ENOTTY”…””}”(hjªh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jìhj’ubhŒ;. To clear a host-initiated halt, userspace must issue the ”…””}”(hj’h²hh³Nh´Nubjí)”}”(hŒ``FUNCTIONFS_CLEAR_HALT``”h]”hŒFUNCTIONFS_CLEAR_HALT”…””}”(hj¼h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jìhj’ubhŒC ioctl directly on the corresponding base endpoint file descriptor.”…””}”(hj’h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´KŠhjŽubah}”(h]”h ]”h"]”h$]”h&]”uh1jVhj‹h²hh³hÊh´NubjW)”}”(hXO**Intentional Stalls:** The traditional mechanism for intentionally halting an endpoint by issuing a reverse-direction data operation (e.g., attempting to read from an IN endpoint) continues to work, but it must be issued on the base endpoint. RW proxy endpoints cannot be used to trigger a stall because they are fully bidirectional. ”h]”hÝ)”}”(hXN**Intentional Stalls:** The traditional mechanism for intentionally halting an endpoint by issuing a reverse-direction data operation (e.g., attempting to read from an IN endpoint) continues to work, but it must be issued on the base endpoint. RW proxy endpoints cannot be used to trigger a stall because they are fully bidirectional.”h]”(j—)”}”(hŒ**Intentional Stalls:**”h]”hŒIntentional Stalls:”…””}”(hjâh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j–hjÞubhX7 The traditional mechanism for intentionally halting an endpoint by issuing a reverse-direction data operation (e.g., attempting to read from an IN endpoint) continues to work, but it must be issued on the base endpoint. RW proxy endpoints cannot be used to trigger a stall because they are fully bidirectional.”…””}”(hjÞh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´KŽhjÚubah}”(h]”h ]”h"]”h$]”h&]”uh1jVhj‹h²hh³hÊh´Nubeh}”(h]”h ]”h"]”h$]”h&]”jÎŒ-”uh1jQh³hÊh´KŠhjðh²hubhÝ)”}”(hŒþNote that DMABUF data transfers (``FUNCTIONFS_DMABUF_TRANSFER``) are unsupported via the rw_proxy endpoint because it does not support IOCTLs. If DMABUF transfers are required, users must use the standard base endpoints. DMABUF interface ================”h]”(hŒ!Note that DMABUF data transfers (”…””}”(hjh²hh³Nh´Nubjí)”}”(hŒ``FUNCTIONFS_DMABUF_TRANSFER``”h]”hŒFUNCTIONFS_DMABUF_TRANSFER”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jìhjubhŒ¿) are unsupported via the rw_proxy endpoint because it does not support IOCTLs. If DMABUF transfers are required, users must use the standard base endpoints. DMABUF interface ================”…””}”(hjh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´K”hjðh²hubhÝ)”}”(hŒ»FunctionFS additionally supports a DMABUF based interface, where the userspace can attach DMABUF objects (externally created) to an endpoint, and subsequently use them for data transfers.”h]”hŒ»FunctionFS additionally supports a DMABUF based interface, where the userspace can attach DMABUF objects (externally created) to an endpoint, and subsequently use them for data transfers.”…””}”(hj'h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´Kšhjðh²hubhÝ)”}”(hŒ¯Note: The DMABUF interface is unsupported on rw_proxy endpoints. See the RW Proxy Endpoints section for details on using DMABUF alongside the ``FUNCTIONFS_RW_PROXY_EPS`` flag.”h]”(hŒŽNote: The DMABUF interface is unsupported on rw_proxy endpoints. See the RW Proxy Endpoints section for details on using DMABUF alongside the ”…””}”(hj5h²hh³Nh´Nubjí)”}”(hŒ``FUNCTIONFS_RW_PROXY_EPS``”h]”hŒFUNCTIONFS_RW_PROXY_EPS”…””}”(hj=h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jìhj5ubhŒ flag.”…””}”(hj5h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´Kžhjðh²hubhÝ)”}”(hŒÈA userspace application can then use this interface to share DMABUF objects between several interfaces, allowing it to transfer data in a zero-copy fashion, for instance between IIO and the USB stack.”h]”hŒÈA userspace application can then use this interface to share DMABUF objects between several interfaces, allowing it to transfer data in a zero-copy fashion, for instance between IIO and the USB stack.”…””}”(hjUh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´K¢hjðh²hubhÝ)”}”(hŒAs part of this interface, three new IOCTLs have been added. These three IOCTLs have to be performed on a data endpoint (ie. not ep0). They are:”h]”hŒAs part of this interface, three new IOCTLs have been added. These three IOCTLs have to be performed on a data endpoint (ie. not ep0). They are:”…””}”(hjch²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´K¦hjðh²hubj)”}”(hXz``FUNCTIONFS_DMABUF_ATTACH(int)`` Attach the DMABUF object, identified by its file descriptor, to the data endpoint. Returns zero on success, and a negative errno value on error. ``FUNCTIONFS_DMABUF_DETACH(int)`` Detach the given DMABUF object, identified by its file descriptor, from the data endpoint. Returns zero on success, and a negative errno value on error. Note that closing the endpoint's file descriptor will automatically detach all attached DMABUFs. ``FUNCTIONFS_DMABUF_TRANSFER(struct usb_ffs_dmabuf_transfer_req *)`` Enqueue the previously attached DMABUF to the transfer queue. The argument is a structure that packs the DMABUF's file descriptor, the size in bytes to transfer (which should generally correspond to the size of the DMABUF), and a 'flags' field which is unused for now. Returns zero on success, and a negative errno value on error.”h]”j)”}”(hhh]”(j )”}”(hŒ³``FUNCTIONFS_DMABUF_ATTACH(int)`` Attach the DMABUF object, identified by its file descriptor, to the data endpoint. Returns zero on success, and a negative errno value on error. ”h]”(j&)”}”(hŒ!``FUNCTIONFS_DMABUF_ATTACH(int)``”h]”jí)”}”(hj~h]”hŒFUNCTIONFS_DMABUF_ATTACH(int)”…””}”(hj€h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jìhj|ubah}”(h]”h ]”h"]”h$]”h&]”uh1j%h³hÊh´K¬hjxubj?)”}”(hhh]”hÝ)”}”(hŒAttach the DMABUF object, identified by its file descriptor, to the data endpoint. Returns zero on success, and a negative errno value on error.”h]”hŒAttach the DMABUF object, identified by its file descriptor, to the data endpoint. Returns zero on success, and a negative errno value on error.”…””}”(hj–h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´Kªhj“ubah}”(h]”h ]”h"]”h$]”h&]”uh1j>hjxubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÊh´K¬hjuubj )”}”(hX``FUNCTIONFS_DMABUF_DETACH(int)`` Detach the given DMABUF object, identified by its file descriptor, from the data endpoint. Returns zero on success, and a negative errno value on error. Note that closing the endpoint's file descriptor will automatically detach all attached DMABUFs. ”h]”(j&)”}”(hŒ!``FUNCTIONFS_DMABUF_DETACH(int)``”h]”jí)”}”(hj¶h]”hŒFUNCTIONFS_DMABUF_DETACH(int)”…””}”(hj¸h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jìhj´ubah}”(h]”h ]”h"]”h$]”h&]”uh1j%h³hÊh´K²hj°ubj?)”}”(hhh]”hÝ)”}”(hŒùDetach the given DMABUF object, identified by its file descriptor, from the data endpoint. Returns zero on success, and a negative errno value on error. Note that closing the endpoint's file descriptor will automatically detach all attached DMABUFs.”h]”hŒûDetach the given DMABUF object, identified by its file descriptor, from the data endpoint. Returns zero on success, and a negative errno value on error. Note that closing the endpoint’s file descriptor will automatically detach all attached DMABUFs.”…””}”(hjÎh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´K¯hjËubah}”(h]”h ]”h"]”h$]”h&]”uh1j>hj°ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÊh´K²hjuubj )”}”(hX``FUNCTIONFS_DMABUF_TRANSFER(struct usb_ffs_dmabuf_transfer_req *)`` Enqueue the previously attached DMABUF to the transfer queue. The argument is a structure that packs the DMABUF's file descriptor, the size in bytes to transfer (which should generally correspond to the size of the DMABUF), and a 'flags' field which is unused for now. Returns zero on success, and a negative errno value on error.”h]”(j&)”}”(hŒD``FUNCTIONFS_DMABUF_TRANSFER(struct usb_ffs_dmabuf_transfer_req *)``”h]”jí)”}”(hjîh]”hŒ@FUNCTIONFS_DMABUF_TRANSFER(struct usb_ffs_dmabuf_transfer_req *)”…””}”(hjðh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jìhjìubah}”(h]”h ]”h"]”h$]”h&]”uh1j%h³hÊh´K¹hjèubj?)”}”(hhh]”hÝ)”}”(hXJEnqueue the previously attached DMABUF to the transfer queue. The argument is a structure that packs the DMABUF's file descriptor, the size in bytes to transfer (which should generally correspond to the size of the DMABUF), and a 'flags' field which is unused for now. Returns zero on success, and a negative errno value on error.”h]”hXPEnqueue the previously attached DMABUF to the transfer queue. The argument is a structure that packs the DMABUF’s file descriptor, the size in bytes to transfer (which should generally correspond to the size of the DMABUF), and a ‘flags’ field which is unused for now. Returns zero on success, and a negative errno value on error.”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´Kµhjubah}”(h]”h ]”h"]”h$]”h&]”uh1j>hjèubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÊh´K¹hjuubeh}”(h]”h ]”h"]”h$]”h&]”uh1jhjqubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÊh´K©hjðh²hubeh}”(h]”Œrw-proxy-endpoints”ah ]”h"]”Œrw proxy endpoints”ah$]”h&]”uh1hµhh·h²hh³hÊh´Keubeh}”(h]”Œhow-functionfs-works”ah ]”h"]”Œhow functionfs works”ah$]”h&]”uh1hµhhh²hh³hÊh´Kubeh}”(h]”h ]”h"]”h$]”h&]”Œsource”hÊuh1hŒcurrent_source”NŒ current_line”NŒsettings”Œdocutils.frontend”ŒValues”“”)”}”(hºNŒ generator”NŒ datestamp”NŒ source_link”NŒ source_url”NŒ toc_backlinks”Œentry”Œfootnote_backlinks”KŒ sectnum_xform”KŒstrip_comments”NŒstrip_elements_with_classes”NŒ strip_classes”NŒ report_level”KŒ halt_level”KŒexit_status_level”KŒdebug”NŒwarning_stream”NŒ traceback”ˆŒinput_encoding”Œ utf-8-sig”Œinput_encoding_error_handler”Œstrict”Œoutput_encoding”Œutf-8”Œoutput_encoding_error_handler”j_Œerror_encoding”Œutf-8”Œerror_encoding_error_handler”Œbackslashreplace”Œ language_code”Œen”Œrecord_dependencies”NŒconfig”NŒ id_prefix”hŒauto_id_prefix”Œid”Œ dump_settings”NŒdump_internals”NŒdump_transforms”NŒdump_pseudo_xml”NŒexpose_internals”NŒstrict_visitor”NŒ_disable_config”NŒ_source”hÊŒ _destination”NŒ _config_files”]”Œ7/var/lib/git/docbuild/linux/Documentation/docutils.conf”aŒfile_insertion_enabled”ˆŒ raw_enabled”KŒline_length_limit”M'Œpep_references”NŒ pep_base_url”Œhttps://peps.python.org/”Œpep_file_url_template”Œpep-%04d”Œrfc_references”NŒ rfc_base_url”Œ&https://datatracker.ietf.org/doc/html/”Œ tab_width”KŒtrim_footnote_reference_space”‰Œsyntax_highlight”Œlong”Œ smart_quotes”ˆŒsmartquotes_locales”]”Œcharacter_level_inline_markup”‰Œdoctitle_xform”‰Œ docinfo_xform”KŒsectsubtitle_xform”‰Œ image_loading”Œlink”Œembed_stylesheet”‰Œcloak_email_addresses”ˆŒsection_self_link”‰Œenv”NubŒreporter”NŒindirect_targets”]”Œsubstitution_defs”}”Œsubstitution_names”}”Œrefnames”}”Œrefids”}”Œnameids”}”(j9j6jÐjÍjíjêj1j.uŒ nametypes”}”(j9‰jЉjí‰j1‰uh}”(j6h·jÍhËjêjÓj.jðuŒ footnote_refs”}”Œ citation_refs”}”Œ autofootnotes”]”Œautofootnote_refs”]”Œsymbol_footnotes”]”Œsymbol_footnote_refs”]”Œ footnotes”]”Œ citations”]”Œautofootnote_start”KŒsymbol_footnote_start”KŒ id_counter”Œ collections”ŒCounter”“”}”…”R”Œparse_messages”]”Œtransform_messages”]”Œ transformer”NŒ include_log”]”Œ decoration”Nh²hub.