Usb mass storage device что это

Настройки связи через USB: что такое режим MSC?

Не знаете, когда использовать режим MSC?

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

Просматривая настройки вашего портативного устройства, вы, возможно, уже видели эту опцию. Если ваш MP3-плеер/портативное устройство поддерживает его, вы обычно найдете его в меню настроек USB. Не все устройства, которые вы подключаете к USB-портам вашего компьютера, будут поддерживать MSC. Вы можете обнаружить, что вместо этого используется какой-то другой протокол, например, MTP.

Несмотря на то, что стандарт MSC более старый и менее функциональный, чем более интуитивный протокол MTP, на рынке все еще есть множество потребительских электронных устройств, которые его поддерживают.

Этот режим передачи через USB иногда называют UMS (сокращение от USB Mass Storage ), что может сбивать с толку. Но это одно и то же.

Какие типы оборудования могут поддерживать режим MSC?

Примерами типов потребительских электронных устройств, которые обычно поддерживают MSC, являются:

Другие потребительские электронные устройства, которые могут поддерживать режим MSC, включают в себя:

Когда вы подключаете USB-устройство к вашему компьютеру, который находится в режиме MSC, оно будет отображаться как простое устройство хранения, которое, скорее всего, будет отображаться только с назначенной ему буквой диска. Это отличается от режима MTP, когда аппаратное устройство контролирует соединение и отображает удобное для пользователя имя, такое как: Sansa Clip +, 8Gb iPod Touch и т. Д.

Недостатки режима MSC для цифровой музыки

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

Вместо этого более новый протокол MTP является предпочтительным режимом для синхронизации аудио, видео и других типов мультимедийных файлов. Это потому, что MTP может сделать гораздо больше, чем просто передача файлов. Например, это облегчает передачу связанной информации, такой как обложка альбома, рейтинги песен, списки воспроизведения и другие типы метаданных, которые MSC не может сделать.

Еще одним недостатком MSC является то, что он не поддерживает защиту от копирования DRM. Для воспроизведения песен с защитой от копирования DRM, которые вы загрузили из онлайновой службы подписки на музыку, вам нужно будет использовать режим MTP на портативном медиаплеере, а не на MSC.

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

Преимущества использования MSC

Есть моменты, когда вы захотите использовать устройство в режиме MSC, а не более полнофункциональный протокол MTP. Например, если вы случайно удалили некоторые из своих файлов песен, вам понадобится программа для восстановления файлов, чтобы восстановить ваши MP3. Однако устройство, находящееся в режиме MTP, будет контролировать соединение, а не операционную систему вашего компьютера. Это не будет выглядеть как обычное устройство хранения данных, поэтому ваша программа восстановления, вероятно, не будет работать.

MSC имеет преимущество в этом сценарии, потому что его файловая система будет доступна так же, как обычный съемный диск.

Другое преимущество использования режима MSC состоит в том, что он более универсально поддерживается различными операционными системами, такими как Mac и Linux. Для использования более продвинутого протокола MTP на компьютере, отличном от Windows, может потребоваться установка стороннего программного обеспечения. Использование режима MSC устраняет необходимость в этом.

Источник

Про поддержку «USB Mass Storage» в Ice Cream Sandwich

Usb mass storage device что это. 3410e5f7. Usb mass storage device что это фото. Usb mass storage device что это-3410e5f7. картинка Usb mass storage device что это. картинка 3410e5f7Из ранних обзоров девайсов (а именно Galaxy Nexus) на новой версии Андроида 4.0 (он же ICS, он же «мороженный бутерброд») выяснилось, что они не поддерживают такую замечательную фишку, как USB Mass Storage, т.е. использование телефона как флешки, без дополнительных ухищрений. Пользователи андроид-аппаратов, вплоть до версии 3.0 «Honeycomb» (а, как оказалось, изменения произошли именно в этой версии) знают, что чтобы перекинуть файлы на телефон или с него, достаточно было просто воткнуть его в компьютер без связи с тем какая операционная система или софт на нем установлены. Логично, что новости об исчезновении этой опции в новых версиях не вызвали энтузиазма среди пользователей андроида, и даже заставили многих задуматься о наличии некой проблемы или недоработки. К счастью, один их инженеров Google Дан Морилл (Dan Morrill) в комментариях к гневному посту в reddit, прояснил ситуацию, подробно объяснив о том, что, собственно произошло, и почему. По моему это очень любопытно, так что ниже перевожу перевод его комментариев.

Сам ICS поддерживает USB Mass Storage (UMS). А телефон Galaxy Nexus — нет. Это та-же история, что и с Honeycomb: HC поддерживает UMS, а планшет Xoom — нет. Если у некого аппарата есть внешняя SD-карточка, то к ней поддерживается доступ через UMS. Если в наличии только встроенная память (как у Xoom и Galaxy Nexus) то доступ к памяти устройства поддерживается только по MTP *(Media Transfer Protocol) и PTP *(Picture Transfer Protocol). Физически, невозможно поддерживать UMS на устройствах, у которых нету выделенного раздела для хранения информации (как, например, внешней SD-карточки или отдельного раздела, как в Nexus S). Причина в том, что USM и это блочный низкоуровневый протокол, который дает хост-машине прямой доступ к физическим блокам носителя, что не позволяет ему быть одновременно примонтированным в Андроиде. С новой объединенной моделью хранения информации, которую мы ввели в Honeycomb, все 32гб (ну или все 16гб, или все N. ) полностью находятся в совместном владении и приложениями и медиа-файлами. Вам больше не приходится грустно взирать на свободные 5гб на вашем Nexus S, в то время как внутренний раздел для приложений забит под завязку — теперь это один большой, счастливый раздел. К сожалению, цена, которую за это пришлось заплатить — это то, что Андроид больше не может позволить себе предоставить ПК прямой доступ и дать ему безнаказанно домогаться до носителя информации по USB. Вместо этого, мы используем MTP. На виндоуз (который у большинства пользователей), есть встроенная поддержка MTP и в эксплорере, и устройство выглядит точно так-же как обычный диск. На Линуксе и Маке, к сожалению, все не так просто, но я уверен, что в скором времени, ситуация улучшится. В целом, это должно сделать использование телефона гораздо более удобным.

На вопрос, если у Nexus S только внутренняя память, как-же программы вроде файловых менеджеров работаю без рута, Дан объяснил:

Сначала, мы выделяем директорию на внутренней памяти которая будет «SD-карточкой». Затем мы берем файловую систему FUSE, которая не делает ничего, кроме перемонтирования этой директории как /sdcard c выключенной проверкой доступов. Кроме доступов, FUSE это просто сквозная оболочка передающая запись и чтение прямо в/из директорию. Другими словами, мы используем липовую файловую систему FUSE, для перемонтирования определенной директории которая маскируется под SD-карточку. Это полностью прозрачно для приложений, которые не знают, что они не обращаются напрямую к диску.

Далее, на вопрос получается ли, что для директории sdcard нету разграничения доступов, он напоминает:

Да. Собственно по определению работающая под FAT32 папка /sdcard (или, как она называется в API — «папка внешнего носителя информации») не поддерживает разграниченного доступа, что нормально, так как это общая, открытая для всех файлопомойка, где одно приложение может топтаться по файлам другого. Она изначально задумывалась для таких вещей как музыка и фотографии, а не приватных данных, которые «живут» в личном хранилище у приложений, расположенном на внутренней памяти с разделенным доступом.
На устройствах без SD-карточки, единственная физически файловая система — это хранилища личный данных приложений. Так что мы выбираем директорию, объявляем ее файловой помойкой, монтируем ее как отдельную FUSE файловую систему, которая игнорирует права доступа, так же как они игнорируются в FAT32.

О причинах всех этих изменений Дан объяснил:

(. ) Мы не сделали это потому, что мы хотели перейти на ext3, хотя мы и выиграли это как побочный эффект. Мы сделали это так как хотели объединить общедоступное пространство для хранения информации (например для музыки и фотографий) с внутренним хранилищем для приложений. Нам надоело наблюдать, как производители телефонов включают гигабайты памяти для музыки, а у пользователей все равно заканчивается место для приложений и информации. Такой подход позволяет объединить все в один раздел, что намного лучше.

Еще один человек поинтересовался почему нельзя использовать оба подхода, ведь слот памяти занимает достаточно мало места. На что, было рассказано немного об идеологии Андроида:

Технически в железе нет никакой проблемы поставить и то и другое. Проблема в том, что этому не сделаешь удобный интерфейс.
Один из базовых принципов Андроида — это то, чтоб пользователю не нужен был файловый менеджер. Никогда. Мы хотели избежать синдрома, когда на каждый чих выскакивает диалог выбора файла, как это часто бывает в других OS. Внутренняя информация, с которой приложения умеют работать, должна быть просто доступна «по волшебству» или же храниться в облаке. Нельзя заставлять пользователя заниматься спелеологией, разыскивая файлы на SD-карточке.

Проблема в том, что поддерживая и внутреннюю память и внешнюю SD-карточку, следовать этому принципу внезапно становится намного сложнее. Для конкретного снимка, камера должна сохранять его на внутренние 16гб или на SD карточку? Приложения из Маркета — их ставить на внутреннюю память или на SD? И так далее. Да, мы можем решить это заставив пользователя самого выбирать или выставлять настройках. Но это в конечном счете и есть тот диалог выбора файла, или что-то на него похожее настолько, что нам это так-же не нравится.

Кроме этого, будут последствия и для API — если вы втыкаете SD карточку с фотографиями, должен ли их индексировать системный media content provider. Если да, то пострадают приложения, потому как они не были спроектированы учитывать, что фотографии могут внезапно появляться и исчезать.
В какой-то момент, мы наверное добавим концепцию импорта/экспорта с подключаемого носителя. Тогда камера всегда будет сохранять фотографии на внутренние 16гб, а когда вы воткнете SD-карточку (или подключите USB флешку), вы сможете начать миграцию или получите окно импорта/экспорта. Но до того момента, у большинства аппаратов будет или SD-карточка или большая внутренняя память, но не оба варианта. Я прекрасно понимаю, что многим нравится SD-карточки, и мне самому не хватает USB Mass Storage, но именно по этому так классно, что у нас есть так много аппаратов, из которых можно выбирать 🙂
А вообще, конечно, это клубок проблем. Мы тут уже обдумываем компромиссы для будущих версий.

Надеюсь, вам это тоже помогла немного прояснить ситуацию, и было интересно заглянуть на внутреннюю кухню разработчиков Андроида 🙂

Источник

USB на регистрах: bulk endpoint на примере Mass Storage

Usb mass storage device что это. 1uz. Usb mass storage device что это фото. Usb mass storage device что это-1uz. картинка Usb mass storage device что это. картинка 1uz

В прошлый раз мы познакомились с общими принципами организации USB и собрали простое устройство, иллюстрирующее работу конечной точки типа Control. Пришло время изучать следующий тип — Bulk. Конечные точки такого типа предназначены для обмена большими объемами информации, причем чувствительной к надежности, но не скорости обмена.

Классические примеры — запоминающие устройства и переходники вроде USB-COM. Но переходники требуют еще наличия конечной точки типа Interrupt, которую мы пока «не проходили», так что остановимся на эмуляции флешки. Точнее, двух флешек одновременно.

Рекомендую параллельно сравнивать написанное с исходным кодом.

Дескриптор

Здесь мы видим сначала заголовок дескриптора с полной длиной и другими неинтересными параметрами. Потом идет описание единственного интерфейса запоминающего устройства, в котором важно правильно указать поля Class, Subclass и Protocol — именно они отвечают за правильную идентификацию устройства в системе. Также важное поле bNumEndpoints, которое показывает сколько конечных точек нашему интерфейсу принадлежит. В нашем случае их две: на чтение и на запись. И тут же идут их описания, в которых внимание нужно уделить номеру (в номере конечной точки типа IN также выставлен 7-й бит, что прописано в дескрипторе как OR с 0x80) и размеру. Организация конечных точек в STM32 позволяет один номер точки использовать как на передачу, так и на прием. Существует еще альтернативный режим, в котором направление у точки одно, а буфер «комплементарной» точки используется для двойной буферизации. По идее, это может повысить скорость, но мы так делать пока не будем и воспользуемся более простым способом — приемник и передатчик, 0x01 и 0x81. А вот поле частоты опроса роли не играет вообще: пока данные для передачи есть, хост будет нашу точку дергать так часто, как только сможет, а когда данные закончатся — оставит в покое.

Еще пару слов надо сказать про размер конечных точек. Согласно стандарту [1], он должен быть равен 8, 16, 32 или 64 байта. Правда, покупные флешки как-то умудряются использовать и 512-байтные… В любом случае, делать полноценную флешку на контроллере общего назначения не самая удачная идея, так что оставим 64 байта. Да и места под буферы у нас немного.

Приведенные в этом примере константы для Class / Subclass / Protocol не являются единственно возможными. Скажем, можно попытаться эмулировать флоппик (Subclass = 0x04 вместо нашего 0x06). И оно при подключении даже показывает красивую иконку дисекты. Правда, не в винде — очевидно, она использует какие-то специфичные запросы и не верит, что бывают флоппики, их не поддерживающие. Но до специфичных запросов мы еще доберемся. Еще, если поменять Protocol, можно воспользоваться для обмена не только Bulk-точками, но и Interrupt. Но опять же, Interrupt мы не проходили, да и реальные флешки таким тоже не пользуются.

Помните, у нас в DeviceDescriptor (который почти ни за что не отвечает, поэтому не меняется и поэтому же здесь не приведен) есть поле iSerialNumber? Так вот, на этом поле растут грабли! Стандарт предписывает последние 12 символов использовать для идентификации экземпляра устройства. Соответственно, «хвост» этой строки должен представлять собой последовательность шестнадцатеричных цифр (‘0’-‘9’, ‘A’-‘F’), закодированных в 16-битной кодировке. Есть подозрение, что перед ними можно оставить осмысленный текст. А практика показала, что и количество «цифр» может быть меньше 12-и.

Скажем, в моем примере вся строка состоит из единственного символа u»1» и, кажется, работает. Но вот подставлять туда не-шестнадцатеричные символы все же не стоит: некоторые версии Windows такого пугаются и не хотят с устройством работать.

SETUP запросы

Несмотря на то, что обмен данными идет только через Bulk-точки, кое-какая информация передается и через ep0 по соответствующим запросам. Нам понадобится всего два таких запроса — USBCLASS_MSC_RESET и USBCLASS_MSC_GET_MAX_LUN, причем первый (ресет) мы пока проигнорируем. А вот второй стоит рассмотреть подробнее. Дело в том, что запоминающее устройство по логике авторов стандарта состоит из независимых логических блоков (адресуемых по logical unit number, LUN), с каждым из которых можно общаться независимо. Дальше мы увидим, что в протокол обмена всегда входит поле bLUN, именно за это отвечающее. Всего в одном устройстве их может быть до 15 штук. Правда, никто не запрещает сделать составное устройство, где по 15 «носителей» будет в каждом. В общем, важная это штука, обрабатываем обязательно. Тем более что в качестве ответа на этот запрос достаточно вернуть всего один байт с номером последнего unit’а. Важно! Не количество, а именно номер. То есть если устройство у нас всего одно с lun=0, то и вернуть надо 0, а не 1.

Принцип обмена bbb

BBB (bulk/bulk/bulk) или, что тоже самое, BOT (bulk only transport) — протокол обмена [1], при котором используется единственный тип конечной точки. Через нее передаются команды, через нее же передаются данные и через нее же успешность команд контролируется. Собственно всю логику обмена я сейчас и описал. Перейдем к подробностям:

Передача команд осуществляется всегда от хоста к устройству, то есть через конечную точку типа OUT, и представляет собой структуру следующего вида:

поле dSignature — волшебное чиселко, равное 0x43425355 (или же 4 символа »USBC»), передающееся хостом для синхронизации. Благодаря им устройство могло более-менее достоверно отличить начало команды от простого потока данных. Дальше идет dTag — порядковый номер команды чтобы если хост не дождался завершения команды и послал другую, смог отличить ответы. Это число надо будет куда-нибудь сохранить, а потом хосту вернуть.

Следующее поле, dDataLength, ограничивает количество байтов ответа. То есть наша посылка не может быть больше, чем dDataLength байт. Поле bmFlags для нас бесполезно, оно по большей части состоит из устаревших настроек. А вот bLUN это то, о чем я говорил раньше — номер «носителя», с которым хочет пообщаться хост. Если носитель у вас единственный, оно всегда будет равно нулю. Но в данном примере мы сделаем их два, так что этот самый LUN придется активно читать. bCBLength — снова бесполезное поле, которое показывает размер дополнительных данных… как будто мы его и так не знаем. И наконец, CB[] — данные, специфичные для конкретного запроса. Их мы будем рассматривать только применительно собственно к запросам. Хотя нет, не совсем так. Поле CB[0] собственно за запрос отвечает, поэтому его мы будем читать и по нему же определять как на данный запрос реагировать.

А реакция может заключаться либо в чтении данных размером dDataLength от хоста, либо запись данных того же объема. Формат этих данных зависит от принятой команды, так что пока не будем углубляться.

И наконец идет подтверждение — специальная структура следующего вида:

Поле dSignature, как и в случае запроса, является магическим чиселком, но другим: 0x53425355 (оно же строка u»USBS»). А вот поле dTag должно в точности совпадать с полученным нами при начале обмена. Смысл следующего поля, dDataResidue, я не слишком понял. Вроде бы оно содержит количество данных, которое мы хотели передать хосту, но в dDataLength не влезло, но не похоже чтобы значение там на что-то влияло. Пожалуй, самое важное поле здесь — bStatus. Если что-то пошло не так, по нему хост может увидеть, что команда завершилась ошибкой и надо что-то делать.

В результате первая посылка всегда идет от хоста, вторая либо от хоста, либо от нас, и третья — всегда от нас.

Реализация этого алгоритма может показаться неочевидной, поэтому рассмотрю ее подробнее:

Как уже было сказано, обмен начинается с того, что в конечную точку OUT приходит посылка от хоста. Проблема в том, что размер посылки составляет 31 байт, а размер конечной точки может быть и 8 байт, так что стоит предусмотреть прием по частям. К счастью, пока мы не ответим на один запрос, другого нам слать не будут (если не вылетим по таймауту, конечно), поэтому для хранения запроса и ответа заведем глобальные переменные

И до тех пор пока количество принятых байтов не сравняется с размером запроса, читать будем именно туда. Если последний байт принят «в нашу смену», то не спешим выходить, а сразу запускаем обработчик команд scsi_command() и даже пересылку ответа (мы ведь помним, что для начала IN транзакции первый пакет надо передать вручную). Но вот запросы на чтение обрабатывать сразу не выйдет, ведь в буфере приема у нас «хвост» команды, а вовсе не данные.

Поэтому scsi_command() только выставляет количество данных (bytestoread). В частности, может выставить в 0 чтобы показать что чтение не нужно. Таким образом дальнейший прием будет повторяться пока количество реально принятых байтов bytescount не достигнет желаемого. После чего все равно произойдет ручной вызов обработчика конечной точки IN, которая пошлет если не данные, то хотя бы отчет об успешности.

Собственно, устройство точки IN не слишком отличается от OUT. Основная разница, что она сначала пытается передать bytestowrite байтов и только потом структуру msc_csw с использованием ее персонального счетчика msc_csw_count.

Организация памяти и прочие извращения

Раз уж решили реализовать несколько LUN’ов, имеет смысл и внутреннюю организацию им сделать максимально различной (впрочем, максимальной она не получилась, чуть позже объясню почему). Причем желательно обойтись без возни с подключением к контроллеру периферии Допустим, LUN=0 будет отображением части флешки контроллера (а поскольку возиться с записью на нее данных опять же лень, сделаем ее read-only), а LUN=1 — оперативки.

Объем флешки у L151 целых 256 кБ, но ведь нам его еще программировать, а это долго.

Ограничимся объемом 100 кБ: на таком объеме уже можно создать файловую систему FAT и даже место для файлов останется. Оперативки у нас поменьше, всего 32 кБ, от которых мы откусим 29 кБ и заполним первый «сектор» копией из образа флешки. Пусть тоже будет считаться FAT’ом, хотя и корявым. Впрочем, если будете экспериментировать с моим кодом, рекомендую взять образ флешки поменьше, чтобы не ждать минуту пока оно прошьется.

Собственно, от его (своего) имени и кидаем туда файлы. Из хулиганских соображений я предпочел записать туда исходники прошивки. Только надо учитывать, что винда не поймет обычный конец строки ‘\n’, ей надо ‘\r\n’. То есть открываем каждый скопированный файл и меняем ему формат конца строки. Возможно, это как-то делается и из консоли, но я не искал.
Наконец снова заходим в рута дабы отмонтировать образ umount /mnt
Сразу предупреждаю: я не знаю как подобное делается в Windows. Не исключено, что по-человечески оно там вообще не делается, придется искать и скачивать какие-то сторонние программы. Ну или пользоваться для тестов каким-то из моих образов.

Обязательные команды

Все команды, с которыми мы будем иметь дело, относятся к семейству SCSI (Small Computer System Interface) — интерфейсу обмена данными с носителями информации и много чем еще. Причем не только по USB.

Обязательными для реализации являются следующие (достаточно подробно описаны тут):

Также еще несколько запросов, которые формально не обязательны, но лучше бы их реализовать

Первым делом хост запрашивает у носителей данных подробности их внутреннего устройства, посылая для этого запрос SCSI_INQUIRY. В ответ он ожидает очередную волшебную структуру, подробно рассматривать которую я не хочу. Для нашего случая достаточно скопировать готовую и немного поиграться с константами. Скажем, поменять строку вендора. Или, например, нулевой байт изменить с 0x00 на 0x05 чтобы данный LUN считался не просто носителем, а CD/DVD диском. Правда, одного этого недостаточно: необходимо дописать поддержку каких-то специфичных запросы. Поэтому уж настолько извращаться не будем… а жаль

Далее идет запрос емкости (SCSI_READ_CAPACITY), на который надо ответить двумя 32-битными числами (суммарно 8 байт, очевидно): 0-3 байты это номер последнего блока, а 4-7 это размер одного блока. Дело в том, что носители данных не обеспечивают доступ к отдельному байту — только к блоку размером обычно 512 байт. На такие же блоки устройство поделим и мы.

Обратите внимание, что передается не количество блоков, а, как и в случае LUN, номер последнего. То есть uint32_t last_lba = capacity / 512 — 1;

Внимание, грабли! Винда почему-то не полагается на запрос SCSI_READ_CAPACITY, а отправляет SCSI_MMC_READ_FORMAT_CAPACITY с немного другим форматом. И ее не волнует что этот запрос не обязателен для реализации, так что после получения ошибки «запрос не поддерживается» она еще долго отключает-подключает устройство в надежде что то образумится. Если не хотите полчаса ждать пока винда таки смирится что неподдерживаемый запрос не поддерживается, лучше этот запрос реализовать. Как несложно догадаться, линукс ведет себя адекватно и понимает с первого раза.

Еще один запрос, который имеет смысл обработать — SCSI_MODE_SENSE_6. Точнее, опять забить вместо ответа чей-то готовый кусок. 1-й байт в нем отвечает за размер посылки и будет равен 3, второй байт описывает тип носителя (что-то вендор-специфичное, оставим ноль).

Третий байт самый для нас интересный. Его 7-й бит означает защиту от записи, его мы и взведем для 0-го LUN чтобы хост даже не пытался писать в нашу флеш-память. Вот в LUN=1 (оперативка) — другое дело, там этот бит будет нулевым и пусть пишет на здоровье.

Потом хост проверяет готов ли вообще носитель с нужным номером к обмену (SCSI_TEST_UNIT_READY), причем пакет данных ему для ответа не нужен — достаточно кода ошибки: готов — не готов.

Далее по хронологии должен идти рассказ про чтение и запись, но их мы оставим на конец.

Хост может попытаться управлять подключением носителей данных при помощи команд SCSI_MMC_START_STOP_UNIT и SCSI_MMC_PREVENT_ALLOW_REMOVAL, причем если они не поддерживаются, ругается что не может отмонтировать устройство. Впрочем, заглушки, возвращающей «все хорошо» ему достаточно, так что глубже я и не копал. В реальном применении покопать все же придется, поскольку некоторой периферии нужно больше нуля секунд для корректного завершения работы. А пока она медленно отключается, надо попросить хоста чтобы подождал.

Если что-то пошло не так (на этапе подтверждения устройство вернуло ошибку), хост запрашивает по этой ошибке подробности (SCSI_REQUEST_SENSE) — массив из трех байтов, кратко поясняющих что же именно случилось. Чаще всего у нас будет случаться SBC_SENSE_KEY_ILLEGAL_REQUEST (неподдерживаемый запрос), но в принципе таким же способом сообщают о неготовности носителя данных и многом другом. Кстати, раз запрос подробностей ошибки — отдельный запрос, то и хранить результат предыдущего надо в отдельной переменной, msc_sense.

READ / WRITE

Ну и наконец самое интересное — чтение и запись данных. На самом деле это не один запрос, а целое семейство, отличающихся размером. Скажем, бывают READ(6), READ(10), READ(12), даже READ(16), которые занимают в msc_cbw.CB соответственно 6, 10, 12 и 16 байтов. Мы будем пользоваться READ(10). И WRITE(10), естественно. Формат у них одинаковый, отличается только направление передачи: от хоста к устройству или от устройства к хосту. Структура запроса такова:

Из нее нас интересуют только поля block_address и length — номер первого блока, который предстоит прочитать и количество этих блоков. Напоминаю, что размер блока мы сообщили хосту раньше, по запросу SCSI_READ_CAPACITY и что составляет он у нас 512 байт.

Следовательно, адрес первого байта, с которого начнем чтение, равен block_address * 512, а их суммарное количество length * 512.

Из соображений простоты демонстрационного кода (ну и из лени, конечно) посекторной работы с внешней памятью вы здесь не увидите. В самом деле, что к оперативке, что к флешке контроллера доступ побайтный. Но вот при взаимодействии с более сложной периферией вроде SD-карточек уже придется лавировать между прерываниями USB и этой периферии. Возможно, кстати, работу с USB будет проще осуществлять опросом, чем прерываниями. По той же причине выбор нужного буфера на чтение или запись остался в обработчике IN и OUT, а не в scsi_command.

Заключение

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

Хотелось бы, конечно, еще сэмулировать флоппик и оптический дисковод, но там используются какие-то свои, специфичные команды. В рамках данной статьи это было бы неуместно.

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

[1] Universal Serial Bus Mass Storage Class Bulk-Only Transport копия
[2] Universal Serial Bus Mass Storage Class Specification Overview копия
[3] SCSI Multimedia Commands – 2 (MMC-2) копия
[4] SCSI Primary Commands-3 (SPC-3) копия
[5] SCSI Commands Reference Manual (от Seagate) копия

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *