Хабрахабр

[Перевод] Взлом цветного картриджа HP: превращаем его в ручной принтер

image

Ещё с юности, когда у нас был старый DeskJet, меня интересовали картриджи струйных принтеров. Эти картриджи казались очень интересными и как только в них заканчивались чернила, я сразу забирал их себе. В то время я не мог сделать с ними ничего, кроме как разобрать и пачкать руки… Хоть я и знал, что там внутри есть какая-то сложная электроника, но при касании контактов батарейкой не происходило ничего интересного, а моих знаний по электронике на большее не хватало.

В то время сам я пользовался лазерным принтером, поэтому он мне был не очень интересен, зато было любопытно исследовать картриджи и попытаться выполнить их реверс-инжиниринг. Чуть позже, когда я стал студентом, мне удалось раздобыть старый струйный принтер. Я в самом деле написал статью об управлении этими картриджами, и хотя они работали достаточно хорошо, были и недостатки: мне так и не удалось выяснить точный порядок сопел, картридж был только монохромным (печатал маджентой), к тому же довольно старым, а потому разрешение оказалось довольно низким.

На этот раз мне повезло: удалось найти способ привязки всех сопел к правильным сигналам. Недавно моя девушка занялась рисованием, поэтому это стало хорошим оправданием для возврата к струйным картриджам в надежде, что и мне удастся нарисовать что-то на холсте. Кроме того, сегодня картриджи принтеров управляют бОльшим количеством сопел используя меньшее количество сигналов, что упрощает управление картриджем и увеличивает поверхность, которую можно покрыть за один проход.
Мне наконец-то удалось получить управление трёхцветным картриджем и печатать в полном цвете!

Видеозапись выступления добавлена ниже. Если вы хотите пройти со мной путь от кучи принтеров до полного контроля над картриджем принтера, то я делал доклад об этом на Hackaday Supercon 2018. В статье я расскажу о технических деталях созданной мной электроники, а также конкретные подробности управления картриджем, чтобы вы сами смогли нарисовать Nyancat при помощи ESP32 или другого микроконтроллера. Если вам интересны подробности реверс-инжиниринга, то посмотрите его.

Если вы не смотрели видео, то вот его содержание вкратце: я разобрал цветной картридж для принтера HP1112 (в Китае это картридж HP 803, но артикул зависит от региона), сделал снимки кристалла и пытался разобраться, как он работает. Когда мне не удалось выяснить многого, я начал считывать сигналы, передаваемые между принтером и картриджем, разобрался, какие сигналы нужно отправлять, чтобы картридж подчинялся моим приказам, а затем распечатал Nyancat и другие забавные штуки.

Я могу только догадываться, какая связь существует между сигналами, поэтому было довольно сложно разобраться в порядке между фронтами и в том, какие сигналы можно отложить, а какие нужно передавать вовремя. Часть исследования, посвящённая таймингам сигналов, в основном была процессом проб и ошибок. Оказалось, что мне и в самом деле удалось получить её, засунув картридж под микроскоп, но совсем не так, как я ожидал. Для получения этой информации я изучил кремний картриджа.

После возвращения с Supercon мне захотелось выполнить обратную разработку и чёрного картриджа: его печатающая головка крупнее, чем у цветного картриджа, поэтому за раз я мог бы печатать больше. До выступления на Supercon я в изучал цветные картриджи, потому что они казались мне самыми интересными. Даже несмотря на то, что ПО передавало цветные изображения, ему всё равно удавалось что-то печатать. Вероятно, добавить поддержку и этого картриджа будет не так сложно: расположение контактов кажется таким же, и я знал, что протокол, скорее всего, будет похожим, потому что уже пробовал подключать чёрный картридж к своему «железу».

Однако чёрный картридж отличался от цветного тем, что на его металлической пластине с соплами было больше надписей: под силиконовым покрытием скрывались названия сигналов для всех контактов! Вот что я сделал с цветным картриджем: засунул его под микроскоп, убрал силиконовое покрытие с контактов, подготовился к соединению нескольких снимков в одно крупное изображение.

image

(Кстати, если вы хотите посмотреть полные снимки с микроскопа во всём 40-мегапиксельном величии, то вот shield и кремний цветного картриджа! Полюбуйтесь на сложность сопел и снимка кристалла чёрного картриджа!)

По наитию я вбил отдельные названия сигналов с названием «Hewlett Packard» в Google Patents и обнаружил конкретный патент (и другой, более старый, на который ссылается первый) с чётким описанием технологий и сигналов, используемых в картриджах. Хотя может показаться, что это не так уж и много, в море немаркированных печатных плат, чипов без справочных материалов и артикулов, которые никуда не ведут, названия нескольких сигналов — это настоящая находка. Могу искренне сказать, что эту подсказку найти было очень сложно: сигналы были не только покрыты силиконовой плёнкой, но и оказались крошечными: буквы имеют размер всего 30 микрометров, а это меньше, чем толщина человеческого волоса. Это бы сэкономило мне так много времени, когда я боролся с таймингами картриджа… ну да ладно.

Сам по себе патент полезен, но его недостаточно для управления картриджем; по крайней мере, основная часть предпринятых мной трудов по реверс-инжинирингу всё равно была бы необходима, даже если бы у меня был этот патент. Патент описывает внутреннюю работу картриджа и его стоит прочитать (если вам удастся разобраться в использованном там юридическом жаргоне) просто чтобы понимать, насколько странную логику иногда применяет HP для управления всеми соплами.

Учтите, что в коде всё равно могут встречаться мои собственные названия сигналов; таблицу переводов я включу вместе с документацией. Здесь и ниже я буду использовать названия сигналов и контактов, применяемые в патенте.

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

На боку есть 16 контактов, идущих снизу, где находится печатающая головка. Как можно было увидеть на снимках с микроскопа, в печатающей головке чёрного картриджа примерно 336 сопел, а в цветном картридже — 612 сопел. На печатающей головке сопла расположены вертикальными рядами, и каждым соплом можно управлять электроникой, чтобы оно выстреливало крошечной капелькой чернил вниз, в сторону вставленной в принтер бумаги. Перемещая головку по вертикали, принтер может печатать «полосу» или любое другое изображение; эта полоса в случае чёрного картриджа имеет длину примерно 15 мм, а для цветного картриджа — 8 мм.

Согласно крошечным надписям на печатающей головке, контакты содержат следующие сигналы: Очевидно, что соплами можно управлять с помощью контактов.

Так как контактов всего 16, должна существовать какая-то схема мультиплексирования для управления всеми соплами. В патенте объясняется, как это работает: управление соплами разделено на 14 отдельных групп. Эти группы срабатывают последовательно: сначала получает свои данные и срабатывает группа 1, затем группа 2, и так далее. Каждая группа управляет максимум 24 соплами, а данные для них передаются по трём шинам передачи данных. В случае цветного картриджа данные в трёх шинах соответствуют цветам: D1 — это данные жёлтого цвета, D2 — данные мадженты, а D3 управляет соплами, печатающими цианом.

На этом рисунке из патента показаны используемые сигналы: В патенте работа подробно описывается на примере одной шины данных.

В шине данных содержится восемь байтов, 0-7. Чётные байты управляются задним фронтом DCLK, нечётные байты — задними фронтами S1-S4. Сопла, данные которых управляются первыми четырьмя байтами, можно включить подачей питания по шине питания F3; сопла, связанные с последними четырьмя битами, включаются шиной F5.

Можно сказать, что здесь бы вполне нормально сработало нечто очевидное, вроде регистра сдвига. Я понятия не имею, почему HP решила использовать для управления данными в соплах такой сложной схемой. Я понимаю, что HP использует свои патенты как оружие против компаний, занимающихся перезаправкой картриджей; возможно, кто-то уже запатентовал более простое решение, и им пришлось придумать это более сложное решение, чтобы быть уникальными.

На этом графике, сделанном мной на логическом анализаторе, несложно найти сигналы, описанные в патенте:

Кроме управления соплами, картриджу также требуется сигнал (csync) для перехода к следующей группе сопел или для сброса и возврата к первой группе. Его можно увидеть на изображении с логического анализатора: на нём показаны предпоследняя и последняя группы из 14, а сигнал csync имеет в последней группе узнаваемую форму; он выполняет «сброс» картриджа, чтобы следующей получала данные первая группа. Этот сигнал также можно использовать для обхода групп сопел в обратном порядке; это полезно, когда печатающая головка ходит и слева направо, и справа налево. Хотя во втором патенте описывается, как это работает, я решил просто закодировать переход к следующей группе и выполнять сброс сигналов, показанных на моих изображениях линией csync.

Заметьте, что всё это происходит с довольно большой скоростью; задержка между двумя передними фронтами сигнала DCLK примерно равна 0,4 мкс, а расстояние между группами примерно равно 4 мкс.

Если бит равен 0, то соответствующее ему сопло срабатывает; если равен 1, то сопло не срабатывает. Теперь мы знаем, что каждый бит в этих трёх шинах данных из 14 байт содержит команду срабатывания для одного сопла. Если вы смотрели презентацию, то знаете, как мне удалось в этом разобраться: я распечатал на работающем принтере известный мне паттерн, перехватывая сигналы с помощью логического анализатора, а затем разобрался, каким должен быть порядок сигналов, чтобы декодировать сигналы обратно исходное изображение
.
К сожалению, соответствие битов соплам кажется довольно постоянным, но не полностью логичным. Чего мы не знаем, так это соответствия между битами и соплами. Кроме того, я также выяснил, что простота маршрутизации сигналов в картридже может сделать сопоставление битов и сопел довольно запутанным. Похоже, что в основном это вызвано необходимостью физического отдаления на достаточное расстояние одновременно срабатывающих сопел (чтобы избежать перегрева или возникновения локального вакуума в ёмкости с чернилами). В своей прошивке я просто реализовал это сопоставление как набор таблиц поиска.

Теперь, когда мы знаем, как работают сигналы, мы можем управлять картриджем принтера с помощью простого микроконтроллера, верно? Ну, не сразу. В картридже принтера не используется простая логика на 5 В или 3,3 В. Шины данных управляются шинами на 16 В или 9 В. Шины питания тоже управляются 16 В и на самом деле в зависимости от количества срабатывающих сопел их можно подтянуть до тока источника питания. Нам нужно выполнить преобразование уровней.

Это старый однонаправленный шестнадцатеричный чип преобразования уровней, который может повышать напряжение до 18 В. В качестве преобразователя уровней я выбрал MC14504. Думаю, он обеспечивает задержку некоторых выходных сигналов в зависимости от картриджа и подаваемой на выводы чипа нагрузки. Хоть этот чип и работает, оглядываясь назад, могу сказать, что это был не лучший выбор: он может подавать на выход всего несколько мА и имеет довольно большую задержку распространения. К сожалению, готовые преобразователи уровней на 16 В сегодня не так доступны, поэтому я не могу заменить его чем-то получше. У меня есть по крайней мере один картридж, которому требуется для работы сигналов небольшая регулировка таймингов, и я думаю, что причина в этом. Впрочем, этого классического чипа с небольшой регулировкой оказывается вполне достаточно.

Кроме того, что эти контакты забирают большую долю тока, также они непосредственно подключены к резисторам включенных сопел: если по каким-то причинам питание будет подаваться слишком долго, то эти крошечные резисторы перегорят и сопло полностью выйдет из строя. С шинами питания всё немного сложнее. Чтобы этого не происходило из-за программного бага или плохого соединения, я добавил аппаратной логики, обеспечивающей ограничение импульса небольшой величиной, кратной 10 мкс. К тому же, этого «слишком долго» достичь довольно просто: достаточно включить сопла всего на несколько микросекунд, а если подать питание всего на миллисекунду, то они просто испарятся, полностью сломав сопло.

В первом прототипе я оставил несколько преобразователей уровней и не знал, как проявит себя ПО, поэтому решил проблему настоящим однотактным мультивибратором. В этой схеме два использованы мультивибратора в 74HC123, генерирующие импульсы, ширина которых задаётся сочетанием R/C, подключённого к контакту RCExt. Получившийся импульс генерируется только при возрастающем входном сигнале, поэтому постоянно высокий сигнал не приведёт ни к чему, кроме точно заданного, но паразитного импульса на выходе. После этого канал MC14504 используется как преобразователь уровней для поднятия напряжения до +16 В, а P-канальный МОП-транзистор обеспечивает необходимый ток.

На второй печатной плате я понял, что если изменю логику контактов питания так, чтобы они не использовали два канала схемы сдвига уровня, то достаточно будет всего двух чипов MC14504. Теперь у меня есть достаточно хороший программный контроль над шириной импульса, но мне всё равно хочется иметь защиту от постоянно высокого сигнала входного контакта. Вот схема, к которой я пришёл. Она работает так: в нормальном состоянии при низком сигнале PWRB_IN конденсатор C28 пуст, потому что любое напряжение в нём медленно стекает по R20 и R21: затвор транзистора Q4 имеет высокий уровень, а PWRB_OUT отсоединён от шины питания 16 В. Как только в PWRB_IN появляется высокий сигнал, Q6 заземляет один из концов C28; так как напряжение по нему равно 0 В, изначально это также подтягивает вниз другую его сторону, которая соединена с затвором Q4. Подтягивание затвора Q4 вниз делает его проводимым, и это позволяет току течь от +16 В к PWRB_OUT. В обычном состоянии PWRB_IN достаточно быстро снова переходит в состояние с низким уровнем, закрывая затвор Q4 и прерывая ток. Однако пока PWRB_IN имеет состояние low, C28 медленно заряжается: одна его сторона заземлена Q6, а другая подключена к 16 В через R21 и R31. Когда конденсатор достаточно зарядится, Q4 «увидит» высокий уровень на своём затворе и перекроет ток в PWRB_OUT, даже если PWRB_IN по-прежнему находится в состоянии с высоким сигналом. Этот механизм гарантирует, что PWRB_OUT будет подавать питание только в ограниченный промежуток времени.

Они нужны для «снятия напряжения» сигнала питания: без них резкое включение и отключение Q4 будет индуцировать кучу электромагнитных помех, искажающих сигналы, передаваемые в картридж. В схеме также имеется небольшой резистор, соединённый последовательно с шиной питания 16 В (R31), а также небольшой конденсатор, подключенный параллельно к выходному сигналу (C15).

Очевидно, что необходимы преобразователи уровней на +9 В и +16 В. Кроме этой логики больше особо ничего не требуется. Так как он питает резисторы сопел, источник 16 В должен чуть более сильным: я сделал так, чтобы мой мог обеспечивать непрерывно не менее 400 мА, а также добавил довольно много развязывающей ёмкости. Источник питания +9 В должен быть довольно скромным: я не замечал, чтобы эти шины в целом использовали больше нескольких мА.

Для этой цели я выбрал ESP32, в основном потому, что взял несколько штук с работы, но ещё и потому, что в нём есть довольно мощный контроллер I2S, в котором используется очень удобный параллельный режим: по сути, мы можем просто задать тактовую частоту, указать контроллеру I2S область памяти, и он будет параллельно выводить эти байты. Наконец, самая важная нагрузка по обработке изображений и генерации сигналов ложится на плечи микроконтроллера. Благодаря этому он идеально подходит для генерации необходимых сигналов управления; то, что у него есть два мощных ядра на 240 МГц, также помогает в обработке изображений.

Разумеется, несколько преобразователей и МОП-транзисторов сами по себе не могут стать работающим контроллером картриджа принтера. Поэтому я создал отдельное устройство, задуманное как платформа для экспериментов с картриджем и его возможностями. Оно имеет модуль ESP32, логику, необходимую для управления картриджем, а также несколько источников питания для работы от литий-ионной ячейки. Также оно оснащено несколькими датчиками, призванными компенсировать неидеальные движения рук человека, а также кнопками и дисплеем, обеспечивающим обратную связь о печатаемых изображениях. Давайте разберём компоненты, возможно, для кого-то это станет источником вдохновения для хакинга картриджей:

Давайте начнём с источника питания. Питание поступает от литий-ионной ячейки и преобразуется в 3,3 В, 16 В и 9 В. Напряжение 3,3 В необходимо для датчиков и ESP32; оно генерируется с помощью простого LDO-регулятора HT7833. Напряжения 9 В и 16 В генерируются двумя повышающими преобразователями, созданными на основе чипа повышающего преобразователя XR2203. Учтите, что источник питания 16 В должен трудиться намного усерднее, чем источник питания 9 В; картридж потребляет от 9 В всего несколько миллиампер. Два повышающих преобразователя созданы на одном чипе просто потому, что мне достаточно было купить для обоих один тип компонентов.

У меня осталось немного места, поэтому я добавил зарядное устройство литий-ионных аккумуляторов на основе TP4056, чтобы можно было подзаряжать аккумулятор от любого USB-источника питания. Так как всё устройство питается от литий-ионной ячейки, нам нужно как-то заряжать и её.

Интеллектуальность устройства обеспечивается модулем ESP-Wrover32. Я использовал вариант с 8 МиБ флеш-памяти и 8 МиБ ОЗУ SPI; вполне достаточно для выполнения сложной обработки изображений. Ещё у модуля есть 5-контактный разъём, позволяющий программировать и отлаживать прошивку, а также две кнопки, которые можно использовать для выбора опций и запуска отрисовки при работающей прошивке.

Выбранные опции отображаются на небольшом цветном ЖК-экране размером 160x80. Экран имеет соединение SPI и может напрямую управляться одним из периферийных SPI-разъёмов, имеющихся в ESP32.

Это интерфейс картриджа. Как сказано выше, он не особо сложен. Уровень всех сигналов преобразуется парой MC14504, один для сигналов 9 В и один для сигналов 16 В. Также на схеме видна схема сдвига уровня/защиты, управляющая двойными шинами питания.

Вот три использованных мной типа датчиков. Все они подключены с помощью одной шины I2C, то есть в ESP32 они занимают всего два GPIO. Это блок инерциальных датчиков MPU9250 (акселерометр, гироскоп и цифровой компас) для измерения движения, три лазерных датчика расстояния VL53L0X (показан только один), направленные вверх, влево и вправо. Идея заключается в том, что комбинируя эту информацию, теоретически можно определить абсолютное положение картриджа. Это полезно, например, при рисовании больших изображений свободным движением руки. Последний — это цветовой датчик TCS3472. Цветовой датчик расположен рядом с белым светодиодом; его можно использовать для «копирования» цвета с объекта или для компенсации цвета носителя, на котором мы печатаем.

Так как мне нужны были дополнительные GPIO, я подключил к шине расширитель GPIO. Он контролирует шины сброса для трёх датчиков расстояния, шину сброса для ЖК-экрана, включение повышающего преобразователя и два МОП-транзистора (не показаны), которые управляют белым светодиодом, используемым для освещения цели для цветового датчика, и подсветку ЖК-экрана. Датчикам расстояния нужна отдельная шина сброса, потому что они включатся по тому же I2C-адресу. Однако у них есть команда, изменяющая I2C-адрес после включения. Включая и перемещая их один за другим по разным I2C-адресам, я могу контролировать все три по одной I2C-шине.

Вот печатная плата, которую я спроектировал на основе схемы. Она имеет странную форму, потому что должна быть разделена на четыре отдельные платы и «окружить» картридж принтера. Они соединены электрически и физически; преимущество этого в том, что производители печатных плат не считают такую схему четырьмя отдельными платами и платить нужно только за одну.

Ещё одно преимущество в том, что я могу собирать плату как один элемент, а затем протестировать её, когда все компоненты находятся на одной плоскости. Это позволяет мне не заниматься тщательной балансировкой собранного устройства при отладке. Небольшое примечание: датчики VL53L0X используют инфракрасный лазерный луч; похоже, он достаточно силён, чтобы пробить фильтр защиты от ИК-излучения в моей «зеркалке» и проявляется в кадре как небольшие фиолетовые пятна света.

И вот каким будет конечный результат после сборки. Заметьте, что при разделении плат соединения между ними оказались разорванными. У плат есть небольшие площадки для пайки, к которым можно припаять небольшой кусок провода и загнуть его. Очевидно, что для производственного уровня нужно будет использовать технологии наподобие FPC PCB или flex-rigid PCB, но для дешёвого прототипа это вполне сойдёт.

Если вы хотите использовать этот прототип для справки или поэкспериментировать с ним, то можете скачать файлы проекта KiCad (там же лежат схема в pdf и gerber) и собрать его самостоятельно, или использовать его подсистемы.

Я дам ссылку на репозиторий, в котором его разрабатывал, но учтите, что это слепок почти всего цикла разработки, поэтому в нём содержится всё по порядку, от записей сигналов логическим анализатором до распечатанных Nyancat и Моны Лизы. Так как это прототип, ПО довольно… неоднородно. Если вы всё ещё хотите изучить его, то можете склонировать в git этот этот URL. К сожалению, поэтому код представляет собой почти недокументированный хаос с наполовину завершёнными путями и остатками старого кода.

Однако если вас больше интересует ПО, способное с лёгкостью управлять картриджем принтера с помощью ESP32 (и содержащее полезные процедуры для управления им через другой микроконтроллер), то продолжайте чтение.

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

Также можно полностью использовать описанный в предыдущем разделе прототип: достаточно просто обеспечить постоянный высокий сигнал BOOST_EN, чтобы повышающие преобразователи 9 В/16 В были всегда включены. Я не создал для него специализированного оборудования, но по сути вы можете заново использовать «железо» из предыдущего раздела: просто возьмите источник питания, ESP32
и преобразователи уровней и примените их в собственной схеме. (Таким образом я отлаживал код.)

Основной код драйвера находится в components/printcart; код, считывающий кнопку и решающий, когда включать сопло, а также код инициализации содержится в main/main.c. Сам код можно найти на Github, он структурирован стандартно для проекта ESP-IDF. В примере данные сопел считываются из встроенного rgb-изображения.

Он выделяет два буфера и передаёт из буферов 16-битные слова с частотой 3,3 МГц контактам GPIO (максимум 16 контактам). Система имеет следующую архитектуру: printcart_i2s.c содержит простой драйвер для параллельного режима периферийных разъёмов I2S контроллера ESP32. (Здесь эти контакты GPIO соединены с преобразователями уровней, управляющими картриджем.) При каждом опустошении буфера драйвер выполняет обработчик события для заполнения буфера.

Он получает данные сопел из очереди данных сопел и передаёт их в функцию в printcart_genwaveform.c, которая по шаблону преобразует эти данные сопел в сигналы. Обработчик события находится в printcart_buffer_filler.c. Шаблон зависит от типа картриджа (цветной или чёрный), и его можно изменять, загружая в браузер tools/waveform_editor.html.

Она ожидает нажатия кнопки, и при нажатии генерирует данные сопел парсингом простого файла изображения, преобразованного в сырые данные rgb и встроенного в прошитый двоичный файл, сканируя данные слева направо. С другой стороны очереди данных сопел находится процедура цикла в main.c. Благодаря этому можно нажать кнопку, проводя картриджем над бумагой, и распечатать содержимое изображения в виде полосы чернил.

Конечный результат выглядит примерно так:

Тут сильно заметно, что чёрный картридж печатает примерно в два раза больше по высоте, чем цветной (0,7 см и 1,5 см), поэтому если вам не нужен цвет и требуется хорошая видимость, то лучше выбирать чёрный картридж. Также стоит заметить, что в main.c есть define, переключающийся между двумя картриджами; код может работать с обоими. Не совсем понятно, почему на чёрном изображении есть смазанные линии: возможно, в моём сигнале есть ошибка, а может быть, картридж немного устал от тестирования. Как бы то ни было, распечатанные данные красивы и хорошо узнаваемы.
Реверс-инжиниринг этих картриджей принтера был долгим приключением, но в конце концов моя работа оказалась плодотворной; хоть и осталось несколько загадок (например: что делает контакт ID?), я считаю, что хорошо разобрался с загадками сигналов, используемых в картридже. Надеюсь, что опубликовав код и схемы этого проекта, я добавлю в инструментарий умельцев, хакеров и творцов использование принтерных картриджей. Не могу дождаться, когда увижу интересные примеры использования, которые придумает сообщество. Если вам удастся сделать что-то интересное с моей работой, то обязательно пришлите мне сообщение.

Что же касается моего намерения творить искусство… эммм… вот это можно так назвать?

Теги
Показать больше

Похожие статьи

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

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

Кнопка «Наверх»
Закрыть