• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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