Общение с USB-устройством

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

USB-устройства, по большей части флешки, отказывали у многих и прежде чем заниматься их восстановлением хотелось бы извлечь из этой флешки побольше информации — чем больше информации, тем лучше .... А вот как поговрить с этим устройством, особо и не расписано.....информация, конечно, имеется, но в основном вся проверка сводится к тестированию несколькими утилитами.... А вот как общаются эти самые утилиты с устройством …. особо и неизвестно ….. а общаются они посредством SCSI команд (запрос/ответ). И напрашивается вывод - а может лучше самим пообщаться с устройством без всяких посредников, напрямую ?
Вот с этими способами общения и хочу ознакомить форумчан......
В основном для тестирования флешек в Linux применяют утилиту hdparm и реже sdparm.
В качестве подопытного будет 16G флешка (при возможности буду приводить похожие выводы всеми способами — обоими утилитами и SCSI командами)
# sdparm -i /dev/sdb
/dev/sdb: JetFlash Transcend 16GB 1100
malformed VPD response, VPD pages probably not supported

USB-устройство, в частности флешка, представляет собой тот же мини/микро компьютер — описывать ее устройство не собираюсь — все давно уже хорошо описано и в инете можно найти кучу схем и описаний (интересующимся даю ссылку на старую статью..... там хоть и много лишнего, но хорошая схемка......что то другой похожей я у себя не нашел, а может плохо искал....)

Для начала - набор команд SCSI разрабатывался, как протокол для устройств, использующих параллельный интерфейс для малых компьютерных систем (Small Computer Systems Interface - SCSI). Команды является инструментом, позволяющим получать информацию об устройстве, менять режим его работы и читать/записывать блоки данных на носитель. Набор команд SCSI используют многие накопители данных, подключаемые через другие аппаратные интерфейсы, в том числе через USB.
Команды SCSI охватывают широкий диапазон типов устройств и задач, все заспецифицировано, а для нас важна спецификация SCSI Block Commands (SBC) - блоковые команды SCSI, которые описывает команды, используемые жёсткими дисками, флэш-дисками и другими блоковыми устройствами прямого доступа. Текущая версия - SBC-3. Кого интересует данная спецификация, формат команд, их описание и.т.п. могут обратится к первоисточнику — можно найти и скачать по названию SCSI Block Commands - 3 (SBC-3)
Ну вот, с водной можно закончить и приступить к основной части.

SCSI команды условно можно разделить на 3 группы
- специфицированные, обязательные для всех устройств;
- специфицированные, но работающие не на всех устройствах;
- неспецифицированные, применяются разработчиками, изготовителями и, как бы сказать....наладчиками...... то есть эти команды не описаны в спецификации и известны узкому кругу лиц.
Специфицированных команд около 60. Но обычным пользователям достаточно 5 базовых команд — минимум команд, которые используются устройством и хостом для начала взаимодействия/общения, чтобы начать полноценную работу. Вот эти команды я и постараюсь описать.

1. INQUIRY (12 00 00 00 60 00) - запрашивает структуру с информацией об устройстве. Устройство должно возвращать ответ даже в случае неготовности носителя и невозможности отвечать на все остальные команды. Все блоковые устройства должны поддерживать команду INQUIRY. В скобках приведен формат команды.
Ответ на команду имеет длину как минимум 36 байт и указывает периферийный тип устройства ("PDT"), версию набора базовых команд SPC, идентификаторы производителя и изделия, номер модификации изделия, а также данные о возможностях устройства и поддерживаемых протоколах.
Забыл написать, что для дальнейшего тестирования должен быть установлен пакет sg3_utils и загружен модуль sg ...... и будем использовать утилиту sg_raw
Вставляем флешку и смотрим как она определилась
# sg_map -i
/dev/sg2 /dev/sdb JetFlash Transcend 16GB 1100
Приступаем к общению ….
# sg_raw /dev/sg2 12 00 00 00 60 00
SCSI Status: Good
или более информативный вывод
# sg_raw -vv /dev/sg2 12 00 00 00 60 00
open /dev/sg2 with flags=0x802
cdb to send: 12 00 00 00 60 00
SCSI Status: Good
No errors
Попросим дать ответ в другой форме и вывести нам всю информацию об устройстве (запросим только первые 64 байта)
# sg_raw -r 64 /dev/sg2 12 00 00 00 60 00
SCSI Status: Good
Received 64 bytes of data:
00 00 80 00 01 1f 73 6d 69 4a 65 74 46 6c 61 73 68 .....smiJetFlash
10 54 72 61 6e 73 63 65 6e 64 20 31 36 47 42 20 20 Transcend 16GB
20 31 31 30 30 00 80 02 00 00 00 00 00 00 00 00 00 1100............
30 00 00 00 00 00 00 28 00 03 01 82 06 00 15 00 00 ......(.........
формат ответа описывать не буду — кому интересно, обращайтесь к спецификации (например, 8..15 байты - обозначение производителя, 16..31 байты - обозначение изделия, 32..35 байты - версия изделия и.т.д....). .....PS...чтобы увеличить количество выводимых байт, нужно вместо 64 прописать, например, 256.....иногда и там имеется полезное)
…..............................
Аналог специальных утилит пакета sg3_utils
# sg_inq /dev/sg2 или # sginfo /dev/sg2
Аналог sdparm (но менее информативный) с опцией -i (--inquiry) команда
# sdparm -i /dev/sdb
….................................
2. READ CAPACITY (25 00 00 00 00 00) - возвращает структуру, содержащую логический адрес (LBA) последнего блока на носителе и размер блока в байтах. Стоит уточнить, что команда запрашивает логический адрес (LBA) последнего блока, а не количество блоков на носителе. Логический адрес первого блока равен нулю, таким образом, логический адрес последнего блока на единицу меньше количества блоков. PS.... команда используется, чтобы выяснить какой объём данных может хранить устройство
# sg_raw -r 8 /dev/sg2 25 00 00 00 00 00
SCSI Status: Good
00 01 e3 bf ff 00 00 02 00
( 01e3bfff=31703039 - (первые 4 байта) количество блоков , (последние 4 байта) 00000200=512 - размер блока)
Проверка
$ sudo fdisk -l /dev/sdb
Диск /dev/sdb: 15,1 GiB, 16231956480 байт, 31703040 секторов
Единицы: секторов по 1 * 512 = 512 байт
Размер сектора (логический/физический): 512 байт / 512 байт
…..................................
Аналог специальной утилиты пакета sg3_utils - # sg_readcap /dev/sg2
…...................................
3. SEND DIAGNOSTIC (1D 00 00 00 00 00) - команда предписывает устройству провести самотестирование и/или проверку логического накопителя. Для блоковых устройств (SBC) обязательна поддержка самотестирования, способ реализации которого оставляется на усмотрение разработчика.
# sg_raw /dev/sg2 1D 00 00 00 00 00
SCSI Status: Good
или
# sg_raw -vv /dev/sg2 1D 00 00 00 00 00
open /dev/sg2 with flags=0x802
cdb to send: 1d 00 00 00 00 00
SCSI Status: Good
No errors

4. REQUEST SENSE (03 00 00 00 00 00) - (запрос о состоянии) столкнувшись с проблемами при исполнении команды или получив неизвестную команду, устройство заполняет структуру, содержащую подробную информацию о состоянии и устанавливает значение поля "bCSWStatus" (CSW) равным "0x01" (ошибка исполнения). Структура с информацией о состоянии называется пояснительными данными (SENSE DATA) и передаётся в ответ на команду REQUEST SENSE (все поля формата не привожу, а только наиболее интересующие пользователей)
Запрашиваю только первые 16 байт (можно и без опции -vv, пишу для того, чтобы увидеть No errors, хотя это и не к чему.... и так все видно)
# sg_raw -vv -r 16 /dev/sg2 03 00 00 00 00 00
open /dev/sg2 with flags=0x802
cdb to send: 03 00 00 00 00 00
SCSI Status: Good
Received 16 bytes of data:
00 70 00 00 00 00 00 00 0a 00 00 00 00 00 00 00 00 p...............
No errors
….....................................
PS..... Забыл отметить, что в спецификации указано, что запрос должен быть равным 252 байтам для того, чтобы устройство могло возвратить всю значимую информацию, включая внутренние данные производителя.
........................................
Аналог специальной утилиты пакета sg3_utils (а вот с этими двумя разными выводами руки так разобраться и не дошли, наверное, потому, что утилиты этого пакета практически не использую.......нравится общаться на прямую....)
# sg_requests /dev/sg2
Decode parameter data as sense data:
Fixed format, current; Sense key: No Sense
Additional sense: No additional sense information
# sg_requests -vv /dev/sg2
open /dev/sg2 with flags=0x800
Request Sense cmd: 03 00 00 00 fc 00
Decode parameter data as sense data:
Fixed format, current; Sense key: No Sense
Additional sense: No additional sense information
Parameter data in hex
00 70 00 00 00 00 00 00 0a 00 00 00 00 00 00 00 00
10 00 00
….............................................

Формат вывода ответа
0 байт - RESPONSE CODE - для сведений о текущих ошибках устанавливается в "0x70". Для сведений об отложенных ошибках (для команд использующих кэширование) устанавливается в "0x71"
2 байт - SENSE KEY - содержит данные, классифицирующие ошибку
7 байт - ADDITIONAL SENSE LENGTH - длина дополнительных пояснительных данных, следующих за данным полем, в байтах, 244 байта максимум

Некоторые значения поля SENSE KEY
00 - NO SENSE (нет ответа)
01 - RECOVERED ERROR (вскрытая ошибка)
02 - NOT READY (не готов)
03 - MEDIUM ERROR (ошибка носителя/средняя ошибка)
04 - HARDWARE ERROR (ошибка аппаратного обеспечения)
05 - ILLEGAL REQUEST (некорректный запрос)
06 - UNIT ATTENTION (устройство требует внимания/ предупреждение)
07 - DATA PROTECT (защищенная информация)
…...... ит.п. ит.д....... и, если мне не изменяет память, есть еще уточняющие коды, посмотреть можно в спецификации...
Примечание: уточнение кода SENSE KEY в части значения 05 - в случае получения неизвестной команды устройство не должно "зависать" или аварийно завершать работу. Правильный ответ на неподдерживаемую команду выглядит так:
- возвратить значение "0x01" (ошибка выполнения) в поле "bCSWStatus" (CSW);
- установить в блоке пояснительных данных ("SENSE DATA") параметр "SENSE KEY" в "0x05" ("Недопустимый запрос" - "ILLEGAL REQUEST"), а параметр "ADDITIONAL SENSE CODE" в "0x20" ("Неверный код операции" - "INVALID COMMAND OPERATION CODE").

Имеются и другие команды, но, если честно, что то уже устал и стал путаться (за найденные ошибки особо не пинать) — думаю для начального ознакомления этого достаточно.
PS.... по ответам, напрямую посланным запросам (на низком уровне), можно судить о состоянии устройства...
Ошибки не исчезают с опытом - они просто умнеют
Спасибо, добавил в закладки :).
00 01 e3 bf ff 00 00 02 00
( 01e3bfff=31703039 - (первые 4 байта) количество блоков , (последние 4 байта) 00000200=512 - размер блока)
я не пойму где здесь в суме 8байт, я вижу здесь только 2байта ( по 8бит в каждом). Объясните что я пропускаю, спасибо.
GVG
я не пойму где здесь в суме 8байт, я вижу здесь только 2байта ( по 8бит в каждом). Объясните что я пропускаю, спасибо.
Как то это понимается само собой, автоматом, никогда на этот счет и не задумывался.....
Постараюсь ответить пополнее. Начну с вопроса - какое максимальное число можно записать с помощью одного байта?
Ответ - 1 байт составляет 8 бит (8 разрядов) и бит может принимать только 2 значения — 0 или 1. Следовательно, максимально возможное число, которое можно записать с помощью одного байта будет (в 2-ичной системе) — 11111111 , или в 10-ричной системе это будет 255.
У нас же имеется значение записанное в 16-ричном исчислении (0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F)
01 e3 bf ff 00 00 02 00
и принято считать байтом (при работе с 16-ричными числами) выражение состоящее из 2 символов, каждый символ в 16-ричном исчислении может принимать 16 значений (смотри выше...0,1,....F) — это и есть один байт ….. посчитай какое максимально возможное число можно записать таким образом....PS....сначала убрал, но решил вернуть - то же 255 , так как максимальное число в 16-ричной системе будет FF , а в 10-ой ....255
Насчет бит …... повторюсь — это только 0 или 1 …... а что унас??? а у нас
01 e3 bf ff 00 00 02 00
т.е. мы видим не только 0 и 1, но и другие символы.......ну не знаю, как еще объяснить...
Ошибки не исчезают с опытом - они просто умнеют
Спасибо, немного Гугла мне помогло, никогда не работал плотно со система счисления, вот и вышла ошибочка. В свете последних событий еще и забанят за злупый вопрос
GVG
никогда не работал плотно со система счисления, вот и вышла ошибочка
Есть хороший gnome-calculator - им очень удобно пользоваться, используя программный режим, когда нужно одновременно видеть число в нескольких системах исчисления.
Например, выбираешь 16-ричную систему и набираешь число — сразу же при наборе (on-line) показывается это число и в 2-системе и в 8-системе и в 10-системе....... (аналогично и вдругих системах исчисления).
Наверное, имеются и другие калькулятоы такого типа, но привык к этому...
Ошибки не исчезают с опытом - они просто умнеют
Зачетная статейка, спасибо.
Хорошая, годная статья. Вопрос: а как прошивается тогда контроллёр флешки? Для винды есть спец утилиты, они умеют изменять прошивку контролёра, например, китайцы этим нагло пользуются и флешки у них из 1-гиговых превращаются в 32-гиговые. Так вот, эти утилиты с помощью тех же комманд на низком уровне переводят мк в режим записи, а потом льют образ, я правильно понимаю? Или есть спец. команды для перевода мк в режим прошивки, не относящиеся к спецификациям SCSI?
root@vpupkin# cat /dev/ass > /dev/head
Прошивка — это бинарный файл, микропрограмма (программное обеспечение), закладываемая в контроллер на этапе изготовления. И все хранится в ПЗУ. В эту микропрограмму зашиты и SCSI команды (т.е. определены его действия на эти команды), а также и информация с параметрами флешки. И разумеется с помощью этих команд изменить содержимое самой микропрограммы, записанной в ПЗУ, не возможно.
Чтобы изменить/подделать информацию о параметрах флешки необходимо внести изменения в сам бинарный файл (микропрограмму) и записать/перезаписать ее в ПЗУ.
Прошивка (запись бинарного файла в ПЗУ) осуществляется в основном автоматизированным способом - специальными утилитами, и намного реже ручным способом - с использованием программаторов. Для этого применяются свои команды, имеющие свой формат — и у них совсем другое назначение (перевести контроллер в режим программирования, стереть, записать, проверить......)
Возможно сейчас и имеются способы (по типу реверсинга бинарников обычных программ) изменения микропрограммы непосредственно в ПЗУ (без полной перезаписи), но я не знаком и думаю отстал в этой части на много ..... А в принципе даже стало интересно и никогда не интересовался структурой записи в ПЗУ и ее реверсинга...
UPD.... кстати имеется еще один инструмент - утилита plscsi (раньше с ее помощью выполняли разблокировку первых флешек с отпечатком пальца, которые имели скрытый запароленный раздел), но работа с ней намного мудренее......
Ошибки не исчезают с опытом - они просто умнеют
 
Зарегистрироваться или войдите чтобы оставить сообщение.