ХАКЕР 04 /171/ 2013 Через эмуляцию к звездам 57USB_PUBLIC uchar usbFunctionWrite(uchar *data,uchar len) {uchar i;// Сохранить полученную порцию данных в буферfor(i = 0; dataReceived < dataLength && i next) {// Перебрать все устройства на шинеfor(dev=bus->devices; dev; dev=dev->next) {// Если идентификаторы вендора и продукта// не совпадают...if(dev->descriptor.idVendor != vendor ||dev->descriptor.idProduct != product)continue; // ...пропустить эту итерацию// Попробовать получить дескриптор устройстваif(!(handle = usb_open(dev))) {Тестирование взаимодействия с ATtiny2313 по USB(заливаем в чип строку, а затем cчитываем ее)fprintf(stderr, "%s\n", usb_strerror());continue;}return handle; // Вернуть дескриптор}}// Устройство не найденоreturn NULL;Как видно, параметрами usbOpenDevice выступают числовыеидентификаторы производителя и устройства. В случаеесли устройство присутствует на шине, возвращается его дескриптор.Если устройств на V-USB будет несколько — придетсядописать проверку символьных имен вендора и продукта.И функция main консольной утилиты usbtest:int main(int argc, char **argv) {// Дескриптор устройстваusb_dev_handle *handle = NULL;int nBytes = 0;char buffer[256];// Ищем устройствоhandle = usbOpenDevice(0x16C0, 0x05DC);if(handle == NULL) {fprintf(stderr, "Could not find USB device!\n");exit(1);}// Аргумент out — получить данные от чипаif(strcmp(argv[1], "out") == 0) {nBytes = usb_control_msg(handle,USB_TYPE_VENDOR | USB_RECIP_DEVICE |Перехват USB-пакетов в WiresharkDVDНа прилагаемомк журналу дискележат исходные кодыописанного в статьепримера и последняяверсия библиотекиV-USB.PROTEUSОТДЫХАЕТВсенародно любимыйсимулятор электрическихсхем Proteus ISISбесполезен при разработкеустройств с программнойреализациейUSB. Его эмулятор USBподдерживает толькочипы с аппаратной поддержкойуниверсальнойпоследовательной шины(например, AT90USB646или AT90USB1286).
58PHREAKINGХАКЕР 04 /171/ 2013USB_ENDPOINT_IN,DATA_OUT, 0, 0, (char *)buffer,sizeof(buffer), 5000);printf("Got %d bytes: %s\n", nBytes, buffer);// Аргумент in — отправить строку// (следующий аргумент)} else if(strcmp(argv[1], "in") == 0 && argc >2) {nBytes = usb_control_msg(handle,USB_TYPE_VENDOR | USB_RECIP_DEVICE |USB_ENDPOINT_OUT,DATA_IN, 0, 0, argv[2], strlen(argv[2])+1,5000);}if(nBytes < 0) fprintf(stderr, "%s\n",usb_strerror());usb_close(handle); // Закрыть дескрипторreturn 0;}Здесь правит бал функция usb_control_msg, которая объявленаво включаемом файле usb.h. Она имеет кучу параметрови собственно создает те управляющие сообщения, обработкакоторых реализована в прошивке микроконтроллера.СОБИРАЕМ, ПРОШИВАЕМ, ТЕСТИРУЕМНиже приведен небольшой, но очень полезный Makefile, c помощьюкоторого командой make из main.c и usbtest.c легко получитьпрошивку для чипа — main.hex и бинарник утилиты usbtest:CC = avr-gccOBJCOPY = avr-objcopyCFLAGS = -Wall -Os -Iusbdrv -mmcu=attiny2313OBJFLAGS = -j .text -j .data -O ihexOBJECTS = usbdrv/usbdrv.o usbdrv/oddebug.ousbdrv/usbdrvasm.o main.oCMDLINE = usbtest# Цель: собрать всеall: main.hex $(CMDLINE)Работа с программатором avrdude$(CC) $(CFLAGS) $(OBJECTS) -o $@# Сборка файлов библиотеки V-USB$(OBJECTS): usbdrv/usbconfig.h# C в объектный код%.o: %.c$(CC) $(CFLAGS) -c $< -o $@# asm в объектный код%.o: %.S$(CC) $(CFLAGS) -x assembler-with-cpp -c $< -o $@# Сборка утилиты для компьютера$(CMDLINE): usbtest.cgcc -I ./libusb/include -L ./libusb/lib/gcc-O -Wall usbtest.c -o usbtest -lusb# Очистить проект от бинарного кодаclean:$(RM) *.o *.hex *.elf usbdrv/*.o# Получение файла прошивки из elf-файла%.hex: %.elf$(OBJCOPY) $(OBJFLAGS) $< $@# Сборка elf-файлаmain.elf: $(OBJECTS)На уровне логики протоколUSB — это, по сути, многоуровневаяпакетная передачаданных. В этом нетрудноубедиться (а заодно узнатьмного интересного про USB),воспользовавшись анализаторомсетевых протоколовWiresharkЛОЖКА ДЕГТЯСофтовый USB не естьпанацея. Программныереализации обычноимеют ряд упрощений,таких как отсутствиепроверки контрольнойсуммы и симметричностиканала, что отрицательносказывается напомехозащищенности.Также обычно софтовыебиблиотеки используютнизкоскоростныережимы работы USB. Даи код USB-библиотеки«кушает» и без того небольшуюпамять чипа.Чтобы залить прошивку в микроконтроллер с помощью программатораusbtiny, набираем команду:$ sudo avrdude -p t2313 -c usbtiny -e -Uflash:w:main.hex:i -U lfuse:w:0xef:mВ avrdude фьюзы задаются не слишком наглядно, но их можнолегко рассчитать в одном из online-калькуляторов.Подключаем устройство к компьютеру и проверяем, как оноработает (usbtest c параметром out считывает строку, in — записываетуказанную строку в буфер чипа):$ sudo ./usbtest in all_ok$ sudo ./usbtest outПОДГЛЯДЫВАЕМ…На уровне логики протокол USB — это, по сути, многоуровневаяпакетная передача данных. В этом нетрудно убедиться (азаодно узнать много интересного про USB), воспользовавшисьанализатором сетевых протоколов Wireshark. Предварительнонеобходимо загрузить драйвер USB-монитора:$ sudo modprobe usbmonТеперь в списке интерфейсов Wireshark можно выбиратьшины USB. Посмотреть номер шины устройства можно, например,в логах.ЗАКЛЮЧЕНИЕНадеюсь, после того, как ты научился пересылать данныемежду компьютером и микроконтроллером AVR, твоя страстьк электронике разгорится с новой силой, породив немало оригинальныхи полезных устройств. Остается лишь пожелать тебеуспехов на этом сложном, но интересном поприще.