Building a Cross-Platform USB Communication Layer in .NET MAUI
π Building a Cross-Platform USB Communication Layer in .NET MAUI
Connecting Industrial Devices, Scanners, Scales, RFID Readers, and Serial Equipment
When most developers think about mobile applications, they imagine:
- REST APIs π
- Bluetooth devices π‘
- Cloud services βοΈ
But many enterprise applications interact directly with physical hardware.
Examples include:
- π¦ Barcode scanners
- βοΈ Industrial scales
- π·οΈ RFID readers
- π PLC controllers
- π³ Card readers
- π¨οΈ Thermal printers
- π¬ Laboratory equipment
- π Logistics hardware
The challenge is that USB communication is highly platform-specific.
Android, Windows, iOS, and MacCatalyst all expose different APIs and permissions for USB access.
In this guide, we'll design a cross-platform USB communication architecture using .NET MAUI that abstracts these differences and provides a unified development experience.
π§ Why USB Still Matters
Many industries still rely heavily on USB-connected devices because they offer: β Lower latency β Better reliability β No wireless interference β Reduced power consumption β Simpler deployment Especially in:
- Warehouses
- Manufacturing
- Healthcare
- Retail
- Logistics USB remains critical.
π The Challenge
Every platform handles USB differently.
| Platform | USB Support |
|---|---|
| Android | USB Host API |
| Windows | WinUSB / Serial / HID |
| MacCatalyst | IOKit |
| iOS | Very Limited |
This means:
Device
β
Platform API
β
Application
must be abstracted.
ποΈ Architecture Overview
A clean architecture looks like:
UI
β
IUsbService
β
Transport Layer
β
Platform Driver
β
USB Device
This keeps business logic independent from hardware details.
π¦ Common USB Device Types
Before writing code, it's important to understand the different device categories.
π Serial Devices
Examples:
- Industrial scales
- PLCs
- Modems Communication:
COM Port
or
TTY Device
π±οΈ HID Devices
Examples:
- Barcode scanners
- Keypads
- RFID readers Communication:
Human Interface Device
π¦ Vendor-Specific Devices
Examples:
- Proprietary equipment
- Medical devices
- Custom controllers Usually require manufacturer SDKs.
π§© Step 1: Create a USB Abstraction
public interface IUsbCommunicationService
{
Task InitializeAsync();
Task<IEnumerable<UsbDeviceInfo>> GetDevicesAsync();
Task ConnectAsync(string deviceId);
Task DisconnectAsync();
Task SendAsync(byte[] data);
event EventHandler<byte[]> DataReceived;
}
The UI should never care whether the device is:
- Serial
- HID
- WinUSB
π Device Model
public class UsbDeviceInfo
{
public string DeviceId { get; set; }
public string Name { get; set; }
public int VendorId { get; set; }
public int ProductId { get; set; }
}
βοΈ Dependency Injection
Register service:
builder.Services.AddSingleton<IUsbCommunicationService,
UsbCommunicationService>();
π± Platform Implementations
Create:
IUsbCommunicationService
β
AndroidUsbService
WindowsUsbService
MacUsbService
π€ Android USB Communication
Android uses:
UsbManager
Discover Devices
var manager =
(UsbManager)Platform.CurrentActivity
.GetSystemService(Context.UsbService);
var devices = manager.DeviceList;
Permissions
Android requires explicit user approval.
<uses-feature
android:name="android.hardware.usb.host"/>
πͺ Windows USB Communication
Windows supports:
- Serial ports
- HID
- WinUSB
Enumerate Serial Ports
var ports =
SerialPort.GetPortNames();
Open Connection
var port = new SerialPort(
"COM3",
9600);
port.Open();
π MacCatalyst Support
MacCatalyst can access USB devices through native frameworks. However: β οΈ Additional entitlements may be required. Architecture remains:
MAUI
β
Native Bridge
β
USB Device
π« What About iOS?
This is where things become complicated. Apple restricts generic USB communication. Usually you need:
- MFi-certified hardware
- External Accessory Framework Many devices simply won't work.
π Reading Data
Most USB devices follow:
Device
β
Bytes
β
Application
Example
port.DataReceived += (_, _) =>
{
var data = port.ReadExisting();
ProcessData(data);
};
π‘ Writing Data
Sending commands:
await _usbService.SendAsync(
Encoding.ASCII.GetBytes(
"START"));
π·οΈ Example: Barcode Scanner
Many scanners behave like keyboards. Input:
123456789
Application receives:
123456789
through standard text events.
π¦ Example: RFID Reader
Typical flow:
RFID Tag
β
Reader
β
USB
β
MAUI App
Data Event
public event EventHandler<string>
TagScanned;
βοΈ Example: Industrial Scale
Scale output:
Weight: 12.35kg
Parse:
var weight =
decimal.Parse(rawValue);
π Example: PLC Communication
Commands:
READ_STATUS
START
STOP
RESET
Send Command
await _usbService.SendAsync(
Encoding.ASCII.GetBytes(
"READ_STATUS"));
π Message-Based Architecture
Instead of exposing raw bytes everywhere:
public interface IUsbMessage
{
}
Examples:
public class WeightReceivedMessage
{
public decimal Weight { get; set; }
}
π§ Device Driver Pattern
Avoid:
UI
β
Raw USB
Use:
UI
β
ScaleDriver
β
USB Layer
π Driver Benefits
| Benefit | Description |
|---|---|
| Reusability | Multiple apps |
| Testing | Easier mocking |
| Maintenance | Cleaner code |
| Extensibility | New devices |
β‘ Performance Considerations
USB can generate huge amounts of data. Examples:
- Scanners
- Sensors
- Telemetry devices
Background Processing
Never process on UI thread.
await Task.Run(() =>
{
ProcessMessage(data);
});
Buffer Incoming Data
ConcurrentQueue<byte[]>
can help avoid dropped packets.
π Security Considerations
USB devices can be dangerous. Recommendations: β Validate Vendor IDs β Validate Product IDs β Restrict supported devices β Verify message formats
π‘ Hot Plug Support
Devices may disconnect unexpectedly. Handle:
Connected
β
Disconnected
β
Reconnect
gracefully.
π§© Device Discovery UI
A MAUI page can display:
| Device | Status |
|---|---|
| Scale | Connected |
| RFID Reader | Connected |
| Scanner | Disconnected |
π Real-World Scenarios
Warehouse Applications
Devices:
- Barcode scanners
- RFID readers
- Label printers
Manufacturing
Devices:
- PLCs
- Sensors
- Controllers
Healthcare
Devices:
- Medical instruments
- Diagnostic equipment
Retail
Devices:
- Scanners
- Receipt printers
- Payment terminals
βοΈ USB vs Bluetooth
| Feature | USB | Bluetooth |
|---|---|---|
| Reliability | Excellent | Good |
| Mobility | Limited | Excellent |
| Latency | Excellent | Good |
| Power Consumption | Excellent | Good |
| Setup Complexity | Medium | Easy |
π Reference Links
- https://learn.microsoft.com/dotnet/maui/
- https://developer.android.com/guide/topics/connectivity/usb
- https://learn.microsoft.com/dotnet/api/system.io.ports
π Key Takeaways
β USB communication is still essential in many enterprise environments β A platform abstraction layer keeps MAUI code clean β Different device categories require different communication strategies β Driver-based architectures scale much better than direct USB access β USB enables integration with industrial, retail, healthcare, and logistics hardware
π Final Thoughts
Most mobile development content focuses on cloud APIs and Bluetooth devices. Yet many real-world business applications still depend heavily on USB-connected hardware.
By building a proper cross-platform USB communication layer in .NET MAUI, you can bridge the gap between modern mobile applications and the physical devices that power industries such as manufacturing, healthcare, logistics, and retail.
The key is to design the architecture around abstractions and device drivers rather than platform APIs. Once that foundation exists, supporting new hardware becomes dramatically simplerβand your MAUI application becomes capable of interacting with an entire ecosystem of enterprise devices. πππ¦
