Поддержка USB в KolibriOS: что внутри? Часть 5: уровень логического устройства

  • Tutorial
Обработка подключения устройства, начатая на уровне поддержки хост-контроллеров, остановилась, подготовив нулевую конечную точку устройства к работе. Уровень поддержки каналов предоставил методы работы с каналами. Самое время их применить для продолжения инициализации устройства: включается функция usb_new_device из bus/usb/protocol.inc.

Сейчас устройство мало что может: оно ещё не получило адрес на шине, ещё не сконфигурировано, может использовать только 100 мА питания от шины. В общем-то, всё, что устройство может, — это рассказать о себе в ответ на подходящие вопросы. Рассказ устройства о себе организован в виде дескрипторов. Подходящим вопросом считается команда GET_DESCRIPTOR, отправленная нулевой конечной точке; в команде должны быть указаны тип дескриптора, порядковый номер дескриптора среди всех с таким типом, длина данных для передачи. Каждая команда к управляющей конечной точке занимает 8 байт и может иметь или не иметь дополнительных данных, в некоторых командах некоторые поля не используются. Структура команд по байтам и используемые поля расписаны в главе 9 спецификации USB, здесь я буду только описывать входные и выходные данные для команд.

Уровень логического устройства имеет две задачи: во-первых, сконфигурировать устройство; во-вторых, расспросить его, загрузить соответствующий драйвер — или даже драйверы — и сообщить драйверу о новом устройстве.


Первые шаги


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

Впрочем, есть одна проблема: эмуляция EHCI в VirtualBox не совсем корректна и требует указания 64 байт для работы с HighSpeed-устройствами. Поскольку других требований нет, канал к нулевой конечной точке начинает существование с максимальным размером пакета в 64 байт.

Пока устройство не получило адрес на шине, оно отзывается на нулевой адрес и мешает сбросу последующих устройств — если прямо сейчас закончится сброс другого устройства, то оба устройства будут реагировать на пакеты с нулевым адресом, что приведёт к беспорядку на шине. Поэтому первое, что делает usb_new_device после открытия канала, — выбирает первый незанятый адрес и посылает команду SET_ADDRESS. На входе у команды SET_ADDRESS — адрес, выходных данных нет.

После завершения команды SET_ADDRESS управление получает процедура usb_set_address_callback. Если устройство не ответило на команду или ответило ошибкой, то единственный вариант действий — отключить устройство от шины на уровне хаба. Если команда выполнена успешно, то usb_set_address_callback сообщает уровню поддержки хост-контроллеров, что адрес изменился; по причинам, о которых я упоминала в одной из предыдущих статей серии, изменение может занять некоторое время. В обоих случаях нулевой адрес на шине перестаёт быть занятым, поэтому можно приступать к сбросу последующих устройств, если они есть; за это отвечает вызов usb_test_pending_port.

Когда хост-контроллер подтверждает изменение адреса в структуре, описывающей устройство, код поддержки вызывает usb_after_set_address. Теперь представления хост-контроллера и устройства об адресе на шине вновь согласованы, можно продолжать настройку. Следующей командой usb_after_set_address посылает вопрос GET_DESCRIPTOR, запрашивая первые 8 байт дескриптора устройства — тип дескриптора 1, номер дескриптора 0. Последний из этих 8 байт задаёт максимальный размер пакета для нулевой конечной точки — последнее из того, чего не хватало для полноценного общения. Обработчик ответа usb_get_descr8_callback вытаскивает максимальный размер пакета, сообщает о нём хост-контроллеру, дожидается подтверждения. После подтверждения происходит вызов usb_after_set_endpoint_size, где вопрос GET_DESCRIPTOR для дескриптора устройства повторяется, теперь запрашивая данные полностью.

Дескриптор устройства



На рисунке показаны шестнадцатеричные дампы дескрипторов двух различных устройств: сверху — виртуального хаба RMH, снизу — некоторой мышки. Дескриптор устройства состоит из следующих данных в little-endian:
  • первый байт любого дескриптора — его размер, второй — его тип, дескриптор устройства имеет тип 1;
  • версия спецификации USB, с которой совместимо устройство, в BCD, 110h — версия 1.1, 200h — версия 2.0;
  • класс, подкласс и протокол устройства в целом; часто здесь бывают нули, тогда данные задаются на уровне отдельных интерфейсов — про них будет дальше;
  • максимальный размер пакета для нулевой конечной точки;
  • Vendor ID и Product ID устройства — ассоциация USB Implementers Forum выделяет каждому производителю USB-устройств двухбайтный Vendor ID, иногда даже не один, производитель назначает каждому своему продукту отдельный двухбайтный Product ID; например, Vendor ID 8087h закреплён за Intel;
  • версия устройства — произвольное число, которое сюда записал производитель:
  • три указателя на строки, каждый из которых может отсутствовать. Первые два — тексты для пользователя, строки-описания производителя и продукта соответственно, последний — серийный номер. Сами строки хранятся в отдельных дескрипторах типа 3;
  • число конфигураций.
Конфигурации — взаимоисключающие режимы работы устройства, между которыми нет ничего общего. В теории USB-устройство может иметь несколько разных конфигураций, между которыми выбирать должен софт. Спецификация USB в качестве несколько надуманного примера приводит модем, который может предоставлять либо один канал на 128 Кбит/с, либо два независимых канала на 64 Кбит/с каждый. На практике подавляющее большинство устройств имеет ровно одну конфигурацию и использует другие методы выбора режима работы. Впрочем, эту одну конфигурацию всё равно нужно явным образом включить, до этого устройство останется нефункциональным и способным только отдавать дескрипторы.

KolibriOS всегда выбирает первую конфигурацию устройства. Функция usb_get_descr_callback, вызываемая после чтения дескриптора устройства, отправляет команду GET_DESCRIPTOR для первого дескриптора конфигурации — тип 2, номер 0.

Вместе с дескриптором конфигурации устройство возвращает много других дескрипторов, задающих детали конфигурации. Общий объём данных, ассоциированных с дескриптором конфигурации, заранее неизвестен, но содержится в самом дескрипторе конфигурации. Поэтому запрос протекает в два этапа — на первом этапе функция usb_get_descr_callback запрашивает 8 байт, на втором этапе функция usb_know_length_callback вытаскивает из прочитанных байт общий размер и запрашивает уже его.

Дескриптор конфигурации



Одна из самых простых конфигураций — у виртуального хаба RMH, она показана на рисунке. Вместе с дескриптором конфигурации устройство возвращает дескрипторы всех интерфейсов этой конфигурации, для каждого интерфейса — дескрипторы всех его конечных точек. Среди ассоциированных данных бывают и дескрипторы других типов — например, HID-устройства вроде мышек и клавиатур возвращают HID-дескриптор между дескриптором интерфейса и дескриптором конечной точки; их разбор — дело драйвера.

Дескриптор конфигурации состоит из следующих данных:
  • размер и тип, как у всех дескрипторов; дескриптор конфигурации имеет тип 2;
  • общий размер всех ассоциированных данных, в примере с RMH это 9+9+7=19h;
  • число интерфейсов;
  • байт-параметр команды SET_CONFIGURATION, соответствующий описываемой конфигурации;
  • индекс строки-описания конфигурации для пользователя, обычно отсутствует — задан как 0;
  • байт атрибутов — старший бит и 5 младших бита зарезервированы, 5-й бит означает поддержку пробуждения из усыплённого состояния в ответ на какое-то внешнее действие, 6-й бит — что устройство имеет свой источник питания, независимый от шины USB;
  • максимальное используемое питание от шины в этой конфигурации, 1 единица = 2 мА, значение 50 соответствует 100 мА.

Дескриптор интерфейса:
  • размер и тип, как у всех дескрипторов; дескриптор конфигурации имеет тип 4;
  • номер интерфейса и идентификатор режима работы интерфейса. У некоторых устройств один интерфейс может работать в нескольких режимах. Пример — веб-камеры: в зависимости от разрешения картинки и кодека скорость потока данных может существенно различаться, различные режимы резервируют различную пропускную способность конечной точки, передающей данные. В таких случаях для одного и того же интерфейса есть несколько дескрипторов, в которых поле номера одно и то же, но различаются идентификаторы режима. По умолчанию после выбора конфигурации интерфейсы работают в нулевом режиме, драйвер может послать команду SET_INTERFACE для переключения режима одного интерфейса;
  • число конечных точек;
  • класс, подкласс и протокол интерфейса. Классы, кроме 0FFh, определяются ассоциацией USB Implementers Forum, их описания собраны на этой странице. Например, к классу 9 относятся хабы. Класс 0FFh используется для устройств, не попавших ни в какой другой класс;
  • индекс строки-описания интерфейса для пользователя, обычно отсутствует — задан как 0.

Дескриптор конечной точки задаёт параметры, необходимые для открытия канала:
  • размер и тип, как у всех дескрипторов; дескриптор конечной точки имеет тип 5;
  • направление — старший бит — и номер — 4 младших бита — конечной точки; например, 81h означает точку номер 1, передающую данные от устройства к хосту;
  • тип конечной точки: 0 = управляющая, 1 = изохронная, 2 = массивов данных, 3 = прерывания; для изохронных точек в этом же байте упакованы уточняющие параметры;
  • 11 бит максимального размера пакета для этой конечной точки плюс ещё 2 бита для HighSpeed-точек, задающие максимальное число транзакций за один микрофрейм;
  • желательный интервал опроса для изохронных точек и точек типа прерывания. Для LowSpeed/FullSpeed-точек типа прерывания интервал задаётся в миллисекундах, для HighSpeed-точек типа прерывания интервал равен 2значение-1 микрофреймов. В примере с RMH получается 211/8 миллисекунд = 0.256 секунд. Для изохронных точек интервал равен 2значение-1 в единицах измерения, соответствующих скорости: миллисекундах для FullSpeed, микрофреймах для HighSpeed.


Функция usb_set_config_callback, получив полные данные, ассоциированные с дескриптором конфигурации, подаёт команду SET_CONFIGURATION с параметром, взятым из дескриптора; выходных данных у этой команды нет. После успешного завершения команды устройство становится полностью функциональным. Последняя из функций уровня логического устройства, usb_got_config_callback, разбирает полученные данные конфигурации: убеждается в том, что устройство не пытается обмануть, подменив общий размер данных между командами GET_DESCRIPTOR; проходит по списку дескрипторов, игнорируя все, кроме дескрипторов интерфейсов; для дескрипторов с нулевым режимом определяет драйвер по классу устройства, загружает драйвер и вызывает его функцию AddDevice, передавая указатель на данные конфигурации и указатель на нужный дескриптор интерфейса внутри них. За дальнейшую работу с устройством отвечает загруженный драйвер. Я расскажу о существующих драйверах KolibriOS в последующих статьях.

Все статьи серии


Часть 1: общая схема
Часть 2: основы работы с хост-контроллерами
Часть 3: код поддержки хост-контроллеров
Часть 4: уровень поддержки каналов
Часть 5: уровень логического устройства
Часть 6: драйвер хабов
KolibriOS Project Team
72.16
Быстрая операционная система для бизнеса и хобби
Share post
AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 31

    –6
    честно говоря поражаюсь увлеченности людей, которые взялись писать свою ОС, да еще на ассемблере.
    Честно говоря, мне это напоминает гонку за лидером.
    Что бы ты не сделал, все равно остаешься позади и немного опоздал.
    Например, пишешь драйвер USB. Пока разобрался с USB2 — опять начинай сначала, т.к. появился USB3.
    Тот же FASM — как иснтрумент. Ограничивает ОС в интеловских процессорах.
    Далеко не факт, что они еще долго будут в лидерах.
    Может стоит подумать как транслировать ОС в ARM системы?
    Например, можно попытаться транслировать на уровне ассемблерных текстов вроде mov eax,[ebx] => ldr r0,[r1] Тогда, наверное, многое из кода можно будет сохранить для портированных версий системы…
      +4
      Назовите аналог VBE для «ARM систем».
        0
        а зачем?
        отсутствие VBE на «ARM системах» никак не говорит о том, что это «отсталые системы».
        Если посмотреть применительно к Linux, то в исходниках ядра есть папка arch а в ней есть другие папки типа arm или openrisc или x86.
        Дальше, в папке arm есть под-папки для специфичных архитектур типа mach-spear6xx или mach-s5pc100.
        Таким образом, единое ядро может быть сконфигурировано под разные процессоры и архитектуры.
        Да, это труднее в поддержке, но потенциал у многоплатформенного решения шире.
          +3
          а зачем?
          Чтобы «транслировать ОС в ARM системы» — KolibriOS использует VBE. Чтобы можно было обойтись без отдельного драйвера для каждой видеокарты.

          отсутствие VBE на «ARM системах» никак не говорит о том, что это «отсталые системы».
          Никто не говорил об отсталости. Проблема в том, что нет единого понятия «ARM системы», есть огромный зоопарк. В отличие от PC, которые неплохо стандартизированы.

          Если посмотреть применительно к Linux, то в исходниках ядра есть папка arch а в ней есть другие папки типа arm или openrisc или x86.
          Дальше, в папке arm есть под-папки для специфичных архитектур типа mach-spear6xx или mach-s5pc100.
          Таким образом, единое ядро может быть сконфигурировано под разные процессоры и архитектуры.
          Да, это труднее в поддержке, но потенциал у многоплатформенного решения шире.

          Нет, нельзя просто взять ядро и сконфигурировать под новую платформу. Все архитектурно-зависимые части должен кто-то написать, кто-то протестировать, они не возьмутся из ниоткуда. У Linux есть большое количество разработчиков, Linux может себе это позволить. Мы — нет.

          Посчитайте, что ли, число подпапок в arch/arm и сравните с той же arch/x86. Зоопарк.
            +1
            Поддерживаю. Сегодня собирал ядро Linux для рабочего контроллера; мало того, что в testing-ветке debian доступно 56 (56!) архитектур ARM, на каждую архитектуру неплохо бы иметь свою версию gcc (ну ладно, ладно, вариантов поменьше — но всё равно много), не говоря уже про огромный зоопарк периферийных устройств, которые тоже неплохо было бы поддерживать. В итоге пришлось пересобирать ядро 7 раз (используя .config-файл, поставляемый производителем, между прочим, и подпиливая через menuconfig по необходимости), и всё равно не всё гладко — банально светодиод PWR на плате не светится, например.
            И всё это на i3 собирается овер 30 минут.
            • UFO just landed and posted this here
                0
                Вообще собиралось только на одном ядре, а «куча ненужного» из периферии таки будет использоваться с большой вероятностью.
                • UFO just landed and posted this here
                    0
                    Компилировал make без дополнительных опций; make -j3 неплохо ускорил сборку ядра. Не могу назвать использование опций по умолчанию «искусственными ограничениями». Или это все же теперь называется так? Ладно, не будем о моей некомпетентности :)
                    Вообще, прогресс радует (хотя я всё еще не могу позволить себе хотя бы i3 в качестве домашней машины; да-да, я нищеброд).
                    • UFO just landed and posted this here
                        0
                        Спасибо за наставление.
                        • UFO just landed and posted this here
                            0
                            Ну так и я серьезно :) Нищебродство — это же скорее не показатель достатка, а поведенческая модель, определяемая, например, не очень уж легкой в прошлом студенческой жизнью, разве нет?
                            • UFO just landed and posted this here
          –1
          Еще я не очень понимаю, почему был выбран ассемблер как язык программирования для ОС.
          Уважать этот выбор я могу, а понять — нет.
          Выиграть в быстродействии у современных компиляторов с С/C++ довольно трудно.
          Тем не менее, выбор сделан, кода и алгоритмов в колибри ос написано на ассемблере уже очень много.
          Как сохранить и преумножить это богатство?
          Я могу представить себе некий транслятор с ассемблера intel в ассемблер для ARM.
          Я когда-то писал нечто похожее с интел в 3rd-party CPU для FPGA.
          Мне тогда потребовалось срочно реализовать алгоритм SHA для специфичного процессора для которого существовал только компилятор ассемблера. Посмотрев на описание SHA я понял, что быстро и правильно я это на ассемблере не напишу. Поэтому был придуман ход конем. Откомпилировали сишный SHA алгоритм в листинг ассемблера x86. Потом написали программу конвертации ассемблерного текста в другой ассемблерный текст для другого процессора. И это получилось и работало.
          Я думаю похожий метод мог бы сработать и для колибри. В конце концов, почему бы не помечтать, что ваша ОС может быть установлена на какой нибудь iPhone.
            +4
            Еще я не очень понимаю, почему был выбран ассемблер как язык программирования для ОС.
            Уважать этот выбор я могу, а понять — нет.
            Выиграть в быстродействии у современных компиляторов с С/C++ довольно трудно.
            В быстродействии — трудно. В размере кода — тривиально.

            Я могу представить себе некий транслятор с ассемблера intel в ассемблер для ARM.
            Я когда-то писал нечто похожее с интел в 3rd-party CPU для FPGA.
            Мне тогда потребовалось срочно реализовать алгоритм SHA для специфичного процессора для которого существовал только компилятор ассемблера
            Теперь понятно, вы просто представляете себе неправильный образ. Для кода, который принимает на вход блок данных и даёт на выход преобразованный блок данных — да, в принципе это возможно. Но операционная система — это не код, который как-то преобразует заданные данные.

            Операционная система управляет ресурсами компьютера. Ресурсы PC в значительной степени одинаковы на разных машинах — по крайней мере, достаточно, чтобы одна и та же дискета или флешка могла загружаться и выводить картинку на всех PC. Зоопарк ARM — другой, там даже загрузиться-то переносимо нельзя, не говоря уже о выводе картинки.
              0
              Я ни в коей мере не умаляю Ваших заслуг.
              Наоборот весьма восхищен Вашим трудолюбием и упорством.
              На мой взгляд проблема состоит в том, что
              1) компьютеры как PC в последнее время сильно сдают позиции. Да, они остаются на рабочих местах инженеров и дизайнеров. Их ПО — это SolidWorks, AutoCAD, PhotoSHop, Corel и так далее. Это специализированное ПО требующее ресурсов и много места для большого монитора. Тем не менее, продажи ПК падают. Еще как-то продаются ноутбуки — да, считаем их PC совместимыми, но как долго это будет продолжаться не известно.
              2) Вы говорите о том, как тривиально выиграть в размере кода, когда пишешь на ассемблере. Но, сколько стоит этот выигрыш? Стоимость носителей, шлеш и ddr памяти будет снижаться. А стоимость ассемблерной разработки — врядли. Я знаю, по своему опыту, что такое писать программу на ассемблере. Я несколько лет сопровождал одну программу для специфичного процессора в FPGA. Там был реализован и TCP стек и графическая библиотека и USB и крипто и всякое-якое. Смена процессора на target device выбросилв всю многолетнюю работу на свалку истории. Жалко.
              Не желаю Вам этого пережить.

                +2
                Вам пытаются объяснить 2 вещи:
                1) Портирование KolibriOS на ARM будет означать практически полное переписывание с нуля. У нас нет для этого ни времени, ни ресурсов (разработчиков, тестеров), ни желания. К тому времени, как это будет сделано, вместо ARM появится что-то ещё, и Вы опять будете недовольны.
                2) Даже если бросить всё и переписать KolibriOS на ARM, она будет работать только на отдельно взятом устройстве (группе устройств). Сейчас на PC она работает (должна работать) на всех компьютерах, использующих процессор x86 Pentium-класса (или совместимые с ним), и выше.

                Кроме того, архитектура x86 вовсе не собирается умирать, а наоборот, в последнее время появляются компьютеры на x86 размером и стоимостью как Raspberry Pi, что делает портирование не только невозможным, но также и бесполезным.
                  +1
                  господи-боже-мой…
                  где Вы в моих комментариях увидели, что я чем-то недоволен?
                  Я желаю Вашему проекту всяческих успехов!
                  Всего лишь высказал свои мысли вслух :-)

                    +1
                    Под словом "Вы" я, скорее, имел в виду не лично Вас, а всех предлагающих портировать Колибри на ARM, так как "компьютеры как PC в последнее время сильно сдают позиции". Не хотел Вас обидеть.
                +1
                Добавил в избранное. Я буду показывать это своим детям. И вообще всем, кто спросит, почему нельзя Колибри перенести на ARM.
                  0
                  В любой ОС всегда есть код, который может быть общим для разных платформ.
                  Например, в том же Linux папки kernel, lib, fs, net и другие содержат, в основном, общий для разных платформ код.
                  Например, как я думаю, VBE нужно, чтобы включить нужный видеорежим. Дальше получив физический адрес framebuffer можно сделать что-то типа mmap в дисплейный драйвер. Собственно дисплейный драйвер далее может быть общим для разных платформ, т.к. пишет-читает из области памяти фреймбуффера и это делается одинаково в интел системах и в арм системах. Таким образом, вероятно функции типа «найти видеоадаптер», «включить видеорежим» и подобные получаются специфическими для платформы. А функции дисплейного драйвера типа нарисовать линию, вывести текст, закрасить область и прочие — получаются едиными для всех платформ.
                  Платформо-зависимого кода в ядре линукс действительно много — это то, что Вы называете зоопарк. Но я не говорил, что непременно нужно и в колибри портировать сразу в 100 вариантов.
                  Имхо — нужна всего навсего плюс еще одна платформа (любая), например, чтобы показать возможным инвесторам привлекательность системы и потенциал развития в разных направлениях. Или другой вариант — Вы предлагаете метод портирования (что-то вроде www.linux-arm.org/pub/LinuxKernel/WebHome/aleph-porting.pdf) — и разработчики, кому нужно сами подтягиваются и дописывают платформо-зависимый код.
                  Прошу не рассматривать мои комментарии как занудство и нравоучительство.
                  Это всего лишь мысли вслух.
                    +2
                    No hard feelings, bro! Просто улыбнуло.
                    Скрытый текст
                    image

                      0
                      да, это смешная картинка.
                      Но, скажите, кто по вашему написал поддержку, например, OpenRISC процессора в Linux?
                      Неужели сам Линус Торвальдс? Конечно нет…
                      OpenRISC — это такой процессор для FPGA, его разработчики недавно пытались насобирать денег на первый чип — но не знаю получилось у них или нет. OpenRISC — это такое мизерое явление в IT индустрии, но зато у них есть свой порт Linux. Именно свой — сами написали.
                      Линукс хорош тем, что хотя бы позволяет надеяться на результат…
                      Конечно, до счастливого конца дойдут не все, многие уйдут в небытие. Например, как ушли ранние процессоры ARM, те что без поддержки MMU.- сейчас их поддержки в kernel3 уже нет.
                      Однако, Linux долго будет на плаву by default, потому, что позволяет внешним силам влиять на себя.
                        +3
                        Я не спорю, что Linux — в общем и целом очень хорошая ОС, и пользуюсь ей на большом количестве устройств с процессорами разных архитектур: x86, x86-64, PowerPC и куче ARM. Но это не отменяет того факта, что Linux — типичный представитель явлений: bloatware, «давайте добавим ещё вот эту фичу» и «каждой бочке затычка». Long live Linux! Админь.~
                        Напомню, есть несколько операционных систем (тсс! среди не-POSIX таких, кажется, большинство), которые не ставят своей целью работать на каждом холодильнике и каждой микроволновке — о нет; их цель — пользователи строго определенного железа.

                        Пардон, что-то меня понесло; речь же о другом: вы говорите, что найдутся желающие что-то куда-то переносить, но увы, за последние несколько лет я видел лишь несколько желающих «поруководить», и огромное количество «эх, если бы у вас была %killer_feature%, я бы %do_something%». Хотя, грех жаловаться — «новобранцы» имеются.
                          0
                          я извиняюсь спросить — колибри ОС — это коммерческая система или нет?
                          В смысле «новобранцы» получают зарплату или нет?
                            +1
                            Колибри — free-as-in-freedom and free-as-in-beer. Какая зарплата, вы о чем? :)
                            Когда KSoC проходил — тогда да, «пионеры» получили честно заработанные, а в подавляющем большинстве случаев награда за помощь системе — это опыт, респект и уважуха.
                              0
                              Однако, корпоративный блог на хабре стоит небольших, но денег: 15тыс./мес.
                              Или «новобранцы» еще и скидываются на поддержание имиджа проекта?
                              Честно, всегда хотелось иметь проект для души, но как? кушать-то хочется…

                                +1
                                За корпоративный блог нужно сказать «Спасибо» добрым людям. :) Как и за пожертвования на KSoC, и всё остальное :)
                                Да, соглашусь — времени на хобби из-за работы порой остается очень мало.
                                  0
                                  Блог на Хабре для таких, как мы, недавно стал бесплатен: habrahabr.ru/company/tm/blog/197634/
                                  Смотрим сюда — пакет «Стартап», цена 0 руб.: habrahabr.ru/info/advertising/corporate/
                                  Прямой линк: habrahabr.ru/info/hello_startup/

                                  За хостинг проекта платит XVilka. На KSoC деньги пожертвовали люди (участники проекта, в том числе). Я лично пожертвовал на проект в общей сложности где-то ± $3,000. У меня была такая возможность, и мне не жалко.

                                  А вот времени на проект из-за работы действительно остаётся очень мало.
                +3
                Бессмысленно, ARM-процы еще меньше стандартизированы, и то, что работает на одном проце, может не работать на другом. Исправте меня, если я ошибаюсь.

              Only users with full accounts can post comments. Log in, please.