1 /*
2 *
3 * SPDX-License-Identifier: GPL-2.0
4 *
5 * Copyright (C) 2011-2018 ARM or its affiliates
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 *
18 */
19 #include <linux/vmalloc.h>
20 #include "acamera_types.h"
21 #include "acamera_logger.h"
22 #include "acamera_math.h"
23 #include "acamera_firmware_config.h"
24 #include "acamera_control_config.h"
25
26 #if ISP_HAS_CONNECTION_BUFFER
27 #define ALIGNMENT_MASK 3
28 #include "acamera_buffer_manager.h"
29 #include "acamera_cmd_queues_config.h"
30 #define CMD_QUEUES_HALF_INX ( ACAMERA_CMD_QUEUES_SIZE >> 3 )
31 #elif ISP_HAS_CONNECTION_UART
32 #define ALIGNMENT_MASK 0
33 #include "acamera_uart.h"
34 #elif ISP_HAS_CONNECTION_SOCKET
35 #define ALIGNMENT_MASK 0
36 #include "acamera_socket.h"
37 #include "acamera_socket_strategy.h"
38 #elif ISP_HAS_CONNECTION_CHARDEV
39 #define ALIGNMENT_MASK 0
40 #include "acamera_chardev.h"
41 #endif
42 #include "system_hw_io.h"
43 #include "system_sw_io.h"
44 #include "acamera_command_api.h"
45 #include "application_command_api.h"
46 #include "acamera_isp_core_nomem_settings.h"
47 #include "acamera_fw.h"
48
49
50
51
52 #if ISP_HAS_CONNECTION_BUFFER
53 static acamera_buffer_manager_t buff_mgr;
54 #elif ISP_HAS_CONNECTION_UART
55 static acamera_uart_t uart;
56 #endif
57
58
59 #if ISP_HAS_CONNECTION_SOCKET
60 extern struct acamera_socket_strategy acamera_socket_init_strategy();
61 #endif
62
63 //#define TRACE
64
65 #ifdef TRACE
66 /* This printf library call put there intentionally to debug the connection
67 * on the limited subset of the supported architectures
68 * bypassing project loglevel settings.
69 */
70 #define ACAMERA_CONNECTION_TRACE printf
71 #else
72 #define ACAMERA_CONNECTION_TRACE( ... )
73 #endif /* TRACE */
74
75 #define HEADER_SIZE 12
76
77 enum {
78 API_RESET = 0,
79 API_READ,
80 API_WRITE
81 };
82
83 enum TransactionType {
84 TransactionTypeRegRead = 1,
85 TransactionTypeRegWrite,
86 TransactionTypeRegMaskWrite,
87 TransactionTypeLUTRead,
88 TransactionTypeLUTWrite,
89
90 TransactionTypeAPIRead = 10,
91 TransactionTypeAPIWrite,
92
93 TransactionTypeBUFRead = 20,
94 TransactionTypeBUFWrite
95 };
96
97 typedef int ( *data_read_f )( void *p_ctrl, uint8_t *data, int size );
98 typedef int ( *data_write_f )( void *p_ctrl, const uint8_t *data, int size );
99
100 enum {
101 STATE_IDLE,
102 STATE_RX_DATA,
103 STATE_SKIP_DATA,
104 STATE_TX_PACKET
105 };
106
107 typedef struct {
108 void *param;
109 data_read_f data_read;
110 data_write_f data_write;
111 int state;
112 uint8_t *buffer;
113 uint32_t rx_buffer_inx;
114 uint32_t rx_buffer_size;
115 uint32_t tx_buffer_inx;
116 uint32_t tx_buffer_size;
117 } connection_t;
118
119 #if ISP_HAS_STREAM_CONNECTION
120 static connection_t con;
121
reset_connection(void)122 static void reset_connection( void )
123 {
124 con.state = STATE_IDLE;
125 con.rx_buffer_inx = 0;
126 con.tx_buffer_inx = 0;
127 ACAMERA_CONNECTION_TRACE( "reset connection" );
128 }
129
130 extern void *acamera_get_api_ctx_ptr( void );
131
132 #if ISP_HAS_CONNECTION_SOCKET
acamera_socket_do_init(connection_t * con)133 static int acamera_socket_do_init( connection_t *con )
134 {
135 struct acamera_socket_f *f;
136 struct acamera_socket *socket;
137 int rc;
138
139
140 /* f = acamera_socket_f_impl();
141 if ( !f ) {
142 LOG( LOG_ERR, "Please double check your platform provide TCP/IP socket routines" );
143 return -1;
144 }
145 */
146 socket = acamera_socket_instance();
147
148
149 rc = acamera_socket_init( socket, acamera_socket_init_strategy() );
150 if ( rc )
151 return rc;
152
153 con->param = socket;
154 con->data_read = (data_read_f)acamera_socket_read;
155 con->data_write = (data_write_f)acamera_socket_write;
156
157 return 0;
158 }
159 #endif
160 #endif //ISP_HAS_STREAM_CONNECTION
161
acamera_connection_init(void)162 void acamera_connection_init( void )
163 {
164 #if ISP_HAS_STREAM_CONNECTION
165 reset_connection();
166 #if ISP_HAS_CONNECTION_BUFFER
167 acamera_buffer_manager_init( &buff_mgr, ACAMERA_CMD_QUEUES_BASE_ADDR, ACAMERA_CMD_QUEUES_SIZE );
168 con.param = &buff_mgr;
169 con.data_read = (data_read_f)acamera_buffer_manager_read;
170 con.data_write = (data_write_f)acamera_buffer_manager_write;
171 acamera_cmd_queues_array_data_write( 0, 2, API_RESET << 24 );
172 acamera_cmd_queues_array_data_write( 0, CMD_QUEUES_HALF_INX, API_RESET );
173 ACAMERA_CONNECTION_TRACE( "Connection is buffer" );
174 #elif ISP_HAS_CONNECTION_UART
175 con.param = &uart;
176 acamera_uart_init( con.param );
177 con.data_read = (data_read_f)acamera_uart_read;
178 con.data_write = (data_write_f)acamera_uart_write;
179 ACAMERA_CONNECTION_TRACE( "Connection is UART" );
180 #elif ISP_HAS_CONNECTION_SOCKET
181 if ( !acamera_socket_do_init( &con ) ) {
182 ACAMERA_CONNECTION_TRACE( "Connection is TCP/IP socket" );
183 } else {
184 LOG( LOG_ERR, "Unable to initialise TCP/IP socket" );
185 }
186 #elif ISP_HAS_CONNECTION_CHARDEV
187 if ( !acamera_chardev_init() ) {
188 ACAMERA_CONNECTION_TRACE( "Connection is character device" );
189 con.data_read = (data_read_f)acamera_chardev_read;
190 con.data_write = (data_write_f)acamera_chardev_write;
191 con.buffer = vmalloc(CONNECTION_BUFFER_SIZE);
192 } else {
193 LOG( LOG_ERR, "Unable to register character device" );
194 }
195 #endif
196 if ( !con.data_read || !con.data_write ) {
197 LOG( LOG_WARNING, "Connection method is not defined" );
198 }
199 #endif //ISP_HAS_STREAM_CONNECTION
200 }
201
acamera_connection_destroy(void)202 void acamera_connection_destroy( void )
203 {
204 #if ISP_HAS_STREAM_CONNECTION
205 #if ISP_HAS_CONNECTION_CHARDEV
206 int rc = acamera_chardev_destroy();
207 if ( rc )
208 LOG( LOG_ERR, "Unable to destroy character device with error %d", rc );
209 #else
210 ACAMERA_CONNECTION_TRACE( LOG_WARNING, "Connection destroy method is not defined" );
211 #endif /* connection type */
212 con.param = NULL;
213 con.data_read = NULL;
214 con.data_write = NULL;
215 if(con.buffer)
216 vfree(con.buffer);
217 #endif /* ISP_HAS_STREAM_CONNECTION */
218 }
219
220
221 #if ISP_HAS_STREAM_CONNECTION
write_32(uint32_t addr,uint8_t value,uint8_t msk)222 static void write_32( uint32_t addr, uint8_t value, uint8_t msk )
223 {
224 acamera_context_ptr_t context_ptr = (acamera_context_ptr_t)acamera_get_api_ctx_ptr();
225 int shift = ( addr & 3 ) << 3;
226 uint32_t mask = msk << shift;
227 uint32_t addr_align = addr & ~3;
228
229 // Use SW registers for ping/pong memory, otherwise, use HW registers.
230 if ( ( addr < ISP_CONFIG_LUT_OFFSET ) ||
231 ( addr > ISP_CONFIG_PING_OFFSET + 2 * ISP_CONFIG_PING_SIZE ) ) {
232 uint32_t data = system_hw_read_32( addr_align );
233 data = ( data & ~mask ) | ( ( uint32_t )( value & msk ) << shift );
234 system_hw_write_32( addr_align, data );
235 } else {
236 // read from software context
237 uintptr_t sw_addr = context_ptr->settings.isp_base + addr_align;
238 uint32_t data = system_sw_read_32( sw_addr );
239 data = ( data & ~mask ) | ( ( uint32_t )( value & msk ) << shift );
240 system_sw_write_32( sw_addr, data );
241 }
242 }
243
read_32(uint32_t addr)244 static uint8_t read_32( uint32_t addr )
245 {
246 acamera_context_ptr_t context_ptr = (acamera_context_ptr_t)acamera_get_api_ctx_ptr();
247
248 uint8_t result = 0;
249 int shift = ( addr & 3 ) << 3;
250 uint32_t addr_align = addr & ~3;
251 uint32_t data = 0;
252
253 // Use SW registers for ping/pong memory, otherwise, use HW registers.
254 if ( ( addr < ISP_CONFIG_LUT_OFFSET ) ||
255 ( addr > ISP_CONFIG_PING_OFFSET + 2 * ISP_CONFIG_PING_SIZE ) ) {
256 data = system_hw_read_32( addr_align );
257 } else {
258 uintptr_t sw_addr = context_ptr->settings.isp_base + addr_align;
259 data = system_sw_read_32( sw_addr );
260 }
261
262 result = ( data >> shift ) & 0xFF;
263 return result;
264 }
265
process_request(void)266 static void process_request( void )
267 {
268 uint32_t *rx_buf = (uint32_t *)&con.buffer[8];
269 uint32_t *tx_buf = (uint32_t *)con.buffer;
270 uint16_t type = ( *rx_buf++ ) & 0xFFFF;
271 ACAMERA_CONNECTION_TRACE( "Processing packet size %ld, id %ld, type %d\n", con.rx_buffer_size, tx_buf[1], type );
272 switch ( type ) {
273 case TransactionTypeRegRead:
274 if ( con.rx_buffer_size == HEADER_SIZE + 8 ) {
275 uint32_t addr = *rx_buf++;
276 uint32_t size = *rx_buf++;
277 if ( size <= CONNECTION_BUFFER_SIZE - HEADER_SIZE - 4 ) {
278 con.tx_buffer_size = HEADER_SIZE + 4 + size;
279 tx_buf[3] = SUCCESS;
280 uint8_t *b = &con.buffer[HEADER_SIZE + 4];
281
282 while ( size-- ) {
283 *b++ = read_32( addr++ ); //system_sw_read_8(addr++);
284 }
285 } else {
286 con.tx_buffer_size = HEADER_SIZE + 4;
287 tx_buf[3] = FAIL;
288 LOG( LOG_WARNING, "Wrong request size %u for type %u", (unsigned int)size, (unsigned int)type );
289 }
290 } else {
291 con.tx_buffer_size = HEADER_SIZE;
292 LOG( LOG_WARNING, "Wrong packet size %u for type %u", (unsigned int)con.rx_buffer_size, (unsigned int)type );
293 }
294 break;
295 case TransactionTypeRegWrite:
296 if ( con.rx_buffer_size >= HEADER_SIZE + 8 ) {
297 uint32_t addr = *rx_buf++;
298 uint32_t size = *rx_buf++;
299 con.tx_buffer_size = HEADER_SIZE + 4;
300 if ( size <= con.rx_buffer_size - HEADER_SIZE - 8 ) {
301 tx_buf[3] = SUCCESS;
302 uint8_t *b = &con.buffer[HEADER_SIZE + 8];
303 while ( size-- ) {
304 write_32( addr++, *b++, 0xFF );
305 }
306 } else {
307 tx_buf[3] = FAIL;
308 LOG( LOG_WARNING, "Wrong request size %u for type %u", (unsigned int)size, (unsigned int)type );
309 }
310 } else {
311 con.tx_buffer_size = HEADER_SIZE;
312 LOG( LOG_WARNING, "Wrong packet size %u for type %u", (unsigned int)con.rx_buffer_size, (unsigned int)type );
313 }
314 break;
315 case TransactionTypeRegMaskWrite:
316 if ( con.rx_buffer_size >= HEADER_SIZE + 8 ) {
317 uint32_t addr = *rx_buf++;
318 uint32_t size = *rx_buf++;
319 con.tx_buffer_size = HEADER_SIZE + 4;
320 if ( 2 * size <= con.rx_buffer_size - HEADER_SIZE - 8 ) {
321 tx_buf[3] = SUCCESS;
322 uint8_t *b = &con.buffer[HEADER_SIZE + 8];
323 uint8_t *m = &con.buffer[HEADER_SIZE + 8 + size];
324 while ( size-- ) {
325 uint8_t mask = *m++;
326 uint8_t val = *b++;
327 write_32( addr, val, mask );
328 addr++;
329 }
330 } else {
331 tx_buf[3] = FAIL;
332 LOG( LOG_WARNING, "Wrong request size %u for type %u", (unsigned int)size, (unsigned int)type );
333 }
334 } else {
335 con.tx_buffer_size = HEADER_SIZE;
336 LOG( LOG_WARNING, "Wrong packet size %u for type %u", (unsigned int)con.rx_buffer_size, (unsigned int)type );
337 }
338 break;
339 case TransactionTypeLUTRead:
340 if ( con.rx_buffer_size == HEADER_SIZE + 8 ) {
341 uint32_t addr = *rx_buf++;
342 uint32_t size = *rx_buf++;
343 if ( size <= CONNECTION_BUFFER_SIZE - HEADER_SIZE - 4 && !( size & 3 ) && !( addr & 3 ) ) {
344 con.tx_buffer_size = HEADER_SIZE + 4 + size;
345 tx_buf[3] = SUCCESS;
346 uint32_t *b = &tx_buf[4];
347 uint32_t i;
348 for ( i = 0; i < size; i += 4 ) {
349 system_hw_write_32( addr, i >> 2 );
350 *b++ = system_hw_read_32( addr + 8 );
351 }
352 } else {
353 con.tx_buffer_size = HEADER_SIZE + 4;
354 tx_buf[3] = FAIL;
355 LOG( LOG_WARNING, "Wrong request size %u for type %u", (unsigned int)size, (unsigned int)type );
356 }
357 } else {
358 con.tx_buffer_size = HEADER_SIZE;
359 LOG( LOG_WARNING, "Wrong packet size %u for type %u", (unsigned int)con.rx_buffer_size, (unsigned int)type );
360 }
361 break;
362 case TransactionTypeLUTWrite:
363 if ( con.rx_buffer_size >= HEADER_SIZE + 8 ) {
364 uint32_t addr = *rx_buf++;
365 uint32_t size = *rx_buf++;
366 con.tx_buffer_size = HEADER_SIZE + 4;
367 if ( size <= con.rx_buffer_size - HEADER_SIZE - 8 && !( size & 3 ) && !( addr & 3 ) ) {
368 tx_buf[3] = SUCCESS;
369 uint32_t i;
370 for ( i = 0; i < size; i += 4 ) {
371 system_hw_write_32( addr, i >> 2 );
372 system_hw_write_32( addr + 4, *rx_buf++ );
373 }
374 } else {
375 tx_buf[3] = FAIL;
376 LOG( LOG_WARNING, "Wrong request size %u for type %u", (unsigned int)size, (unsigned int)type );
377 }
378 } else {
379 con.tx_buffer_size = HEADER_SIZE;
380 LOG( LOG_WARNING, "Wrong packet size %u for type %u", (unsigned int)con.rx_buffer_size, (unsigned int)type );
381 }
382 break;
383 case TransactionTypeAPIRead:
384 if ( con.rx_buffer_size == HEADER_SIZE + 8 ) {
385 uint8_t t = rx_buf[0] & 0xFF;
386 uint8_t c = ( rx_buf[0] >> 8 ) & 0xFF;
387 con.tx_buffer_size = HEADER_SIZE + 8;
388 tx_buf[3] = application_command( t, c, rx_buf[1], COMMAND_GET, &tx_buf[4] );
389 } else {
390 con.tx_buffer_size = HEADER_SIZE;
391 LOG( LOG_WARNING, "Wrong packet size %u for type %u", (unsigned int)con.rx_buffer_size, (unsigned int)type );
392 }
393 break;
394 case TransactionTypeAPIWrite:
395 if ( con.rx_buffer_size == HEADER_SIZE + 8 ) {
396 uint8_t t = rx_buf[0] & 0xFF;
397 uint8_t c = ( rx_buf[0] >> 8 ) & 0xFF;
398 con.tx_buffer_size = HEADER_SIZE + 8;
399 tx_buf[3] = application_command( t, c, rx_buf[1], COMMAND_SET, &tx_buf[4] );
400 } else {
401 con.tx_buffer_size = HEADER_SIZE;
402 LOG( LOG_WARNING, "Wrong packet size %u for type %u", (unsigned int)con.rx_buffer_size, (unsigned int)type );
403 }
404 break;
405 case TransactionTypeBUFRead:
406 if ( con.rx_buffer_size == HEADER_SIZE + 8 ) {
407 uint8_t id = rx_buf[0] & 0xFF;
408 uint8_t buf_class = ( rx_buf[0] >> 8 ) & 0xFF;
409 uint32_t size = rx_buf[1];
410 uint32_t value;
411 if ( size <= CONNECTION_BUFFER_SIZE - HEADER_SIZE - 4 ) {
412 switch ( buf_class ) {
413 case STATIC_CALIBRATIONS_ID:
414 case DYNAMIC_CALIBRATIONS_ID:
415 con.tx_buffer_size = HEADER_SIZE + 4 + size;
416 tx_buf[3] = application_api_calibration( buf_class, id, COMMAND_GET, &tx_buf[4], size, &value );
417 if ( tx_buf[3] != SUCCESS ) {
418 con.tx_buffer_size = HEADER_SIZE + 4;
419 }
420 break;
421
422 default:
423 con.tx_buffer_size = HEADER_SIZE + 4;
424 tx_buf[3] = FAIL;
425 LOG( LOG_WARNING, "Wrong buffer class %u", (unsigned int)buf_class );
426 }
427 } else {
428 con.tx_buffer_size = HEADER_SIZE + 4;
429 tx_buf[3] = FAIL;
430 LOG( LOG_WARNING, "Wrong request size %u for type %u", (unsigned int)size, (unsigned int)type );
431 }
432 } else {
433 con.tx_buffer_size = HEADER_SIZE;
434 LOG( LOG_WARNING, "Wrong packet size %u for type %u", (unsigned int)con.rx_buffer_size, (unsigned int)type );
435 }
436 break;
437 case TransactionTypeBUFWrite:
438 if ( con.rx_buffer_size >= HEADER_SIZE + 8 ) {
439 uint8_t id = rx_buf[0] & 0xFF;
440 uint8_t buf_class = ( rx_buf[0] >> 8 ) & 0xFF;
441 uint32_t size = rx_buf[1];
442 uint32_t value;
443 con.tx_buffer_size = HEADER_SIZE + 4;
444 if ( size <= con.rx_buffer_size - HEADER_SIZE - 8 ) {
445 switch ( buf_class ) {
446 case STATIC_CALIBRATIONS_ID:
447 case DYNAMIC_CALIBRATIONS_ID:
448 tx_buf[3] = application_api_calibration( buf_class, id, COMMAND_SET, &rx_buf[2], size, &value );
449 break;
450
451 default:
452 tx_buf[3] = FAIL;
453 LOG( LOG_WARNING, "Wrong buffer class %d", buf_class );
454 }
455 } else {
456 tx_buf[3] = FAIL;
457 LOG( LOG_WARNING, "Wrong request size %u for type %u", (unsigned int)size, (unsigned int)type );
458 }
459 } else {
460 con.tx_buffer_size = HEADER_SIZE;
461 LOG( LOG_WARNING, "Wrong packet size %u for type %u", (unsigned int)con.rx_buffer_size, (unsigned int)type );
462 }
463 break;
464 default:
465 con.tx_buffer_size = HEADER_SIZE;
466 LOG( LOG_WARNING, "Wrong packet type %d", type );
467 }
468 *tx_buf = con.tx_buffer_size;
469 con.tx_buffer_size = ( con.tx_buffer_size + ALIGNMENT_MASK ) & ~ALIGNMENT_MASK;
470 con.tx_buffer_inx = 0;
471 con.state = STATE_TX_PACKET;
472 }
473 #endif //ISP_HAS_STREAM_CONNECTION
474
475 #if ISP_HAS_CONNECTION_BUFFER
process_api_request(void)476 static void process_api_request( void )
477 {
478 uint8_t cmd_type, cmd;
479 uint32_t status;
480 uint32_t value;
481 uint32_t request = acamera_cmd_queues_array_data_read( 0, 2 );
482 switch ( request >> 24 ) {
483 case API_READ:
484 if ( ( acamera_cmd_queues_array_data_read( 0, CMD_QUEUES_HALF_INX ) & 0xFF ) == API_RESET ) {
485 acamera_cmd_queues_array_data_write( 0, CMD_QUEUES_HALF_INX + 1, acamera_cmd_queues_array_data_read( 0, 0 ) );
486 acamera_cmd_queues_array_data_write( 0, 2, API_RESET << 24 );
487 cmd_type = ( uint8_t )( request & 0xFF );
488 cmd = ( uint8_t )( ( request >> 8 ) & 0xFF );
489 value = acamera_cmd_queues_array_data_read( 0, 1 );
490 status = application_command( cmd_type, cmd, value, COMMAND_GET, &value );
491 acamera_cmd_queues_array_data_write( 0, CMD_QUEUES_HALF_INX + 2, value );
492 acamera_cmd_queues_array_data_write( 0, CMD_QUEUES_HALF_INX, ( status << 16 ) | API_READ );
493 ACAMERA_CONNECTION_TRACE( "Processed API read id %ld\n", acamera_cmd_queues_array_data_read( 0, CMD_QUEUES_HALF_INX + 1 ) );
494 }
495 break;
496 case API_WRITE:
497 if ( ( acamera_cmd_queues_array_data_read( 0, CMD_QUEUES_HALF_INX ) & 0xFF ) == API_RESET ) {
498 acamera_cmd_queues_array_data_write( 0, CMD_QUEUES_HALF_INX + 1, acamera_cmd_queues_array_data_read( 0, 0 ) );
499 value = acamera_cmd_queues_array_data_read( 0, 1 );
500 acamera_cmd_queues_array_data_write( 0, 2, API_RESET << 24 );
501 cmd_type = ( uint8_t )( request & 0xFF );
502 cmd = ( uint8_t )( ( request >> 8 ) & 0xFF );
503 status = application_command( cmd_type, cmd, value, COMMAND_SET, &value );
504 acamera_cmd_queues_array_data_write( 0, CMD_QUEUES_HALF_INX + 2, value );
505 acamera_cmd_queues_array_data_write( 0, CMD_QUEUES_HALF_INX, ( status << 16 ) | API_WRITE );
506 ACAMERA_CONNECTION_TRACE( "Processed API write id %ld\n", acamera_cmd_queues_array_data_read( 0, CMD_QUEUES_HALF_INX + 1 ) );
507 }
508 break;
509 case API_RESET:
510 break;
511 default:
512 LOG( LOG_ERR, "Wrong request %ld\n", request >> 24 );
513 acamera_cmd_queues_array_data_write( 0, CMD_QUEUES_HALF_INX + 1, acamera_cmd_queues_array_data_read( 0, 0 ) );
514 acamera_cmd_queues_array_data_write( 0, CMD_QUEUES_HALF_INX + 2, ERR_BAD_ARGUMENT );
515 acamera_cmd_queues_array_data_write( 0, CMD_QUEUES_HALF_INX, ( FAIL << 16 ) | request );
516 acamera_cmd_queues_array_data_write( 0, 2, API_RESET << 24 );
517 break;
518 }
519 }
520 #endif
521
acamera_connection_process(void)522 void acamera_connection_process( void )
523 {
524 #if ISP_HAS_STREAM_CONNECTION
525 int res = 0;
526 int cnt = 20;
527 uint32_t *const buf = (uint32_t *)con.buffer;
528
529 if ( !con.data_read || !con.data_write ) {
530 return;
531 }
532
533 #if ISP_HAS_CONNECTION_BUFFER
534 process_api_request();
535 #endif
536
537 do {
538 switch ( con.state ) {
539 case STATE_IDLE:
540 res = con.data_read( con.param, &con.buffer[con.rx_buffer_inx], HEADER_SIZE - con.rx_buffer_inx );
541 if ( res != 0 )
542 ACAMERA_CONNECTION_TRACE( "state %d res %d\n", con.state, res );
543 if ( res < 0 ) {
544 reset_connection();
545 return;
546 }
547 con.rx_buffer_inx += res;
548 if ( con.rx_buffer_inx >= HEADER_SIZE ) {
549 con.rx_buffer_size = buf[0];
550 if ( con.rx_buffer_size > CONNECTION_BUFFER_SIZE ) {
551 reset_connection();
552 LOG( LOG_WARNING, "Too big request %u, maximum allowed %u", (unsigned int)con.rx_buffer_size, (unsigned int)CONNECTION_BUFFER_SIZE );
553 con.state = STATE_SKIP_DATA;
554 } else {
555 con.state = STATE_RX_DATA;
556 }
557 }
558 break;
559 case STATE_SKIP_DATA:
560 res = con.data_read( con.param, &con.buffer[HEADER_SIZE], MIN( CONNECTION_BUFFER_SIZE - HEADER_SIZE, con.rx_buffer_size - con.rx_buffer_inx ) );
561 if ( res != 0 )
562 ACAMERA_CONNECTION_TRACE( "state %d res %d\n", con.state, res );
563 if ( res < 0 ) {
564 reset_connection();
565 return;
566 }
567 con.rx_buffer_inx += res;
568 if ( con.rx_buffer_inx >= con.rx_buffer_size ) {
569 con.tx_buffer_size = HEADER_SIZE;
570 *buf = con.tx_buffer_size;
571 con.tx_buffer_inx = 0;
572 con.state = STATE_TX_PACKET;
573 }
574 break;
575 case STATE_RX_DATA:
576 res = con.data_read( con.param, &con.buffer[con.rx_buffer_inx], con.rx_buffer_size - con.rx_buffer_inx );
577 if ( res != 0 )
578 ACAMERA_CONNECTION_TRACE( "state %d res %d\n", con.state, res );
579 if ( res < 0 ) {
580 reset_connection();
581 return;
582 }
583 con.rx_buffer_inx += res;
584 if ( con.rx_buffer_inx >= con.rx_buffer_size ) {
585 process_request();
586 }
587 break;
588 case STATE_TX_PACKET:
589 res = con.data_write( con.param, &con.buffer[con.tx_buffer_inx], con.tx_buffer_size - con.tx_buffer_inx );
590 if ( res != 0 )
591 ACAMERA_CONNECTION_TRACE( "state %d res %d\n", con.state, res );
592 if ( res < 0 ) {
593 reset_connection();
594 return;
595 }
596 con.tx_buffer_inx += res;
597 if ( con.tx_buffer_inx >= con.tx_buffer_size ) {
598 ACAMERA_CONNECTION_TRACE( "packet size %ld is transferred\n", con.tx_buffer_size );
599 reset_connection();
600 return; // this will make sure that FW itself will work as required
601 }
602 break;
603 default:
604 res = -1;
605 LOG( LOG_CRIT, "Wrong state %d", con.state );
606 reset_connection();
607 return;
608 }
609 } while ( res > 0 && --cnt );
610 #endif //ISP_HAS_STREAM_CONNECTION
611 }
612