目录
构建ipc_chan 将chan list node 挂到chan->dev->ipc_list 上获取ipc msg
memcpy_fromio 获取send 到arm1 上的ipc msg
Kernel backcar 接收RVC_IPC_KEY_ARM2_NOTIFY
backcar 使用backcardrv ioctl 发送ipc msg
通过metazone 获取METAZONE_BACKCAR_VDO_SOURCE的值
arm 2 上的rtos 获取倒车的gpio的信息通过backcar驱动解析后将event事件挂在notify_event_list
arm ap 侧使用驱动read的接口获取backcardrv arm2 的msg
hal层rvcDataChangeNotify将回调java注册callback函数
java层backcar service 注册hal 回调函数
backcar service callbac函数 sendmsg EVENT_TYPE_RVC_DATA_CHANGE给app
RVC RTOS 代码流程分析
dtsi 中配置的gpio 用于触发RVC
g_device_dtb_info->avin_info.gpio_trigger_backcar
vendor/autochips/proprietary/tinysys/viss/os/drivers/backcar/
/*********************************************************************
* Task for handle backcar events: start/stop/update/suspend/resume.
*********************************************************************/
void vBackcarMainTask( void *pvParameters )
{
//TickType_t xQueueReceiveWait = pdMS_TO_TICKS( 0 );
BCEventType_t xBCEventType = eBCNoneEvent;
RVCData_t xRVCData;
BC_INFO("backcar main task start. videoin viss time: %dms\n", get_current_time_ms());
(void)pvParameters;
/*check backcar status and notify apm first to ensure LOGO/ANI can show in time*/
BC_INFO("backcarGPIO_NUM=%d\r\n", backcarGPIO_NUM);
if( pdPASS != xBCGPIOInit( backcarGPIO_NUM ) )
{
BC_ERR("init backcar gpio fail\r\n");
}
xBCEventType = xBCGPIOGetCurEvent();
if( eBCStopEvent == xBCEventType )
{
BC_INFO("backcar at stop status before backcar init \r\n");
if( NULL != pxBCCallback )
{
pxBCCallback( xBCEventType );
}
}
if( pdFAIL == xBCModulesInit() )
{
BC_ERR("backcar task init failed \r\n");
if( eBCStartEvent == xBCEventType )
{
xBCEventType = eBCStopEvent;
pxBCCallback( xBCEventType );
}
}
for( ; ; )
{
if( NULL == xBCEventQueue )
{
BC_ERR("backcar event queue is null \r\n");
break;
}
if( pdPASS == xQueueReceive( xBCEventQueue, &xBCEventType, portMAX_DELAY ) ) //always block for events
{
BC_INFO("backcar event received: %d \r\n", xBCEventType);
if( pdTRUE == xStopHandleEvent )
{
BC_INFO("viss rvc will exit, stop handle any rvc event!\r\n");
continue;
}
switch( xBCEventType )
{
case eBCStartEvent:
BC_INFO("get start event. videoin viss time: %dms\n", get_current_time_ms());
if( xArm1BCIsReady || !xScreenMCUOn || !xDisplayPowerOn )
{
BC_INFO("arm1 backcar is ready or screen is off, do not respond to eBCStartEvent\r\n");
break;
}
if( pdPASS != xBackcarShow() )
{
BC_ERR("backcar start failed \r\n");
break;
}
if( NULL != pxBCCallback )
{
pxBCCallback( xBCEventType );
}
g_xRVCCurDataSet.lRVCStatus = 0;
memset( &xRVCData, 0, sizeof( RVCData_t ) );
strcpy( xRVCData.ipc_key, RVC_IPC_KEY_ARM2_NOTIFY );
xRVCData.type = RVC_DATA_RVC_STATUS;
xRVCData.data[0] = g_xRVCCurDataSet.lRVCStatus;
xBackcarSendMsgToArm1( (void *)&xRVCData );
break;
case eBCStopEvent:
if( !xScreenMCUOn || !xDisplayPowerOn )
{
BC_INFO("screen is off, do not respond to eBCStopEvent\r\n");
break;
}
if( pdPASS != xBackcarHide() )
{
BC_ERR("backcar stop failed \r\n");
}
if( xArm1BCIsReady )
{
BC_INFO("arm1 backcar is ready, quit arm2 backcar forever\r\n");
xStopHandleEvent = pdTRUE;
xBCEventType = eBCQuitEvent;
}
if( NULL != pxBCCallback )
{
pxBCCallback( xBCEventType );
}
g_xRVCCurDataSet.lRVCStatus = 1;
memset( &xRVCData, 0, sizeof( RVCData_t ) );
strcpy( xRVCData.ipc_key, RVC_IPC_KEY_ARM2_NOTIFY );
xRVCData.type = RVC_DATA_RVC_STATUS;
xRVCData.data[0] = g_xRVCCurDataSet.lRVCStatus;
xBackcarSendMsgToArm1( (void *)&xRVCData );
break;
case eBCUpdateEvent:
if( pdPASS != xBackcarUpdate() )
{
BC_ERR("backcar update failed \r\n");
break;
}
break;
case eBCSuspendEvent:
if( pdPASS != xBackcarSuspend() )
{
BC_ERR("backcar suspend failed \r\n");
break;
}
break;
case eBCResumeEvent:
if( pdPASS != xBackcarResume() )
{
BC_ERR("backcar resume failed \r\n");
break;
}
break;
default:
BC_ERR("backcar unknown event occured \r\n");
break;
}
}
}
vTaskDelete(NULL);
}
创建vBackcarGPIOMonitorTask监控线程
触发倒车eBCStartEvent
/**********************************************************************
* Task for monitor backcar switch event through polling gpio value
**********************************************************************/
void vBackcarGPIOMonitorTask( void *pvParameters )
{
TickType_t xDelay = pdMS_TO_TICKS( 200 );
TickType_t xQueueSendWait = pdMS_TO_TICKS( 0 ); //no wait, if queue is full and send fail, do not change last gpio value, wait for next task circle to send
int lCurGPIOVal = gpioUNKNOWN;
int lLastGPIOVal = gpioUNKNOWN;
BCEventType_t xBCEventType = eBCNoneEvent;
BC_INFO("backcar gpio monitor task start\r\n");
(void)pvParameters;
for( ; ; )
{
if( NULL == xBCEventQueue )
{
BC_ERR("backcar event queue is null \r\n");
goto end;
}
//获取gpio_trigger_backcar gpio value
lCurGPIOVal = lBCGPIOGetValue();
if( lLastGPIOVal != lCurGPIOVal )
{
if( gpioHIGH == lCurGPIOVal )
{
BC_INFO("[%d ms] _lyq backcar start event occured \r\n",get_current_time_ms());
//触发倒车
xBCEventType = eBCStartEvent;
}
else if( gpioLOW == lCurGPIOVal )
{
BC_INFO("_lyq backcar stop event occured \r\n");
//结束倒车
xBCEventType = eBCStopEvent;
}
else
{
BC_ERR("backcar unknow event occured \r\n");
goto end;
}
//Notice: if many other events sent to queue after xQueueReset and before xQueueSend. this event may send fail
xQueueReset( xBCEventQueue ); //clean event queue.The interface always return pdPASS since FreeRTOS V7.2.0
if( pdPASS != xQueueSend( xBCEventQueue, &xBCEventType, xQueueSendWait ) )
{
BC_ERR("send backcar start/stop event to queue fail \r\n");
goto end;
}
lLastGPIOVal = lCurGPIOVal;
}
xDelay = pdMS_TO_TICKS( 10 );
vTaskDelay( xDelay );
continue;
end:
xBCEventType = eBCNoneEvent;
xDelay = pdMS_TO_TICKS( 100 ); //change frequence of checking gpio value when error accured
vTaskDelay( xDelay );
}
vTaskDelete(NULL);
}
获取backcar gpio的值
static int lBCGPIOGetValue()
{
int lGPIOValue = gpioUNKNOWN;
if( ulBCGPIONum != 0 )
{
lGPIOValue = xGpioGetPinValue( ulBCGPIONum );
}
return lGPIOValue;
}
int xGpioGetPinValue(long lPin)
{
unsigned int ext_info = 0;
unsigned int group = 0, offset = 0;
unsigned int value = 0;
if (lPin >= GPIO_NUM) {
GPIO_ERR("Input pin number is %ld, Not support!\n", lPin);
return -1;
}
ext_info = gpio_ext_info[lPin];
group = GET_GROUP_NUM(ext_info);
if (group == GPIO_UNSUPPORT) {
GPIO_INFO("Input pin number is %ld, Not support!\n", lPin);
return -1;
}
offset = GET_GROUP_OFFSET(ext_info);
value = gpio_hal_input_value_get(group);
return (value >> offset & GPIO_BITMASK);
}
接收eBCStartEvent 事件
发送RVC_IPC_KEY_ARM2_NOTIFY给arm1 ap 侧
/*********************************************************************
* Task for handle backcar events: start/stop/update/suspend/resume.
*********************************************************************/
void vBackcarMainTask( void *pvParameters )
{
//TickType_t xQueueReceiveWait = pdMS_TO_TICKS( 0 );
BCEventType_t xBCEventType = eBCNoneEvent;
RVCData_t xRVCData;
BC_INFO("backcar main task start. videoin viss time: %dms\n", get_current_time_ms());
(void)pvParameters;
/*check backcar status and notify apm first to ensure LOGO/ANI can show in time*/
BC_INFO("backcarGPIO_NUM=%d\r\n", backcarGPIO_NUM);
if( pdPASS != xBCGPIOInit( backcarGPIO_NUM ) )
{
BC_ERR("init backcar gpio fail\r\n");
}
xBCEventType = xBCGPIOGetCurEvent();
if( eBCStopEvent == xBCEventType )
{
BC_INFO("backcar at stop status before backcar init \r\n");
if( NULL != pxBCCallback )
{
pxBCCallback( xBCEventType );
}
}
if( pdFAIL == xBCModulesInit() )
{
BC_ERR("backcar task init failed \r\n");
if( eBCStartEvent == xBCEventType )
{
xBCEventType = eBCStopEvent;
pxBCCallback( xBCEventType );
}
}
for( ; ; )
{
if( NULL == xBCEventQueue )
{
BC_ERR("backcar event queue is null \r\n");
break;
}
if( pdPASS == xQueueReceive( xBCEventQueue, &xBCEventType, portMAX_DELAY ) ) //always block for events
{
BC_INFO("backcar event received: %d \r\n", xBCEventType);
if( pdTRUE == xStopHandleEvent )
{
BC_INFO("viss rvc will exit, stop handle any rvc event!\r\n");
continue;
}
switch( xBCEventType )
{
case eBCStartEvent:
BC_INFO("get start event. videoin viss time: %dms\n", get_current_time_ms());
if( xArm1BCIsReady || !xScreenMCUOn || !xDisplayPowerOn )
{
BC_INFO("arm1 backcar is ready or screen is off, do not respond to eBCStartEvent\r\n");
break;
}
if( pdPASS != xBackcarShow() )
{
BC_ERR("backcar start failed \r\n");
break;
}
if( NULL != pxBCCallback )
{
pxBCCallback( xBCEventType );
}
//arm2 对arm1 发送ipc 消息
g_xRVCCurDataSet.lRVCStatus = 0;
memset( &xRVCData, 0, sizeof( RVCData_t ) );
strcpy( xRVCData.ipc_key, RVC_IPC_KEY_ARM2_NOTIFY );
xRVCData.type = RVC_DATA_RVC_STATUS;
xRVCData.data[0] = g_xRVCCurDataSet.lRVCStatus;
xBackcarSendMsgToArm1( (void *)&xRVCData );
break;
case eBCStopEvent:
if( !xScreenMCUOn || !xDisplayPowerOn )
{
BC_INFO("screen is off, do not respond to eBCStopEvent\r\n");
break;
}
if( pdPASS != xBackcarHide() )
{
BC_ERR("backcar stop failed \r\n");
}
if( xArm1BCIsReady )
{
BC_INFO("arm1 backcar is ready, quit arm2 backcar forever\r\n");
xStopHandleEvent = pdTRUE;
xBCEventType = eBCQuitEvent;
}
if( NULL != pxBCCallback )
{
pxBCCallback( xBCEventType );
}
g_xRVCCurDataSet.lRVCStatus = 1;
memset( &xRVCData, 0, sizeof( RVCData_t ) );
strcpy( xRVCData.ipc_key, RVC_IPC_KEY_ARM2_NOTIFY );
xRVCData.type = RVC_DATA_RVC_STATUS;
xRVCData.data[0] = g_xRVCCurDataSet.lRVCStatus;
xBackcarSendMsgToArm1( (void *)&xRVCData );
break;
case eBCUpdateEvent:
if( pdPASS != xBackcarUpdate() )
{
BC_ERR("backcar update failed \r\n");
break;
}
break;
case eBCSuspendEvent:
if( pdPASS != xBackcarSuspend() )
{
BC_ERR("backcar suspend failed \r\n");
break;
}
break;
case eBCResumeEvent:
if( pdPASS != xBackcarResume() )
{
BC_ERR("backcar resume failed \r\n");
break;
}
break;
default:
BC_ERR("backcar unknown event occured \r\n");
break;
}
}
}
vTaskDelete(NULL);
}
autochip ipc arm1&arm2核间通信
构建ipc_chan 将chan list node 挂到chan->dev->ipc_list 上获取ipc msg
#define ipc_request_chan_detailed(proc, direction, snd, rcv) \
163 ({ \
164 ipc_chan_t *__chan = ipc_request_chan(proc, direction); \
165 if (__chan) { \
166 strncpy(__chan->sender, snd, 8); \
167 strncpy(__chan->receiver, rcv, 8); \
168 } \
169 __chan; \
170 })
482 ipc_chan_t *ipc_request_chan(enum IPC_CORE proc, enum IPC_DIRECTION direction)
483 {
484 ipc_chan_t *chan = NULL;
485
486 if (proc != CORE_VEHICLE) {
487 pr_err("[AIPC] %s unsupport communicate with core=%d\n", __func__,
488 proc);
489 return NULL;
490 }
491
492 chan = kzalloc(sizeof(ipc_chan_t), GFP_KERNEL);
493 if (!chan) {
494 pr_err("[AIPC] %s no memory\n", __func__);
495 return NULL;
496 }
497
498 spin_lock_init(&chan->lock);
499
500 if (direction == MSGSEND) { //send
501 chan->dev = dev_ap2viss;
502 } else if (direction == MSGRECV) {
//receive
//接收msg
503 chan->dev = dev_viss2ap;
504 init_waitqueue_head(&chan->wait);
505
506 mutex_lock(&ipc_mutex);
//将chan list node 挂到chan->dev->ipc_list 上获取ipc msg
507 list_add(&chan->list_node, &(chan->dev->ipc_list));
508 chan->dev->idr_ref++;
509 mutex_unlock(&ipc_mutex);
510 }
511
512 return chan;
513 }
514
515 EXPORT_SYMBOL_GPL(ipc_request_chan);
memcpy_fromio 获取send 到arm1 上的ipc msg
Linux-IO端口、IO内存详解_memcpy_fromio-优快云博客
static void ipc_find_work(struct work_struct *work)
145 {
146 uint8_t first_entry = 0;
147 ipc_msg_t *ipc_msg = NULL;
148 ipc_chan_t *chan = NULL;
149 ipc_chan_dev_t *dev = dev_viss2ap; // AP <- VEHICLE
150 void *msg;
151 unsigned idx = 0;
152 unsigned long flags;
153
154 // 2. account all.
155 mutex_lock(&ipc_mutex);
156 while (ipc_hal_responder_get_number_valid(dev->oid, dev->rid)) {
157 first_entry = ipc_hal_responder_get_first_valid(dev->oid, dev->rid);
158 ipc_msg =
159 (ipc_msg_t *) (dev->base_addr + first_entry * IPC_PACKET_SIZE);
160
//循环遍历ipc_list的list_node 匹配receiver
161 list_for_each_entry(chan, &dev->ipc_list, list_node) {
162 if (!strncmp(chan->receiver, ipc_msg->receiver, 8)) {
163 //pr_info("[AIPC] the lucker %s\n", chan->receiver);
164 spin_lock_irqsave(&chan->lock, flags);
165 if (chan->msg_count == IPC_MSG_QUEUE_LEN) {
166 spin_unlock_irqrestore(&chan->lock, flags);
167 continue;
168 }
169
170 idx = chan->msg_free;
171 //判断ipc msg不为空
172 if (ipc_msg->msg && ipc_msg->size) {
173 msg = kmalloc(ipc_msg->size, GFP_KERNEL);
174 if (!msg) {
175 pr_err("[AIPC] %s no memory\n",
__func__);
176 spin_unlock_irqrestore(&chan->lock,
flags);
177 continue;
178 }
179 //获取ipc msg 保存到chan msg_data
180 memcpy_fromio(msg, ipc_msg->msg,
ipc_msg->size);
181 chan->msg_data[idx].msg = msg;
182 chan->msg_data[idx].size = ipc_msg->size;
183 } else {
184 chan->msg_data[idx].msg = NULL;
185 chan->msg_data[idx].size = 0;
186 }
187
188 pr_debug("[AIPC] ipc_find_work %s->%s, %s, %d, %u, %u\n", chan->sender, chan->receiver,
189 (char *)(chan->msg_data[idx].msg), chan-
>msg_data[idx].size,
190 chan->msg_count, chan->msg_free);
191
192 chan->msg_count++;
193
194 if (idx == IPC_MSG_QUEUE_LEN - 1)
195 chan->msg_free = 0;
196 else
197 chan->msg_free++;
198
199 spin_unlock_irqrestore(&chan->lock, flags);
200
201 wake_up_interruptible(&chan->wait);
202 }
203 }//1: no luck receiver, publish ,account it
204
205 ipc_ack(dev);
206 }
207 mutex_unlock(&ipc_mutex);
208 }
#define ipc_receivemsg_timeout(c, m, s, t) \
183 ({ \
184 int __rc = 0; \
185 __rc = ipc_receive_timeout(c, t); \
186 if (__rc == 0) { \
187 __rc = (int)ipc_read(c, m, s); \
188 } \
189 __rc; \
190 })
191
192 #define ipc_receive(c) ipc_receive_timeout(c, 0)
193
194 #define ipc_receivemsg(c, m, s) ipc_receivemsg_timeout(c, m, s, 0)
将ipc msg 拷贝到内核的buf
ssize_t ipc_read(ipc_chan_t *chan, void *buf, size_t nbytes)
309 {
310 unsigned long flags;
311 ssize_t n = 0;
312 unsigned idx = 0;
313 unsigned count = 0;
314
315 spin_lock_irqsave(&chan->lock, flags);
316 count = chan->msg_count;
317 if (count == 0) {
318 spin_unlock_irqrestore(&chan->lock, flags);
319 return 0;
320 }
321
322 idx = chan->msg_free;
323 if (idx >= count)
324 idx -= count;
325 else //初始化 msg_free
326 idx += IPC_MSG_QUEUE_LEN - count;
327
328 pr_debug("[AIPC] ipc_read %s->%s, %s, %d, %u, %u\n", chan->sender, chan- >receiver,
329 (char *)(chan->msg_data[idx].msg), chan->msg_data[idx].size,
330 chan->msg_count, chan->msg_free);
331
332 n = nbytes < chan->msg_data[idx].size ? nbytes : chan->msg_data[idx].size;
333 if (chan->msg_data[idx].msg && n) {
334 memcpy(buf, chan->msg_data[idx].msg, n);
335 }
336
337 if (chan->msg_data[idx].msg){
338 kfree(chan->msg_data[idx].msg);
339 chan->msg_data[idx].msg = NULL;
340 }
341
342 chan->msg_count--;
343
344 spin_unlock_irqrestore(&chan->lock, flags);
345
346 return n;
347 }
348
349 EXPORT_SYMBOL_GPL(ipc_read);
Kernel backcar 接收RVC_IPC_KEY_ARM2_NOTIFY
#ifndef CONFIG_BACKCAR_NO_ARM2
202 static int backcar_ipc_receive_thread(void *data)
203 {
204 int ret = 0;
205 char arm2_msg[ipcMSG_LENGTH] = {0,};
206 struct rvc_data received_rvc_data;
207 struct arm2_rvc_event *event = NULL;
208 BACKCAR_LOG(BACKCAR_INFO, "backcar_ipc_receive_thread start\n");
209
210 do {
211 if (!g_ipc_receive_chan) {
212 BACKCAR_LOG(BACKCAR_INFO, "ipc receive chan is null, request chan first.\n");
//一个创建ipc recevice chan
//sender= g_ipc_arm1_ap
//receiver=g_ipc_arm2_rvc
213 g_ipc_receive_chan = ipc_request_chan_detailed(CORE_VEHICLE, MSGRECV, , g_ipc_arm1_ap);
214 if (!g_ipc_receive_chan) {
215 BACKCAR_LOG(BACKCAR_ERR, "ipc request receive chan fail\n");
216 continue;
217 }
218 }
219
220 memset(arm2_msg, 0, sizeof(arm2_msg));
//IPC通信接收小核 arm2的msg
221 ret = ipc_receivemsg(g_ipc_receive_chan, arm2_msg, ipcMSG_LENGTH);
222 if (ret < 0) {
223 BACKCAR_LOG(BACKCAR_ERR, "ipc receive fail %d\n", ret);
224 continue;
225 }
226
227 BACKCAR_LOG(BACKCAR_DEBUG, "ipc receive arm2_msg %s\n", arm2_msg);
228 if (!strncmp(cIpcMsgRcvArm2BCExit, arm2_msg, ipcMSG_LENGTH)) {
229 BACKCAR_LOG(BACKCAR_INFO, "backcar receive msg %s success \n", cIpcMsgRcvArm2BCExit);
230 if (NULL != g_ioctlwaitq) {
231 wake_up(g_ioctlwaitq);
232 } else {
233 BACKCAR_LOG(BACKCAR_WARNING, "g_ioctl waitq has been waked. but not by arm2 msg\n");
234 }
235 } else {
236 memset(&received_rvc_data, 0, sizeof(struct rvc_data));
237 memcpy(&received_rvc_data, arm2_msg, ipcMSG_LENGTH);
238 if (0 == strcmp(received_rvc_data.ipc_key, RVC_IPC_KEY_ARM2_RESPOND)) {
239 BACKCAR_LOG(BACKCAR_DEBUG, "RVC_IPC_KEY_ARM2_NOTIFY received. type = %d, data[0]= %d\n",
240 received_rvc_data.type, received_rvc_data.data[0]);
241 memset(&g_responsed_rvc_data, 0, sizeof(struct rvc_data));
242 memcpy(&g_responsed_rvc_data, arm2_msg, ipcMSG_LENGTH);
243 } else if (0 == strcmp(received_rvc_data.ipc_key, RVC_IPC_KEY_ARM2_NOTIFY)) {
244 BACKCAR_LOG(BACKCAR_INFO, "RVC_IPC_KEY_ARM2_NOTIFY received. type = %d, data[0]= %d\n",
245 received_rvc_data.type, received_rvc_data.data[0]);
246 event = kzalloc(sizeof(*event), GFP_KERNEL);
247 if (!event) {
248 BACKCAR_LOG(BACKCAR_ERR, "kzalloc failed \n");
249 break;
250 }
251 memset(&(event->data), 0, sizeof(struct rvc_data));
252 memcpy(&(event->data), arm2_msg, ipcMSG_LENGTH);
253 mutex_lock(&g_event_manager.event_mutex);
254 list_add_tail(&event->list, &g_event_manager.notify_event_list);
255 mutex_unlock(&g_event_manager.event_mutex);
256 wake_up(&g_event_manager.event_queue_wait);
257 } else {
258 BACKCAR_LOG(BACKCAR_INFO, "ipc not receive request msg \n");
259 break;
260 }
261 }
262 msleep(1);
263 } while (!kthread_should_stop());
264
265 BACKCAR_LOG(BACKCAR_INFO, "backcar_ipc_receive_thread leave \n");
266 return 0;
267 }
268 #endif
IPC send
102 static long ipc_send_msg(const char* msg)
103 {
104 int ret = 0;
105 if (!g_ipc_send_chan) {
106 BACKCAR_LOG(BACKCAR_INFO, "ipc send chan is null, request chan first.\n");
107 g_ipc_send_chan = ipc_request_chan_detailed(CORE_VEHICLE, MSGSEND, g_ipc_arm1_ap, g_ipc_arm2_apm);
108 if (!g_ipc_send_chan) {
109 BACKCAR_LOG(BACKCAR_ERR, "ipc request send chan fail\n");
110 return -EFAULT;
111 }
112 }
113
114 ret = ipc_sendmsg(g_ipc_send_chan, msg, ipcMSG_LENGTH);
115 if (ret < 0) {
116 BACKCAR_LOG(BACKCAR_ERR, "ipc send fail %d\n", ret);
117 return -EFAULT;
118 }
119 return 0;
120 }
#define ipc_sendmsg(c, m, s) \
173 ({ \
174 int __rc = 0; \
175 preempt_disable(); \
176 ipc_write(c, m, s); \
177 __rc = ipc_send(c); \
178 preempt_enable(); \
179 __rc; \
180 })
更新msg_free
351 ssize_t ipc_write(ipc_chan_t *chan, const void *buf, size_t nbytes)352 {
353 unsigned long flags;
354 unsigned idx = 0;
355 ssize_t n = 0;
356
357 spin_lock_irqsave(&chan->lock, flags);
358 if (chan->msg_count == IPC_MSG_QUEUE_LEN) {
359 spin_unlock_irqrestore(&chan->lock, flags);
360 return 0;
361 }
362
363 idx = chan->msg_free;
364
365 n = nbytes < MAX_MSG_LEN ? nbytes : MAX_MSG_LEN;
366 chan->msg_data[idx].size = n;
367 chan->msg_data[idx].msg = (void *)buf;
368
369 pr_debug("[AIPC] ipc_write %s->%s, %s, %d, %u, %u\n", chan->sender, chan- >receiver,
370 (char *)(chan->msg_data[idx].msg), chan->msg_data[idx].size,
371 chan->msg_count, chan->msg_free);
372
373 chan->msg_count++;
374
375 if (idx == IPC_MSG_QUEUE_LEN - 1)
376 chan->msg_free = 0;
377 else
378 chan->msg_free++;
379
380 spin_unlock_irqrestore(&chan->lock, flags);
381
382 return n;
383 }
384
385 EXPORT_SYMBOL_GPL(ipc_write);
获取chan msg 发送到ipc msg
int ipc_send(ipc_chan_t *chan)
388 {
389 uint32_t n = 0;
390 uint8_t last_entry = 0;
391 ipc_chan_dev_t *dev = NULL;
392 ipc_msg_t *ipc_msg = NULL;
393 unsigned count = 0;
394 unsigned idx = 0;
395 unsigned long flags;
396
397 if (!chan || !(chan->dev)) {
398 pr_err("[AIPC] %s invalid chan\n", __func__);
399 return -EINVAL;
400 }
401
402 dev = chan->dev;
403
404 spin_lock_irqsave(&chan->lock, flags);
405 count = chan->msg_count;
406
407 while (count) {
408 if (ipc_hal_originator_not_full(dev->oid, dev->rid) == 0) {
409 pr_err("[AIPC] %s chan is full\n", __func__);
410 spin_unlock_irqrestore(&chan->lock, flags);
411 return -EBUSY;
412 }
413
414 last_entry = ipc_hal_originator_get_last_valid(dev->oid, dev->rid);
415 ipc_msg = (ipc_msg_t *) (dev->base_addr + last_entry * dev- >packet_size);
416
417 strncpy(ipc_msg->sender, chan->sender, 8);
418 strncpy(ipc_msg->receiver, chan->receiver, 8);
419
420 idx = chan->msg_free;
421 if (idx >= count)
422 idx -= count;
423 else
424 idx += IPC_MSG_QUEUE_LEN - count;
425
426 n = chan->msg_data[idx].size < MAX_MSG_LEN ? chan->msg_data[idx].size : MAX_MSG_LEN;
427 if (chan->msg_data[idx].msg && n) {
428 memcpy_toio(ipc_msg->msg, chan->msg_data[idx].msg, n);
429 } else { // NULL msg
430 n = 0;
431 }
432
433 ipc_msg->size = n;
434
435 wmb();
436
437 pr_debug("[AIPC] ipc_send %s->%s, %s, %d, %u, %u\n", chan->sender, chan->receiver,
438 (char *)(chan->msg_data[idx].msg), chan- >msg_data[idx].size,
439 chan->msg_count, chan->msg_free);
440
441 ipc_notify(dev);
442
443 chan->msg_count--;
444 count = chan->msg_count;
445 }
446
447 spin_unlock_irqrestore(&chan->lock, flags);
448
449 return n;
450 }
451
452 EXPORT_SYMBOL_GPL(ipc_send);
backcar 使用backcardrv ioctl 发送ipc msg
284 static long backcar_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
285 {
286 void __user *argp = (void __user *)arg;
287 u_long size = 0;
288 int ret = 0;
289 unsigned gpio_value = 0;
290 struct rvc_solution_info rvc_solution;
291 #ifndef CONFIG_BACKCAR_NO_ARM2
292 wait_queue_head_t wait_queue_head;
293 DECLARE_WAITQUEUE(cur_wait_queue, current);
294 #endif
295
296 size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT;
297
298 if (cmd & IOC_IN) {
299 if (!access_ok(VERIFY_READ, argp, size)) {
300 BACKCAR_LOG(BACKCAR_ERR, "backcar_ioctl(): error 1, so bc_failed\n");
301 return -EFAULT;
302 }
303 }
304
305 if (cmd & IOC_OUT) {
306 if (!access_ok(VERIFY_WRITE, argp, size)) {
307 BACKCAR_LOG(BACKCAR_ERR, "backcar_ioctl(): error 2, so bc_failed\n");
308 return -EFAULT;
309 }
310 }
311
312 switch(cmd){
313 case IOCTL_FSC_NOTIFY_APP_READY:
314 BACKCAR_LOG(BACKCAR_INFO,
315 "execute IOCTL_FSC_NOTIFY_APP_READY ioctl\n");
316 memset(&rvc_solution, 0, sizeof(struct rvc_solution_info));
317 if (!videoin_get_rvc_solution_info(&rvc_solution)) {
318 BACKCAR_LOG(BACKCAR_WARNING,
319 "get rvc solution info from metazone fail!");
320 }
321 if (RVC_SOLUTION_ARM2_ONLY != rvc_solution.solution) {
322 BACKCAR_LOG(BACKCAR_INFO, "wait arm2 exit start\n");
323 mutex_lock(&g_ioctl_mutex);
324 if (gArm2AlreadyExit) {
325 BACKCAR_LOG(BACKCAR_INFO, "wait arm2 already exit done\n");
326 mutex_unlock(&g_ioctl_mutex);
327 break;
328 }
329 #ifndef CONFIG_BACKCAR_NO_ARM2
330 init_waitqueue_head(&wait_queue_head);
331 add_wait_queue(&wait_queue_head, &cur_wait_queue);
332 g_ioctlwaitq = &wait_queue_head;
333 set_current_state(TASK_INTERRUPTIBLE);
334
335 BACKCAR_LOG(BACKCAR_INFO, "Inform Arm2, Arm1 Backcar apk is ready\n");
336 BACKCAR_LOG(BACKCAR_INFO, "send arm1 ready to arm2 start\n");
337 ipc_send_msg(cIpcMsgSendArm1BCReady);
338 BACKCAR_LOG(BACKCAR_INFO, "send arm1 ready to arm2 end\n");
339 BACKCAR_LOG(BACKCAR_INFO, "wait arm2 interrupt before schedule\n");
340 schedule();
341 BACKCAR_LOG(BACKCAR_INFO, "wait arm2 interrupt after schedule\n");
342
343 if (signal_pending(current)) {
344 BACKCAR_LOG(BACKCAR_WARNING, "interrupted by system signal\n");
345 ret = -ERESTARTSYS;
346 } else {
347 BACKCAR_LOG(BACKCAR_INFO, "wait arm2 interrupt done\n");
348 }
349
350 remove_wait_queue(&wait_queue_head, &cur_wait_queue);
351 set_current_state(TASK_RUNNING);
352 g_ioctlwaitq = NULL;
353 gArm2AlreadyExit = true;
354 #ifdef CONFIG_MEMBLK_RELEASE_POLICY
355 backcar_free_viss_reserve_mem("autochips,backcar_rt");
356 backcar_free_viss_reserve_mem("autochips,backcar_mrf");
357 #endif
358 #endif //CONFIG_BACKCAR_NO_ARM2
359 }
360 videoin_dma_config();
361 BACKCAR_LOG(BACKCAR_INFO, "videoin_dma_config have successfully\n");
362
363 mutex_unlock(&g_ioctl_mutex);
364 BACKCAR_LOG(BACKCAR_INFO, "wait arm2 exit done\n");
365 break;
366 case IOCTL_BC_GPIOINIT:
367 GPIO_Init();
368 BACKCAR_LOG(BACKCAR_INFO, "init GPIO success!\n");
369 break;
370 case IOCTL_BC_DETECTGPIO:
371 gpio_value = GPIO_Get_value();
372 ret = copy_to_user(argp, &gpio_value, sizeof(gpio_value));
373 if (ret != 0) {
374 BACKCAR_LOG(BACKCAR_ERR, "copy gpio status to userspace bc_failed\n");
375 }
376 break;
377 case IOCTL_BC_FORCE_STOP_ARM2:
378 backcar_force_stop_arm2();
379 break;
380 case IOCTL_BC_NOTIFY_VBA_EXIT:
381 #ifndef CONFIG_BACKCAR_NO_ARM2
382 BACKCAR_LOG(BACKCAR_INFO, "Send MSG_IPC %s\n", cIpcMsgSendVbaExit);
383 ret = ipc_send_msg(cIpcMsgSendVbaExit);
384 if (ret < 0) {
385 BACKCAR_LOG(BACKCAR_ERR, "IPC Request Send failed\n");
386 }
387 #endif
388 break;
389 case IOCTL_BC_NOTIFY_AUDIO_MUTE:
390 #ifndef CONFIG_BACKCAR_NO_ARM2
391 {
392 unsigned mute = 0;
393 const char *muteMsg = NULL;
394 if (get_user(mute, (unsigned __user *)arg)) {
395 BACKCAR_LOG(BACKCAR_INFO, "get_user error\n");
396 ret = -EFAULT;
397 break;
398 }
399 muteMsg = mute ? cIpcMsgRcvArm2AudioMute : cIpcMsgRcvArm2AudioUnMute;
400 BACKCAR_LOG(BACKCAR_INFO, "Send MSG_IPC %s\n", muteMsg);
401 ret = ipc_send_msg(muteMsg);
402 if (ret < 0) {
403 BACKCAR_LOG(BACKCAR_ERR, "IPC Request Send failed\n");
404 }
405 }
406 #endif
407 break;
408 case IOCTL_MCU_BC_START_SUCCESS:
409 if (!gpio_is_valid(backcar_mcu_gpio_num)) {
410 BACKCAR_LOG(BACKCAR_ERR, "get backcar mcu notify gpio number bc_failed\n");
411 } else {
412 gpio_direction_output(backcar_mcu_gpio_num, BACKCAR_NOTIFY_MCU_GPIO_HIGH);
413 gpio_set_value_cansleep(backcar_mcu_gpio_num, BACKCAR_NOTIFY_MCU_GPIO_HIGH);
414 BACKCAR_LOG(BACKCAR_INFO, "MCU Test: current gpio number = %d, gpio value = %d\n", backcar_mcu_gpio_num, gpio_get_value(backcar_mcu_gpio_num));
415 }
416 break;
417 case IOCTL_MCU_BC_START_STOP:
418 if (!gpio_is_valid(backcar_mcu_gpio_num)) {
419 BACKCAR_LOG(BACKCAR_ERR, "get backcar mcu notify gpio number bc_failed\n");
420 } else {
421 gpio_direction_output(backcar_mcu_gpio_num, BACKCAR_NOTIFY_MCU_GPIO_LOW);
422 gpio_set_value_cansleep(backcar_mcu_gpio_num, BACKCAR_NOTIFY_MCU_GPIO_LOW);
423 BACKCAR_LOG(BACKCAR_INFO, "MCU Test: current gpio number = %d, gpio value = %d\n", backcar_mcu_gpio_num, gpio_get_value(backcar_mcu_gpio_num));
424 }
425 break;
426 case IOCTL_GET_RVC_DATA_FROM_ARM2:
427 case IOCTL_SET_RVC_DATA_TO_ARM2:
428 #ifndef CONFIG_BACKCAR_NO_ARM2
429 {
430 struct rvc_data data;
431 int wait_time = 0;
432 mutex_lock(&g_ioctl_mutex);
433 memset(&data, 0, sizeof(struct rvc_data));
434 if (copy_from_user(&data, argp, sizeof(struct rvc_data ))) {
435 BACKCAR_LOG(BACKCAR_ERR, "copy_from_user error\n");
436 ret = -EFAULT;
437 mutex_unlock(&g_ioctl_mutex);
438 break;
439 }
440 if ((0 == strcmp(data.ipc_key, RVC_IPC_KEY_GET_DATA)) ||
441 (0 == strcmp(data.ipc_key, RVC_IPC_KEY_SET_DATA))) {
442 BACKCAR_LOG(BACKCAR_DEBUG, "ipc_key(%s), data_type(%d)\n", data.ipc_key, data.type);
443 } else {
444 BACKCAR_LOG(BACKCAR_ERR, "ipc_key(%s) is invalid\n", data.ipc_key);
445 ret = -EFAULT;
446 mutex_unlock(&g_ioctl_mutex);
447 break;
448 }
449 memset(&g_responsed_rvc_data, 0, sizeof(struct rvc_data));
450 ret = ipc_send_msg((const char *)&data);
451 if (ret < 0) {
452 BACKCAR_LOG(BACKCAR_ERR, "IPC Request Send failed\n");
453 ret = -EFAULT;
454 mutex_unlock(&g_ioctl_mutex);
455 break;
456 }
457 // wait arm2 response
458 msleep(50);
459 while (0 != strcmp(g_responsed_rvc_data.ipc_key, RVC_IPC_KEY_ARM2_RESPOND)
460 && (wait_time < 500)) {
461 msleep(20);
462 wait_time += 20;
463 }
464 if (500 == wait_time) {
465 BACKCAR_LOG(BACKCAR_ERR, "wait arm2 response time out\n");
466 ret = -EFAULT;
467 mutex_unlock(&g_ioctl_mutex);
468 break;
469 }
470
471 BACKCAR_LOG(BACKCAR_DEBUG, "get rvc data success:ipc_key:%s, type:%d, data[%d, %d, %d, %d]\n",
472 g_responsed_rvc_data.ipc_key, g_responsed_rvc_data.type,
473 g_responsed_rvc_data.data[0], g_responsed_rvc_data.data[1],
474 g_responsed_rvc_data.data[2], g_responsed_rvc_data.data[3]);
475 if (g_responsed_rvc_data.type != data.type) {
476 BACKCAR_LOG(BACKCAR_ERR, "data type is not match. request(%d), receive(%d)\n",
477 data.type, g_responsed_rvc_data.type);
478 ret = -EFAULT;
479 mutex_unlock(&g_ioctl_mutex);
480 break;
481 }
482
483 if (copy_to_user(argp, &g_responsed_rvc_data, sizeof(struct rvc_data))) {
484 BACKCAR_LOG(BACKCAR_ERR, "copy_to_user error\n");
485 ret = -EFAULT;
486 mutex_unlock(&g_ioctl_mutex);
487 break;
488 }
489 mutex_unlock(&g_ioctl_mutex);
490 }
491 #endif
492 break;
493 default:
494 BACKCAR_LOG(BACKCAR_WARNING, "this ioctl(%d) is not supported", cmd);
495 ret = -1;
496 break;
497 }
498
499 return ret;
500 }
vendor/autochips/proprietary/hardware/backcar/backcar/src/BackcarImpl.cpp
bool BackcarImpl::waitArm2Exit()
309 {
310 BACKCAR_LOGI("enter");
311 unsigned int status = 0;
312 int ret = ::ioctl(mBackcarFd, IOCTL_FSC_NOTIFY_APP_READY, &status);
313 if (ret < 0) {
314 BACKCAR_LOGE("execute IOCTL_FSC_NOTIFY_APP_READY failed, and error message is %s",strerror(errno));
315 return false;
316 }
317 BACKCAR_LOGI("leave arm2 status is %d", status);
318
319 return true;
320 }
RVC hal 层
/autochips/proprietary/hardware/backcar/backcar/src/BackcarImpl.cpp
define BACKCAR_DRIVER_NAME "/dev/backcardrv"
54 BackcarImpl::BackcarImpl():
55 mBackcarFd(-1),
56 mArm2Status(ARM2_RVC_STATUS_RUNNING),
57 mBackcarEnable(0),
58 mProcessThread(nullptr),
59 mRvcDataThread(nullptr)
60 {
61 BACKCAR_LOGI("enter");
62 Mutex::Autolock _l(mLock);
//open backcardrv
63 mBackcarFd = ::open(BACKCAR_DRIVER_NAME, O_RDWR | O_NONBLOCK);
64 if (mBackcarFd < 0) {
65 BACKCAR_LOGE("open %s fail. %s", BACKCAR_DRIVER_NAME, strerror(errno));
66 return;
67 } else {
68 BACKCAR_LOGI("open success %d ", mBackcarFd);
69 }
70 //获取RVC的metazone的配置信息
71 mRvcSolution = getRVCSolutionType();
72 switch (mRvcSolution) {
73 case RVC_SOLUTION_ARM2_WITH_ARM1:
74 mProcessThread = new FunctionThread(std::bind(&BackcarImpl::mainThreadLoop, this));
75 mProcessThread->run("mainThreadLoop");
76 BACKCAR_LOGI("rvc solution is arm1 with arm2 rvc. run mainThreadLoop");
77 break;
78 case RVC_SOLUTION_AVM:
79 buttonInit();
80 mArm2Status = ARM2_RVC_STATUS_EXIT;
81 mProcessThread = new FunctionThread(std::bind(&BackcarImpl::mainThreadLoop, this));
82 mProcessThread->run("mainThreadLoop");
83 BACKCAR_LOGI("rvc solution is avm. run mainThreadLoop");
84 break;
85 case RVC_SOLUTION_ARM2_ONLY:
86 mRvcDataThread = new FunctionThread(std::bind(&BackcarImpl::rvcDataThreadLoop, this));
87 mRvcDataThread->run("rvcDataThreadLoop");
88 BACKCAR_LOGI("rvc solution is arm2 rvc only. run rvcDataThreadLoop");
89 break;
90 default:
91 break;
92 }
93 BACKCAR_LOGI("leave");
94 }
通过metazone 获取METAZONE_BACKCAR_VDO_SOURCE的值
734 int BackcarImpl::getRVCSolutionType()
735 {
736 unsigned int metazoneValue = 0;
737 int rvcSolution = -1;
738 if (MZ_SUCCESS == ::MetaZone_Init()) {
739 if (MZ_SUCCESS == ::MetaZone_Read(METAZONE_BACKCAR_VDO_SOURCE, &metazoneValue)) {
740 auto source = (unsigned char *)(&metazoneValue);
741 rvcSolution = source[METAZONE_RVC_SOLUTION_BYTE_INDEX];
742 } else {
743 BACKCAR_LOGW("MetaZone_Read(METAZONE_SOURCE_MODE) fail.");
744 }
745 ::MetaZone_Deinit();
746 } else {
747 BACKCAR_LOGE("metazone init failed\n");
748 }
749
750 BACKCAR_LOGI("get rvc solution type(%d) success", rvcSolution);
751 return rvcSolution;
752 }
753
通过backcardrv文件节点获取msg
#define SELECT_TIMEOUT 5000 //ms
191 bool BackcarImpl::rvcDataThreadLoop()
192 {
193 int ret = 0;
194 RVCData halData;
195 struct rvc_data drvData;
196 struct timeval tv;
197 fd_set rd_set;
198
199 do {
200 memset(&halData, 0, sizeof(RVCData));
201 memset(&drvData, 0, sizeof(struct rvc_data));
202 memset(&tv, 0, sizeof(tv));
203 tv.tv_sec = SELECT_TIMEOUT / 1000;
204 tv.tv_usec = (SELECT_TIMEOUT % 1000) * 1000;
205 FD_ZERO(&rd_set);
206 FD_SET(mBackcarFd, &rd_set);
207 if (!FD_ISSET(mBackcarFd, &rd_set)) {
208 BACKCAR_LOGE("FD_ISSET fail. error %s", strerror(errno));
209 break;
210 }
211 ret = select(mBackcarFd + 1, &rd_set, nullptr, nullptr, &tv);
212 if (ret < 0) {
213 BACKCAR_LOGE("select fail. error %s", strerror(errno));
214 } else if (ret == 0) {
215 BACKCAR_LOGD("select timeout. ");
216 } else {
217 read(mBackcarFd, (char *)&drvData, sizeof(struct rvc_data));
218 if (0 == strcmp(drvData.ipc_key, RVC_IPC_KEY_ARM2_NOTIFY)) {
219 halData.type = (RVCDataType)drvData.type;
220 halData.data[0] = drvData.data[0];
221 halData.data[1] = drvData.data[1];
222 halData.data[2] = drvData.data[2];
223 halData.data[3] = drvData.data[3];
224 BACKCAR_LOGI("type: %d, data: [%d, %d, %d, %d]", drvData.type, drvData.data[0], drvData.data[1], drvData.data[2], drvData.data[3]);
225 rvcDataChangeNotify(halData);
226 if (RVC_DATA_RVC_STATUS == drvData.type) {
227 mBackcarEnable = drvData.data[0];
228 }
229 }
230 }
231 usleep(1000000 / 100);
232 } while (0);
233
234 return true;
235 }
arm 2 上的rtos 获取倒车的gpio的信息通过backcar驱动解析后将event事件挂在notify_event_list
#ifndef CONFIG_BACKCAR_NO_ARM2
202 static int backcar_ipc_receive_thread(void *data)203 {
204 int ret = 0;
205 char arm2_msg[ipcMSG_LENGTH] = {0,};
206 struct rvc_data received_rvc_data;
207 struct arm2_rvc_event *event = NULL;
208 BACKCAR_LOG(BACKCAR_INFO, "backcar_ipc_receive_thread start\n");
209
210 do {
211 if (!g_ipc_receive_chan) {
212 BACKCAR_LOG(BACKCAR_INFO, "ipc receive chan is null, request chan first.\n");
213 g_ipc_receive_chan = ipc_request_chan_detailed(CORE_VEHICLE, MSGRECV, g_ipc_arm2_rvc, g_ipc_arm1_ap);
214 if (!g_ipc_receive_chan) {
215 BACKCAR_LOG(BACKCAR_ERR, "ipc request receive chan fail\n");
216 continue;
217 }
218 }
219
220 memset(arm2_msg, 0, sizeof(arm2_msg));
221 ret = ipc_receivemsg(g_ipc_receive_chan, arm2_msg, ipcMSG_LENGTH);
222 if (ret < 0) {
223 BACKCAR_LOG(BACKCAR_ERR, "ipc receive fail %d\n", ret);
224 continue;
225 }
226
227 BACKCAR_LOG(BACKCAR_DEBUG, "ipc receive arm2_msg %s\n", arm2_msg);
228 if (!strncmp(cIpcMsgRcvArm2BCExit, arm2_msg, ipcMSG_LENGTH)) {
229 BACKCAR_LOG(BACKCAR_INFO, "backcar receive msg %s success \n", cIpcMsgRcvArm2BCExit);
230 if (NULL != g_ioctlwaitq) {
231 wake_up(g_ioctlwaitq);
232 } else {
233 BACKCAR_LOG(BACKCAR_WARNING, "g_ioctl waitq has been waked. but not by arm2 msg\n");
234 }
235 } else {
236 memset(&received_rvc_data, 0, sizeof(struct rvc_data));
237 memcpy(&received_rvc_data, arm2_msg, ipcMSG_LENGTH);
238 if (0 == strcmp(received_rvc_data.ipc_key, RVC_IPC_KEY_ARM2_RESPOND)) {
239 BACKCAR_LOG(BACKCAR_DEBUG, "RVC_IPC_KEY_ARM2_NOTIFY received. type = %d, data[0]= %d\n",
240 received_rvc_data.type, received_rvc_data.data[0]);
241 memset(&g_responsed_rvc_data, 0, sizeof(struct rvc_data));
242 memcpy(&g_responsed_rvc_data, arm2_msg, ipcMSG_LENGTH);
243 } else if (0 == strcmp(received_rvc_data.ipc_key, RVC_IPC_KEY_ARM2_NOTIFY)) {
//解析小核 arm2 RTOS的 ipc msg
244 BACKCAR_LOG(BACKCAR_INFO, "RVC_IPC_KEY_ARM2_NOTIFY received. type = %d, data[0]= %d\n",
245 received_rvc_data.type, received_rvc_data.data[0]);
246 event = kzalloc(sizeof(*event), GFP_KERNEL);
247 if (!event) {
248 BACKCAR_LOG(BACKCAR_ERR, "kzalloc failed \n");
249 break;
250 }
//将arm2 msg 填充event data
251 memset(&(event->data), 0, sizeof(struct rvc_data));
252 memcpy(&(event->data), arm2_msg, ipcMSG_LENGTH);
253 mutex_lock(&g_event_manager.event_mutex);
//将event list 挂到notify_event_list
254 list_add_tail(&event->list, &g_event_manager.notify_event_list);
255 mutex_unlock(&g_event_manager.event_mutex);
256 wake_up(&g_event_manager.event_queue_wait);
257 } else {
258 BACKCAR_LOG(BACKCAR_INFO, "ipc not receive request msg \n");
259 break;
260 }
261 }
262 msleep(1);
263 } while (!kthread_should_stop());
264
265 BACKCAR_LOG(BACKCAR_INFO, "backcar_ipc_receive_thread leave \n");
266 return 0;
267 }
268 #endif
arm ap 侧使用驱动read的接口获取backcardrv arm2 的msg
static ssize_t backcar_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
534 {
535 int ret = 0;
536 struct arm2_rvc_event *event = NULL;
537 if (!access_ok(VERIFY_WRITE, buf, count))
538 return -EFAULT;
539
540 mutex_lock(&g_event_manager.event_mutex);
541 if (!list_empty(&g_event_manager.notify_event_list)) {
542 event = list_first_entry(&g_event_manager.notify_event_list, struct arm2_rvc_event, list);
543 if (!event) {
544 BACKCAR_LOG(BACKCAR_ERR, "event is null.\n");
545 mutex_unlock(&g_event_manager.event_mutex);
546 return -EFAULT;
547 }
548 //获取rvc event data
549 BACKCAR_LOG(BACKCAR_INFO, "event read: type(%d) ", event->data.type);
550 if (copy_to_user(buf, &event->data, sizeof(struct rvc_data))) {
551 BACKCAR_LOG(BACKCAR_ERR, "copy_to_user error\n");
552 ret = -EFAULT;
553 }
554 list_del(&event->list);
555 kfree(event);
556 }
557 mutex_unlock(&g_event_manager.event_mutex);
558
559 return ret;
560 }
hal层rvcDataChangeNotify将回调java注册callback函数
258 void BackcarImpl::rvcDataChangeNotify(RVCData rvcData)
259 {
260 BACKCAR_LOGI("enter. type: %d, data: [%d, %d, %d, %d]",
261 rvcData.type, rvcData.data[0], rvcData.data[1], rvcData.data[2], rvcData.data[3]);
262 std::map<const sp<IBackcarCallback>,std::vector<EventType>>::iterator cb_iter;
263
264 for (cb_iter = mCallbackMap.begin(); cb_iter != mCallbackMap.end(); cb_iter++) {
265 const sp<IBackcarCallback>& callback = cb_iter->first;
266 std::vector<EventType>& evts = cb_iter->second;
267 for (std::vector<EventType>::iterator iter = evts.begin(); iter != evts.end(); iter++) {
268 if (*iter == EventType::RVC_DATA_CHANGE) {
//回调java层callback的rvcDataChangeNotify
269 auto callbackRet = callback->rvcDataChangeNotify(rvcData);
270 if (!callbackRet.isOk()) {
271 BACKCAR_LOGE("Callback rvcDataChangeNotify error");
272 }
273 break;
274 }
275 }
276 }
277 BACKCAR_LOGI("leave");
278 }
java层backcar service 注册hal 回调函数
vendor/autochips/proprietary/frameworks/base/backcar/java/com/autochips/backcar/BackCar.java
/**
191 * Construct for RVC
192 * @param looper handler using this looper
193 */
194 public BackCar(Looper looper) {
195 Log.d(TAG, "RVC() enter");
196
197 if (null == looper) {
198 looper = Looper.myLooper();
199 if (null == looper) {
200 looper = Looper.getMainLooper();
201 }
202 }
203
204 mHandler = new EventHandler(looper);
205 mCallback = new BackcarCallback();
206 mDeathRecipient = new DeathRecipient();
207
208 try {
209 mService = IBackcar.getService();
210 mService.linkToDeath(mDeathRecipient, 0);
211 } catch (RemoteException e) {
212 Log.e(TAG, "getService() failure");
213 e.printStackTrace();
214 mService = null;
215 }
216
217 Log.d(TAG, "RVC() leave");
218 }
/saic_cn202sr/vendor/autochips/proprietary/frameworks/base/backcar/java/com/autochips/backcar/BackCar.java
/**
221 * Set event listener
222 * @param listener listener object, can be null
223 * @param evts all event type for listening
224 * @return true is success, false is fail.
225 */
226 public boolean setListener(Listener listener, ArrayList<Integer> evts) {
227 Log.d(TAG, "setListener() enter");
228
229 if (null == mService) {
230 Log.e(TAG, "mService = null");
231 return false;
232 }
233
234 mListener = listener;
235 mEvts = evts;
236 int status = Status.FAILURE;
237
238 try {
239 if ((null != mListener) && (null != evts)){
240 mService.registerEventCallback_V2(mCallback, evts, new IBackcar.registerEventCallback_V2Callback() {
241 @Override
242 public void onValues(int Status, long callbackId) {
243 mCallbackId[0] = callbackId;
244 }
245 });
246 } else {
247 status = mService.unregisterEventCallback_V2(mCallbackId[0]);
248 }
249 status = Status.SUCCESS;
250 } catch (RemoteException e) {
251 Log.e(TAG, "call registerEventCallback()/unregisterEventCallback() failure");
252 e.printStackTrace();
253 status = Status.FAILURE;
254 }
255
256 Log.d(TAG, "setListener() leave");
257 return (Status.SUCCESS == status);
258 }
259
445 Return<void> BackcarImpl::registerEventCallback_V2(const sp<IBackcarCallback>& callback, const hidl_vec<EventType>& evts, registerEventCallback_V2_cb _hidl_cb) {
446 Mutex::Autolock _l(mLock);
447 BACKCAR_LOGI("enter callback = %p, evts.size() = %d", callback.get(), (int)evts.size());
448
449 if (mBackcarFd < 0) {
450 _hidl_cb(Status::FAILURE, 0);
451 return Void();
452 }
453
454 if (nullptr == callback.get() || 0 == evts.size()) {
455 BACKCAR_LOGE("Invalid param callback = %p, evts.size() = %d", callback.get(), (int)evts.size());
456 _hidl_cb(Status::FAILURE, 0);
457 return Void();
458 }
459
460 mCallbackMap[callback] = evts;
461
462 callback->linkToDeath(this, 888);
463
464 afterRegisterRun(callback);
465
466 BACKCAR_LOGI("leave");
467 _hidl_cb(Status::SUCCESS, (uint64_t)callback.get());
468 return Void();
469 }
344 void BackcarImpl::afterRegisterRun(const sp<IBackcarCallback>& callback)
345 {
346 BACKCAR_LOGI("enter");
347 if (ARM2_RVC_STATUS_EXIT == mArm2Status) {
348 std::vector<EventType>& evts = mCallbackMap[callback];
349 for (std::vector<EventType>::iterator iter = evts.begin(); iter != evts.end(); iter++) {
350 if (*iter == EventType::ARM2EXIT) {
351 auto callbackRet = callback->eventNotify(EventType::ARM2EXIT, 0, 0, 0);
352 if (!callbackRet.isOk()) {
353 BACKCAR_LOGE("Callback eventNotify error");
354 }
355 break;
356 }
357 }
358 }
359
360 switch (mRvcSolution) {
361 case RVC_SOLUTION_ARM2_WITH_ARM1:
362 case RVC_SOLUTION_AVM:
363 if (mBackcarEnable) {
364 BACKCAR_LOGI("rvc button already on");
365 std::vector<EventType>& evts = mCallbackMap[callback];
366 for (std::vector<EventType>::iterator iter = evts.begin(); iter != evts.end(); iter++) {
367 if (*iter == EventType::BC) {
368 auto callbackRet = callback->eventNotify(EventType::BC, 1, 0, 0);
369 if (!callbackRet.isOk()) {
370 BACKCAR_LOGE("Callback eventNotify error");
371 }
372 break;
373 }
374 }
375 }
376 break;
377 case RVC_SOLUTION_ARM2_ONLY:
378 {
379 RVCData halData;
380 if (__getRVCDataFromArm2(RVCDataType::RVC_DATA_RVC_STATUS, halData)) {
381 if (1 == halData.data[0]) {
382 rvcDataChangeNotify(halData);
383 }
384 }
385 }
386 break;
387 default:
388 break;
389 }
390
391 BACKCAR_LOGI("leave");
392 }
backcar service callbac函数 sendmsg EVENT_TYPE_RVC_DATA_CHANGE给app
private class BackcarCallback extends IBackcarCallback.Stub {
169 public void eventNotify(int evt, int param1, int param2, int param3) {
170 Log.d(TAG, "eventNotify() enter evt = " + evt + ", param1 = " + param1);
171 mHandler.sendMessage(Message.obtain(mHandler, evt, param1, param2));
172 Log.d(TAG, "eventNotify() leave");
173 }
174
175 public void rvcDataChangeNotify(vendor.autochips.hardware.backcar.V1_0.RVCData hidlRVCData) {
176 Log.d(TAG, "rvcDataChangeNotify() enter rvcDataType =" + hidlRVCData.type + ", data = [" + hidlRVCData.data[0]
177 + ", " + hidlRVCData.data[1] + ", " + hidlRVCData.data[2] + ", " + hidlRVCData.data[3] + "]" );
178 mHandler.sendMessage(Message.obtain(mHandler, EVENT_TYPE_RVC_DATA_CHANGE, hidlRVCData.type, hidlRVCData.data[0]));
179 Log.d(TAG, "rvcDataChangeNotify() leave");
180 }
181 }
触发app start RVC
/vendor/autochips/proprietary/packages/apps/AtcCamera/src/com/autochips/camera/CameraService.java
public class CameraService extends Service{
38 private static final String TAG = "CameraService";
39
40 private CameraServiceImpl mCameraServiceImpl;
41
42 private static final String ACTION_QB_OFF = "autochips.intent.action.QB_POWEROFF";
43 private static final String ACTION_QB_ON = "autochips.intent.action.QB_POWERON";
44 private static final String ACTION_PREQB_ON =
"autochips.intent.action.PREQB_POWERON";
45 private static final String ACTION_PREQB_OFF =
"autochips.intent.action.PREQB_POWEROFF";
46 private static final String NOTIFICATION_CHANNEL_ID_SERVICE =
"com.autochips.camera.CameraService";
47 private static final int NOTIFICATION_ID = 105;
48 private static final int BC_TYPE_ADDR =
MetazoneIndex.DwordIndex.METAZONE_BACKCAR_VDO_SOURCE;
49 private static final int ADDR_RVC_CAMERA_ID =
MetazoneIndex.DwordIndex.METAZONE_RVC_AVM_CAMERA_ID;
50 private static final int TYPE_RVC = 0;
51
52 private BackCar mBackcar;
53 private String mCurrentBackcarCameraId;
54 private boolean mIsArm2Exited;
55 private boolean mIsQBOn = true;
56 private boolean mNeedStartBackcarAfterQBOn;
57 private boolean mHasShownTouchInputFilterView;
58 private boolean mhasEnableBackcarAudio = false;
59 private boolean mIsBackcarOn = false;
60 private boolean mIsRVCMode = false;
61 private int mCurrentUserId = UserHandle.myUserId();
62 private final Thread.UncaughtExceptionHandler mDefaultUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
63 private Handler mHandler = new Handler();
64
65 private BackCar.Listener mListenerSignal = new BackCar.Listener() {
66 public void onEvent(int event, int param1, int param2) {
67 LogUtil.d(TAG,"onSignal - event:" + event);
68 if (BackCar.EVENT_TYPE_BC == event) {
69 if (param1 != 0) {
70 LogUtil.i(TAG,"onSignal():BACKCAR_START");
71 if (!mhasEnableBackcarAudio) {
72 mCameraServiceImpl.enableBackcarAudio();
73 mhasEnableBackcarAudio = true;
74 }
75
76 if (!mIsArm2Exited && !mHasShownTouchInputFilterView) {
77 mCameraServiceImpl.showTouchInputFilterView();
78 mHasShownTouchInputFilterView = true;
79 return;
80 }
81 if (!mIsQBOn) {
82 mNeedStartBackcarAfterQBOn = true;
83 LogUtil.d(TAG, "start backcar later after qb on");
84 return;
85 }
86 if (mCurrentUserId == UserHandle.myUserId() && getBackcarCameraId()) {
87 mCameraServiceImpl.startBackcar(mCurrentBackcarCameraId);
88 }
89 mIsBackcarOn = true;
90 }else {
91 LogUtil.i(TAG,"onSignal():BACKCAR_STOP");
92 if (mhasEnableBackcarAudio) {
93 mCameraServiceImpl.disableBackcarAudio();
94 mhasEnableBackcarAudio = false;
95 }
96
97 if (mNeedStartBackcarAfterQBOn) {
98 mNeedStartBackcarAfterQBOn = false;
99 LogUtil.d(TAG, "cancel stop backcar");
100 return;
101 }
102 if (mCurrentBackcarCameraId != null) {
103 mCameraServiceImpl.stopBackcar(mCurrentBackcarCameraId);
104 }
105 mIsBackcarOn = false;
106 }
107 }else if (BackCar.EVENT_TYPE_ARM2EXIT == event) {
108 mIsArm2Exited = true;
109 if (mHasShownTouchInputFilterView) {
110 mCameraServiceImpl.cancelTouchInputFilterView();
111 mHasShownTouchInputFilterView = false;
112 }
113 mCameraServiceImpl.notifyCameraResourceAvailable();
114
115 if (mhasEnableBackcarAudio) {
116 mCameraServiceImpl.disableBackcarAudio();
117 mhasEnableBackcarAudio = false;
118 }
119 LogUtil.i(TAG, "exit arm2 backcar");
//cemera app 接收EVENT_TYPE_RVC_DATA_CHANGE
120 } else if (BackCar.EVENT_TYPE_RVC_DATA_CHANGE == event) {
121 LogUtil.i(TAG,"param2 =" + param2);
122 if (param2 != 0 && mIsRVCMode) {
123 LogUtil.i(TAG,"handle ARM2 start backcar");
124 mCameraServiceImpl.handleARM2RVCStart(mBackcar);
125 } else {
126 LogUtil.i(TAG,"handle ARM2 stop backcar");
127 mCameraServiceImpl.handleARM2RVCStop();
128 }
129 }else {
130 LogUtil.i(TAG, "do nothing");
131 }
132 }
133 };
542

被折叠的 条评论
为什么被折叠?



