Как и почти любой другой тип интерфейса связи, USB реализован в виде стека протоколов. Уровни в этом стеке, которые являются общими для всех или нескольких типов устройств, определяются самими стандартами USB, что обеспечивает совместимость и не позволяет каждому устройству создавать избыточные протоколы. Кроме того, каждый уровень протокола абстрагируется от деталей, о которых не нужно беспокоиться на следующем уровне. Таким образом, когда вы на самом деле пишете слой, специфичный для устройства, у вас просто есть общие функции отправки и получения, которые передают данные из конечной точки A в конечную точку B. Вам, как разработчику устройства, не нужно заботиться о как это происходит Кроме того, более низкие уровни в стеке протоколов могут изменить реализацию, если они предоставляют общий интерфейс для уровня над ними. Таким образом, когда одна часть стека протоколов изменяется, остальная часть стека не обязательно должна меняться. В идеале протоколы на более высоких уровнях стека даже не должны заботиться о том, какой именно протокол используется на более низком уровне стека. Вообще говоря, каждый последовательный уровень вниз по стеку будет инкапсулировать сообщение, создаваемое следующим самым высоким уровнем в его собственном поле полезной нагрузки, во время отправки сообщения. Когда сообщение получено, каждый уровень снимает часть, относящуюся к этому уровню, и перенаправляет свою полезную нагрузку на следующий соответствующий уровень вверх по стеку. Это касается не только USB, но и почти всех коммуникационных шин. Например, стек TCP/IP/Ethernet, вероятно, является наиболее часто используемым из них. Задачи, за которые обычно отвечают эти уровни, описаны в моделях, таких как модель OSI.
В USB есть протокол физического уровня, который определяет состояния напряжения / время / и т.д. на проводе и как их следует интерпретировать. Этот протокол, очевидно, должен быть частью самих стандартов USB, а не только для конкретного устройства (тем более что хост не может знать, какое устройство будет подключено к данному USB-порту).
Далее, есть протокол управления шиной, используемый для описания, кто может разговаривать по шине, когда. Это называется уровнем доступа к среде в модели OSI. В USB этот уровень можно в значительной степени суммировать как «устройство может передавать, когда хост говорит ему об этом», так что на этом уровне в USB нет особенно сложного протокола.
Далее, есть стандартный протокол для описания пакета данных и того, как он должен быть направлен от отправителя к получателю. Этот уровень также должен быть частью самого стандарта USB, так что первоначальная связь с целью определения того, какой тип устройства был подключен, может произойти до того, как конкретный тип устройства будет фактически известен хосту. В дополнение к каждому устройству, имеющему конкретный идентификатор на этом уровне, в USB также существует концепция идентификатора конечной точки. Это позволяет любому устройству иметь несколько оконечных точек USB, которые мультиплексируются и демультиплексируются стандартным стеком USB, во многом так же, как сокеты мультиплексируются и демультиплексируются стандартным стеком TCP/IP. Приложение может обрабатывать каждую из этих конечных точек как отдельные потоки данных.
Наконец, есть протокол, определенный для самого устройства. Обратите внимание, что на самом деле есть некоторые общие предварительно разработанные, включенные как часть стандарта USB для общих случаев использования, таких как устройства хранения данных, мыши, клавиатуры и т.д., Так что каждый производитель устройства не должен заново изобретать рулевое колесо. Тем не менее, более сложные устройства могут самостоятельно разрабатывать собственные протоколы на этом уровне. Выходные данные этого уровня для данной передачи передаются как полезная нагрузка пакета данных на предыдущем уровне. Обратите внимание, что для достаточно сложных устройств специфичная для устройства часть протокола сама может быть разделена на несколько независимых уровней, но нижние уровни не должны знать об этом или заботиться о них. Все, что им нужно знать, это то, что им нужно передать заданный набор байтов от хоста к конкретной конечной точке устройства или от конкретной конечной точки устройства к хосту. Опять же, наличие стандартного интерфейса между уровнями позволяет разделить задачи, поэтому один уровень не должен заботиться о внутренней работе другого уровня, а только о конкретных данных, которые он должен передать или ожидать получить от уровней непосредственно выше или ниже его в стеке.