Предисловие:
Я давно пользуюсь данным приёмом, но не хотел предавать его огласке. Считал, что это моё конкурентное преимущество. И действительно. В частности за счёт этого мой USB девайс выиграл тендер. Т.к. во время испытаний у конкурентов девайс вешался, а у меня нет. Т.е. у меня тоже вешался, но потом сам развешивался. Но теперь я как-то осознал себя в одной лодке с другими разработчиками. Да ещё меня в другой ветке похвалили за то, что я выложил то, что по моему мнению было всем известно. Я предполагаю, что такой приём некоторые знают, но молчат, как молчал я. Пишу это в надежде, что и другие, кому есть что сказать, последуют моему примеру.
Проблемма:
USB девайсы бывает вешаются. Обсуждалось это и здесь. Пришли к выводу, что это хаб блокирует порт к которому подключен девайс. Разблокировать программно его можно (см. параллельные ветки). Но что делать в тех случаях, когда нельзя ставить/запускать никаких программ. Например ваш девайс это MassStorage с записанным в нем логом. Или HID, к которому обращаются стандартной программой. Или CDC с чужой программой?
Решение - теория:
Когда хаб блокирует порт, то со стороны девайса это воспринимается как переход в Suspend. Т.е. нужно засыпать, потребляя не более 500 микроампер. А различить со стороны девайса реальный Suspend и блокировку порта хабом невозможно. Невозможно без некоторых действий. Если девайс отключит свой подтягивающий резистор к D+, то хаб воспримет это как отключение девайса. Со стороны хаба это неотличимо. А раз девайс вытащили, то хаб переводит порт из заблокированного состояния в отключенное. При последующем подключении, хаб решит, что в этот порт воткнут новый/другой девайс и все начнет работать. Причём это никак не противоречит спецификации USB.
Решение - практика:
Когда мой девайс видит на шине USB состояние Suspend, он действительно засыпает и потребляет при этом не более 500 микроампер. Т.е. удовлетворяет всем спецификациям USB. НО. Периодически обычно раз в 2 секунды он отключает свой подтягивающий резистор на время более 2,5 микросекунд. Реально я делаю около 20 милисекуд и процессор у меня в это время спит. Проснувшись он подключает подтягивающий резистор и смотрит на реакцию шины. По описанию вроде д.б. в течении 15 милисекунд, но реально надо делать побольше. Если ничего не произошло - спит дальше. Появилась активность, пошла энумерация - девайс различает такой вариан от первого втыкания в USB.
Данный способ можно реализовать даже и на FTDI и подобных микросхемах. У них обычно есть выход Suspend. Хотя лично мне эти переходники крайне не нравятся. ИМХО они допустимы ТОЛЬКО как временная мера.
Заключение:
Описанный способ это крайняя мера. Он не предназначен для исправления программных ляпов. Мне он видится чем-то подобным сторожевому таймеру. Надеюсь, что вы не будете уповать только на этот способ, но и будете отлаживать свой девайсы. Хотя в случае FTDI других способов и нет...