Понимание и декодирование стандартных USB-команд до конечной точки ноль?
Я пытаюсь написать процедуру инициализации USB для 8-битного RISC MCU. Ссылка на лист данных приведена ниже.
Моя цель - написать код прототипа устройства, который позволит хосту успешно перечислять мое устройство и отправлять / получать данные.
В SDK этого IC есть статическая библиотека UFI без источников, которая имеет только несколько функций, определенных в заголовочном файле:
//
// Command/Data/Status Protocol
//
typedef struct _CBW // Command Block Wrapper
{
unsigned char dSignature[4]; // 43425355h (little endian)
unsigned char dTag[4];
unsigned char dDataTransferLength[4];
unsigned char bmFlags; // Bit 7 0 = Data-Out from host to the device.
// 1 = Data-In from the device to host.
// Bit 6 Obsolete
unsigned char bLUN;
unsigned char bCBLength;
unsigned char CB[0x10]; // offset: (15 + bCBLength - 1)
} CBW;
typedef struct _CSW // Command Status Wrapper
{
unsigned char dSignature[4]; // 53425355h (little endian)
unsigned char dTag[4];
unsigned char dDataResidue[4];
unsigned char bStatus; // 00h Command Passed ("good status")
// 01h Command Failed
// 02h Phase Error
// 03h and 04h Reserved (Obsolete)
} CSW;
#define COMMAND_PASSED 0x00
#define COMMAND_FAILED 0x01
#define PHASE_ERROR 0x02
enum
{
UFI_MODE_TIMESYNC = 1,
UFI_MODE_DOWNSTART,
UFI_MODE_DOWNFINISH,
UFI_MODE_IGNORE,
UFI_MODE_NORMAL
};
//
// UFI Command
//
#define INQUIRY 0x12
#define READ_FORMAT_CAPACITIES 0x23
#define READ_CAPACITY 0x25
#define READ_10 0x28
#define REQUEST_SENSE 0x03
#define TEST_UNIT_READY 0x00
#define PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e
#define WRITE_10 0x2a
#define VERIFY 0x2f
typedef struct
{
UCHAR memType; // 0:eflash 1:s-flash
ULONG tgtAddr; // Target address to write
ULONG totSize; // Total size of data
ULONG curSize; // Downloaded size of data
}stUfiDwnStatus;
UFI_EXT CBW g_cbw;
UFI_EXT CSW g_csw;
UFI_EXT unsigned char g_bUfiWriteMode;
UFI_EXT unsigned char g_bUfiWriteMode_post;
UFI_EXT stUfiDwnStatus g_ufiDwnStaus;
void UFI_proc(void);
void UFI_InitMem(UCHAR *buf, UCHAR *name); // Buffer size must be larger than 0x200
void UFI_InitFuncEFlash(void (*funcSectorErase)(UCHAR AddH, UCHAR AddM, UCHAR AddL),
void (*funcPageProgram)(UCHAR AddH, UCHAR AddM, UCHAR AddL, int size, UCHAR *Buffer),
void (*funcRead)(UCHAR AddH, UCHAR AddM, UCHAR AddL, int size, UCHAR *Buffer) );
void UFI_InitFuncSFlash(void (*funcBlockErase)(UCHAR AddH, UCHAR AddM, UCHAR AddL),
void (*funcPageProgram)(UCHAR AddH, UCHAR AddM, UCHAR AddL, int size, UCHAR *Buffer),
void (*funcRead)(UCHAR AddH, UCHAR AddM, UCHAR AddL, int size, UCHAR *Buffer) );
Каким-то образом мне нужно использовать эту библиотеку, чтобы установить мое устройство в качестве запоминающего устройства, чтобы избежать работы с пользовательскими драйверами хост-устройств.
Проблема в том, что я не знаю с чего начать. Особенно я не понимаю, как настроить EP0? Список возможностей USB упоминает
Understanding and decoding of standard USB commands to endpoint zero
Что именно это значит? Документация действительно скудная, и я не знаю, какую логику придерживаться, чтобы инициализировать USB-устройство хотя бы на стороне устройства. Обычно я читаю об USB, но не могу связать эти знания с тем, как я должен конструировать свой код... Я выполнил кодирование всех периферийных устройств на этой микросхеме, кроме USB.
Любая идея будет высоко оценена.
https://www.dropbox.com/s/qd9d25oxxvh23ia/BMC51A_UM_REV1.0.pdf
2 ответа
"Стандартные команды USB для конечной точки ноль" описаны в главе 9 спецификации USB. Я обычно ссылаюсь на ревизию 2.0, которую вы можете найти здесь:
http://www.usb.org/developers/docs/usb20_docs/
Просто скачайте ZIP-файл, найдите usb_20.pdf
и перейдите к Главе 9. В этой главе определяются передачи управления на нулевой конечной точке, которые используются USB-хостом для получения дескрипторов и настройки устройства. Спецификация USB составляет около 600 страниц, но она очень удобочитаема, и вы сможете многому научиться на ней.
Чтобы ваше устройство работало как запоминающее устройство, вам необходимо реализовать некоторые дополнительные функции, описанные в документах класса устройств USB-IF в категории запоминающее устройство:
http://www.usb.org/developers/docs/devclass_docs/
Если вы используете USB на этом уровне, вам понадобится какой-то способ посмотреть на низкоуровневый трафик на шине. Я рекомендую использовать аппаратный анализатор протоколов USB, но вы также можете найти программное решение. Вы также можете использовать осциллограф, но вам потребуется много минут, чтобы декодировать каждый пакет и найти то, что вы ищете.
Выложенный вами код не похож на стандартные команды USB. Это может быть связано с классом MSD или, может быть, это какой-то специальный протокол.
"Конечная точка ноль" - это "передача управления" в USB.
Для обмена данными существуют "массовые передачи" (массовая передача и массовая передача, с разными конечными точками).
Я советую сначала написать простой драйвер USB на компьютере, чтобы узнать, как работает USB.
Вы можете прослушивать usb-пакеты в linux с помощью "tcpdump" (используя интерфейс usbmon0, usbmon1 и т. Д. После "modprobe usbmon"). Используйте wireshark для просмотра пакетов.
Вы можете легко получить доступ к USB из пользовательского пространства с помощью libusb.