-
Notifications
You must be signed in to change notification settings - Fork 6.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
usb: usbip: add initial support for USBIP server #74141
base: main
Are you sure you want to change the base?
Changes from all commits
200d364
88215af
ad07fb2
3bd53b1
473a7b2
ec3c55f
be54735
2c3a937
7819bb8
d378c15
e8ccf3c
303621d
a3a126d
1d9207f
9503032
c7d8814
edd80e6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
.. _usbip: | ||
|
||
USB/IP protocol support | ||
####################### | ||
|
||
Overview | ||
******** | ||
|
||
New USB support includes initial support for the USB/IP protocol. It is still | ||
under development and is currently limited to supporting only one device | ||
connected to the host controller being exported. | ||
|
||
USB/IP uses TCP/IP. Both of the underlying connectivity stacks, USB and | ||
networking, require significant memory resources, which must be considered when | ||
choosing a platform. | ||
|
||
In the USB/IP protocol, a server exports the USB devices and a client imports | ||
them. USB/IP support in the Zephyr RTOS implements server functionality and | ||
exports a device connected to a host controller on a device running the Zephyr | ||
RTOS. A client, typically running the Linux kernel, imports this device. The | ||
USB/IP protocol is described in `USB/IP protocol documentation`_. | ||
|
||
To use USB/IP support, make sure the required modules are loaded on the client side. | ||
|
||
.. code-block:: console | ||
|
||
modprobe vhci_hcd | ||
modprobe usbip-core | ||
modprobe usbip-host | ||
|
||
On the client side, you will also need the **usbip** user tool. It can be installed | ||
using your Linux distribution's package management system or built from Linux | ||
kernel sources. | ||
|
||
There are a few basic commands for everyday use. To list exported USB devices, | ||
run the following command: | ||
|
||
.. code-block:: console | ||
|
||
$ usbip list -r 192.0.2.1 | ||
Exportable USB devices | ||
====================== | ||
- 192.0.2.1 | ||
1-1: NordicSemiconductor : unknown product (2fe3:0001) | ||
: /sys/bus/usb/devices/usb1/1-1 | ||
: Miscellaneous Device / ? / Interface Association (ef/02/01) | ||
: 0 - Communications / Abstract (modem) / None (02/02/00) | ||
: 1 - CDC Data / Unused / unknown protocol (0a/00/00) | ||
|
||
To attach an exported device with busid 1-1: | ||
|
||
.. code-block:: console | ||
|
||
$ sudo usbip attach -r 192.0.2.1 -b 1-1 | ||
|
||
To detach an exported device on port 0: | ||
|
||
.. code-block:: console | ||
|
||
$ sudo usbip detach -p 0 | ||
|
||
USB/IP with native_sim | ||
********************** | ||
|
||
The preferred method to develop with USB/IP support enabled is to use | ||
:ref:`native_sim <native_sim>`. Use on real hardware is not really tested yet. | ||
USB/IP requires a network connection, see :ref:`networking_with_native_sim` | ||
for how to set up the interface on the client side. | ||
|
||
Building and running a sample with USB/IP requires extensive configuration, | ||
you can use usbip-native-sim snippet to configure host and USB/IP support. | ||
|
||
.. zephyr-app-commands:: | ||
:zephyr-app: samples/subsys/usb/cdc_acm | ||
:board: native_sim/native/64 | ||
:gen-args: -DSNIPPET=usbip-native-sim -DEXTRA_DTC_OVERLAY_FILE=app.overlay | ||
:goals: build | ||
|
||
.. _USB/IP protocol documentation: https://www.kernel.org/doc/html/latest/usb/usbip_protocol.html |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -92,39 +92,54 @@ void uhc_xfer_buf_free(const struct device *dev, struct net_buf *const buf) | |
} | ||
|
||
struct uhc_transfer *uhc_xfer_alloc(const struct device *dev, | ||
const uint8_t addr, | ||
const uint8_t ep, | ||
const uint8_t attrib, | ||
const uint16_t mps, | ||
const uint16_t timeout, | ||
void *const udev, | ||
void *const cb) | ||
struct usb_device *const udev, | ||
void *const cb, | ||
void *const cb_priv) | ||
{ | ||
uint8_t ep_idx = USB_EP_GET_IDX(ep) & 0xF; | ||
const struct uhc_api *api = dev->api; | ||
struct uhc_transfer *xfer = NULL; | ||
uint16_t mps; | ||
|
||
api->lock(dev); | ||
|
||
if (!uhc_is_initialized(dev)) { | ||
goto xfer_alloc_error; | ||
} | ||
|
||
LOG_DBG("Allocate xfer, ep 0x%02x attrib 0x%02x cb %p", | ||
ep, attrib, cb); | ||
if (ep_idx == 0) { | ||
mps = udev->dev_desc.bMaxPacketSize0; | ||
} else { | ||
struct usb_ep_descriptor *ep_desc; | ||
|
||
if (USB_EP_DIR_IS_IN(ep)) { | ||
ep_desc = udev->ep_in[ep_idx].desc; | ||
} else { | ||
ep_desc = udev->ep_out[ep_idx].desc; | ||
} | ||
|
||
if (ep_desc == NULL) { | ||
LOG_ERR("Endpoint 0x%02x is not configured", ep); | ||
goto xfer_alloc_error; | ||
} | ||
|
||
mps = ep_desc->wMaxPacketSize; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How is There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Device descriptor is stored in CPU native endianness. |
||
} | ||
|
||
LOG_DBG("Allocate xfer, ep 0x%02x mps %u cb %p", ep, mps, cb); | ||
|
||
if (k_mem_slab_alloc(&uhc_xfer_pool, (void **)&xfer, K_NO_WAIT)) { | ||
LOG_ERR("Failed to allocate transfer"); | ||
goto xfer_alloc_error; | ||
} | ||
|
||
memset(xfer, 0, sizeof(struct uhc_transfer)); | ||
xfer->addr = addr; | ||
xfer->ep = ep; | ||
xfer->attrib = attrib; | ||
xfer->mps = mps; | ||
xfer->timeout = timeout; | ||
xfer->udev = udev; | ||
xfer->cb = cb; | ||
xfer->priv = cb_priv; | ||
|
||
xfer_alloc_error: | ||
api->unlock(dev); | ||
|
@@ -133,13 +148,10 @@ struct uhc_transfer *uhc_xfer_alloc(const struct device *dev, | |
} | ||
|
||
struct uhc_transfer *uhc_xfer_alloc_with_buf(const struct device *dev, | ||
const uint8_t addr, | ||
const uint8_t ep, | ||
const uint8_t attrib, | ||
const uint16_t mps, | ||
const uint16_t timeout, | ||
void *const udev, | ||
struct usb_device *const udev, | ||
void *const cb, | ||
void *const cb_priv, | ||
size_t size) | ||
{ | ||
struct uhc_transfer *xfer; | ||
|
@@ -150,7 +162,7 @@ struct uhc_transfer *uhc_xfer_alloc_with_buf(const struct device *dev, | |
return NULL; | ||
} | ||
|
||
xfer = uhc_xfer_alloc(dev, addr, ep, attrib, mps, timeout, udev, cb); | ||
xfer = uhc_xfer_alloc(dev, ep, udev, cb, cb_priv); | ||
if (xfer == NULL) { | ||
net_buf_unref(buf); | ||
return NULL; | ||
|
@@ -298,7 +310,8 @@ int uhc_disable(const struct device *dev) | |
return ret; | ||
} | ||
|
||
int uhc_init(const struct device *dev, uhc_event_cb_t event_cb) | ||
int uhc_init(const struct device *dev, | ||
uhc_event_cb_t event_cb, const void *const event_ctx) | ||
{ | ||
const struct uhc_api *api = dev->api; | ||
struct uhc_data *data = dev->data; | ||
|
@@ -316,6 +329,7 @@ int uhc_init(const struct device *dev, uhc_event_cb_t event_cb) | |
} | ||
|
||
data->event_cb = event_cb; | ||
data->event_ctx = event_ctx; | ||
sys_dlist_init(&data->ctrl_xfers); | ||
sys_dlist_init(&data->bulk_xfers); | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
worth mentioning packages to get for ubuntu here so users don't have to search for why the command is not found?