<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/modern-usb-gadget-on-linux-how-to-integrate-it-with-systemd-part-2--i8jfroiru" -->

---
title: Modern USB gadget on Linux & how to integrate it with...
description: A deep dive into implementing a custom USB function using FunctionFS on Linux and integrating it with systemd. Covers USB endpoint types (control, bulk,...
canonical: https://daily.dev/posts/modern-usb-gadget-on-linux-how-to-integrate-it-with-systemd-part-2--i8jfroiru
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: Modern USB gadget on Linux & how to integrate it with systemd (Part 2) | daily.dev
og:description: A deep dive into implementing a custom USB function using FunctionFS on Linux and integrating it with systemd. Covers USB endpoint types (control, bulk,...
og:url: https://daily.dev/posts/modern-usb-gadget-on-linux-how-to-integrate-it-with-systemd-part-2--i8jfroiru
og:image: https://api.daily.dev/og/posts/I8jfRoIRU.png
og:image:alt: Modern USB gadget on Linux & how to integrate it with systemd (Part 2)
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Modern USB gadget on Linux & how to integrate it with systemd (Part 2)

**[Collabora Blog](https://daily.dev/sources/collabora)** · 11 min read · 0 upvotes · 0 comments

## Summary

A deep dive into implementing a custom USB function using FunctionFS on Linux and integrating it with systemd. Covers USB endpoint types (control, bulk, isochronous, interrupt), how FunctionFS exposes a filesystem interface for userspace USB function implementation, and the full systemd unit chain required: a oneshot service to load the gadget scheme, a mount unit for the FunctionFS instance, a socket unit with ListenUSBFunction for lazy daemon activation, and a service unit that writes USB descriptors and strings to ep0. Includes hex dumps of binary descriptor/string blobs, a loopback test using the generic USB serial driver, and a link to a modified ffs-test.c adapted for systemd socket activation.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://www.collabora.com/news-and-blog/blog/2019/03/27/modern-usb-gadget-on-linux-and-how-to-integrate-it-with-systemd-part-2>

## Questions this post answers

### How do I use systemd socket activation with a FunctionFS USB gadget on Linux?

A FunctionFS gadget requires a chain of four systemd units: a oneshot service to load the gadget scheme without binding, a mount unit to mount the FunctionFS instance (e.g. at /run/ffs_test), a socket unit with ListenUSBFunction pointing at that mount, and a service unit carrying USBFunctionDescriptors and USBFunctionStrings entries. The socket unit writes descriptors to ep0 and starts the daemon only when USB traffic arrives, with ExecStartPost binding the gadget.

_Engineers wiring USB gadgets into systemd find the full unit examples and descriptor blobs worth bookmarking on daily.dev._

### What format do I use to write USB descriptors to ep0 in FunctionFS?

Use the usb_functionfs_descs_head_v2 format defined in include/uapi/linux/usb/functionfs.h (line 89 in v5.0-rc6). The older format is deprecated. An example of constructing the binary blobs in C is in tools/usb/ffs-test.c in the kernel sources. You can modify that program to write descriptors and strings to stdout and capture the output as .bin files for use with USBFunctionDescriptors and USBFunctionStrings.

_Developers working with FunctionFS descriptor formats track kernel API changes like this on daily.dev._

### What are the four USB endpoint types in Linux USB gadget development?

The four USB endpoint types are control, bulk, isochronous, and interrupt. Endpoint 0 is the mandatory bidirectional control endpoint used for enumeration and device control. Bulk endpoints transfer large data on a best-effort basis with error-free delivery but no timing guarantees. Isochronous endpoints provide guaranteed bandwidth and bounded latency for time-sensitive data like audio or video, without delivery or integrity guarantees. Interrupt endpoints offer guaranteed latency for device-initiated transfers such as mouse or keyboard input.

_Embedded developers building USB gadgets on Linux stay current on kernel and tooling changes through daily.dev._

## Similar posts on daily.dev

- [USB for Software Developers](https://daily.dev/posts/usb-for-software-developers-4nurp8au8) · Hacker News · 3 upvotes · 0 comments
- [USB for Software Developers: an introduction to writing userspace USB drivers](https://daily.dev/posts/usb-for-software-developers-an-introduction-to-writing-userspace-usb-drivers-y5bylphzx) · Adafruit Blog · 0 upvotes · 0 comments
- [USB, Abstracted](https://daily.dev/posts/usb-abstracted-rftkbghtp) · Hackaday · 1 upvotes · 0 comments

---

Tags: [#linux](https://daily.dev/tags/linux), [#embedded](https://daily.dev/tags/embedded)

[View this post on daily.dev](https://daily.dev/posts/modern-usb-gadget-on-linux-how-to-integrate-it-with-systemd-part-2--i8jfroiru)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"Modern USB gadget on Linux & how to integrate it with systemd (Part 2)","url":"https://daily.dev/posts/modern-usb-gadget-on-linux-how-to-integrate-it-with-systemd-part-2--i8jfroiru","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/modern-usb-gadget-on-linux-how-to-integrate-it-with-systemd-part-2--i8jfroiru"},"datePublished":"2026-08-11T08:55:47.515Z","dateModified":"2026-08-11T09:36:41.108Z","description":"A deep dive into implementing a custom USB function using FunctionFS on Linux and integrating it with systemd. Covers USB endpoint types (control, bulk,...","image":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/6ee4c4f40956e0c1978b7ede3f84dc80?_a=AQAEuop","thumbnailUrl":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/6ee4c4f40956e0c1978b7ede3f84dc80?_a=AQAEuop","isAccessibleForFree":true,"articleSection":"Collabora Blog","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"Collabora Blog","logo":"https://media.daily.dev/image/upload/s--ZGZ0FjqS--/f_auto,q_auto/v1786438306/logos/collabora?_a=BAMAMicg0","url":"https://daily.dev/sources/collabora"},"commentCount":0,"discussionUrl":"https://daily.dev/posts/modern-usb-gadget-on-linux-how-to-integrate-it-with-systemd-part-2--i8jfroiru","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":0},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"keywords":"linux,embedded","timeRequired":"PT11M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Collabora Blog","item":"https://daily.dev/sources/collabora"},{"@type":"ListItem","position":3,"name":"Modern USB gadget on Linux & how to integrate it with systemd (Part 2)"}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/modern-usb-gadget-on-linux-how-to-integrate-it-with-systemd-part-2--i8jfroiru#faq","mainEntity":[{"@type":"Question","name":"How do I use systemd socket activation with a FunctionFS USB gadget on Linux?","acceptedAnswer":{"@type":"Answer","text":"A FunctionFS gadget requires a chain of four systemd units: a oneshot service to load the gadget scheme without binding, a mount unit to mount the FunctionFS instance (e.g. at /run/ffs_test), a socket unit with ListenUSBFunction pointing at that mount, and a service unit carrying USBFunctionDescriptors and USBFunctionStrings entries. The socket unit writes descriptors to ep0 and starts the daemon only when USB traffic arrives, with ExecStartPost binding the gadget. Engineers wiring USB gadgets into systemd find the full unit examples and descriptor blobs worth bookmarking on daily.dev."}},{"@type":"Question","name":"What format do I use to write USB descriptors to ep0 in FunctionFS?","acceptedAnswer":{"@type":"Answer","text":"Use the usb_functionfs_descs_head_v2 format defined in include/uapi/linux/usb/functionfs.h (line 89 in v5.0-rc6). The older format is deprecated. An example of constructing the binary blobs in C is in tools/usb/ffs-test.c in the kernel sources. You can modify that program to write descriptors and strings to stdout and capture the output as .bin files for use with USBFunctionDescriptors and USBFunctionStrings. Developers working with FunctionFS descriptor formats track kernel API changes like this on daily.dev."}},{"@type":"Question","name":"What are the four USB endpoint types in Linux USB gadget development?","acceptedAnswer":{"@type":"Answer","text":"The four USB endpoint types are control, bulk, isochronous, and interrupt. Endpoint 0 is the mandatory bidirectional control endpoint used for enumeration and device control. Bulk endpoints transfer large data on a best-effort basis with error-free delivery but no timing guarantees. Isochronous endpoints provide guaranteed bandwidth and bounded latency for time-sensitive data like audio or video, without delivery or integrity guarantees. Interrupt endpoints offer guaranteed latency for device-initiated transfers such as mouse or keyboard input. Embedded developers building USB gadgets on Linux stay current on kernel and tooling changes through daily.dev."}}]}
```

