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


πŸš€ 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. πŸš€πŸ”ŒπŸ“¦


An unhandled error has occurred. Reload πŸ—™