Эта первая (вводная) статья серии о том, как я собираюсь доработать медиасистему автомобиля. Сам проект в процессе, времени, как и у всех — нет, поэтому, дорогие читатели, запаситесь терпением, ибо часто клепать статьи не обещаю.
А началось все с того, что у меня появился Prius.
И первое, что бросилось в глаза — проблемы с обновлением навигации. Следующее — весьма скудные, но местами необходимые возможности устройства с названием «Многофункциональный дисплей» (в простонародье — голова). И это на фоне огромного количества китайских радио с Android на борту, и множеством приятностей. Но их установка на штатное место подразумевает лишение таких «плюшек», как диаграмма распределения энергии и управление климатом.
Родилась идея как-то соединить Android магнитолу с автомобилем более плотно, чем предлагают братья-китайцы. Об этом и статья.
Исходная ситуация
Итак. На борту имеется около 7-дюймовый дисплей с резистивным тач-скрином, соединенный с прочей электроникой линиями TX+ и TX-. И таких пар от головы идет аж 3. В схеме это чудо поименовано AVC-LAN, и выглядит следующим образом:
Часть 1: Осматриваемся внутри
Как видно, голова стоит в разрыве сети, между маршрутизатором и дальнейшей цепочкой из магнитолы, усилителя (он отдельный у меня), и по отдельному каналу следует связь с блоком навигации. Где-то еще болтается блок автопарковки, никак не упомянутый в имеющихся у меня схемах. Ну, что ж… я решил отложить близость с оным до лучших времен. Тем более, что автопарковка — скорее игровая ф-ция, нежели реально нужная.
Убрав все лишнее, получим примерно следующую блок-схему устройств:
Размышления
Была мысль просто заменить блок навигации на что-нибудь андроидное, однако она угасла, когда я глубже разобрался, как они общаются с головой. Помимо AVC-LAN эти модули соединены так же линией GVIF (Gigabit Video InterFace), причем этот самый фэйс у производителей конвертеров может случайно треснуть, если еще и я куплю преобразователь видеосигнала в GVIF за более, чем 100 долл. «Жить без лица — быть может трудно, но..» — прозвучало в голове на мотив известной песни, и решение мне не понравилось.
Встречались в сети решения с установкой китайской магнитолы вместо радиоресивера. Это меня не устроило тем, что два дисплея — необоснованная избыточность. Имхо.
Решение
Родилось следующее решение: заменить целиком голову, и доработать андроид-магнитолу, подружив ее с Prius-ом, для чего:
- Разработать аппаратный конвертер USB <-> AVC-LAN
- Разработать firmware к нему, чтобы он подключался, как USB-HID.
- Сделать его composite, чтобы одна из функций детектировалась, как обычная аппаратная клавиатура (с целью использовать в качестве нативного управления с кнопок на панели)
- Разработать Android-приложение с функционалом, аналогичным (или превосходящим) родной, приусовский
- Согласовать работу задней камеры
- Решить задачи по механической части (установка на штатное место)
В процессе предстит разработать еще одно приложение для андроид — обыкновенный снифер, чтобы удобнее было реверсить пакеты по AVC-LAN. Заодно и потренироваться.
Выглядеть это все должно следующим образом:
В качестве аппаратной основы было решено использовать обучающую плату на SM32F103:
заказанную с AliExpress за $2.05.
STM32F103C8T6 ARM STM32 Minimum System Development Board Module
Чем она мне нравится:
- Аппаратный модуль USB(Device) на борту у процессора
- Адекватный USB-стек от производителя (в отличие от Freescale-овского, не к ночи будь помянут).
- Свободные порты GPIO, которые можно использовать для подключения штатных кнопок по бокам монитора. Возможно, это позволит скрыть под панелью аппаратные кнопки магнитолы. Я пока не знаю, какой она будет
- И на нее можно навесить конвертер AVC-LAN в логические уровни
Дальнейшее буду описывать в порядке реализации, который обусловлен, прежде всего, моими личными знаниями. Т.е. места, в которых их не было, я старался реализовывать в самом начале, напоследок оставляя то, что уж точно должно получиться.
В любом случае, статей планируется несколько, в разных хабах. Проект получается уж сильно FullStack — от аппаратного подключения до андроид-приложения.
Часть 2: USB, HID, дескрипторы, и все, чтобы получить пилотный прототип
Первым этапом я хотел получить связку устройства и телефона, причем чтобы устройство могло передать пакет на телефон, а тот — отобразить его в приложении.
Как говорил Гагарин: Поехали!
USB HID Composite device на STM32
За что я решил взяться — это адаптировать пример от ST моим задачам, и получить USB устройство, которое опознается хостом, как составное из клавиатуры и «чего-то еще» — RAW HID Device. Первое, как я уже говорил, предназначено для нативного управления андроидом, второе — для прямого обмена AVC-LAN пакетами с программой на устройстве.
Взяв за основу CubeMX от STM, и прочитав много статей о том, как можно реализовать кастомный HID, я обнаружил в сети одну неприятную вещь: практически нет или весьма скудно рассмотрен вопрос создания составных устройств.
В том виде, в котором они есть, выкладывать бессмысленно — бардака в интернете и без меня хватает.
USB, Composite, HID
Буквально несколько слов на эту тему. Предполагается, что Вы более или менее знакомы со стандартом USB. Если нет — лучше сначала ознакомится и поэкспериментировать с примерами из CubeMX.
Итак, имеем:
Стек USB от STM и пример реализации мыши. Там у нас настроены какие-то дескрипторы и функциональная конечная точка. Это помимо пары 0x00 и 0x80 для управления устройством целиком.
Для реализации моего проекта требуется, чтобы конечная точка клавиатуры была двунаправленной (не знаю, зачем — пригодится) и еще пара конечных точек, которые будут использованы для обмена данными со второй — RAW — функцией. Добавляем их.
Делаем точку двунаправленной, добавляя в дескриптор точку OUT:
(2c5cf968121f0d8fa43a6755c09e15ef3a317791):
0x07, /*bLength: Endpoint Descriptor size*/
USB_DESC_TYPE_ENDPOINT, /*bDescriptorType:*/
HID_EPOUT_ADDR, /*bEndpointAddress: Endpoint Address (IN)*/
0x03, /*bmAttributes: Interrupt endpoint*/
HID_EPOUT_SIZE, /*wMaxPacketSize: 4 Byte max */
0x00,
HID_FS_BINTERVAL,
И добавляем еще пару точек:
/* 59 */
0x07, /*bLength: Endpoint Descriptor size*/
USB_DESC_TYPE_ENDPOINT, /*bDescriptorType:*/
HID_EPIN_ADDR2, /*bEndpointAddress: Endpoint Address (IN)*/
0x03, /*bmAttributes: Interrupt endpoint*/
HID_EPIN_SIZE, /*wMaxPacketSize: 4 Byte max */
0x00,
HID_FS_BINTERVAL, /*bInterval: Polling Interval (10 ms)*/
/* 66 */
0x07, /*bLength: Endpoint Descriptor size*/
USB_DESC_TYPE_ENDPOINT, /*bDescriptorType:*/
HID_EPOUT_ADDR2, /*bEndpointAddress: Endpoint Address (IN)*/
0x03, /*bmAttributes: Interrupt endpoint*/
HID_EPOUT_SIZE, /*wMaxPacketSize: 4 Byte max */
0x00,
HID_FS_BINTERVAL, /*bInterval: Polling Interval (10 ms)*/
Это был дескриптор конфигурации. Теперь хост будет уверен, что у нас есть некое составное HID-устройство, и во все эти точки можно слать данные. Но это пока не так.
Для того, чтобы это стало правдой:
1. В нашем контроллере есть специально выделенный кусочек памяти, который тактируется вместе с модулями CAN и USB. Учитывая, что модуль USB самостоятельно занимается процессом приема/передачи пакета данных, нужно задать ему буферы в этом кусочке памяти для каждой отдельно взятой конечной точки:
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x00 , PCD_SNG_BUF, 0x18);
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x80 , PCD_SNG_BUF, 0x58);
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , HID_EPOUT_ADDR , PCD_SNG_BUF, 0x100);
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , HID_EPIN_ADDR , PCD_SNG_BUF, 0x140);
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , HID_EPOUT_ADDR2 , PCD_SNG_BUF, 0x180);
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , HID_EPIN_ADDR2 , PCD_SNG_BUF, 0x1B0);
Адреса буферов произвольные, лишь бы не пересекались.
Почему-то стек от ST написан из расчета, что в устройстве будет не более одной двунаправленной конечной точки, потому чуть дорабатываем стек:
Передача
Процедуру USBD_HID_SendReport переименовываем в USBD_HID_SendReportEP, добавляя еще один параметр — номер конечной точки. Процедуру со старым именем оставляем для обратной совместимости, но в теле вызываем USBD_HID_SendReportEP с константой в виде конечной точки. Решение пока не самое эстетичное, но для эксперимента сойдет, и даже если и останется — конкретному проекту это жить мешать не будет.
uint8_t USBD_HID_SendReportEP (USBD_HandleTypeDef *pdev,
uint8_t ep,
uint8_t *report,
uint16_t len)
{
... тело, бывшее раньше USBD_HID_SendReport
}
uint8_t USBD_HID_SendReport (USBD_HandleTypeDef *pdev,
uint8_t *report,
uint16_t len)
{
return USBD_HID_SendReportEP(pdev,HID_EPIN_ADDR,report,len);
}
Теперь для отправки данных все готово, остается лишь в нужный момент вызвать эту функцию.
Финализация
Порядка ради ищем по проекту и вызываем USBD_LL_CloseEP еще раз, но для вновь созданных конечных точек.
Прием
Для того, чтобы конечные точки морально настроились на работу, нужно вызвать для них USBD_LL_PrepareReceive. Рекомендую читателю пробежаться поиском по проекту на предмет этой строки, и адаптировать эти вызовы под свои нужды.
У меня в коде получилась вот такая вот некрасивая каракатица:
USBD_LL_PrepareReceive(pdev, HID_EPOUT_ADDR+(epnum&0x7F)-1 , hhid->Report_buf,
USBD_HID_OUTREPORT_BUF_SIZE);
Т.е. я исходил из того, что номера конечных точек идут подряд. Это плохо, имхо. Не делайте так. Впрочем, и как ST тоже не делайте.
Дальше остается только сходить в файл usbd_hid.c, а конкретно в функцию USBD_HID_DataOut, и позаботится о том, чтобы вызов обработчика принятых данных соответствовал вашим личным представлениям о прекрасном. У меня получилось тоже не очень, поэтому код и описание получатся длинными и непонятными. Проще сделать самому.
Репорт
Все, в этом месте мы получили композитное устройство, которое способно обмениваться данными через две двунаправленные точки. Последним штрихом «затыкаем» любопытство драйверу HID, описывая такой вот дескриптор репорта:
__ALIGN_BEGIN static uint8_t HID_ReportDesc2[33] __ALIGN_END =
{
0x06, 0x00, 0xff, // USAGE_PAGE (Vendor Defined Page 1)
0x09, 0x01, // USAGE (Vendor Usage 1)
0xa1, 0x01, // COLLECTION (Application)
0x85, 0x01, // REPORT_ID (1)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x1f, // REPORT_COUNT (31)
0x09, 0x00, // USAGE (Undefined)
0x81, 0x00, // INPUT (Data,Ary,Abs)
0x85, 0x02, // REPORT_ID (2)
0x09, 0x01, // USAGE (Vendor Usage 1)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x1f, // REPORT_COUNT (31)
0x91, 0x00, // OUTPUT (Data,Ary,Abs)
0xc0 // END_COLLECTION
};
Этот репорт говорит HID-драйверу: тут будут какие-то 31 байт данных. Не нужно разбираться, что за они — просто отдай их открывшей это устройство программе. В физическом репорте нулевой байт будет равен индексу репорта (REPORT_ID (2)). Соответственно, всего придет 32 байта.
И вписываем данные о нем в usbd-hid.c, функция USBD_HID_Setup.:
switch (req->bRequest)
{
case USB_REQ_GET_DESCRIPTOR:
if( req->wValue >> 8 == HID_REPORT_DESC)
{
// TODO: !!! Отдать нужный дескриптор, в зависимости от значения req->wIndex !!!
THIDDescPtrLen * rep = (req->wIndex==1)?&HID_ReportDesc:&HID_ReportDesc2;
len = MIN(rep->len , req->wLength);
pbuf = rep->ptr;
}
Далее в программе:
- Сборка преобразователя логических уровней AVC-LAN, и подключение к плате. Анализ физического уровня AVC-LAN, реальные осциллограммы.
- Обработка интерфейса на уровне контроллера и отправка пакетов репортами
- Сквозной интерфейс и реверс-инжиниринг Prius. Снифер пакетов (или мое первое Android-приложение)
P.S.
- Статью решил написать, поскольку меня заставили (почти), убедив, что этим нужно делиться. Даже если и не доведу проект до конца, некоторое количество свежей информации может кому-то помочь даже в «сыром» виде.
- Критика проекта приветствуется, т.к. сам пока не до конца представляю, что это получится.
- Критика статьи, оформления, изложения — особенно, т.к. это первая статья для ресурса. При продолжении работы хотелось бы излагать мысли в привычном и удобоваримом для читателей виде
Комментарии (34)
mbait
21.04.2018 06:32А где вы взяли диаграммы, и есть ли там же для Приуса третьего поколения?
remixoff Автор
21.04.2018 23:13Диаграммы? Осциллограммы снял со своего, будут в след. статье. В этой — фрагмент схемы из мана по обслуживанию и ремонту (есть бумажная книга). Но, наверняка, можно скачать и скан. Цветные — рисовал, чтобы показать суть изменений.
bugdesigner
21.04.2018 09:14Хочу пожелать удачи в реализации!
Скажите, а протокол обмена по CAN у Вас уже есть? Или Вы планируете дампить и вылавливать нужные команды? В любом случае проект очень интересный и буду ждать продолжения.remixoff Автор
21.04.2018 23:17Спасибо. Очень надеюсь, что хватит сил допилить.
Голова не подключена к CAN. Только AVC-LAN. Это гибрид, созданный злым умыслом компании (если правильно помню) NEC. Это тоже планирую в след. статью, но пока делаю снифер. В нете есть статьи по этой шине, но инфа скудная, хотя для начала помогла. Думаю, будет интересно добавить реальных данных в сеть.
sashka_amur
21.04.2018 16:25Судя по фото голова послерестайловая, у меня просто был 20 приус и я заморачивался установкой камеры, как выяснилось существует 6 разных голов, 2 дорестайловые и 4 послерестайловые. И все они различаются, та что была у меня не могла получать видео напрямую с камеры, в систему пришлось добавлять штатный блок парковки, вот он то какраз конвертил видео картинку в формат для головы и по этому же каналу передавал сигнал о том что пора вывести изображение. Так что схемы то да есть, но от той ли они головы. А так удачи в проекте, как закончите к вам в очередь встанут владельцы всех гибридных лексусов и не только. А кстати блок парковки нашёлся на автосайтах буквально за 500р.
remixoff Автор
21.04.2018 23:22Да, голова послерестайловая. И видеоинтерфейс — это что-то кошмарное и пропиетарное. Со сменой головы, надеюсь, необходимость в нем отпадет.
Очень хочется помочь себе и братьям-приусоводам.
Я ж хочу не просто картинку. Я хочу снять оковы с рук, вставить открытую систему. А там и нави, и заметки, и плей-маркет.sashka_amur
23.04.2018 09:08Там, на сколько я помню с блока автопарковки ещё идут контакты на рулевую рейку с которой он берет информацию о её положении и скорее всего ею же и управляет, а информацию он берет что б нарисовать сверху картинки с камеры линии направления парковки, когда рулём вращаешь эти линии движутся и указывают направление, думаю для этого и нужен огород со своим стандартом, причём те провода должны быть экранированы и картинка там идёт в каком то подобии RGB потому если как во время работы отключить 1 из проводов картинка зеленеет или краснеет как при отключении одного канала цвета в фоторедакторе. соответственно без этого блока автопаркинг работать не будет, + тем кто хочет себе поставить атопаркинг, нужно проверить какая у него рулевая рейка по-тому, что их как минимум 2 вида с разным колличествлм контактов, и та что с меньшим не сможет парковать автомобиль. Не помню где именно встречал реализацию такой системы, ставили какой то пк в систему изображение с которого подавали на блок автопаркигна и соответственно в голову, на экран сверху накладывали ещё один тачскрин и соответсвенно ставили кнопку переключения на вывод изображения с камеры и отключение родного тачскрина. А управление с руля для сторонних пк для Тойоты давно уже реализовано.
remixoff Автор
23.04.2018 09:44Да, и если все это он способен делать сам — то пусть продолжает этим заниматься. Моей задачей будет просто отдать ему информацию, куда пользователь «ткнул пальцем».
А огород с тачскринами видел — тоже мне не понравился. Все-таки хочется чего-то, что пусть будет сложнее в разработке, но при этом избавит от бутербродов и наслоений.
Я убежден, что простота и надежность находятся в прямой зависимости.
Управление с руля реализовано даже в китайских шарманках. В этом сложностей нет — там цепочка резисторов, и АЦП на входе.
Задача — реализовать шататные ф-ции тойоты на китайце.
«Насколько я помню» — значит ли это, что можете помочь схемами подключения блока автопарковки?sashka_amur
23.04.2018 21:12Это было 2 года назад, конечно, но думаю посмотрев на разъёмы и схему, подскажу, что куда.
remixoff Автор
23.04.2018 21:21Нет, интересовали, скорее, подписи на контактах разъемов. Я дотянулся до того, чтобы посмотреть на них физически. К несчастью, линия GVIF, похоже, и в самом деле проходит блок автопарковки «насквозь». Т.е. с навигации через парк-ассист, и с него уже на голову.
Пока не знаю, как оставить работать парк-ассист при моей реализации. Возможно, придется искать до-рестайловый.
Andrey_13
21.04.2018 16:25Хорошая тема. Занимаюсь почти подобным, только на SUBARU. Только пока никак не созрею на написание статьи.
remixoff Автор
21.04.2018 23:27А что там с шинами? Тоже АВЦ-лан, или CAN-ом обошлись?
Andrey_13
22.04.2018 09:57Там нет страшных гибридов. Я использовал К-линию и протокол Subaru. Если интересно — вот статья www.drive2.ru/l/499650795206082616. Пока в раздумьях: имеет ли смысл здесь выкладывать что то подобное и будет ли это интересно сообществу.
BurlakovSG
21.04.2018 19:37А AVC-LAN это не просто обычный CAN? На форуме Citroen парни занимаются ковырянием CAN-шины. Из достижений — сделали парктроник, который прикидывается штатным и, соответственно, данные показываются на штатном дисплее.
У себя в машине поставил китайскую ГУ и у неё есть модуль CAN, через который ГУ общается с шиной машины, выводятся сообщения, с кнопок руля управляется и т.д. Неужели для примуса китайцы не сделали такую интеграцию?remixoff Автор
21.04.2018 23:25Нет. AVC-LAN — это отдельный мутант (см. коммент выше). В приусе три шины (CAN, BEAN, AVC LAN), и маршрутизатор между ними. Костыльно-велосипедный девелопмент. Впрочем, это ж — гибрид.
BurlakovSG
22.04.2018 22:23А как на стороне Андройда будете обрабатывать данные RAW из шины USB? Я делал связку USB-TTL + Android. Писал сервис, который получая сообщение по СОМ-порту выводить сервисное сообщение на экран. Данный способ мне не нравится, т.к. постоянно идёт запрос разрешения доступа к СОМ-порту.
remixoff Автор
23.04.2018 08:50Да, именно поэтому я начал с HID. Забегая вперед: пока разрешение нужно выдавать только при переподключении устройства (или при перезаливке ПО). Пока не понял, где андроид теряет его, но когда apk-шка не трогалась, и устр-во не отключалось — запускается тихо. RAW-HID остается hid-ом.
Идея использования COM порта сегодня мне тоже не нравится — слишком много "но".
Сейчас есть некоторые наработки по сниферу, все это будет в одной из двух след. статей. Пока не знаю, с какой начать: андроид-снифер или физическое поключение к avc-lan. В любом случае, с моим свободным временем, до след. статьи недели три пройдет.BurlakovSG
23.04.2018 17:44А после перезагрузки тоже не требует разрешения?
remixoff Автор
23.04.2018 17:55Проверю в течение пары дней — напишу, хорошо? Пока просто этим не заморачивался, предполагая, что устройство все равно рутовать.
BurlakovSG
23.04.2018 17:58Хорошо. А Вы не могли бы ткнуть в инфу как на андройде с RAW-HID работать?
remixoff Автор
23.04.2018 21:04gist.github.com/archeg/8333021
Хороший пример, с пояснениями.
То, что там запрос делается при старте — андроид еще дает поставить галочку «всегда использовать программу для этого устройства». И, как я понял, при перезапуске автоматом выдает разрешение на этой строке:
_usbManager.requestPermission(_usbDevice, mPermissionIntent);
mihnik
23.04.2018 08:58Не очень понятно, «многофункциональный экран» — это лишь средство отображения информации? Никакой нагрузки в обработке и управлении системами машины не несет? Все можно свести к отображению результатов, приходящих от других узлов авто и командам управления — типа нажатия кнопок или элементов на экране? Причем всего по одной шине?
Как-то странно это звучит. Там же и управление климатом, и отображение режимов работы батарей и двигателя, и навигация. Для навигации, как я понял- картинка формируется внешней системой (блок навигации) и передается по доп интерфейсу.
Но вот что с климатом?
Или вот что с картинкой с задней камеры? В штатной голове Приуса картинка формируется с отображением траектории с учетом положения руля. Можно реализовать это и китайской шарманкой, но где-то нужно взять информацию о положении руля, если ты хочешь выводить линии подсказки на изображение камеры…
remixoff Автор
23.04.2018 09:09Точно так. Управление климатом, отбражение состояния системы — именно это Андроид-приложение нужно написать. Здесь все более или менее понятно, осталось доделать снифер и разобрать команды. А голова подключена именно по штатной шине.
Таким образом, я пока не вижу, как еще может передаваться управление климатом (и усилителем, к слову), и полагаю, что все это идет по AVC.
А адаптер двунаправленный, т.е. может не только получать, но и передавать информацию.
В планах, соответственно, сделать некое climat.apk, которое запускается по внешней кнопке, открывает этот девайс, и общается с машиной через описанный в статье переходник.
По кнопке «инфо» на руле, соответственно, запускаем info.apk, и слушаем состояние машины на предмет информации о батарее.
Хотя, не исключаю, что это будет и Android-сервис, обрабатывающий устройство, а в систему отдающий уже некий API. Это все предстоит установить экспериментальным путем.
Сейчас ведется работа над, собственно, снифером, после — реверс шины, и уж тогда будет решение.
Конечно, можно было бы воткнуть BT-CAN (OBD2) переходник, и получать те же параметры, но я сторонник архитектурно-совместимых решений, а голова подключена в приусе _только_ к AVC-LAN. Т.е. вся эта информация передается по ней.
Что касается согласования камеры с линиями положения руля — да, это отдельная (возможно, достаточно масштабная) задача. Потому что я пока не знаю, кто именно рисует эти линии — голова или блок парковки. Если голова — то информация о положении руля тоже должна приходить по AVC. Если блок парковки — будет сложнее. Тогда придется и его функционал частично подменять/повторять.sashka_amur
23.04.2018 09:28Линии парковки рисуются с информации от рейки и рисуются в блоке автопарковки, выше уже написал.
remixoff Автор
23.04.2018 09:53Понял. Буду проверять. У меня просто нет схемы подключения блока автопарковки. Что там: тот же GVIF, будь он неладен, или обычный RGB или AV. Вроде, в голове и в нави — один GVIF. Т.е., только если он «пропущен» через парковочник. В противном случае сигнал должен идти по AV/RGB. Это упростит задачу.
Сегодня попробую посмотреть на разъемы.
mehos
23.04.2018 11:50А зачем нужна китайская Андроид-голова? Можно же взять отдельно экран с драйвером и ягоду. Я бы наверно так делал.
remixoff Автор
23.04.2018 14:39Да, и эти мысли тоже были. Дополнительно нужно будет:
- распустить звук на 4 канала
- прикрутить управление с руля (сервис)
- AV-видеовход для камеры заднего вида
- Корпус с креплением (желательно — металл)
- GPS
Думаю, это не весь перечень, но я посчитал достаточным для того, чтобы не заморачиваться.
Впрочем, решенеие с адаптером позволит желающим пойти и этим путем. В моем случае это опасно тем, что проект уж слишком затянется.
betony
Спасибо за статью!