Библиотека LUFA (раннее название MyUSB) версия 101122
USB Class Drivers

Modules

 Audio Class Driver
 CDC-ACM (Virtual Serial) Class Driver
 HID Class Driver
 Mass Storage Class Driver
 MIDI Class Driver
 Printer Class Driver
 RNDIS (Networking) Class Driver
 Still Image Class Driver

Detailed Description

Драйвера для стандартных классов USB - и для режима хоста, и для режима устройства, для ускоренной разработки приложений. Драйверы класса дают рабочее окружение, которое основано на низкоуровневой библиотеке API, что позволяет реализовать в проектах стандартные классы USB с минимальным добавлением кода пользователя. Эти драйверы можно использовать в соединении с низкоуровневым API библиотеки для реализации интерфейсов и с драйверами класса, и с стандартной библиотекой API.

В одном проекте можно использовать совмещенные драйверы класса, включая несколько экземпляров драйвера того же самого класса. В этом случае, хосты USB и устройства USB могут быть быстро изготовлены с использованием внутренних драйверов класса, что позволит вместо протокола USB уделить больше времени для конечного проложения.

Ниже перечислены доступные драйверы класса и их режимы.

USB Class Device Mode Host Mode
Audio Yes No
CDC Yes Yes
HID Yes Yes
MIDI Yes Yes
Mass Storage Yes Yes
Printer No Yes
RNDIS Yes Yes
Still Image No Yes

Использование драйверов класса

Для простого интегрирования драйверов класса в приложение пользователя, все используют стандартизованный дизайн с простыми для именования/использования функциями, перечислениями (enum), определениями (define) и типами. Два разных режима реализованы несколько по-разному, и поэтому должны быть разъяснены по отдельности. Для информации по специфическому драйверу класса, читайте документацию к модулю этого драйвера класса.

Драйвера класса режима устройства USB (Device Mode Class Drivers)

Реализация драйвера USB режима устройства (Device Mode Class Driver) в приложении пользователя требует выполнения некоторого количества шагов. Во-первых, в исходники проекта дожны быть добавлены конфигурация модуля и структура состояния. Эти структуры для разных классов называются в одинаковом стиле, как USB_ClassInfo_{Class Name}_Device_t, и они используются для удержания полного состояния и конфигурации для каждого экземпляра класса. Несколько экземпляров одного и того же класса - в этом заключается сила драйверов класса; реализация нескольких интерфейсов того же самого класса просто требует нескольких экземпляров структур ClassInfo (информация драйвера класса).

Внутри структуры ClassInfo расположены две секции - секция Config и секция State. Секция Config содержит экземпляр параметров конфигурации, и должна иметь все поля установленными в приложении пользователя перед тем, как драйвер класса может быть использован. Каждый драйвер класса режима устройства USB обычно состоит их набора параметров конфигурации для размера/количества конечных точек (endpoint) привязанного логического интерфейса USB, плюс любые специфические для класса параметры конфигурации.

Секция State (состояние) структуры ClassInfo разработана для того, чтобы быть управляемой только драйверами класса, для поддержки состояния экземпляра драйвера класса, и обычно не должна быть установлена приложением пользователя.

В следующем примере показан правильно инициализированный экземпляр структуры Audio Class Driver:

  USB_ClassInfo_Audio_Device_t My_Audio_Interface =
  {
      .Config =
          {
              .StreamingInterfaceNumber = 1,

              .DataINEndpointNumber     = 1,
              .DataINEndpointSize       = 256,
          },
  };
Note:
Параметры конфигурации драйвера класса должны соответствовать используемым дескрипторам устройства, которые отправляются хосту.

Для инициализации интерфейса драйвера класса должны быть вызваны функции драйвера {Class Name}_Device_ConfigureEndpoints() в ответ на событие EVENT_USB_Device_ConfigurationChanged(). Эти функции вернут двоичное true, если экземпляр драйвера успешно инициализирован. Как и все функции драйвера, эта функция получает адрес конкретного экземпляра, который нужно инициализировать - в этом случае можно инициализировать несколько отдельных экземпляров того же самого класса, например:

  void EVENT_USB_Device_ConfigurationChanged(void)
  {
    LEDs_SetAllLEDs(LEDMASK_USB_READY);

    if (!(Audio_Device_ConfigureEndpoints(&My_Audio_Interface)))
      LEDs_SetAllLEDs(LEDMASK_USB_ERROR);
  }

Как только класс инициализирован, важно поддерживать его состояние постоянными повторяющимися вызовами функций класса драйвера {Class Name}_Device_USBTask() из главного цикла программы. Точная реализация этой функции различается для каждого класса драйвера, и может быть использована для любых внутренних нужд экземпляра класса драйвера. И как в прошлый раз, эта функция использует для работы адрес экземпляра, и поэтому должна вызваться для каждого отдельного экземпляра, как и главная процедура поддержки USB USB_USBTask():

  int main(void)
  {
      SetupHardware();

      LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);

      for (;;)
      {
          Create_And_Process_Samples();

          Audio_Device_USBTask(&My_Audio_Interface);
          USB_USBTask();
      }
  }

Последней стандартизованной функцией для драйвера класса устройства (Device Class Driver) является функция обработчика управляющего запроса (Control Request handler) {Class Name}_Device_ProcessControlRequest(), которая должна быть вызвана, когда срабатывает событие EVENT_USB_Device_ControlRequest(). Эта функция также должна быть вызвана для каждого экземпляра драйвера класса, используя адрес экземпляра как параметр функции. Обработчик прерывания будет прерывать работу, если он определил, что текущий запрос не предназначен для указанного экземпляра класса, следовательно эти методы можно безопасно вызывать без проверки ошибок друг за другом в обработчике события:

Каждый драйвер класса может также определить набор функций обратного вызова (имеющие префикс "CALLBACK_" в имени функции), которые должны быть также добавлены в приложение пользователя - обратитесь к индивидуальной документации драйвера класса для обязательных callback. В дополнение каждый драйвер класса может также определить набор событий (идентифицируемые по префиксу "EVENT_" в имени функции), которые приложение пользователя может обработать или игнорировать, если событие не интересно.

Индивидуальная документация по Device Mode Class Driver содержит более подробную информацию по не стандартизованным, class-specific функциям, которые приложение пользователя может использовать в экземпляре драйвера, такие как подпрограммы чтения и записи данных. Для подробностей по class-specific функциям см. индивидуальную документацию по каждому драйверу.

Драйверы класса режима хоста (Host Mode Class Drivers)

Реализация драйвера класса режима хоста в приложении пользователя требует выполнения нескольких шагов. Во-первых, в исходники проекта дожны быть добавлены конфигурация модуля и структура состояния. Эти структуры для разных классов называются в одинаковом стиле, как USB_ClassInfo_{Class Name}_Host_t, и они используются для удержания полного состояния и конфигурации для каждого экземпляра класса. Несколько экземпляров одного и того же класса - в этом заключается сила драйверов класса; реализация нескольких интерфейсов того же самого класса просто требует нескольких экземпляров структур ClassInfo (информация драйвера класса).

Внутри структуры ClassInfo расположены две секции - секция Config и секция State. Секция Config содержит экземпляр параметров конфигурации, и должна иметь все поля установленными в приложении пользователя перед тем, как драйвер класса может быть использован. Каждый драйвер класса режима устройства USB обычно состоит их набора параметров конфигурации для размера/количества конечных точек (endpoint) привязанного логического интерфейса USB, плюс любые специфические для класса параметры конфигурации.

Секция State (состояние) структуры ClassInfo разработана для того, чтобы быть управляемой только драйверами класса, для поддержки состояния экземпляра драйвера класса, и обычно не должна быть установлена приложением пользователя.

В следующем примере показан правильно инициализированный экземпляр структуры MIDI Class Driver:

  USB_ClassInfo_MIDI_Host_t My_MIDI_Interface =
  {
      .Config =
          {
              .DataINPipeNumber       = 1,
              .DataINPipeDoubleBank   = false,

              .DataOUTPipeNumber      = 2,
              .DataOUTPipeDoubleBank  = false,
          },
  };

Для инициализации экземпляра драйвера класса должна быть вызвана функция драйвера {Class Name}_Host_ConfigurePipes() в ответ на вход машины состояния хоста в состояние HOST_STATE_Addressed. Эта функция возвратит код ошибки из перечисления драйвера класса {Class Name}_EnumerationFailure_ErrorCodes_t чтобы показать, что драйвер успешно инициализировал свой экземпляр и сделал его привязку к интерфейсу в подключенном устройстве. Как и все функции драйвера класса, эта функция принимает адрес отдельного экземпляра, который нужно инициализировать - в этом случае можно инициализировать несколько отдельных экземпляров одного и того же типа класса. Фрагмент драйвера класса, бизирующегося на приложении режима хоста может выглядеть так:

      switch (USB_HostState)
      {
          case HOST_STATE_Addressed:
              LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);

              uint16_t ConfigDescriptorSize;
              uint8_t  ConfigDescriptorData[512];

              if (USB_Host_GetDeviceConfigDescriptor(1, &ConfigDescriptorSize, ConfigDescriptorData,
                                                     sizeof(ConfigDescriptorData)) != HOST_GETCONFIG_Successful)
              {
                  LEDs_SetAllLEDs(LEDMASK_USB_ERROR);
                  USB_HostState = HOST_STATE_WaitForDeviceRemoval;
                  break;
              }

              if (MIDI_Host_ConfigurePipes(&My_MIDI_Interface,
                                           ConfigDescriptorSize, ConfigDescriptorData) != MIDI_ENUMERROR_NoError)
              {
                  LEDs_SetAllLEDs(LEDMASK_USB_ERROR);
                  USB_HostState = HOST_STATE_WaitForDeviceRemoval;
                  break;
              }

              // Other state handler code here

Обратите внимание, что функция также требует дескриптор конфигурации устройства, чтобы можно было определить, какой интерфейс в устройстве связать с драйвером - это можно получить, как показано в вышеупомянутом фрагменте с использованием функции USB_Host_GetDeviceConfigDescriptor(). Если устройство не реализует интерфейс, который ищет драйвер класса, если все подходящие интерфейсы уже привязаны к экземплярам драйвера класса или если произошла ошибка при привязке к интерфейсу устройства (например, используемый банк конечной точки больше, чем максимально поддерживаемый размер банка), то конфигурация перестанет работать.

Как только класс инициализирован, важно поддерживать его состояние постоянными повторяющимися вызовами функций класса драйвера {Class Name}_Host_USBTask() из главного цикла программы. Точная реализация этой функции различается для каждого класса драйвера, и может быть использована для любых внутренних нужд экземпляра класса драйвера. И как в прошлый раз, эта функция использует для работы адрес экземпляра, и поэтому должна вызваться для каждого отдельного экземпляра, как и главная процедура поддержки USB USB_USBTask():

  int main(void)
  {
      SetupHardware();

      LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);

      for (;;)
      {
          switch (USB_HostState)
          {
             // Host state machine handling here
          }

          MIDI_Host_USBTask(&My_Audio_Interface);
          USB_USBTask();
      }
  }

Каждый драйвер класса может также определить набор функций обратного вызова (имеющие префикс "CALLBACK_" в имени функции), которые должны быть также добавлены в приложение пользователя - обратитесь к индивидуальной документации драйвера класса для обязательных callback. В дополнение каждый драйвер класса может также определить набор событий (идентифицируемые по префиксу "EVENT_" в имени функции), которые приложение пользователя может обработать или игнорировать, если событие не интересно.

Индивидуальная документация по Device Mode Class Driver содержит более подробную информацию по не стандартизованным, class-specific функциям, которые приложение пользователя может использовать в экземпляре драйвера, такие как подпрограммы чтения и записи данных. Для подробностей по class-specific функциям см. индивидуальную документацию по каждому драйверу.

 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines