xref: /utopia/UTPA2-700.0.x/modules/hsl/api/hsl/frhsl_autotest.c (revision 53ee8cc121a030b8d368113ac3e966b4705770ef)
1 //<MStar Software>
2 //******************************************************************************
3 // MStar Software
4 // Copyright (c) 2010 - 2012 MStar Semiconductor, Inc. All rights reserved.
5 // All software, firmware and related documentation herein ("MStar Software") are
6 // intellectual property of MStar Semiconductor, Inc. ("MStar") and protected by
7 // law, including, but not limited to, copyright law and international treaties.
8 // Any use, modification, reproduction, retransmission, or republication of all
9 // or part of MStar Software is expressly prohibited, unless prior written
10 // permission has been granted by MStar.
11 //
12 // By accessing, browsing and/or using MStar Software, you acknowledge that you
13 // have read, understood, and agree, to be bound by below terms ("Terms") and to
14 // comply with all applicable laws and regulations:
15 //
16 // 1. MStar shall retain any and all right, ownership and interest to MStar
17 //    Software and any modification/derivatives thereof.
18 //    No right, ownership, or interest to MStar Software and any
19 //    modification/derivatives thereof is transferred to you under Terms.
20 //
21 // 2. You understand that MStar Software might include, incorporate or be
22 //    supplied together with third party`s software and the use of MStar
23 //    Software may require additional licenses from third parties.
24 //    Therefore, you hereby agree it is your sole responsibility to separately
25 //    obtain any and all third party right and license necessary for your use of
26 //    such third party`s software.
27 //
28 // 3. MStar Software and any modification/derivatives thereof shall be deemed as
29 //    MStar`s confidential information and you agree to keep MStar`s
30 //    confidential information in strictest confidence and not disclose to any
31 //    third party.
32 //
33 // 4. MStar Software is provided on an "AS IS" basis without warranties of any
34 //    kind. Any warranties are hereby expressly disclaimed by MStar, including
35 //    without limitation, any warranties of merchantability, non-infringement of
36 //    intellectual property rights, fitness for a particular purpose, error free
37 //    and in conformity with any international standard.  You agree to waive any
38 //    claim against MStar for any loss, damage, cost or expense that you may
39 //    incur related to your use of MStar Software.
40 //    In no event shall MStar be liable for any direct, indirect, incidental or
41 //    consequential damages, including without limitation, lost of profit or
42 //    revenues, lost or damage of data, and unauthorized system use.
43 //    You agree that this Section 4 shall still apply without being affected
44 //    even if MStar Software has been modified by MStar in accordance with your
45 //    request or instruction for your use, except otherwise agreed by both
46 //    parties in writing.
47 //
48 // 5. If requested, MStar may from time to time provide technical supports or
49 //    services in relation with MStar Software to you for your use of
50 //    MStar Software in conjunction with your or your customer`s product
51 //    ("Services").
52 //    You understand and agree that, except otherwise agreed by both parties in
53 //    writing, Services are provided on an "AS IS" basis and the warranty
54 //    disclaimer set forth in Section 4 above shall apply.
55 //
56 // 6. Nothing contained herein shall be construed as by implication, estoppels
57 //    or otherwise:
58 //    (a) conferring any license or right to use MStar name, trademark, service
59 //        mark, symbol or any other identification;
60 //    (b) obligating MStar or any of its affiliates to furnish any person,
61 //        including without limitation, you and your customers, any assistance
62 //        of any kind whatsoever, or any information; or
63 //    (c) conferring any license or right under any intellectual property right.
64 //
65 // 7. These terms shall be governed by and construed in accordance with the laws
66 //    of Taiwan, R.O.C., excluding its conflict of law rules.
67 //    Any and all dispute arising out hereof or related hereto shall be finally
68 //    settled by arbitration referred to the Chinese Arbitration Association,
69 //    Taipei in accordance with the ROC Arbitration Law and the Arbitration
70 //    Rules of the Association by three (3) arbitrators appointed in accordance
71 //    with the said Rules.
72 //    The place of arbitration shall be in Taipei, Taiwan and the language shall
73 //    be English.
74 //    The arbitration award shall be final and binding to both parties.
75 //
76 //******************************************************************************
77 //<MStar Software>
78 
79 ////////////////////////////////////////////////////////////////////////////////
80 //
81 // Copyright (c) 2008-2009 MStar Semiconductor, Inc.
82 // All rights reserved.
83 //
84 // Unless otherwise stipulated in writing, any and all information contained
85 // herein regardless in any format shall remain the sole proprietary of
86 // MStar Semiconductor Inc. and be kept in strict confidence
87 // ("MStar Confidential Information") by the recipient.
88 // Any unauthorized act including without limitation unauthorized disclosure,
89 // copying, use, reproduction, sale, distribution, modification, disassembling,
90 // reverse engineering and compiling of the contents of MStar Confidential
91 // Information is unlawful and strictly prohibited. MStar hereby reserves the
92 // rights to any and all damages, losses, costs and expenses resulting therefrom.
93 //
94 ////////////////////////////////////////////////////////////////////////////////
95 #if defined (MSOS_TYPE_LINUX)
96 #include <stdio.h>
97 #include <stdlib.h>
98 #include <string.h>
99 #include <stddef.h>
100 #include <assert.h>
101 // ----------------------------------------------------------
102 // The Little-Endian and Big-Endian is ignor in the firmware,
103 // The PC-side client should take care of the tranfer data endian.
104 // ----------------------------------------------------------
105 
106 
107 /* According to earlier standards */
108 #include <unistd.h>
109 #include <fcntl.h>
110 #include <pthread.h>
111 #include <termios.h>
112 
113 #include "apiHSL.h"
114 #include "frhsl_datalink.h"
115 #include "frhsl_autotest.h"
116 #include "apiHSL_SHM.h"
117 #include "frhsl_cfg.h"
118 
119 #ifdef HSL_TCPIP
120 #include <sys/socket.h>
121 #include <errno.h>
122 #include <netinet/in.h>
123 #include <arpa/inet.h>
124 
125 #define LENGTH_OF_LISTEN_QUEUE 50 //length of listen queue in server
126 #define DBG_OUTPUT_TCPIP 0
127 #define DBG_OUTPUT_FILE 0
128 
129 #define HSL_DBG_OUTPUT_FILE     "/utopia_test/HSL_Log"
130 #define MSG_RESPONSE_OVERFLOW   "Invalid AT response length specified which exceeds %u char"
131 
132 #endif
133 
134 //#define HSL_FILE_MSG(FILE_NAME, fmt, arg...) printf(fmt, ##arg)
135 #define HSL_FILE_MSG(FILE_NAME, fmt, arg...)
136 
137 
138 FILE *OutputFp;
139 cHslSyncMem hslSyncMem;
140 
141 static void CmdRecvStart(p_HslController _hsl);
142 
143 // =============================
144 // For AutoTest
145 // =============================
146 
InitThread(void * pHsl)147 static void* InitThread(void* pHsl)
148 {
149     p_HslController hsl = (p_HslController)pHsl;
150     CmdRecvStart(hsl) ;
151     return NULL;
152 }
153 
154 #define SET_RESP_DWORD(buffer, index, value) \
155         *((MS_U32*)(buffer+LINK_HEADER_SIZE+4*index)) = value
156 
157 
158 
CmdSend(stHslController * const _hsl,const void * message,int length)159 void CmdSend(stHslController* const _hsl, const void *message, int length)
160 {
161     send(_hsl->hClientSocket,message,length,0);
162 }
163 
SendMessage(p_HslController _hsl,void * a_pBody,int a_bodySize)164 MS_BOOL SendMessage(p_HslController _hsl, void *a_pBody, int a_bodySize)
165 {
166     CmdInfo   rb_cmd;
167 
168     rb_cmd.u32Pid = 0x12345678;     // test
169     rb_cmd.u16Cmd = (MS_U16)HSL_CMD_SEND_DATA;
170     rb_cmd.u32Len = a_bodySize;
171     rb_cmd.pu8Buf = a_pBody;
172 
173     return FrHslCommand(_hsl, &rb_cmd);
174 }
175 
RespCardStatus(p_HslController _hsl,MS_U8 * a_buffer)176 MS_BOOL RespCardStatus(p_HslController _hsl, MS_U8 *a_buffer)
177 {
178     /* TP: Need to add some error notification for the pc.
179      * At the moment if anything goes wrong this function
180      * aborts and quietly returns FALSE causing a timeout
181      * on the PC. Let's assume that a response of (0,0)
182      * will mean a problem with retrieving data from the RB.
183      */
184 
185     CmdInfo rb_cmd;
186     MS_BOOL bRetn = FALSE;
187 
188     MS_U32 totalSize = 0;
189     MS_U32 usedSize  = 0;
190 
191     // -----------------------------------------------
192     // get Total size
193     // -----------------------------------------------
194     rb_cmd.u32Pid = 0x12345678;          // test -- is it still needed (TP)?
195 
196     rb_cmd.u16Cmd = HSL_CMD_RB_TOTAL_SIZE;
197     rb_cmd.pu8Buf = NULL;
198     rb_cmd.u32Len = 0;  // put the size in here
199 
200     if( FrHslCommand(_hsl, &rb_cmd) )
201     {
202         totalSize = rb_cmd.u32Len;
203 
204         // -----------------------------------------------
205         // get Used size
206         // -----------------------------------------------
207         rb_cmd.u16Cmd = HSL_CMD_RB_EXIST_DATA_SIZE;
208         rb_cmd.u32Len = 0;  // put the size in here
209         if( FrHslCommand(_hsl, &rb_cmd) )
210         {
211             usedSize = rb_cmd.u32Len;
212             bRetn = TRUE;
213         }
214     }
215 
216     // -----------------------------------------------
217     // detect error
218     // -----------------------------------------------
219     if((usedSize > totalSize) && (usedSize != 0xffffffff))
220     {
221         // body.usedSize = body.totalSize / 2; // TP: why was this necessary?
222         HSL_FILE_MSG(OutputFp, "Ring buffer internal error\n");
223         bRetn = FALSE;
224     }
225 
226     // -----------------------------------------------
227     // send Response
228     // -----------------------------------------------
229     if( bRetn != TRUE )
230     {
231         usedSize = totalSize = 0; // clear any rubbish
232     }
233 
234     a_buffer[0] = (MS_U8)EN_LINK_CMD_RESP_CARD_STATUS;
235     // seqNo should remain the same as in the received message
236 
237     SET_RESP_DWORD(a_buffer, 0, usedSize);
238     SET_RESP_DWORD(a_buffer, 1, totalSize);
239 
240     bRetn &= SendMessage(_hsl, a_buffer, LINK_HEADER_SIZE+LINK_DATA_RESPONSE_CARD_STATUS);
241 
242     //HSL_FILE_MSG(OutputFp, "Used_Size:%lx RingBuf_Size:%lx\n", body.usedSize, body.totalSize);
243     // HSL_FILE_MSG(OutputFp, "CardStatus=%x/%x\n", usedSize, totalSize);
244 
245     return bRetn;
246 }
247 
RespHslData(p_HslController _hsl,MS_U8 * a_buffer)248 MS_BOOL RespHslData(p_HslController _hsl, MS_U8 *a_buffer)
249 {
250     MS_BOOL bRetn = FALSE;
251     int     blength;
252 
253     CmdInfo rb_cmd;
254 
255     // -----------------------------------------------
256     // recv "Request Size"
257     // -----------------------------------------------
258     blength = recv(_hsl->hClientSocket, a_buffer+LINK_HEADER_SIZE, LINK_DATA_GET_HSL_DATA, 0);
259     if (blength == 0)
260     {
261         HSL_FILE_MSG(OutputFp,"Client connection has been closed.\n");
262         return FALSE;
263     }
264 
265     MS_U32 reqSize = *((MS_U32*)(a_buffer+LINK_HEADER_SIZE));
266     //HSL_FILE_MSG(OutputFp, "RequestSize : %lx\n", reqSize);
267 
268     // -----------------------------------------------
269     // get Used size
270     // -----------------------------------------------
271 
272     rb_cmd.u16Cmd = HSL_CMD_RB_EXIST_DATA_SIZE;
273     rb_cmd.u32Len = 0;  // put the size in here
274     bRetn = FrHslCommand(_hsl, &rb_cmd);
275     if( !bRetn )
276     {
277         return FALSE;
278     }
279     MS_U32 usedSize = rb_cmd.u32Len;
280 
281     // -----------------------------------------------
282     // Decide bytes send back
283     // -----------------------------------------------
284     if( reqSize > usedSize)
285     {
286         reqSize = usedSize;
287         HSL_FILE_MSG(OutputFp, "RealSize : %lx\n", reqSize);
288     }
289 
290     // -----------------------------------------------
291     // Send "Response CMD"
292     // -----------------------------------------------
293 
294     //TODO: Check if the requested data is still available in the ringbuffer
295     /* (TP) By the look of it it is always attempted to send exactly the requested amount
296      * of data from the ringbuffer. Could see no query to the RB if such amount is available.
297      * will leave it like this for now but it must be addressed before release.
298      */
299 
300     a_buffer[0] = (MS_U8)EN_LINK_CMD_RESP_HSL_DATA; // only need to change the cmd id in this case
301     SET_RESP_DWORD(a_buffer, 0, reqSize);
302 
303     bRetn = SendMessage(_hsl, a_buffer, LINK_HEADER_SIZE+LINK_DATA_RESPONSE_HSL_CMD);
304 
305     if( bRetn)
306     {
307         // -----------------------------------------------
308         // pop Data
309         // -----------------------------------------------
310         // HSL_FILE_MSG(OutputFp, "Start to send packet type 4, request size:%x.\n", reqStru.reqSize);
311         rb_cmd.u32Pid = 0;     // test
312         rb_cmd.u16Cmd = HSL_CMD_GET_HSL_DATA;
313         rb_cmd.u32Len = reqSize;
314         rb_cmd.pu8Buf = NULL;
315 
316         bRetn = FrHslCommand(_hsl, &rb_cmd);
317     }
318 
319     return bRetn;
320 }
321 
ProcessCmd(p_HslController _hsl,MS_U8 * a_cmdBuffer)322 MS_U32 ProcessCmd(p_HslController _hsl, MS_U8 *a_cmdBuffer)
323 {
324     MS_U32 errCode = EN_CMD_EC_OK;
325     int i = 0;
326 
327     // At this point we assume that the PC has sent all the data in
328     // and cast the buffer onto a command structure
329     ST_HSL_CMD_REQ* p_command = (ST_HSL_CMD_REQ*)a_cmdBuffer;
330 
331     HSL_FILE_MSG(OutputFp,"CmdId=%X, Ver=%X\n", p_command->cmdId, p_command->ver);
332 
333     if( p_command->ver != LINK_PROTOCOL_VERSION )
334     {
335       errCode = EN_CMD_EC_VERSION;
336     }
337     else
338     {
339       switch( p_command->cmdId )
340       {
341           case EN_CMD_TEST_NONE:
342               errCode = EN_CMD_EC_CMD_UNKNOWN;
343               break;
344           case EN_CMD_TEST_AT:
345               if( !StoreShareMemory(&hslSyncMem, p_command->U_Cmd.atCmd) )
346               {
347                 errCode = EN_CMD_EC_AT_FAILURE;
348                 PackAtCmdEchoIntoHslCmdResp(false, p_command->U_Cmd.atCmd);
349               }
350               else
351               {
352                 PackAtCmdEchoIntoHslCmdResp(true, p_command->U_Cmd.atCmd);
353               }
354               break;
355           case EN_CMD_TEST_LOAD:
356           {
357               HSL_FILE_MSG(OutputFp, "Load Test request received\n");
358               gRunLoadTest = true;
359               for(i=0; i<p_command->U_Cmd.loadTestCmd.mThreadNo; i++)
360               {
361                   if( 0 != pthread_create(&gTestThreads[i], 0, HslSelfTestThreadFun, (void*)(&p_command->U_Cmd.loadTestCmd) ) )
362                   {
363                       HSL_FILE_MSG(OutputFp, "Failed to create thread! Stop the load test\n");
364                       errCode = EN_CMD_EC_THREAD_FAIL;
365                       gRunLoadTest = false;
366                       break;
367                   }
368                   else
369                   {
370                       HSL_FILE_MSG(OutputFp, "Load test thread %d created\n", i);
371                   }
372               }
373 
374           }
375               break;
376           default:
377             errCode = EN_CMD_EC_CMD_UNKNOWN;
378             break;
379       }
380     }
381 
382     return errCode;
383 }
384 
385 /** Wrapper function to echo back input AT command back to PC.
386     This is done to permit to get an exact timestamp on when the command was processed.  */
PackAtCmdEchoIntoHslCmdResp(MS_BOOL a_result,const char * a_atCmd)387 void PackAtCmdEchoIntoHslCmdResp(MS_BOOL a_result, const char* a_atCmd)
388 {
389     AtCmdEcho obj;
390     obj.result = a_result;
391     memset(obj.atCmd, '\0', sizeof(obj.atCmd));
392     strncpy(obj.atCmd, a_atCmd, sizeof(obj.atCmd) - 1);
393     PackIntoHslCmdResp(EN_RESP_TEST_AT_ECHO, (const void*)&obj);
394 }
395 
396 
397 /** Wrapper function for sending AT command response back to PC */
PackAtRespIntoHslCmdResp(const char * a_atResp)398 void PackAtRespIntoHslCmdResp(const char* a_atResp)
399 {
400     PackIntoHslCmdResp(EN_RESP_TEST_AT, (const void*)a_atResp);
401 }
402 
403 
404 /** Wrapper function to transport over log point id 0x000A the Hsl Command response
405  * The implementation depends closely on the definition of ST_HSL_CMD_RESP; Any
406  * update to that structure would need to be reflected here. */
PackIntoHslCmdResp(EN_RESPONSE_ID a_respId,const void * a_body)407 void PackIntoHslCmdResp(EN_RESPONSE_ID a_respId, const void* a_body)
408 {
409     MS_U16 packedStructLength = offsetof(ST_HSL_CMD_RESP, U_Resp); /* This gets the total size up to the start of the union. */
410 
411     ST_HSL_CMD_RESP container;
412 
413     container.respId = a_respId;
414 
415     switch (a_respId)
416     {
417     case EN_RESP_TEST_AT:
418     {
419         MS_U32 strLength = strlen((const char*)a_body) + 1; /* +1 for the null char as this is a string */
420         if (strLength > RSP_MAX_AT)
421         {
422             snprintf(container.U_Resp.atResponse, strlen(MSG_RESPONSE_OVERFLOW)+10,MSG_RESPONSE_OVERFLOW, RSP_MAX_AT);
423             packedStructLength += (MS_U16)(strlen(container.U_Resp.atResponse) + 1);
424         }
425         else
426         {
427             strncpy(container.U_Resp.atResponse, (char*) a_body,strLength);
428             packedStructLength += (MS_U16)strLength;
429         }
430     }
431     break;
432 
433     case EN_RESP_TEST_AT_ECHO:
434     {
435         const AtCmdEcho* cmdEchoPtr = (const AtCmdEcho*) a_body;
436         container.U_Resp.atCmdEcho.result = (MS_BOOL) (cmdEchoPtr->result);
437 
438         MS_U32 strLength = strlen((const char*)cmdEchoPtr->atCmd) + 1; /* +1 for the null char as this is a string */
439         if (strLength > CMD_MAX_AT)
440         {
441             snprintf(container.U_Resp.atCmdEcho.atCmd, strlen(MSG_RESPONSE_OVERFLOW)+10,MSG_RESPONSE_OVERFLOW, CMD_MAX_AT);
442             packedStructLength += (MS_U16)(strlen(container.U_Resp.atCmdEcho.atCmd) + 1);
443         }
444         else
445         {
446             strncpy(container.U_Resp.atCmdEcho.atCmd, (char*) cmdEchoPtr->atCmd,strLength);
447             packedStructLength += (MS_U16)strLength;
448         }
449 
450     }
451     break;
452 
453     case EN_RESP_TEST_CMD_LAST:
454         break;
455 
456     default:
457         break;
458     }
459 
460     if ((packedStructLength % 2) == 1)
461     {
462         packedStructLength += (MS_U16)1;  // This ensures we don't lose one character as we transfer in MS_U16 blocks over HSL.
463     }
464 
465     HSL_FILE_MSG(OutputFp,"Length=%d\n", packedStructLength);
466 
467     /* Using hard coded log point ID for this structure; Do not modify this log point ID as tools
468      * on PC depend on it. */
469     M_FrHslArray16(0x000A, HSL_DBG_UTOPIA_ALL_DEBUG, "ST_HSL_CMD_RESP: %#04X", packedStructLength/sizeof(MS_U16), &container);
470 
471 }
472 
473 // -----------------------------------------------
474 // Process HSL command
475 // If error occured and can not be recovered, return false
476 // This connection should be closed
477 // -----------------------------------------------
RespHslCmd(p_HslController _hsl,MS_U8 * a_buffer)478 MS_BOOL RespHslCmd(p_HslController _hsl, MS_U8 *a_buffer)
479 {
480     int     bLength     = 0;
481     int     bReceived   = 0;
482     MS_U8   cmdBuffer[LINK_MAX_COMMAND];
483     MS_BOOL bRetn       = FALSE;
484     MS_U32  errCode     = EN_CMD_EC_OK;
485 
486     //----------------------------------
487     // Read "len" field first
488     //----------------------------------
489     bLength = recv(_hsl->hClientSocket, a_buffer+LINK_HEADER_SIZE, LINK_DATA_SEND_HSL_CMD, 0);
490     if (bLength == 0)
491     {
492         HSL_FILE_MSG(OutputFp,"Client connection has been closed.\n");
493         return FALSE;
494     }
495     else
496     {
497         bRetn = TRUE;
498     }
499 
500     //----------------------------------
501     // Read all payload after "len"
502     //----------------------------------
503     MS_U32 reqLen = *((MS_U32*)(a_buffer+LINK_HEADER_SIZE));
504     if( reqLen > LINK_MAX_COMMAND )
505     {
506         // No recovery - in case of failure everything should shutdown
507         errCode = EN_CMD_EC_DATA_SIZE;
508         HSL_FILE_MSG(OutputFp, "Command received, wrong size: %u is not < %u\n", (unsigned int)reqLen, LINK_MAX_COMMAND);
509     }
510     else
511     {
512         // Read the whole message - may come in one or more pieces
513         bReceived = 0;
514         while( bReceived < reqLen )
515         {
516             //TODO!: add timeout handling
517             bLength = recv(_hsl->hClientSocket, (char*)(cmdBuffer+bReceived), reqLen-bReceived, 0);
518             bReceived += bLength;
519         }
520         errCode = ProcessCmd(_hsl, cmdBuffer);
521     }
522 
523     a_buffer[0] = (MS_U8)EN_LINK_CMD_RESP_HSL_CMD;
524     SET_RESP_DWORD(a_buffer, 0, errCode);
525 
526     // bRetn = (errCode == EN_CMD_EC_OK); // All or nothing, in case of error close the connection
527     bRetn &= SendMessage(_hsl, a_buffer, LINK_HEADER_SIZE+LINK_DATA_RESPONSE_HSL_CMD);
528     HSL_FILE_MSG(OutputFp, "After processing a command: err code: %u, result: %d\n", (unsigned int)errCode, (int)bRetn);
529     return bRetn;
530 }
531 
532 
RespFilterMx(p_HslController _hsl,MS_U8 * a_buffer)533 MS_BOOL RespFilterMx(p_HslController _hsl, MS_U8 * a_buffer)
534 {
535     int     bLength     = 0;
536     int     bReceived   = 0;
537     MS_U8   cmdBuffer[CMD_MAX_FILTER];
538     MS_BOOL bRetn       = FALSE;
539     MS_U32  errCode     = EN_CMD_EC_OK;
540 
541     //----------------------------------
542     // Read "len" field first
543     //----------------------------------
544     bLength = recv(_hsl->hClientSocket, a_buffer+LINK_HEADER_SIZE, LINK_DATA_SEND_HSL_CMD, 0);
545     if (bLength == 0)
546     {
547         HSL_FILE_MSG(OutputFp,"Client connection has been closed.\n");
548         return FALSE;
549     }
550 
551     //----------------------------------
552     // Read all payload after "len"
553     //----------------------------------
554     MS_U32 reqLen = *((MS_U32*)(a_buffer+LINK_HEADER_SIZE));
555     if( reqLen > CMD_MAX_FILTER )
556     {
557         // No recovery - in case of failure everything should shutdown
558         errCode = EN_CMD_EC_DATA_SIZE;
559     }
560     else
561     {
562         // Read the whole message - may come in one or more pieces
563         bReceived = 0;
564         while( bReceived < reqLen )
565         {
566             bLength = recv(_hsl->hClientSocket, (char*)(cmdBuffer+bReceived), reqLen-bReceived, 0);
567             bReceived += bLength;
568         }
569         //errCode = ProcessCmd(cmdBuffer);
570         KiTtiProcessSetsFilter((KiSetsFilterMatrix*)cmdBuffer);
571     }
572 
573     a_buffer[0] = (MS_U8)EN_LINK_CMD_RSP_FILTER_MX;
574     SET_RESP_DWORD(a_buffer, 0, errCode);
575 
576     HSL_FILE_MSG(OutputFp,"reqLen=%lx, errCode=%lx\n", reqLen, errCode);
577 
578     bRetn = (errCode == EN_CMD_EC_OK); // All or nothing, in case of error close the connection
579     bRetn &= SendMessage(_hsl, a_buffer, LINK_HEADER_SIZE+LINK_DATA_RESPONSE_HSL_CMD);
580     return bRetn;
581 }
582 
583 // -----------------------------------------------
584 // Thread Start Function
585 // -----------------------------------------------
CmdRecvStart(p_HslController _hsl)586 static void CmdRecvStart(p_HslController _hsl)
587 {
588     struct sockaddr_in  servaddr;
589     struct sockaddr_in  cliaddr;
590     socklen_t       socklen;
591     int         blength;
592     struct          timeval tv;
593     int           iResult;
594 
595     MS_BOOL       bRetn = FALSE;
596     //string output;
597     //long timestamp;
598 
599     // -----------------------------------------------
600     // Initial
601     // -----------------------------------------------
602 
603     assert(_hsl!=0);
604 
605     blength = 0;
606     bRetn = true;
607 
608     socklen = sizeof(cliaddr);
609 
610     bzero(&servaddr,sizeof(servaddr));
611     servaddr.sin_family       = AF_INET;
612     servaddr.sin_port         = htons(_hsl->u32Port);
613     servaddr.sin_addr.s_addr  = htons(INADDR_ANY);
614 
615 #if DBG_OUTPUT_FILE
616     OutputFp = fopen(HSL_DBG_OUTPUT_FILE,"w+");
617     fclose(OutputFp);
618 #endif
619 
620     // -----------------------------------------------
621     // listen port
622     // -----------------------------------------------
623     HSL_FILE_MSG(OutputFp,"HSL: create socket!\n");
624     _hsl->hServerSocket = socket(AF_INET,SOCK_STREAM,0);
625     if (_hsl->hServerSocket < 0)
626     {
627         HSL_FILE_MSG(OutputFp,"create socket error!\n");
628         return;
629     }
630 
631     HSL_FILE_MSG(OutputFp, "HSL: bind to port %u!\n", (unsigned int)_hsl->u32Port);
632     iResult = bind(_hsl->hServerSocket, (struct sockaddr*)&servaddr, sizeof(servaddr));
633     if (iResult < 0)
634     {
635         HSL_FILE_MSG(OutputFp, "HSL: bind to port %u failure!\n",  (unsigned int)_hsl->u32Port);
636         return;
637     }
638 
639     HSL_FILE_MSG(OutputFp,"HSL: call listen!\n");
640     if (listen(_hsl->hServerSocket,LENGTH_OF_LISTEN_QUEUE) < 0)
641     {
642         HSL_FILE_MSG(OutputFp,"HSL: call listen failure!\n");
643         return;
644     }
645 
646     HSL_FILE_MSG(OutputFp,"HSL: Start to accept socket connection.\n");
647 
648     if(_hsl->u8Instance == 0 )
649     {
650         if( false == InitShareMemory(&hslSyncMem, true))
651         {
652             HSL_FILE_MSG(OutputFp,"HSL: InitShareMemory() error!\n");
653             return;
654         }
655         HSL_FILE_MSG(OutputFp,"HSL: InitShareMemory() successful!\n");
656     }
657 
658     HSL_FILE_MSG(OutputFp,"HSL: check if flash ok, before while(1)\n");
659 
660     // -----------------------------------------------
661     // set timeout
662     // -----------------------------------------------
663 
664     tv.tv_sec = LINK_CONNECTION_TIMEOUT;
665     tv.tv_usec = 0;
666     if(setsockopt(_hsl->hServerSocket, SOL_SOCKET, SO_RCVTIMEO, (struct timeval *)&tv, sizeof(struct timeval)) < 0)
667     {
668         HSL_FILE_MSG(OutputFp,"HSL: setsockopt error!\n");
669         return;
670     }
671 
672     // -----------------------------------------------
673     // process data
674     // -----------------------------------------------
675     MS_U8 socketBuffer[LINK_BUFFER_SIZE];
676     pthread_mutex_lock(&(_hsl->socketReadMutex));
677 
678     while(_hsl->g_AutoTestRun)
679     {
680         // -----------------------------------------------
681         // accept()
682         // -----------------------------------------------
683         HSL_FILE_MSG(OutputFp, "HSL: Waiting for an access to the RCV loop\n");
684         while(_hsl->g_AutoTestRun)
685         {
686             _hsl->hClientSocket = accept(_hsl->hServerSocket, (struct sockaddr*)&cliaddr, &socklen);
687             if( _hsl->hClientSocket >= 0)
688             {
689                 FrHslResetConnection(_hsl); // when new connection come, reset it
690                 bRetn = TRUE;
691                 break;
692             }
693             else
694             {
695                 HSL_FILE_MSG(OutputFp, "HSL: Socket not connected: errno=%d ", errno);
696                 if( errno == 11 )
697                 {
698                     HSL_FILE_MSG(OutputFp, "(Try again)\n");
699                 }
700                 else
701                 {
702                     HSL_FILE_MSG(OutputFp, "\n");
703                 }
704             }
705             errno = 0;
706         }
707 
708         HSL_FILE_MSG(OutputFp,"HSL: Accepted connection from client,IP:%s,Port:%d\n",inet_ntoa(cliaddr.sin_addr),ntohs(cliaddr.sin_port));
709 
710         while((_hsl->hClientSocket >= 0) && (_hsl->g_AutoTestRun))
711         {
712             // -----------------------------------------------
713             // Receive packet header: Command(1 byte) and Sequence Number (1 byte)
714             // -----------------------------------------------
715 
716             // The return value will be 0 when the peer has performed an orderly shutdown and errno == 0
717             blength = recv(_hsl->hClientSocket, socketBuffer, LINK_HEADER_SIZE, 0);
718             if (blength > 0)
719             {
720 //                HSL_FILE_MSG(OutputFp, "HSL: Received %d bytes\n", blength);
721                 bRetn = TRUE;
722             }
723             else if(blength == 0)
724             {
725                 HSL_FILE_MSG(OutputFp, "HSL: Connection closed by client\n");
726                 bRetn = FALSE;
727             }
728             else // blength <= 0
729             {
730                 HSL_FILE_MSG(OutputFp, "HSL: Socket error: %d\n", errno);
731                 bRetn = FALSE;
732             }
733 
734             if(bRetn != FALSE)
735             {
736                 MS_U8 cmdId = socketBuffer[0];
737 
738                 switch(cmdId)
739                 {
740                 case EN_LINK_CMD_GET_CARD_STATUS:
741                     bRetn = RespCardStatus(_hsl, socketBuffer);
742                     break;
743 
744                 case EN_LINK_CMD_GET_HSL_DATA:
745                     bRetn = RespHslData(_hsl, socketBuffer);
746                     break;
747 
748                 case EN_LINK_CMD_SEND_HSL_CMD:
749                     bRetn = RespHslCmd(_hsl, socketBuffer);
750                     break;
751 
752                 case EN_LINK_CMD_SND_FILTER_MX:
753                     bRetn = RespFilterMx(_hsl ,socketBuffer);
754                     break;
755 
756                 default:
757                     //TODO: need to think if any feedback to the pc is required
758                     bRetn = false;
759                     HSL_FILE_MSG(OutputFp, "HSL: ERROR: Unknown command!\n");
760                     break;
761                 }
762 //                HSL_FILE_MSG(OutputFp,"HSL: Finished processing a command\n");
763             }
764             else
765             {
766                 HSL_FILE_MSG(OutputFp,"HSL: Connection closed or HSL transport layer failure\n");
767                 break; // ToDo: uncomment it, if teraHSL can create new clifd
768                 // TP: if the protocol is broken for some reason there is no point
769                 // in keeping the connection alive. If TeraHSL cannot cope with it
770                 // it's should not compromise the implementation on the target.
771             }
772         }
773         if (_hsl->hClientSocket >=0)
774         {
775             HSL_FILE_MSG(OutputFp,"HSL: Closing client socket %d\n", _hsl->hClientSocket);
776             close(_hsl->hClientSocket);
777         }
778         else
779         {
780             printf("HSL: ERROR: Invalid id when attempting to close a socket (%d)\n", _hsl->hClientSocket);
781         }
782     }
783 
784     pthread_mutex_unlock(&(_hsl->socketReadMutex));
785     close(_hsl->hServerSocket);
786     FreeShareMemory(&hslSyncMem);
787 
788     return;
789 }
790 
FrHsl_AutoTest_Init(stHslController * const _hsl)791 MS_BOOL FrHsl_AutoTest_Init(stHslController* const _hsl)
792 {
793     pthread_attr_t attr;
794     pthread_attr_init(&attr);
795 
796     _hsl->g_AutoTestRun = true;
797     if(!pthread_create(&(_hsl->threadCmdRecvStart), &attr, InitThread, _hsl))
798         return true;
799     else
800         return false;
801 }
802 
FrHsl_AutoTest_End(stHslController * const _hsl)803 void FrHsl_AutoTest_End(stHslController* const _hsl)
804 {
805     _hsl->g_AutoTestRun = false;
806     if( 0 != pthread_join(_hsl->threadCmdRecvStart, 0))
807     {
808         HSL_FILE_MSG(OutputFp, "ERROR: Failed to shutdown the HSL receive thread!\n");
809     }
810 }
811 
812 #endif
813 /* END OF FILE */
814 
815