1 /**
2 ******************************************************************************
3 * @file shci.c
4 * @author MCD Application Team
5 * @brief HCI command for the system channel
6 ******************************************************************************
7 * @attention
8 *
9 * <h2><center>© Copyright (c) 2019 STMicroelectronics.
10 * All rights reserved.</center></h2>
11 *
12 * This software component is licensed by ST under BSD 3-Clause license,
13 * the "License"; You may not use this file except in compliance with the
14 * License. You may obtain a copy of the License at:
15 * opensource.org/licenses/BSD-3-Clause
16 *
17 ******************************************************************************
18 */
19
20
21 /* Includes ------------------------------------------------------------------*/
22 #include "stm32_wpan_common.h"
23
24 #include "shci_tl.h"
25 #include "shci.h"
26 #include "stm32wbxx.h"
27
28 /* Private typedef -----------------------------------------------------------*/
29 /* Private defines -----------------------------------------------------------*/
30 /* Private macros ------------------------------------------------------------*/
31 /* Private variables ---------------------------------------------------------*/
32 /* Global variables ----------------------------------------------------------*/
33 /* Private function prototypes -----------------------------------------------*/
34 /* Local Functions Definition ------------------------------------------------------*/
35 /* Public Functions Definition ------------------------------------------------------*/
36
37 /**
38 * C2 COMMAND
39 * These commands are sent to the CPU2
40 */
SHCI_C2_FUS_GetState(SHCI_FUS_GetState_ErrorCode_t * p_error_code)41 uint8_t SHCI_C2_FUS_GetState( SHCI_FUS_GetState_ErrorCode_t *p_error_code )
42 {
43 /**
44 * A command status event + payload has the same size than the expected command complete
45 */
46 uint8_t local_buffer[TL_BLEEVT_CS_BUFFER_SIZE + 1];
47 TL_EvtPacket_t * p_rsp;
48
49 p_rsp = (TL_EvtPacket_t *)local_buffer;
50
51 shci_send( SHCI_OPCODE_C2_FUS_GET_STATE,
52 0,
53 0,
54 p_rsp );
55
56 if(p_error_code != 0)
57 {
58 *p_error_code = (SHCI_FUS_GetState_ErrorCode_t)(((TL_CcEvt_t*)(p_rsp->evtserial.evt.payload))->payload[1]);
59 }
60
61 return (((TL_CcEvt_t*)(p_rsp->evtserial.evt.payload))->payload[0]);
62 }
63
SHCI_C2_FUS_FwUpgrade(uint32_t fw_src_add,uint32_t fw_dest_add)64 SHCI_CmdStatus_t SHCI_C2_FUS_FwUpgrade( uint32_t fw_src_add, uint32_t fw_dest_add )
65 {
66 /**
67 * TL_BLEEVT_CS_BUFFER_SIZE is 15 bytes so it is large enough to hold the 8 bytes of command parameters
68 * Buffer is large enough to hold command complete without payload
69 */
70 uint8_t local_buffer[TL_BLEEVT_CS_BUFFER_SIZE];
71 TL_EvtPacket_t * p_rsp;
72 uint32_t *p_cmd;
73 uint8_t cmd_length;
74
75 p_cmd = (uint32_t*)local_buffer;
76 cmd_length = 0;
77
78 if(fw_src_add != 0)
79 {
80 *p_cmd = fw_src_add;
81 cmd_length += 4;
82 }
83
84 if(fw_dest_add != 0)
85 {
86 *(p_cmd+1) = fw_dest_add;
87 cmd_length += 4;
88 }
89
90 p_rsp = (TL_EvtPacket_t *)local_buffer;
91
92 shci_send( SHCI_OPCODE_C2_FUS_FW_UPGRADE,
93 cmd_length,
94 local_buffer,
95 p_rsp );
96
97 return (SHCI_CmdStatus_t)(((TL_CcEvt_t*)(p_rsp->evtserial.evt.payload))->payload[0]);
98 }
99
SHCI_C2_FUS_FwDelete(void)100 SHCI_CmdStatus_t SHCI_C2_FUS_FwDelete( void )
101 {
102 /**
103 * Buffer is large enough to hold command complete without payload
104 */
105 uint8_t local_buffer[TL_BLEEVT_CS_BUFFER_SIZE];
106 TL_EvtPacket_t * p_rsp;
107
108 p_rsp = (TL_EvtPacket_t *)local_buffer;
109
110 shci_send( SHCI_OPCODE_C2_FUS_FW_DELETE,
111 0,
112 0,
113 p_rsp );
114
115 return (SHCI_CmdStatus_t)(((TL_CcEvt_t*)(p_rsp->evtserial.evt.payload))->payload[0]);
116 }
117
SHCI_C2_FUS_UpdateAuthKey(SHCI_C2_FUS_UpdateAuthKey_Cmd_Param_t * pParam)118 SHCI_CmdStatus_t SHCI_C2_FUS_UpdateAuthKey( SHCI_C2_FUS_UpdateAuthKey_Cmd_Param_t *pParam )
119 {
120 /**
121 * Buffer is large enough to hold command complete without payload
122 */
123 uint8_t local_buffer[TL_BLEEVT_CS_BUFFER_SIZE];
124 TL_EvtPacket_t * p_rsp;
125
126 p_rsp = (TL_EvtPacket_t *)local_buffer;
127
128 shci_send( SHCI_OPCODE_C2_FUS_UPDATE_AUTH_KEY,
129 sizeof( SHCI_C2_FUS_UpdateAuthKey_Cmd_Param_t ),
130 (uint8_t*)pParam,
131 p_rsp );
132
133 return (SHCI_CmdStatus_t)(((TL_CcEvt_t*)(p_rsp->evtserial.evt.payload))->payload[0]);
134 }
135
SHCI_C2_FUS_LockAuthKey(void)136 SHCI_CmdStatus_t SHCI_C2_FUS_LockAuthKey( void )
137 {
138 /**
139 * Buffer is large enough to hold command complete without payload
140 */
141 uint8_t local_buffer[TL_BLEEVT_CS_BUFFER_SIZE];
142 TL_EvtPacket_t * p_rsp;
143
144 p_rsp = (TL_EvtPacket_t *)local_buffer;
145
146 shci_send( SHCI_OPCODE_C2_FUS_LOCK_AUTH_KEY,
147 0,
148 0,
149 p_rsp );
150
151 return (SHCI_CmdStatus_t)(((TL_CcEvt_t*)(p_rsp->evtserial.evt.payload))->payload[0]);
152 }
153
SHCI_C2_FUS_StoreUsrKey(SHCI_C2_FUS_StoreUsrKey_Cmd_Param_t * pParam,uint8_t * p_key_index)154 SHCI_CmdStatus_t SHCI_C2_FUS_StoreUsrKey( SHCI_C2_FUS_StoreUsrKey_Cmd_Param_t *pParam, uint8_t *p_key_index )
155 {
156 /**
157 * Buffer is large enough to hold command complete without payload
158 */
159 uint8_t local_buffer[TL_BLEEVT_CS_BUFFER_SIZE + 1];
160 TL_EvtPacket_t * p_rsp;
161 uint8_t local_payload_len;
162
163 if(pParam->KeyType == KEYTYPE_ENCRYPTED)
164 {
165 /**
166 * When the key is encrypted, the 12 bytes IV Key is included in the payload as well
167 * The IV key is always 12 bytes
168 */
169 local_payload_len = pParam->KeySize + 2 + 12;
170 }
171 else
172 {
173 local_payload_len = pParam->KeySize + 2;
174 }
175
176 p_rsp = (TL_EvtPacket_t *)local_buffer;
177
178 shci_send( SHCI_OPCODE_C2_FUS_STORE_USR_KEY,
179 local_payload_len ,
180 (uint8_t*)pParam,
181 p_rsp );
182
183 *p_key_index = (((TL_CcEvt_t*)(p_rsp->evtserial.evt.payload))->payload[1]);
184
185 return (SHCI_CmdStatus_t)(((TL_CcEvt_t*)(p_rsp->evtserial.evt.payload))->payload[0]);
186 }
187
SHCI_C2_FUS_LoadUsrKey(uint8_t key_index)188 SHCI_CmdStatus_t SHCI_C2_FUS_LoadUsrKey( uint8_t key_index )
189 {
190 /**
191 * Buffer is large enough to hold command complete without payload
192 */
193 uint8_t local_buffer[TL_BLEEVT_CS_BUFFER_SIZE];
194 TL_EvtPacket_t * p_rsp;
195
196 p_rsp = (TL_EvtPacket_t *)local_buffer;
197
198 local_buffer[0] = key_index;
199
200 shci_send( SHCI_OPCODE_C2_FUS_LOAD_USR_KEY,
201 1,
202 local_buffer,
203 p_rsp );
204
205 return (SHCI_CmdStatus_t)(((TL_CcEvt_t*)(p_rsp->evtserial.evt.payload))->payload[0]);
206 }
207
SHCI_C2_FUS_StartWs(void)208 SHCI_CmdStatus_t SHCI_C2_FUS_StartWs( void )
209 {
210 /**
211 * Buffer is large enough to hold command complete without payload
212 */
213 uint8_t local_buffer[TL_BLEEVT_CS_BUFFER_SIZE];
214 TL_EvtPacket_t * p_rsp;
215
216 p_rsp = (TL_EvtPacket_t *)local_buffer;
217
218 shci_send( SHCI_OPCODE_C2_FUS_START_WS,
219 0,
220 0,
221 p_rsp );
222
223 return (SHCI_CmdStatus_t)(((TL_CcEvt_t*)(p_rsp->evtserial.evt.payload))->payload[0]);
224 }
225
226
SHCI_C2_FUS_LockUsrKey(uint8_t key_index)227 SHCI_CmdStatus_t SHCI_C2_FUS_LockUsrKey( uint8_t key_index )
228 {
229 /**
230 * Buffer is large enough to hold command complete without payload
231 */
232 uint8_t local_buffer[TL_BLEEVT_CS_BUFFER_SIZE];
233 TL_EvtPacket_t * p_rsp;
234
235 p_rsp = (TL_EvtPacket_t *)local_buffer;
236
237 local_buffer[0] = key_index;
238
239 shci_send( SHCI_OPCODE_C2_FUS_LOCK_USR_KEY,
240 1,
241 local_buffer,
242 p_rsp );
243
244 return (SHCI_CmdStatus_t)(((TL_CcEvt_t*)(p_rsp->evtserial.evt.payload))->payload[0]);
245 }
246
SHCI_C2_BLE_Init(SHCI_C2_Ble_Init_Cmd_Packet_t * pCmdPacket)247 SHCI_CmdStatus_t SHCI_C2_BLE_Init( SHCI_C2_Ble_Init_Cmd_Packet_t *pCmdPacket )
248 {
249 /**
250 * Buffer is large enough to hold command complete without payload
251 */
252 uint8_t local_buffer[TL_BLEEVT_CS_BUFFER_SIZE];
253 TL_EvtPacket_t * p_rsp;
254
255 p_rsp = (TL_EvtPacket_t *)local_buffer;
256
257 shci_send( SHCI_OPCODE_C2_BLE_INIT,
258 sizeof( SHCI_C2_Ble_Init_Cmd_Param_t ),
259 (uint8_t*)&pCmdPacket->Param,
260 p_rsp );
261
262 return (SHCI_CmdStatus_t)(((TL_CcEvt_t*)(p_rsp->evtserial.evt.payload))->payload[0]);
263 }
264
SHCI_C2_THREAD_Init(void)265 SHCI_CmdStatus_t SHCI_C2_THREAD_Init( void )
266 {
267 /**
268 * Buffer is large enough to hold command complete without payload
269 */
270 uint8_t local_buffer[TL_BLEEVT_CS_BUFFER_SIZE];
271 TL_EvtPacket_t * p_rsp;
272
273 p_rsp = (TL_EvtPacket_t *)local_buffer;
274
275 shci_send( SHCI_OPCODE_C2_THREAD_INIT,
276 0,
277 0,
278 p_rsp );
279
280 return (SHCI_CmdStatus_t)(((TL_CcEvt_t*)(p_rsp->evtserial.evt.payload))->payload[0]);
281 }
282
SHCI_C2_LLDTESTS_Init(uint8_t param_size,uint8_t * p_param)283 SHCI_CmdStatus_t SHCI_C2_LLDTESTS_Init( uint8_t param_size, uint8_t * p_param )
284 {
285 /**
286 * Buffer is large enough to hold command complete without payload
287 */
288 uint8_t local_buffer[TL_BLEEVT_CS_BUFFER_SIZE];
289 TL_EvtPacket_t * p_rsp;
290
291 p_rsp = (TL_EvtPacket_t *)local_buffer;
292
293 shci_send( SHCI_OPCODE_C2_LLD_TESTS_INIT,
294 param_size,
295 p_param,
296 p_rsp );
297
298 return (SHCI_CmdStatus_t)(((TL_CcEvt_t*)(p_rsp->evtserial.evt.payload))->payload[0]);
299 }
300
SHCI_C2_ZIGBEE_Init(void)301 SHCI_CmdStatus_t SHCI_C2_ZIGBEE_Init( void )
302 {
303 /**
304 * Buffer is large enough to hold command complete without payload
305 */
306 uint8_t local_buffer[TL_BLEEVT_CS_BUFFER_SIZE];
307 TL_EvtPacket_t * p_rsp;
308
309 p_rsp = (TL_EvtPacket_t *)local_buffer;
310
311 shci_send( SHCI_OPCODE_C2_ZIGBEE_INIT,
312 0,
313 0,
314 p_rsp );
315
316 return (SHCI_CmdStatus_t)(((TL_CcEvt_t*)(p_rsp->evtserial.evt.payload))->payload[0]);
317 }
SHCI_C2_DEBUG_Init(SHCI_C2_DEBUG_Init_Cmd_Packet_t * pCmdPacket)318 SHCI_CmdStatus_t SHCI_C2_DEBUG_Init( SHCI_C2_DEBUG_Init_Cmd_Packet_t *pCmdPacket )
319 {
320 /**
321 * Buffer is large enough to hold command complete without payload
322 */
323 uint8_t local_buffer[TL_BLEEVT_CS_BUFFER_SIZE];
324 TL_EvtPacket_t * p_rsp;
325
326 p_rsp = (TL_EvtPacket_t *)local_buffer;
327
328 shci_send( SHCI_OPCODE_C2_DEBUG_INIT,
329 sizeof( SHCI_C2_DEBUG_init_Cmd_Param_t ),
330 (uint8_t*)&pCmdPacket->Param,
331 p_rsp );
332
333 return (SHCI_CmdStatus_t)(((TL_CcEvt_t*)(p_rsp->evtserial.evt.payload))->payload[0]);
334 }
335
SHCI_C2_FLASH_EraseActivity(SHCI_EraseActivity_t erase_activity)336 SHCI_CmdStatus_t SHCI_C2_FLASH_EraseActivity( SHCI_EraseActivity_t erase_activity )
337 {
338 /**
339 * Buffer is large enough to hold command complete without payload
340 */
341 uint8_t local_buffer[TL_BLEEVT_CS_BUFFER_SIZE];
342 TL_EvtPacket_t * p_rsp;
343
344 p_rsp = (TL_EvtPacket_t *)local_buffer;
345
346 local_buffer[0] = erase_activity;
347
348 shci_send( SHCI_OPCODE_C2_FLASH_ERASE_ACTIVITY,
349 1,
350 local_buffer,
351 p_rsp );
352
353 return (SHCI_CmdStatus_t)(((TL_CcEvt_t*)(p_rsp->evtserial.evt.payload))->payload[0]);
354 }
355
SHCI_C2_CONCURRENT_SetMode(SHCI_C2_CONCURRENT_Mode_Param_t Mode)356 SHCI_CmdStatus_t SHCI_C2_CONCURRENT_SetMode( SHCI_C2_CONCURRENT_Mode_Param_t Mode )
357 {
358 /**
359 * Buffer is large enough to hold command complete without payload
360 */
361 uint8_t local_buffer[TL_BLEEVT_CS_BUFFER_SIZE];
362 TL_EvtPacket_t * p_rsp;
363
364 p_rsp = (TL_EvtPacket_t *)local_buffer;
365
366 local_buffer[0] = Mode;
367
368 shci_send( SHCI_OPCODE_C2_CONCURRENT_SET_MODE,
369 1,
370 local_buffer,
371 p_rsp );
372
373 return (SHCI_CmdStatus_t)(((TL_CcEvt_t*)(p_rsp->evtserial.evt.payload))->payload[0]);
374 }
375
SHCI_C2_FLASH_StoreData(SHCI_C2_FLASH_Ip_t Ip)376 SHCI_CmdStatus_t SHCI_C2_FLASH_StoreData( SHCI_C2_FLASH_Ip_t Ip )
377 {
378 /**
379 * Buffer is large enough to hold command complete without payload
380 */
381 uint8_t local_buffer[TL_BLEEVT_CS_BUFFER_SIZE];
382 TL_EvtPacket_t * p_rsp;
383
384 p_rsp = (TL_EvtPacket_t *)local_buffer;
385
386 local_buffer[0] = Ip;
387
388 shci_send( SHCI_OPCODE_C2_FLASH_STORE_DATA,
389 1,
390 local_buffer,
391 p_rsp );
392
393 return (SHCI_CmdStatus_t)(((TL_CcEvt_t*)(p_rsp->evtserial.evt.payload))->payload[0]);
394 }
395
SHCI_C2_FLASH_EraseData(SHCI_C2_FLASH_Ip_t Ip)396 SHCI_CmdStatus_t SHCI_C2_FLASH_EraseData( SHCI_C2_FLASH_Ip_t Ip )
397 {
398 /**
399 * Buffer is large enough to hold command complete without payload
400 */
401 uint8_t local_buffer[TL_BLEEVT_CS_BUFFER_SIZE];
402 TL_EvtPacket_t * p_rsp;
403
404 p_rsp = (TL_EvtPacket_t *)local_buffer;
405
406 local_buffer[0] = Ip;
407
408 shci_send( SHCI_OPCODE_C2_FLASH_ERASE_DATA,
409 1,
410 local_buffer,
411 p_rsp );
412
413 return (SHCI_CmdStatus_t)(((TL_CcEvt_t*)(p_rsp->evtserial.evt.payload))->payload[0]);
414 }
415
SHCI_C2_RADIO_AllowLowPower(SHCI_C2_FLASH_Ip_t Ip,uint8_t FlagRadioLowPowerOn)416 SHCI_CmdStatus_t SHCI_C2_RADIO_AllowLowPower( SHCI_C2_FLASH_Ip_t Ip,uint8_t FlagRadioLowPowerOn)
417 {
418 /**
419 * Buffer is large enough to hold command complete without payload
420 */
421 uint8_t local_buffer[TL_BLEEVT_CS_BUFFER_SIZE];
422 TL_EvtPacket_t * p_rsp;
423
424 p_rsp = (TL_EvtPacket_t *)local_buffer;
425
426 local_buffer[0] = Ip;
427 local_buffer[1] = FlagRadioLowPowerOn;
428
429 shci_send( SHCI_OPCODE_C2_RADIO_ALLOW_LOW_POWER,
430 2,
431 local_buffer,
432 p_rsp );
433
434 return (SHCI_CmdStatus_t)(((TL_CcEvt_t*)(p_rsp->evtserial.evt.payload))->payload[0]);
435 }
436
SHCI_C2_MAC_802_15_4_Init(void)437 SHCI_CmdStatus_t SHCI_C2_MAC_802_15_4_Init( void )
438 {
439 /**
440 * Buffer is large enough to hold command complete without payload
441 */
442 uint8_t local_buffer[TL_BLEEVT_CS_BUFFER_SIZE];
443 TL_EvtPacket_t * p_rsp;
444
445 p_rsp = (TL_EvtPacket_t *)local_buffer;
446
447 shci_send( SHCI_OPCODE_C2_MAC_802_15_4_INIT,
448 0,
449 0,
450 p_rsp );
451
452 return (SHCI_CmdStatus_t)(((TL_CcEvt_t*)(p_rsp->evtserial.evt.payload))->payload[0]);
453 }
454
SHCI_C2_Reinit(void)455 SHCI_CmdStatus_t SHCI_C2_Reinit( void )
456 {
457 /**
458 * Buffer is large enough to hold command complete without payload
459 */
460 uint8_t local_buffer[TL_BLEEVT_CS_BUFFER_SIZE];
461 TL_EvtPacket_t * p_rsp;
462
463 p_rsp = (TL_EvtPacket_t *)local_buffer;
464
465 shci_send( SHCI_OPCODE_C2_REINIT,
466 0,
467 0,
468 p_rsp );
469
470 return (SHCI_CmdStatus_t)(((TL_CcEvt_t*)(p_rsp->evtserial.evt.payload))->payload[0]);
471 }
472
473 /**
474 * Local System COMMAND
475 * These commands are NOT sent to the CPU2
476 */
477
SHCI_GetWirelessFwInfo(WirelessFwInfo_t * pWirelessInfo)478 SHCI_CmdStatus_t SHCI_GetWirelessFwInfo( WirelessFwInfo_t* pWirelessInfo )
479 {
480 uint32_t ipccdba = 0;
481 MB_RefTable_t * p_RefTable = NULL;
482 uint32_t version = 0;
483 uint32_t memorySize = 0;
484 uint32_t infoStack = 0;
485
486 ipccdba = READ_BIT( FLASH->IPCCBR, FLASH_IPCCBR_IPCCDBA );
487 p_RefTable = (MB_RefTable_t*)((ipccdba<<2) + SRAM2A_BASE);
488
489 /**
490 * Retrieve the WirelessFwInfoTable
491 * This table is stored in RAM at startup during the TL (transport layer) initialization
492 */
493 version = p_RefTable->p_device_info_table->WirelessFwInfoTable.Version;
494 pWirelessInfo->VersionMajor = ((version & INFO_VERSION_MAJOR_MASK) >> INFO_VERSION_MAJOR_OFFSET);
495 pWirelessInfo->VersionMinor = ((version & INFO_VERSION_MINOR_MASK) >> INFO_VERSION_MINOR_OFFSET);
496 pWirelessInfo->VersionSub = ((version & INFO_VERSION_SUB_MASK) >> INFO_VERSION_SUB_OFFSET);
497 pWirelessInfo->VersionBranch = ((version & INFO_VERSION_BRANCH_MASK) >> INFO_VERSION_BRANCH_OFFSET);
498 pWirelessInfo->VersionReleaseType = ((version & INFO_VERSION_TYPE_MASK) >> INFO_VERSION_TYPE_OFFSET);
499
500 memorySize = p_RefTable->p_device_info_table->WirelessFwInfoTable.MemorySize;
501 pWirelessInfo->MemorySizeSram2B = ((memorySize & INFO_SIZE_SRAM2B_MASK) >> INFO_SIZE_SRAM2B_OFFSET);
502 pWirelessInfo->MemorySizeSram2A = ((memorySize & INFO_SIZE_SRAM2A_MASK) >> INFO_SIZE_SRAM2A_OFFSET);
503 pWirelessInfo->MemorySizeSram1 = ((memorySize & INFO_SIZE_SRAM1_MASK) >> INFO_SIZE_SRAM1_OFFSET);
504 pWirelessInfo->MemorySizeFlash = ((memorySize & INFO_SIZE_FLASH_MASK) >> INFO_SIZE_FLASH_OFFSET);
505
506 infoStack = p_RefTable->p_device_info_table->WirelessFwInfoTable.InfoStack;
507 pWirelessInfo->StackType = ((infoStack & INFO_STACK_TYPE_MASK) >> INFO_STACK_TYPE_OFFSET);
508
509 /**
510 * Retrieve the FusInfoTable
511 * This table is stored in RAM at startup during the TL (transport layer) initialization
512 */
513 version = p_RefTable->p_device_info_table->FusInfoTable.Version;
514 pWirelessInfo->FusVersionMajor = ((version & INFO_VERSION_MAJOR_MASK) >> INFO_VERSION_MAJOR_OFFSET);
515 pWirelessInfo->FusVersionMinor = ((version & INFO_VERSION_MINOR_MASK) >> INFO_VERSION_MINOR_OFFSET);
516 pWirelessInfo->FusVersionSub = ((version & INFO_VERSION_SUB_MASK) >> INFO_VERSION_SUB_OFFSET);
517
518 memorySize = p_RefTable->p_device_info_table->FusInfoTable.MemorySize;
519 pWirelessInfo->FusMemorySizeSram2B = ((memorySize & INFO_SIZE_SRAM2B_MASK) >> INFO_SIZE_SRAM2B_OFFSET);
520 pWirelessInfo->FusMemorySizeSram2A = ((memorySize & INFO_SIZE_SRAM2A_MASK) >> INFO_SIZE_SRAM2A_OFFSET);
521 pWirelessInfo->FusMemorySizeFlash = ((memorySize & INFO_SIZE_FLASH_MASK) >> INFO_SIZE_FLASH_OFFSET);
522
523 return (SHCI_Success);
524 }
525
526 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
527